[
  {
    "path": ".buckconfig",
    "content": "[cxx]\n  cppflags = -DXXH_NAMESPACE=ZSTD_ -DZSTD_LEGACY_SUPPORT=4\n  cflags = -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow -Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement -Wstrict-prototypes -Wundef -Wpointer-arith\n  cxxppflags = -DXXH_NAMESPACE=ZSTD_ -DZSTD_LEGACY_SUPPORT=4\n  cxxflags = -std=c++11 -Wno-deprecated-declarations\n  gtest_dep = //contrib/pzstd:gtest\n\n[httpserver]\n  port = 0\n"
  },
  {
    "path": ".buckversion",
    "content": "c8dec2e8da52d483f6dd7c6cd2ad694e8e6fed2b\n"
  },
  {
    "path": ".cirrus.yml",
    "content": "task:\n  name: FreeBSD (make check)\n  freebsd_instance:\n    matrix:\n      image_family: freebsd-15-0-amd64-zfs\n  install_script: pkg install -y gmake coreutils\n  script: |\n    MOREFLAGS=\"-Werror\" gmake -j all\n    gmake check\n"
  },
  {
    "path": ".gitattributes",
    "content": "# Set the default behavior\n* text eol=lf\n\n# Explicitly declare source files\n*.c text eol=lf\n*.h text eol=lf\n\n# Denote files that should not be modified.\n*.odt binary\n*.png binary\n\n# Visual Studio\n*.sln text eol=crlf\n*.vcxproj* text eol=crlf\n*.vcproj* text eol=crlf\n*.suo binary\n*.rc text eol=crlf\n\n# Windows\n*.bat text eol=crlf\n*.cmd text eol=crlf\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Downloads data '...'\n2. Run '...' with flags '...'\n3. Scroll up on the log to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots and charts**\nIf applicable, add screenshots and charts to help explain your problem.\n\n**Desktop (please complete the following information):**\n - OS: [e.g. Mac]\n - Version [e.g. 22]\n - Compiler [e.g. gcc]\n - Flags [e.g. O2]\n - Other relevant hardware specs [e.g. Dual-core]\n - Build system [e.g. Makefile]\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"monthly\"\n"
  },
  {
    "path": ".github/workflows/android-ndk-build.yml",
    "content": "name: Android NDK Build\n\non:\n  pull_request:\n    branches: [ dev, release, actionsTest ]\n  push:\n    branches: [ actionsTest, '*ndk*' ]\n\npermissions: read-all\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n\n    - name: Set up JDK 17\n      uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0\n      with:\n        java-version: '17'\n        distribution: 'temurin'\n\n    - name: Setup Android SDK\n      uses: android-actions/setup-android@9fc6c4e9069bf8d3d10b2204b1fb8f6ef7065407 # v3.2.2\n\n    - name: Install Android NDK\n      run: |\n        sdkmanager --install \"ndk;27.0.12077973\"\n        echo \"ANDROID_NDK_HOME=$ANDROID_SDK_ROOT/ndk/27.0.12077973\" >> $GITHUB_ENV\n\n    - name: Build with NDK\n      run: |\n        export PATH=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH\n        make CC=aarch64-linux-android21-clang \\\n             AR=llvm-ar \\\n             RANLIB=llvm-ranlib \\\n             STRIP=llvm-strip\n\n    - name: Build with CMake and NDK\n      run: |\n        mkdir -p build-android\n        cd build-android\n        cmake --version\n        cmake ../build/cmake \\\n          -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake \\\n          -DANDROID_ABI=arm64-v8a \\\n          -DANDROID_PLATFORM=android-21 \\\n          -DCMAKE_BUILD_TYPE=Release\n        cmake --build . --parallel\n"
  },
  {
    "path": ".github/workflows/cmake-tests.yml",
    "content": "name: cmake-tests\n# CMake-specific build and test workflows\n# This workflow validates zstd builds across different CMake configurations,\n# platforms, and edge cases to ensure broad compatibility.\n\nconcurrency:\n  group: cmake-${{ github.ref }}\n  cancel-in-progress: true\n\non:\n  pull_request:\n    branches: [ dev, release, actionsTest ]\n\npermissions: read-all\n\nenv:\n  # Centralized test timeouts for consistency\n  QUICK_TEST_TIME: \"30s\"\n  STANDARD_TEST_TIME: \"1mn\"\n  # Common CMake flags\n  COMMON_CMAKE_FLAGS: \"-DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DZSTD_BUILD_TESTS=ON\"\n\njobs:\n  # Basic cmake build using the root CMakeLists.txt\n  # Provides a lightweight sanity check that the top-level project config builds\n  # with the default Unix Makefiles generator driven purely through cmake commands\n  cmake-root-basic:\n    name: \"CMake Root Build\"\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: Configure (Root)\n      run: |\n        cmake -S . -B cmake-build -DCMAKE_BUILD_TYPE=Release ${{ env.COMMON_CMAKE_FLAGS }}\n    - name: Build (Root)\n      run: |\n        cmake --build cmake-build --config Release\n\n  # Ubuntu-based cmake build using make wrapper\n  # This test uses the make-driven cmake build to ensure compatibility\n  # with the existing build system integration\n  cmake-ubuntu-basic:\n    name: \"CMake build using make wrapper\"\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: Install dependencies\n      run: |\n        sudo apt install liblzma-dev  # Required for compression algorithms\n    - name: CMake build and test via make\n      run: |\n        # Use make wrapper for cmake build with quick test timeouts\n        FUZZERTEST=-T${{ env.STANDARD_TEST_TIME }} ZSTREAM_TESTTIME=-T${{ env.STANDARD_TEST_TIME }} make cmakebuild V=1\n\n  # Cross-platform cmake build with edge case: source paths containing spaces\n  # This test ensures cmake handles filesystem paths with spaces correctly\n  # across different operating systems and build generators\n  cmake-cross-platform-spaces:\n    name: \"CMake Cross-Platform (Spaces in Path)\"\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        include:\n          - os: ubuntu-latest\n            generator: \"Unix Makefiles\"\n            name: \"Linux\"\n          - os: windows-latest\n            generator: \"NMake Makefiles\"\n            name: \"Windows NMake\"\n          - os: macos-latest\n            generator: \"Unix Makefiles\"\n            name: \"macOS\"\n    env:\n      SRC_DIR: \"source directory with spaces\"\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n      with:\n        path: \"${{ env.SRC_DIR }}\"\n    - uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0\n      if: ${{ matrix.generator == 'NMake Makefiles' }}\n    - name: \"CMake build and install (${{ matrix.name }})\"\n      run: |\n        # Test Release build with installation to verify packaging\n        cmake -S \"${{ env.SRC_DIR }}/build/cmake\" -B build -DBUILD_TESTING=ON -G \"${{ matrix.generator }}\" -DCMAKE_BUILD_TYPE=Release --install-prefix \"${{ runner.temp }}/install\"\n        cmake --build build --config Release\n        cmake --install build --config Release\n\n  # Windows-specific cmake testing with Visual Studio 2022\n  # Tests multiple generators and toolchains to ensure broad Windows compatibility\n  # including MSVC (x64, Win32, ARM64), MinGW, and Clang-CL with various architectures and optimizations\n  cmake-windows-comprehensive:\n    name: \"CMake Windows VS2022 (${{ matrix.name }})\"\n    runs-on: ${{ matrix.runner }}\n    strategy:\n      fail-fast: false\n      matrix:\n        include:\n          - generator: \"Visual Studio 17 2022\"\n            flags: \"-A x64\"\n            name: \"MSVC x64\"\n            runner: \"windows-2022\"\n            cmake_extra_flags: \"-DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DZSTD_BUILD_TESTS=ON\"\n          - generator: \"Visual Studio 17 2022\"\n            flags: \"-A Win32\"\n            name: \"MSVC Win32\"\n            runner: \"windows-2022\"\n            cmake_extra_flags: \"-DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DZSTD_BUILD_TESTS=ON\"\n          - generator: \"Visual Studio 17 2022\"\n            flags: \"-A x64\"\n            name: \"MSVC x64 (No ZSTD_BUILD_TESTS)\"\n            runner: \"windows-2022\"\n            # Intentionally omit ZSTD_BUILD_TESTS to reproduce the CXX language configuration bug\n            cmake_extra_flags: \"-DCMAKE_COMPILE_WARNING_AS_ERROR=ON\"\n          - generator: \"Visual Studio 17 2022\"\n            flags: \"-A ARM64\"\n            name: \"MSVC ARM64\"\n            runner: \"windows-11-arm\"  # githuh runner for WOA instance\n          - generator: \"MinGW Makefiles\"\n            flags: \"\"\n            name: \"MinGW\"\n            runner: \"windows-2022\"\n            cmake_extra_flags: \"-DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DZSTD_BUILD_TESTS=ON\"\n          - generator: \"Visual Studio 17 2022\"\n            flags: \"-T ClangCL\"\n            name: \"Clang-CL\"\n            runner: \"windows-2022\"\n            cmake_extra_flags: \"-DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DZSTD_BUILD_TESTS=ON\"\n          - generator: \"Visual Studio 17 2022\"\n            flags: \"-T ClangCL -A x64 -DCMAKE_C_FLAGS=/arch:AVX2\"\n            name: \"Clang-CL AVX2\"\n            runner: \"windows-2022\"\n            cmake_extra_flags: \"-DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DZSTD_BUILD_TESTS=ON\"\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: Add MSBuild to PATH\n      uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # tag=v2.0.0\n    - name: \"Configure CMake (${{ matrix.name }})\"\n      run: |\n        cd build\\cmake\n        mkdir build\n        cd build\n        cmake.exe -G \"${{matrix.generator}}\" ${{matrix.flags}} -DCMAKE_BUILD_TYPE=Debug ${{ matrix.cmake_extra_flags }} -DZSTD_ZSTREAM_FLAGS=-T${{ env.QUICK_TEST_TIME }} -DZSTD_FUZZER_FLAGS=-T${{ env.QUICK_TEST_TIME }} -DZSTD_FULLBENCH_FLAGS=-i0 ..\n    - name: \"Build (${{ matrix.name }})\"\n      run: |\n        cd build\\cmake\\build\n        cmake.exe --build .\n    - name: \"Test (${{ matrix.name }})\"\n      run: |\n        cd build\\cmake\\build\n        ctest.exe -V -C Debug\n\n  # macOS ARM64 (Apple Silicon) specific cmake testing\n  # Validates zstd builds and runs correctly on Apple Silicon architecture\n  # Uses native ARM64 hardware for optimal performance and compatibility testing\n  cmake-macos-arm64:\n    name: \"CMake macOS ARM64 (Apple Silicon)\"\n    runs-on: macos-14  # ARM64 runner\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: \"CMake build and test (ARM64)\"\n      run: |\n        # Configure and build with ARM64-specific optimizations\n        cd build/cmake\n        mkdir build\n        cd build\n        cmake -DCMAKE_BUILD_TYPE=Release ${{ env.COMMON_CMAKE_FLAGS }} -DZSTD_ZSTREAM_FLAGS=-T${{ env.QUICK_TEST_TIME }} -DZSTD_FUZZER_FLAGS=-T${{ env.QUICK_TEST_TIME }} -DZSTD_FULLBENCH_FLAGS=-i1 ..\n        make -j$(sysctl -n hw.ncpu)\n        ctest -V\n"
  },
  {
    "path": ".github/workflows/commit.yml",
    "content": "name: facebook/zstd/commit\non:\n  push:\n    branches:\n    - dev\n  pull_request:\n    branches:\n    - dev\n\npermissions: read-all\n\njobs:\n  short-tests-0:\n    runs-on: ubuntu-latest\n    services:\n      docker:\n        image: fbopensource/zstd-circleci-primary:0.0.1\n        options: --entrypoint /bin/bash\n    steps:\n    - uses: actions/checkout@v6.0.2\n    - name: Install Dependencies\n      run: |\n        sudo apt-get update\n        sudo apt-get install libcurl4-gnutls-dev\n    - name: Test\n      run: |\n        ./tests/test-license.py\n        cc -v\n        CFLAGS=\"-O0 -Werror -pedantic\" make allmost; make clean\n        make c99build; make clean\n        make c11build; make clean\n        make -j regressiontest; make clean\n        make check; make clean\n        make cxxtest; make clean\n\n  short-tests-1:\n    runs-on: ubuntu-latest\n    services:\n      docker:\n        image: fbopensource/zstd-circleci-primary:0.0.1\n        options: --entrypoint /bin/bash\n    steps:\n    - uses: actions/checkout@v6.0.2\n    - name: Install Dependencies\n      run: |\n        sudo apt-get update\n        sudo apt-get install gcc-powerpc-linux-gnu gcc-arm-linux-gnueabi gcc-aarch64-linux-gnu libc6-dev-ppc64-powerpc-cross libcurl4-gnutls-dev lib64gcc-13-dev-powerpc-cross\n    - name: gnu90 build\n      run: make gnu90build && make clean\n    - name: gnu99 build\n      run: make gnu99build && make clean\n    - name: ppc64 build\n      run: make ppc64build V=1 && make clean\n    - name: ppc build\n      run: make ppcbuild V=1 && make clean\n    - name: arm build\n      run: make armbuild V=1 && make clean\n    - name: aarch64 build\n      run: make aarch64build V=1 && make clean\n    - name: test-legacy\n      run: make -C tests test-legacy V=1 && make clean\n    - name: test-longmatch\n      run: make -C tests test-longmatch V=1 && make clean\n    - name: libzstd-nomt build\n      run: make -C lib libzstd-nomt V=1 && make clean\n\n  regression-test:\n    runs-on: ubuntu-latest\n    services:\n      docker:\n        image: fbopensource/zstd-circleci-primary:0.0.1\n        options: --entrypoint /bin/bash\n    env:\n      CIRCLE_ARTIFACTS: \"/tmp/circleci-artifacts\"\n    steps:\n    - uses: actions/checkout@v6.0.2\n    - name: restore_cache\n      uses: actions/cache@v5\n      with:\n        key: regression-cache-{{ checksum \"tests/regression/data.c\" }}-v0\n        path: tests/regression/cache\n        restore-keys: regression-cache-{{ checksum \"tests/regression/data.c\" }}-v0\n    - name: Install Dependencies\n      run: |\n        sudo apt-get update\n        sudo apt-get install libcurl4-gnutls-dev\n    - name: Regression Test\n      run: |\n        make -C programs zstd\n        make -C tests/regression test\n        mkdir -p $CIRCLE_ARTIFACTS\n        ./tests/regression/test                     \\\n            --cache  tests/regression/cache         \\\n            --output $CIRCLE_ARTIFACTS/results.csv  \\\n            --zstd   programs/zstd\n        echo \"NOTE: The new results.csv is uploaded as an artifact to this job\"\n        echo \"      If this fails, go to the Artifacts pane in CircleCI, \"\n        echo \"      download /tmp/circleci-artifacts/results.csv, and if they \"\n        echo \"      are still good, copy it into the repo and commit it.\"\n        echo \"> diff tests/regression/results.csv $CIRCLE_ARTIFACTS/results.csv\"\n        diff tests/regression/results.csv $CIRCLE_ARTIFACTS/results.csv\n    - uses: actions/upload-artifact@v7.0.0\n      with:\n        path: \"/tmp/circleci-artifacts\"\n"
  },
  {
    "path": ".github/workflows/dev-long-tests.yml",
    "content": "name: dev-long-tests\n# Tests generally longer than 10mn\n\nconcurrency:\n  group: long-${{ github.ref }}\n  cancel-in-progress: true\n\non:\n  pull_request:\n    branches: [ dev, release, actionsTest ]\n\npermissions: read-all\n\njobs:\n  # lasts ~7mn\n  make-all:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: make all\n      run: make all\n\n  # lasts ~19mn\n  make-test:\n    runs-on: ubuntu-latest\n    env:\n      DEVNULLRIGHTS: 1\n      READFROMBLOCKDEVICE: 1\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: make test\n      run: |\n        make test\n        make -j zstd\n        ./tests/test_process_substitution.bash ./zstd\n\n  # lasts ~16mn\n  make-test-macos:\n    runs-on: macos-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: make test on macos\n      run: make test\n\n  # lasts ~10mn\n  make-test-32bit:\n    runs-on: ubuntu-latest\n    env:\n      DEVNULLRIGHTS: 1\n      READFROMBLOCKDEVICE: 1\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: make test # note: `make -j test success` seems to require a clean state\n      run: |\n        sudo apt-get -qqq update\n        make libc6install\n        make clean\n        CFLAGS=\"-m32 -O2\" make -j test V=1\n\n  # lasts ~7mn\n  test-largeDictionary:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: largeDictionary\n      run: |\n        CFLAGS=\"-Werror -O3\" make -j -C tests test-largeDictionary\n\n  # lasts ~9mn\n  no-intrinsics-fuzztest:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: no intrinsics fuzztest\n      run: MOREFLAGS=\"-DZSTD_NO_INTRINSICS\" make -C tests fuzztest\n\n  # lasts ~8mn\n  tsan-zstreamtest:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: thread sanitizer zstreamtest\n      run: CC=clang ZSTREAM_TESTTIME=-T3mn make tsan-test-zstream\n\n  uasan-zstreamtest:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: ub + address sanitizer on zstreamtest\n      run: CC=clang make uasan-test-zstream\n\n  # lasts ~11mn\n  tsan-fuzztest:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: thread sanitizer fuzztest\n      run: CC=clang make tsan-fuzztest\n\n  big-tests-zstreamtest32:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: zstream tests in 32bit mode, with big tests\n      run: |\n        sudo apt-get -qqq update\n        make libc6install\n        CC=clang make -C tests test-zstream32 FUZZER_FLAGS=\"--big-tests\"\n\n  # lasts ~13mn\n  gcc-8-asan-ubsan-testzstd:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: gcc-8 + ASan + UBSan + Test Zstd\n      # See https://askubuntu.com/a/1428822\n      run: |\n        echo \"deb [arch=amd64] http://archive.ubuntu.com/ubuntu focal main universe\" | sudo tee -a /etc/apt/sources.list\n        sudo apt-get -qqq update\n        make gcc8install\n        CC=gcc-8 make -j uasan-test-zstd </dev/null V=1\n\n  clang-asan-ubsan-testzstd:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: clang + ASan + UBSan + Test Zstd\n      run: CC=clang make -j uasan-test-zstd </dev/null V=1\n\n  gcc-asan-ubsan-testzstd-32bit:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: ASan + UBSan + Test Zstd, 32bit mode\n      run: |\n        sudo apt-get -qqq update\n        make libc6install\n        make -j uasan-test-zstd32 V=1\n\n    # Note : external libraries must be turned off when using MSAN tests,\n    # because they are not msan-instrumented,\n    # so any data coming from these libraries is always considered \"uninitialized\"\n\n  gcc-8-asan-ubsan-fuzz:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: gcc-8 + ASan + UBSan + Fuzz Test\n      # See https://askubuntu.com/a/1428822\n      run: |\n        echo \"deb [arch=amd64] http://archive.ubuntu.com/ubuntu focal main universe\" | sudo tee -a /etc/apt/sources.list\n        sudo apt-get -qqq update\n        make gcc8install\n        CC=gcc-8 FUZZER_FLAGS=\"--long-tests\" make clean uasan-fuzztest\n\n  clang-asan-ubsan-fuzz:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: clang + ASan + UBSan + Fuzz Test\n      run: CC=clang FUZZER_FLAGS=\"--long-tests\" make clean uasan-fuzztest\n\n  gcc-asan-ubsan-fuzz32:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: ASan + UBSan + Fuzz Test 32bit\n      run: |\n        sudo apt-get -qqq update\n        make libc6install\n        CFLAGS=\"-O3 -m32\" FUZZER_FLAGS=\"--long-tests\" make uasan-fuzztest\n\n  clang-asan-fuzz32:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: clang + ASan + Fuzz Test 32bit\n      run: |\n        sudo apt-get -qqq update\n        make libc6install\n        CC=clang CFLAGS=\"-O3 -m32\" FUZZER_FLAGS=\"--long-tests\" make asan-fuzztest\n\n# The following test seems to have issues on github CI specifically,\n# it does not provide the `__mulodi4` instruction emulation\n# required for signed 64-bit multiplication.\n# Replaced by asan-only test (above)\n#\n#  clang-asan-ubsan-fuzz32:\n#    runs-on: ubuntu-20.04\n#    steps:\n#    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n#    - name: clang + ASan + UBSan + Fuzz Test 32bit\n#      run: |\n#        sudo apt-get -qqq update\n#        make libc6install\n#        CC=clang CFLAGS=\"-O3 -m32\" FUZZER_FLAGS=\"--long-tests\" make uasan-fuzztest\n\n  asan-ubsan-regression:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: ASan + UBSan + Regression Test\n      run: make -j uasanregressiontest\n\n  clang-asan-ubsan-regression:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: clang + ASan + UBSan + Regression Test\n      run: CC=clang make -j uasanregressiontest\n\n  msan-regression:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: MSan + Regression Test\n      run: make -j msanregressiontest\n\n  clang-msan-fuzz-unoptimized:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n      - name: clang + MSan + Fuzz Test\n        run: |\n          sudo apt-get -qqq update\n          sudo apt-get install clang\n          CC=clang MOREFLAGS=\"-O0\" make clean msan-fuzztest\n\n  clang-msan-fuzz:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: clang + MSan + Fuzz Test\n      run: |\n        sudo apt-get -qqq update\n        sudo apt-get install clang\n        CC=clang FUZZER_FLAGS=\"--long-tests\" make clean msan-fuzztest\n\n  clang-msan-testzstd:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: clang + MSan + Test Zstd\n      run: |\n        CC=clang make -j msan-test-zstd HAVE_ZLIB=0 HAVE_LZ4=0 HAVE_LZMA=0 V=1\n\n  armfuzz:\n      runs-on: ubuntu-latest\n      steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n      - name: Qemu ARM emulation + Fuzz Test\n        run: |\n          sudo apt-get -qqq update\n          make arminstall\n          make armfuzz\n\n  valgrind-fuzz-test:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: valgrind + fuzz test stack mode    # ~ 7mn\n      shell: 'script -q -e -c \"bash {0}\"'\n      run: |\n        sudo apt-get -qqq update\n        make valgrindinstall\n        make -C tests test-valgrind\n        make clean\n        make -C tests test-fuzzer-stackmode\n\n  mingw-long-test:\n    runs-on: windows-latest\n    defaults:\n      run:\n        shell: msys2 {0}\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - uses: msys2/setup-msys2@4f806de0a5a7294ffabaff804b38a9b435a73bda # tag=v2.30.0\n      with:\n        msystem: MINGW64\n        install: make\n        update: true\n    # Based on https://ariya.io/2020/07/on-github-actions-with-msys2\n    - name: install mingw gcc\n      run: pacman --noconfirm -S gcc\n    - name: MINGW64 gcc fuzztest\n      run: |\n        export CC=\"gcc\"\n        export CXX=\"g++\"\n        export FUZZERTEST=\"-T2mn\"\n        export ZSTREAM_TESTTIME=\"-T2mn\"\n        echo \"Testing $CC $CXX MINGW64\"\n        make -v\n        $CC --version\n        $CXX --version\n        make -C tests fuzztest\n\n  # lasts ~20mn\n  oss-fuzz:\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        sanitizer: [address, undefined, memory]\n    steps:\n    - name: Build Fuzzers (${{ matrix.sanitizer }})\n      id: build\n      uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master\n      with:\n        oss-fuzz-project-name: 'zstd'\n        dry-run: false\n        sanitizer: ${{ matrix.sanitizer }}\n    - name: Run Fuzzers (${{ matrix.sanitizer }})\n      uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master\n      with:\n        oss-fuzz-project-name: 'zstd'\n        fuzz-seconds: 600\n        dry-run: false\n        sanitizer: ${{ matrix.sanitizer }}\n    - name: Upload Crash\n      uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # tag=v7.0.0\n      if: failure() && steps.build.outcome == 'success'\n      with:\n        name: ${{ matrix.sanitizer }}-artifacts\n        path: ./out/artifacts\n"
  },
  {
    "path": ".github/workflows/dev-short-tests.yml",
    "content": "name: dev-short-tests\n# Faster tests: mostly build tests, along with some other\n# misc tests\n\nconcurrency:\n  group: fast-${{ github.ref }}\n  cancel-in-progress: true\n\non:\n  pull_request:\n    branches: [ dev, release, actionsTest ]\n\npermissions: read-all\n\njobs:\n  linux-kernel:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: linux kernel, library + build + test\n      run: make -C contrib/linux-kernel test CFLAGS=\"-Werror -Wunused-const-variable -Wunused-but-set-variable\"\n\n  benchmarking:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: make benchmarking\n      run: make benchmarking\n\n  check-32bit: # designed to catch https://github.com/facebook/zstd/issues/2428\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: make check on 32-bit\n      run: |\n        sudo apt update\n        APT_PACKAGES=\"gcc-multilib\" make apt-install\n        CFLAGS=\"-m32 -O1 -fstack-protector\" make check V=1\n        CFLAGS=\"-m32 -O1 -fstack-protector\" make V=1 -C tests test-cli-tests\n\n  build-c89:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: ensure zstd can be built with c89/c90 compilers (+ long long support + variadic macros)\n      run: |\n        make c89build V=1\n\n  build-zstd-dll:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: build zstd bin against a dynamic lib (debuglevel for more dependencies)\n      run: |\n        make -C lib lib-mt-release\n        DEBUGLEVEL=2 make -C programs zstd-dll\n\n  gcc-7-libzstd:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: gcc-7 + libzstdmt compilation\n      # See https://askubuntu.com/a/1428822\n      run: |\n        echo \"deb [arch=amd64] http://archive.ubuntu.com/ubuntu focal main universe\" | sudo tee -a /etc/apt/sources.list\n        sudo apt-get -qqq update\n        make gcc7install\n        CC=gcc-7 CFLAGS=-Werror make -j all\n        make clean\n        LDFLAGS=-Wl,--no-undefined make -C lib libzstd-mt\n\n    # candidate test (for discussion) : underlink test\n    # LDFLAGS=-Wl,--no-undefined : will make the linker fail if dll is underlinked\n\n  cpp-gnu90-c99-compatibility:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: C++, gnu90 and c99 compatibility\n      run: |\n        make cxxtest\n        make clean\n        make gnu90build\n        make clean\n        make c99build\n        make clean\n        make travis-install   # just ensures `make install` works\n\n  mingw-cross-compilation:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: mingw cross-compilation\n      run: |\n        # sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix; (doesn't work)\n        sudo apt-get -qqq update\n        sudo apt-get install gcc-mingw-w64\n        CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ CFLAGS=\"-Werror -O1\" make zstd\n\n  armbuild:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: ARM Build Test\n      run: |\n        sudo apt-get -qqq update\n        make arminstall\n        make armbuild\n\n  bourne-shell:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: Bourne shell compatibility (shellcheck)\n      run: |\n        wget https://github.com/koalaman/shellcheck/releases/download/v0.7.1/shellcheck-v0.7.1.linux.x86_64.tar.xz\n        tar -xf shellcheck-v0.7.1.linux.x86_64.tar.xz\n        shellcheck-v0.7.1/shellcheck --shell=sh --severity=warning --exclude=SC2010 tests/playTests.sh\n\n  zlib-wrapper:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: install valgrind\n      run: |\n        sudo apt-get -qqq update\n        make valgrindinstall V=1\n    - name: zlib wrapper test\n      run: make -C zlibWrapper test V=1\n    - name: zlib wrapper test under valgrind\n      run: make -C zlibWrapper test-valgrind V=1\n\n  lz4-threadpool-libs:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: LZ4, thread pool, and libs build testslib wrapper test\n      run: |\n        make -C tests test-lz4\n        make check < /dev/null | tee   # mess with lz4 console detection\n        make clean\n        make -C tests test-pool\n        make clean\n        bash tests/libzstd_builds.sh\n\n  gcc-make-all-avx2:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: Make all, with AVX2\n      run: |\n        sudo apt-get -qqq update\n        make libc6install\n        CFLAGS=\"-Werror -mavx2\" make -j all\n\n  gcc-make-all-32bit:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: Make all, 32bit mode\n      run: |\n        sudo apt-get -qqq update\n        make libc6install\n        CFLAGS=\"-Werror -m32\" make -j all32\n\n  gcc-make-all-32bit-avx2:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: Make all, 32bit + AVX2 mode\n      run: |\n        sudo apt-get -qqq update\n        make libc6install\n        CPPFLAGS=\"-DSTATIC_BMI2=1\" CFLAGS=\"-Werror -m32 -mavx2 -mbmi2\" make -j all32\n\n\n  gcc-8-make:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n      - name: gcc-8 build\n        # See https://askubuntu.com/a/1428822\n        run: |\n          echo \"deb [arch=amd64] http://archive.ubuntu.com/ubuntu focal main universe\" | sudo tee -a /etc/apt/sources.list\n          sudo apt-get -qqq update\n          make gcc8install\n          CC=gcc-8 CFLAGS=\"-Werror\" make -j all\n\n  make-external-compressors:\n    strategy:\n      matrix:\n        include:\n          - name: \"no external compressors\"\n            flags: \"HAVE_ZLIB=0 HAVE_LZ4=0 HAVE_LZMA=0\"\n          - name: \"only zlib\"\n            flags: \"HAVE_ZLIB=1 HAVE_LZ4=0 HAVE_LZMA=0\"\n          - name: \"only lz4\"\n            flags: \"HAVE_ZLIB=0 HAVE_LZ4=1 HAVE_LZMA=0\"\n          - name: \"only lzma\"\n            flags: \"HAVE_ZLIB=0 HAVE_LZ4=0 HAVE_LZMA=1\"\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n      - name: Build with ${{matrix.name}}\n        run: |\n          sudo apt install liblzma-dev\n          ${{matrix.flags}} make zstd\n\n\n  implicit-fall-through:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n      - name: -Wimplicit-fallthrough build\n        run: |\n          make clean\n          CC=gcc MOREFLAGS=\"-Werror -Wimplicit-fallthrough=2 -O0\" make -C lib -j libzstd.a ZSTD_LEGACY_SUPPORT=0\n          make clean\n          CC=clang MOREFLAGS=\"-Werror -Wimplicit-fallthrough -O0\" make -C lib -j libzstd.a ZSTD_LEGACY_SUPPORT=0\n\n  meson-linux:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n      - name: Install packages\n        run: |\n          sudo apt-get update\n          sudo apt-get -y install build-essential python3-pip ninja-build liblz4-dev liblzma-dev\n          pip install --pre meson\n      - name: Build with Meson\n        run: |\n          meson setup \\\n            --buildtype=debugoptimized \\\n            -Db_lundef=false \\\n            -Dauto_features=enabled \\\n            -Dbin_programs=true \\\n            -Dbin_tests=true \\\n            -Dbin_contrib=true \\\n            -Ddefault_library=both \\\n            build/meson mesonBuild\n          ninja -C mesonBuild/\n          meson test -C mesonBuild/ --print-errorlogs\n          meson install -C mesonBuild --destdir staging/\n\n  meson-mingw-cross-compilation:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n      - name: Install packages\n        run: |\n          sudo apt-get -qqq update\n          sudo apt-get -y install build-essential python3-pip ninja-build {gcc,g++}-mingw-w64-x86-64\n          pip install --pre meson\n      - name: Build with Meson\n        run: |\n          cat > cross.ini <<EOF\n          [binaries]\n          ar = 'x86_64-w64-mingw32-ar'\n          c = 'x86_64-w64-mingw32-gcc'\n          cpp = 'x86_64-w64-mingw32-g++'\n          ld = 'x86_64-w64-mingw32-ld'\n          objcopy = 'x86_64-w64-mingw32-objcopy'\n          objdump = 'x86_64-w64-mingw32-objdump'\n          strip = 'x86_64-w64-mingw32-strip'\n          windres = 'x86_64-w64-mingw32-windres'\n\n          [host_machine]\n          system = 'windows'\n          endian = 'little'\n          cpu_family = 'x86_64'\n          cpu = 'x86_64'\n          EOF\n\n          # pzstd doesn't build; skip -Dbin_contrib=true\n          meson setup \\\n            --buildtype=debugoptimized \\\n            --cross-file=cross.ini \\\n            -Db_lundef=false \\\n            -Dbin_programs=true \\\n            -Dbin_tests=true \\\n            -Ddefault_library=both \\\n            build/meson builddir\n          ninja -C builddir/\n          if grep -- -pthread builddir/meson-private/libzstd.pc; then\n            echo \"Error: found stray pthread dependency\"\n            exit 1\n          fi\n\n  meson-windows:\n    runs-on: windows-latest\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n      - name: Install packages\n        run: pip install --pre meson\n      - name: Configure with Meson\n        run: |\n          meson setup --vsenv build/meson/ builddir -Dbin_tests=true -Dbin_programs=true -Dbin_contrib=true\n      - name: Build with Meson\n        run: |\n          meson compile -C builddir/\n      - name: Test with Meson\n        run: |\n          meson test -C builddir/ --print-errorlogs\n      - name: Install with Meson\n        run: |\n          meson install -C builddir --destdir staging/\n\n  msbuild-visual-studio:\n    strategy:\n      fail-fast: false  # 'false' means Don't stop matrix workflows even if some matrix failed.\n      matrix:\n        include: [\n          { name: \"VS 2022 x64 Debug\", platform: x64, configuration: Debug, toolset: v143, runner: \"windows-2022\", arch: \"\" },\n          { name: \"VS 2022 Win32 Debug\", platform: Win32, configuration: Debug, toolset: v143, runner: \"windows-2022\", arch: \"\" },\n          { name: \"VS 2022 x64 Release\", platform: x64, configuration: Release, toolset: v143, runner: \"windows-2022\", arch: \"\"},\n          { name: \"VS 2022 Win32 Release\", platform: Win32, configuration: Release, toolset: v143, runner: \"windows-2022\", arch: \"\"},\n          { name: \"VS 2025 x64 Debug\", platform: x64, configuration: Debug, toolset: v143, runner: \"windows-2025\", arch: \"\"},\n          { name: \"VS 2022 x64 Release AVX2\", platform: x64, configuration: Release, toolset: v143, runner: \"windows-2022\", arch: \"AdvancedVectorExtensions2\" },\n        ]\n    runs-on: ${{matrix.runner}}\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: Add MSBuild to PATH\n      uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # tag=v2.0.0\n    - name: Build ${{matrix.name}}\n      working-directory: ${{env.GITHUB_WORKSPACE}}\n      # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference\n      if: ${{ matrix.arch == '' }}\n      run: >\n        msbuild \"build\\VS2010\\zstd.sln\" /m /verbosity:minimal /property:PlatformToolset=${{matrix.toolset}}\n        /t:Clean,Build /p:Platform=${{matrix.platform}} /p:Configuration=${{matrix.configuration}} /warnaserror\n    - name: Build ${{matrix.name}}\n      working-directory: ${{env.GITHUB_WORKSPACE}}\n      # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference\n      if: ${{ matrix.arch != '' }}\n      run: >\n        msbuild \"build\\VS2010\\zstd.sln\" /m /verbosity:minimal /property:PlatformToolset=${{matrix.toolset}}\n        /t:Clean,Build /p:Platform=${{matrix.platform}} /p:Configuration=${{matrix.configuration}} /warnaserror\n        /p:InstructionSet=${{matrix.arch}}\n\n  # This tests that we don't accidentally grow the size too much.\n  # If the size grows intentionally, you can raise these numbers.\n  # But we do need to think about binary size, since it is a concern.\n  libzstd-size:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: libzstd size test\n      run: |\n        make clean && make -j -C lib libzstd && ./tests/check_size.py lib/libzstd.so 1100000\n        make clean && make -j -C lib libzstd ZSTD_LIB_COMPRESSION=0 ZSTD_LIB_DICTBUILDER=0 && ./tests/check_size.py lib/libzstd.so 400000\n        make clean && make -j -C lib libzstd ZSTD_LIB_MINIFY=1 && ./tests/check_size.py lib/libzstd.so 300000\n        make clean && make -j -C lib libzstd ZSTD_LIB_MINIFY=1 ZSTD_LIB_COMPRESSION=0 ZSTD_LIB_DICTBUILDER=0 && ./tests/check_size.py lib/libzstd.so 80000\n\n  minimal-decompressor-macros:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: minimal decompressor macros\n      run: |\n        make clean && make -j all ZSTD_LIB_MINIFY=1 MOREFLAGS=\"-Werror\"\n        make clean && make check ZSTD_LIB_MINIFY=1 MOREFLAGS=\"-Werror\"\n        make clean && make -j all MOREFLAGS=\"-Werror -DHUF_FORCE_DECOMPRESS_X1 -DZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT\"\n        make clean && make check MOREFLAGS=\"-Werror -DHUF_FORCE_DECOMPRESS_X1 -DZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT\"\n        make clean && make -j all MOREFLAGS=\"-Werror -DHUF_FORCE_DECOMPRESS_X2 -DZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG\"\n        make clean && make check MOREFLAGS=\"-Werror -DHUF_FORCE_DECOMPRESS_X2 -DZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG\"\n        make clean && make -j all MOREFLAGS=\"-Werror -DZSTD_NO_INLINE -DZSTD_STRIP_ERROR_STRINGS\"\n        make clean && make check MOREFLAGS=\"-Werror -DZSTD_NO_INLINE -DZSTD_STRIP_ERROR_STRINGS\"\n        make clean && make check ZSTD_LIB_EXCLUDE_COMPRESSORS_DFAST_AND_UP=1 MOREFLAGS=\"-Werror\"\n        make clean && make check ZSTD_LIB_EXCLUDE_COMPRESSORS_GREEDY_AND_UP=1 MOREFLAGS=\"-Werror\"\n\n  dynamic-bmi2:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: dynamic bmi2 tests\n      run: |\n        make clean && make -j check MOREFLAGS=\"-O0 -Werror -mbmi2\"\n        make clean && make -j check MOREFLAGS=\"-O0 -Werror -DDYNAMIC_BMI2=1\"\n        make clean && make -j check MOREFLAGS=\"-O0 -Werror -DDYNAMIC_BMI2=1 -mbmi2\"\n        make clean && make -j check MOREFLAGS=\"-O0 -Werror -DDYNAMIC_BMI2=0\"\n        make clean && make -j check MOREFLAGS=\"-O0 -Werror -DDYNAMIC_BMI2=0 -mbmi2\"\n\n  test-variants:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: make all variants & validate\n      run: |\n        make -j -C programs allVariants MOREFLAGS=-O0\n        ./tests/test-variants.sh\n\n  qemu-consistency:\n    name: QEMU ${{ matrix.name }}\n    runs-on: ubuntu-24.04\n    strategy:\n      fail-fast: false  # 'false' means Don't stop matrix workflows even if some matrix failed.\n      matrix:\n        include: [\n          { name: ARM,      xcc_pkg: gcc-arm-linux-gnueabi,     xcc: arm-linux-gnueabi-gcc,     xemu_pkg: qemu-system-arm,    xemu: qemu-arm-static     },\n          { name: ARM64,    xcc_pkg: gcc-aarch64-linux-gnu,     xcc: aarch64-linux-gnu-gcc,     xemu_pkg: qemu-system-aarch64,xemu: qemu-aarch64-static },\n          { name: PPC,      xcc_pkg: gcc-powerpc-linux-gnu,     xcc: powerpc-linux-gnu-gcc,     xemu_pkg: qemu-system-ppc,    xemu: qemu-ppc-static     },\n          { name: PPC64LE,  xcc_pkg: gcc-powerpc64le-linux-gnu, xcc: powerpc64le-linux-gnu-gcc, xemu_pkg: qemu-system-ppc,    xemu: qemu-ppc64le-static },\n          { name: S390X,    xcc_pkg: gcc-s390x-linux-gnu,       xcc: s390x-linux-gnu-gcc,       xemu_pkg: qemu-system-s390x,  xemu: qemu-s390x-static   },\n          { name: MIPS,     xcc_pkg: gcc-mips-linux-gnu,        xcc: mips-linux-gnu-gcc,        xemu_pkg: qemu-system-mips,   xemu: qemu-mips-static    },\n          { name: RISC-V,   xcc_pkg: gcc-14-riscv64-linux-gnu,  xcc: riscv64-linux-gnu-gcc-14,  xemu_pkg: qemu-system-riscv64,xemu: qemu-riscv64-static },\n          { name: M68K,     xcc_pkg: gcc-m68k-linux-gnu,        xcc: m68k-linux-gnu-gcc,        xemu_pkg: qemu-system-m68k,   xemu: qemu-m68k-static    },\n          { name: SPARC,    xcc_pkg: gcc-sparc64-linux-gnu,     xcc: sparc64-linux-gnu-gcc,     xemu_pkg: qemu-system-sparc,  xemu: qemu-sparc64-static },\n        ]\n    env:                        # Set environment variables\n      XCC: ${{ matrix.xcc }}\n      XEMU: ${{ matrix.xemu }}\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: apt update & install\n      run: |\n        sudo apt-get update\n        sudo apt-get install gcc-multilib g++-multilib qemu-utils qemu-user-static\n        sudo apt-get install ${{ matrix.xcc_pkg }} ${{ matrix.xemu_pkg }}\n    - name: Environment info\n      run: |\n        echo && which $XCC\n        echo && $XCC --version\n        echo && $XCC -v  # Show built-in specs\n        echo && which $XEMU\n        echo && $XEMU --version\n    - name: ARM\n      if: ${{ matrix.name == 'ARM' }}\n      run: |\n        LDFLAGS=\"-static\" CC=$XCC QEMU_SYS=$XEMU make clean check\n    - name: ARM64\n      if: ${{ matrix.name == 'ARM64' }}\n      run: |\n        make clean\n        LDFLAGS=\"-static\" CC=$XCC QEMU_SYS=$XEMU make -j check\n        LDFLAGS=\"-static\" CC=$XCC QEMU_SYS=$XEMU make -j -C tests test-cli-tests\n        CFLAGS=\"-O3 -march=armv8.2-a+sve2\" LDFLAGS=\"-static\" CC=$XCC QEMU_SYS=$XEMU make -j check\n        CFLAGS=\"-O3 -march=armv8.2-a+sve2\" LDFLAGS=\"-static\" CC=$XCC QEMU_SYS=$XEMU make -j -C tests test-cli-tests\n# This test is only compatible with standard libraries that support BTI (Branch Target Identification).\n# Unfortunately, the standard library provided on Ubuntu 24.04 does not have this feature enabled.\n#        make clean\n#        LDFLAGS=\"-static -z force-bti\" MOREFLAGS=\"-mbranch-protection=standard\" CC=$XCC QEMU_SYS=$XEMU make check V=1\n    - name: PPC\n      if: ${{ matrix.name == 'PPC' }}\n      run: |\n        LDFLAGS=\"-static\" CC=$XCC QEMU_SYS=$XEMU make clean check\n    - name: PPC64LE\n      if: ${{ matrix.name == 'PPC64LE' }}\n      run: |\n        LDFLAGS=\"-static\" CC=$XCC QEMU_SYS=$XEMU make clean check\n    - name: S390X\n      if: ${{ matrix.name == 'S390X' }}\n      run: |\n        LDFLAGS=\"-static\" CC=$XCC QEMU_SYS=$XEMU make clean check\n    - name: MIPS\n      if: ${{ matrix.name == 'MIPS' }}\n      run: |\n        LDFLAGS=\"-static\" CC=$XCC QEMU_SYS=$XEMU make clean check\n    - name: RISC-V\n      if: ${{ matrix.name == 'RISC-V' }}\n      run: |\n        LDFLAGS=\"-static\" CC=$XCC QEMU_SYS=$XEMU make clean check\n        CFLAGS=\"-march=rv64gcv -O3\" LDFLAGS=\"-static -DMEM_FORCE_MEMORY_ACCESS=0\" CC=$XCC QEMU_SYS=\"$XEMU -cpu rv64,v=true,vlen=128\" make clean check\n        CFLAGS=\"-march=rv64gcv -O3\" LDFLAGS=\"-static -DMEM_FORCE_MEMORY_ACCESS=0\" CC=$XCC QEMU_SYS=\"$XEMU -cpu rv64,v=true,vlen=256\" make clean check\n        CFLAGS=\"-march=rv64gcv -O3\" LDFLAGS=\"-static -DMEM_FORCE_MEMORY_ACCESS=0\" CC=$XCC QEMU_SYS=\"$XEMU -cpu rv64,v=true,vlen=512\" make clean check\n    - name: M68K\n      if: ${{ matrix.name == 'M68K' }}\n      run: |\n        LDFLAGS=\"-static\" CC=$XCC QEMU_SYS=$XEMU make clean check\n    - name: SPARC\n      if: ${{ matrix.name == 'SPARC' }}\n      run: |\n        LDFLAGS=\"-static\" CC=$XCC QEMU_SYS=$XEMU make clean check\n\n  mingw-short-test:\n    runs-on: windows-latest\n    strategy:\n      fail-fast: false  # 'false' means Don't stop matrix workflows even if some matrix failed.\n      matrix:\n        include: [\n          { compiler: gcc, msystem: MINGW32, cflags: \"-Werror\"},\n          { compiler: gcc, msystem: MINGW64, cflags: \"-Werror\"},\n          { compiler: clang, msystem: MINGW64, cflags: \"--target=x86_64-w64-mingw32 -Werror -Wconversion -Wno-sign-conversion -Wno-unused-command-line-argument\"},\n        ]\n    defaults:\n      run:\n        shell: msys2 {0}\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - uses: msys2/setup-msys2@4f806de0a5a7294ffabaff804b38a9b435a73bda # tag=v2.30.0\n      with:\n        msystem: ${{ matrix.msystem }}\n        install: make diffutils\n        update: true\n    # Based on https://ariya.io/2020/07/on-github-actions-with-msys2\n    - name: install mingw gcc i686\n      if: ${{ (matrix.msystem == 'MINGW32') && (matrix.compiler == 'gcc') }}\n      run: pacman --noconfirm -S mingw-w64-i686-gcc\n    - name: install mingw gcc x86_64\n      if: ${{ (matrix.msystem == 'MINGW64') && (matrix.compiler == 'gcc') }}\n      run: pacman --noconfirm -S mingw-w64-x86_64-gcc\n    - name: install mingw clang i686\n      if: ${{ (matrix.msystem == 'MINGW32') && (matrix.compiler == 'clang') }}\n      run: pacman --noconfirm -S mingw-w64-i686-clang\n    - name: install mingw clang x86_64\n      if: ${{ (matrix.msystem == 'MINGW64') && (matrix.compiler == 'clang') }}\n      run: pacman --noconfirm -S mingw-w64-x86_64-clang\n    - name: run mingw tests\n      run: |\n        make -v\n        export CC=${{ matrix.compiler }}\n        $CC --version\n        CFLAGS=\"${{ matrix.cflags }}\" make -j allzstd\n        echo \"Testing $CC ${{ matrix.msystem }}\"\n        make clean\n        MSYS=\"\" make check\n\n  visual-runtime-tests:\n    runs-on: windows-latest\n    strategy:\n      matrix:\n        platform: [x64, Win32]\n        configuration: [Release]\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: Add MSBuild to PATH\n      uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # tag=v2.0.0\n    - name: Build and run tests\n      working-directory: ${{env.GITHUB_WORKSPACE}}\n      env:\n        ZSTD_BIN: ./zstd.exe\n        DATAGEN_BIN: ./datagen.exe\n      # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference\n      run: |\n        msbuild \"build\\VS2010\\zstd.sln\" /m /verbosity:minimal /property:PlatformToolset=v142 /t:Clean,Build /p:Platform=${{matrix.platform}} /p:Configuration=${{matrix.configuration}}\n        COPY build\\VS2010\\bin\\${{matrix.platform}}_${{matrix.configuration}}\\*.exe tests\\\n        CD tests\n        sh -e playTests.sh\n        .\\fuzzer.exe -T2m\n\n  # Following instructions at: https://github.com/marketplace/actions/install-cygwin-action\n  cygwin-tests:\n    runs-on: windows-latest\n    steps:\n    - run: git config --global core.autocrlf input\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - uses: cygwin/cygwin-install-action@711d29f3da23c9f4a1798e369a6f01198c13b11a # tag=v6\n      with:\n        platform: x86_64\n        packages: >-\n          autoconf,\n          automake,\n          gcc-g++,\n          make,\n          mingw64-x86_64-gcc-g++,\n          patch,\n          perl\n    - name: cygwin tests\n      shell: C:\\cygwin\\bin\\bash.exe --noprofile --norc -eo pipefail '{0}'\n      run: >-\n        export PATH=/usr/bin:$(cygpath ${SYSTEMROOT})/system32 &&\n        export CFLAGS=\"-Werror -O1\" &&\n        ls &&\n        make -j allzstd &&\n        make -C tests fuzzer &&\n        ./tests/fuzzer.exe -v -T1m\n    - name: cygwin install test\n      shell: C:\\cygwin\\bin\\bash.exe --noprofile --norc -eo pipefail '{0}'\n      run: >-\n        make -j &&\n        make install\n\n  pkg-config:\n    runs-on: ubuntu-latest\n    container:\n      image: debian:testing\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n      - name: Install dependencies\n        run: |\n          apt -y update\n          apt -y install --no-install-recommends gcc libc6-dev make pkg-config\n      - name: Build and install\n        run: make -C lib install\n      - name: Test pkg-config\n        run: |\n          cc -Wall -Wextra -Wpedantic -Werror -o simple examples/simple_compression.c $(pkg-config --cflags --libs libzstd)\n          ./simple LICENSE\n\n  versions-compatibility:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: Versions Compatibility Test\n      run: |\n        make -C tests versionsTest\n\n  clangbuild:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: make clangbuild\n      run: |\n        make clangbuild\n\n  gcc-pgo:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: Build PGO Zstd with GCC\n      env:\n        CC: gcc\n      run: |\n        make -C programs zstd-pgo\n        ./programs/zstd -b\n\n  clang-pgo:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: Build PGO Zstd with Clang\n      env:\n        CC: clang\n      run: |\n        sudo apt install -y llvm\n        llvm-profdata --version\n        make -C programs zstd-pgo\n        ./programs/zstd -b\n\n  musl-build:\n    runs-on: ubuntu-22.04\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n      - name: Install musl-tools\n        run: |\n          sudo apt install -y musl-tools\n      - name: Compile with musl-gcc and test-zstd\n        run: |\n          CC=musl-gcc CFLAGS=\"-Werror -O3\" CPPFLAGS=-DZDICT_QSORT=ZDICT_QSORT_C90 make -j -C tests test-zstd V=1\n\n  intel-cet-compatibility:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: Build Zstd\n      run: |\n        make -j zstd V=1\n        readelf -n zstd\n    - name: Get Intel SDE\n      run: |\n        curl -LO https://downloadmirror.intel.com/813591/sde-external-9.33.0-2024-01-07-lin.tar.xz\n        tar xJvf sde-external-9.33.0-2024-01-07-lin.tar.xz\n    - name: Configure Permissions\n      run: |\n        echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope\n    - name: Run Under SDE\n      run: |\n        sde-external-9.33.0-2024-01-07-lin/sde -cet -cet-raise 0 -cet-endbr-exe -cet-stderr -cet-abort -- ./zstd -b3\n\n  icx:\n    # install instructions: https://www.intel.com/content/www/us/en/docs/oneapi/installation-guide-linux/2025-0/apt-005.html\n    name: icx-check\n    runs-on: ubuntu-latest\n    steps:\n    - name: install icx\n      run: |\n        # download the key to system keyring\n        wget -O- https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB \\\n        | gpg --dearmor | sudo tee /usr/share/keyrings/oneapi-archive-keyring.gpg > /dev/null\n\n        # add signed entry to apt sources and configure the APT client to use Intel repository:\n        echo \"deb [signed-by=/usr/share/keyrings/oneapi-archive-keyring.gpg] https://apt.repos.intel.com/oneapi all main\" | sudo tee /etc/apt/sources.list.d/oneAPI.list\n        sudo apt-get update\n        sudo apt-get install -y intel-basekit intel-hpckit\n    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n    - name: make check\n      run: |\n        source /opt/intel/oneapi/setvars.sh\n        make CC=icx check\n        make CC=icx -C tests test-cli-tests\n"
  },
  {
    "path": ".github/workflows/nightly.yml",
    "content": "name: facebook/zstd/nightly\non:\n  schedule:\n    - cron: '0 0 * * *'\n  push:\n    branches:\n      - release\n      - dev\n      - '*nightly*'\npermissions: read-all\njobs:\n  regression-test:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v6.0.2\n    - name: Install dependencies\n      run: sudo apt-get update && sudo apt-get install -y libcurl4-openssl-dev\n    - name: Regression Test\n      run: |\n        make -C programs zstd\n        make -C tests/regression test\n\n# Longer tests\n  #- make -C tests test-zstd-nolegacy && make clean\n  #- pyenv global 3.4.4; make -C tests versionsTest && make clean\n  #- make zlibwrapper         && make clean\n  #- gcc -v; make -C tests test32 MOREFLAGS=\"-I/usr/include/x86_64-linux-gnu\" && make clean\n  #- make uasan               && make clean\n  #- make asan32              && make clean\n  #- make -C tests test32 CC=clang MOREFLAGS=\"-g -fsanitize=address -I/usr/include/x86_64-linux-gnu\"\n# Valgrind tests\n  #- CFLAGS=\"-O1 -g\" make -C zlibWrapper valgrindTest && make clean\n  #- make -C tests valgrindTest && make clean\n# ARM, AArch64, PowerPC, PowerPC64 tests\n  #- make ppctest             && make clean\n  #- make ppc64test           && make clean\n  #- make armtest             && make clean\n  #- make aarch64test         && make clean\n"
  },
  {
    "path": ".github/workflows/publish-release-artifacts.yml",
    "content": "name: publish-release-artifacts\n\non:\n  release:\n    types:\n      - published\n\npermissions: read-all\n\njobs:\n  publish-release-artifacts:\n    permissions:\n      contents: write # to fetch code and upload artifacts\n\n    runs-on: ubuntu-latest\n    if: startsWith(github.ref, 'refs/tags/')\n\n    steps:\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n\n      - name: Archive\n        env:\n          RELEASE_SIGNING_KEY: ${{ secrets.RELEASE_SIGNING_KEY }}\n          RELEASE_SIGNING_KEY_PASSPHRASE: ${{ secrets.RELEASE_SIGNING_KEY_PASSPHRASE }}\n        run: |\n          # compute file name\n          export TAG=\"$(echo \"$GITHUB_REF\" | sed -n 's_^refs/tags/__p')\"\n          if [ -z \"$TAG\" ]; then\n            echo \"action must be run on a tag. GITHUB_REF is not a tag: $GITHUB_REF\"\n            exit 1\n          fi\n          # Attempt to extract \"1.2.3\" from \"v1.2.3\" to maintain artifact name backwards compat.\n          # Otherwise, degrade to using full tag.\n          export VERSION=\"$(echo \"$TAG\" | sed 's_^v\\([0-9]\\+\\.[0-9]\\+\\.[0-9]\\+\\)$_\\1_')\"\n          export ZSTD_VERSION=\"zstd-$VERSION\"\n\n          # archive\n          git archive $TAG \\\n              --prefix $ZSTD_VERSION/ \\\n              --format tar \\\n              -o $ZSTD_VERSION.tar\n\n          # Do the rest of the work in a sub-dir so we can glob everything we want to publish.\n          mkdir artifacts/\n          mv $ZSTD_VERSION.tar artifacts/\n          cd artifacts/\n\n          # compress\n          zstd -k -19 $ZSTD_VERSION.tar\n          gzip -k  -9 $ZSTD_VERSION.tar\n\n          # we only publish the compressed tarballs\n          rm $ZSTD_VERSION.tar\n\n          # hash\n          sha256sum $ZSTD_VERSION.tar.zst > $ZSTD_VERSION.tar.zst.sha256\n          sha256sum $ZSTD_VERSION.tar.gz  > $ZSTD_VERSION.tar.gz.sha256\n\n          # sign\n          if [ -n \"$RELEASE_SIGNING_KEY\" ]; then\n            export GPG_BATCH_OPTS=\"--batch --no-use-agent --pinentry-mode loopback --no-tty --yes\"\n            echo \"$RELEASE_SIGNING_KEY\" | gpg $GPG_BATCH_OPTS --import\n            gpg $GPG_BATCH_OPTS --armor --sign --sign-with signing@zstd.net --detach-sig --passphrase \"$RELEASE_SIGNING_KEY_PASSPHRASE\" --output $ZSTD_VERSION.tar.zst.sig $ZSTD_VERSION.tar.zst\n            gpg $GPG_BATCH_OPTS --armor --sign --sign-with signing@zstd.net --detach-sig --passphrase \"$RELEASE_SIGNING_KEY_PASSPHRASE\" --output $ZSTD_VERSION.tar.gz.sig  $ZSTD_VERSION.tar.gz\n          fi\n\n      - name: Publish\n        uses: skx/github-action-publish-binaries@b9ca5643b2f1d7371a6cba7f35333f1461bbc703 # tag=release-2.0\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        with:\n          args: artifacts/*\n"
  },
  {
    "path": ".github/workflows/release_check.yml",
    "content": "name: release_checks\n\non:\n  push:\n    branches:\n      - release\n  pull_request:\n    branches:\n      - release\n\npermissions: read-all\n\njobs:\n  verify-manual:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Check out repository\n        uses: actions/checkout@v6.0.2\n\n      - name: Save current manual\n        run: mv doc/zstd_manual.html doc/zstd_manual_saved.html\n\n      - name: Generate new manual\n        run: make manual\n\n      - name: Compare manuals\n        run: |\n          if ! cmp -s doc/zstd_manual.html doc/zstd_manual_saved.html; then\n            echo \"The API manual was not updated before release !\"\n            exit 1\n          fi\n\n  verify-man-pages:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Check out repository\n        uses: actions/checkout@v6.0.2\n\n      - name: Install dependencies\n        run: |\n          sudo apt-get update\n          sudo apt-get install -y ruby ruby-dev\n          sudo gem install ronn\n\n      - name: Display ronn version\n        run: ronn --version\n\n      - name: Save current man pages\n        run: |\n          mv programs/zstd.1 programs/zstd.1.saved\n          mv programs/zstdgrep.1 programs/zstdgrep.1.saved\n          mv programs/zstdless.1 programs/zstdless.1.saved\n\n      - name: Generate new manual pages\n        run: make -C programs man\n\n      - name: Compare man pages\n        run: |\n          for file in zstd.1 zstdgrep.1 zstdless.1; do\n            if ! cmp -s programs/$file programs/$file.saved; then\n              echo \"The man page $file should have been updated.\"\n              exit 1\n            fi\n          done\n"
  },
  {
    "path": ".github/workflows/scorecards.yml",
    "content": "name: Scorecards supply-chain security\non:\n  # Only the default branch is supported.\n  branch_protection_rule:\n  schedule:\n    - cron: '22 21 * * 2'\n  push:\n    # TODO: Add release branch when supported?\n    branches: [ \"dev\" ]\n\n# Declare default permissions as read only.\npermissions: read-all\n\njobs:\n  analysis:\n    name: Scorecards analysis\n    if: github.repository == 'facebook/zstd'\n    runs-on: ubuntu-latest\n    permissions:\n      # Needed to upload the results to code-scanning dashboard.\n      security-events: write\n      # Used to receive a badge.\n      id-token: write\n      # Needs for private repositories.\n      contents: read\n      actions: read\n\n    steps:\n      - name: \"Checkout code\"\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n        with:\n          persist-credentials: false\n\n      - name: \"Run analysis\"\n        uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # tag=v2.4.1\n        with:\n          results_file: results.sarif\n          results_format: sarif\n          # (Optional) Read-only PAT token. Uncomment the `repo_token` line below if:\n          # - you want to enable the Branch-Protection check on a *public* repository, or\n          # - you are installing Scorecards on a *private* repository\n          # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.\n          # repo_token: ${{ secrets.SCORECARD_READ_TOKEN }}\n\n          # Publish the results for public repositories to enable scorecard badges. For more details, see\n          # https://github.com/ossf/scorecard-action#publishing-results.\n          # For private repositories, `publish_results` will automatically be set to `false`, regardless\n          # of the value entered here.\n          publish_results: true\n\n      # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF\n      # format to the repository Actions tab.\n      - name: \"Upload artifact\"\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # tag=v7.0.0\n        with:\n          name: SARIF file\n          path: results.sarif\n          retention-days: 5\n\n      # Upload the results to GitHub's code scanning dashboard.\n      - name: \"Upload to code-scanning\"\n        uses: github/codeql-action/upload-sarif@0499de31b99561a6d14a36a5f662c2a54f91beee # tag=v4.31.2\n        with:\n          sarif_file: results.sarif\n"
  },
  {
    "path": ".github/workflows/windows-artifacts.yml",
    "content": "name: windows-artifacts\n\non:\n  push:\n    branches: [ test_artifacts, win_artifacts, release ]\n  release:\n    types:\n      - published\n\npermissions: read-all\n\njobs:\n  windows-artifacts:\n    permissions:\n      contents: write # to fetch code and upload artifacts\n    # For msys2, see https://ariya.io/2020/07/on-github-actions-with-msys2\n    runs-on: ${{ matrix.shell == 'cmake' && 'windows-11-arm' || 'windows-latest' }}\n    strategy:\n      # For msys2, see https://github.com/msys2/setup-msys2\n      matrix:\n        include:\n          - { msystem: mingw64, env: x86_64, ziparch: win64, shell: msys2 }\n          - { msystem: mingw32, env: i686, ziparch: win32, shell: msys2 }\n          - { msystem: null, env: arm64, ziparch: win-arm64, shell: cmake }\n\n    defaults:\n      run:\n        shell: ${{ matrix.shell == 'cmake' && 'pwsh' || 'msys2 {0}' }}\n\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # tag=v6.0.2\n\n      # MSYS2 setup\n      - uses: msys2/setup-msys2@4f806de0a5a7294ffabaff804b38a9b435a73bda # tag=v2.30.0\n        if: matrix.shell == 'msys2'\n        with:\n          msystem: ${{ matrix.msystem }}\n          install: make p7zip git mingw-w64-${{matrix.env}}-gcc\n          update: true\n\n      - name: display versions (MSYS2)\n        if: matrix.shell == 'msys2'\n        run: |\n          make -v\n          cc -v\n\n      - name: display versions (CMake)\n        if: matrix.shell == 'cmake'\n        run: |\n          cmake --version\n\n      # Build dependencies (MSYS2 only)\n      - name: Building zlib to static link\n        if: matrix.shell == 'msys2'\n        run: |\n          git clone --depth 1 --branch v1.3.1 https://github.com/madler/zlib\n          make -C zlib -f win32/Makefile.gcc libz.a\n\n      - name: Building lz4 to static link\n        if: matrix.shell == 'msys2'\n        run: |\n          git clone --depth 1 --branch v1.10.0 https://github.com/lz4/lz4\n          # ensure both libraries use the same version of libxxhash\n          cp lib/common/xxhash.* lz4/lib\n          CPPFLAGS=-DXXH_NAMESPACE=LZ4_ make -C lz4/lib liblz4.a V=1\n\n      # Build zstd\n      - name: Building zstd programs\n        if: matrix.shell == 'msys2'\n        run: |\n          CPPFLAGS=\"-I../zlib -I../lz4/lib\" LDFLAGS=-static make -j allzstd V=1 HAVE_ZLIB=1 HAVE_LZ4=1 HAVE_LZMA=0 LDLIBS=\"../zlib/libz.a ../lz4/lib/liblz4.a\"\n\n      - name: Build zstd (CMake ARM64)\n        if: matrix.shell == 'cmake'\n        run: |\n          cd build\\cmake\n          mkdir build\n          cd build\n          cmake.exe -G \"Visual Studio 17 2022\" -A ARM64 -DCMAKE_BUILD_TYPE=Release -DZSTD_BUILD_PROGRAMS=ON -DZSTD_BUILD_SHARED=ON -DZSTD_BUILD_STATIC=ON ..\n          cmake.exe --build . --config Release --parallel\n\n      - name: Create artifacts (MSYS2)\n        if: matrix.shell == 'msys2'\n        run: |\n          ./lib/dll/example/build_package.bat || exit 1\n          mv bin/ zstd-${{ github.ref_name }}-${{matrix.ziparch}}/\n\n      - name: Create artifacts (CMake)\n        if: matrix.shell == 'cmake'\n        run: |\n          .\\lib\\dll\\example\\build_package.bat\n          if ($LASTEXITCODE -ne 0) { exit 1 }\n          mv bin/ zstd-${{ github.ref_name }}-${{matrix.ziparch}}/\n\n      - name: Publish zstd-$VERSION-${{matrix.ziparch}}.zip for manual inspection\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # tag=v7.0.0\n        with:\n          compression-level: 9  # maximum compression\n          if-no-files-found: error # defaults to `warn`\n          path: ${{ github.workspace }}/zstd-${{ github.ref_name }}-${{matrix.ziparch}}/\n          name: zstd-${{ github.ref_name }}-${{matrix.ziparch}}\n\n      - name: Package artifact for upload (MSYS2)\n        if: matrix.shell == 'msys2'\n        run: |\n          7z a -tzip -mx9 \"$(cygpath -u '${{ github.workspace }}/zstd-${{ github.ref_name }}-${{ matrix.ziparch }}.zip')\" \"$(cygpath -u '${{ github.workspace }}/zstd-${{ github.ref_name }}-${{ matrix.ziparch }}')\"\n\n      - name: Package artifact for upload (CMake)\n        if: matrix.shell == 'cmake'\n        run: |\n          Compress-Archive -Path \"zstd-${{ github.ref_name }}-${{ matrix.ziparch }}\" -DestinationPath \"zstd-${{ github.ref_name }}-${{ matrix.ziparch }}.zip\" -CompressionLevel Optimal\n\n      - name: Upload release asset\n        if: github.event_name == 'release'\n        shell: pwsh\n        env:\n          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        run: |\n          gh release upload \"${{ github.ref_name }}\" \"$env:GITHUB_WORKSPACE/zstd-${{ github.ref_name }}-${{ matrix.ziparch }}.zip\" --clobber"
  },
  {
    "path": ".gitignore",
    "content": "# Object files\n*.o\n*.ko\n*.dSYM\n\n# Libraries\n*.lib\n*.a\n\n# Shared objects (inc. Windows DLLs)\n*.dll\n*.so\n*.so.*\n*.dylib\n*.framework\n*.xcframework\n\n# Executables\n/zstd\nzstdmt\n*.exe\n*.out\n*.app\n\n# Build artefacts\ncontrib/linux-kernel/linux/\nprojects/\nbin/\n.buckd/\nbuck-out/\nbuild-*\n*.gcda\ncmakebuild/\ncmake-build/\n\n# Test artefacts\ntmp*\n*.zst\n*.zstd\ndictionary.\ndictionary\nNUL\ninstall/\n\n# IDE\n.clang_complete\ncompile_flags.txt\n.clang-format\n\n# Other files\n.directory\n_codelite/\n_zstdbench/\n*.idea\n*.swp\n.DS_Store\ngoogletest/\n*.d\n*.vscode\n*.code-workspace\ncompile_commands.json\n.clangd\nperf.data\nperf.data.old\n"
  },
  {
    "path": "CHANGELOG",
    "content": "v1.6.0 (Dec 2025)\napi: legacy format support is now disabled by default\nbuild: `ZSTD_LEGACY_SUPPORT` defaults to `0` in Makefile and CMake\n\nV1.5.7 (Feb 2025)\nfix: compression bug in 32-bit mode associated with long-lasting sessions\napi: new method `ZSTD_compressSequencesAndLiterals()` (#4217, #4232)\napi: `ZSTD_getFrameHeader()` works on skippable frames (#4228)\nperf: substantial compression speed improvements (up to +30%) on small data, by @TocarIP (#4144) and @cyan4973 (#4165)\nperf: improved compression speed (~+5%) for dictionary compression at low levels (#4170)\nperf: much faster speed for `--patch-from` at high compression levels (#4276)\nperf: higher `--patch-from` compression ratios, notably at high levels (#4288)\nperf: better speed for binaries on Windows (@pps83) and when compiled with Visual Studio (@MessyHack)\nperf: slight compression ratio improvement thanks to better block boundaries (#4136, #4176, #4178)\nperf: slight compression ratio improvement for `dfast`, aka levels 3 and 4 (#4171)\nperf: runtime bmi2 detection enabled on x86 32-bit mode (#4251)\ncli: multi-threading as default CLI setting, by @daniellerozenblit\ncli: new `--max` command (#4290)\nbuild: improve `msbuild` version autodetection, support VS2022, by @ManuelBlanc\nbuild: fix `meson` build by @artem and @Victor-C-Zhang, and on Windows by @bgilbert\nbuild: compatibility with Apple Framework, by @Treata11\nbuild: improve icc/icx compatibility, by @josepho0918 and @luau-project\nbuild: improve compatibility with Android NDK, by Adenilson Cavalcanti\nportability: linux kernel branch, with improved support for Sequence producers (@embg, @gcabiddu, @cyan4973)\nportability: improved qnx compatibility, suggested by @rainbowball\nportability: improved install script for FreeBSD, by @sunpoet\nportability: fixed test suite compatibility with gnu hurd, by @diegonc\ndoc: clarify specification, by @elasota\nmisc: improved tests/decodecorpus validation tool (#4102), by antmicro\n\nV1.5.6 (Mar 2024)\napi: Promote `ZSTD_c_targetCBlockSize` to Stable API by @felixhandte\napi: new `ZSTD_d_maxBlockSize` experimental parameter, to reduce streaming decompression memory, by @terrelln\nperf: improve performance of param `ZSTD_c_targetCBlockSize`, by @Cyan4973\nperf: improved compression of arrays of integers at high compression, by @Cyan4973\nlib: reduce binary size with selective build-time exclusion, by @felixhandte\nlib: improved huffman speed on small data and linux kernel, by @terrelln\nlib: accept dictionaries with partial literal tables, by @terrelln\nlib: fix CCtx size estimation with external sequence producer, by @embg\nlib: fix corner case decoder behaviors, by @Cyan4973 and @aimuz\nlib: fix zdict prototype mismatch in static_only mode, by @ldv-alt\nlib: fix several bugs in magicless-format decoding, by @embg\ncli: add common compressed file types to `--exclude-compressed`` by @daniellerozenblit\ncli: fix mixing `-c` and `-o` commands with `--rm`, by @Cyan4973\ncli: fix erroneous exclusion of hidden files with `--output-dir-mirror` by @felixhandte\ncli: improved time accuracy on BSD, by @felixhandte\ncli: better errors on argument parsing, by @KapJI\ntests: better compatibility with older versions of `grep`, by @Cyan4973\ntests: lorem ipsum generator as default backup content, by @Cyan4973\nbuild: cmake improvements by @terrelln, @sighingnow, @gjasny, @JohanMabille, @Saverio976, @gruenich, @teo-tsirpanis\nbuild: bazel support, by @jondo2010\nbuild: fix cross-compiling for AArch64 with lld by @jcelerier\nbuild: fix Apple platform compatibility, by @nidhijaju\nbuild: fix Visual 2012 and lower compatibility, by @Cyan4973\nbuild: improve win32 support, by @DimitriPapadopoulos\nbuild: better C90 compliance for zlibWrapper, by @emaste\nport: make: fat binaries on macos, by @mredig\nport: ARM64EC compatibility for Windows, by @dunhor\nport: QNX support by @klausholstjacobsen\nport: MSYS2 and Cygwin makefile installation and test support, by @QBos07\nport: risc-v support validation in CI, by @Cyan4973\nport: sparc64 support validation in CI, by @Cyan4973\nport: AIX compatibility, by @likema\nport: HP-UX compatibility, by @likema\ndoc: Improved specification accuracy, by @elasota\nbug: Fix and deprecate ZSTD_generateSequences (#3981)\n\nv1.5.5 (Apr 2023)\nfix: fix rare corruption bug affecting the high compression mode, reported by @danlark1 (#3517, @terrelln)\nperf: improve mid-level compression speed (#3529, #3533, #3543, @yoniko and #3552, @terrelln)\nlib: deprecated bufferless block-level API (#3534) by @terrelln\ncli: mmap large dictionaries to save memory, by @daniellerozenblit\ncli: improve speed of --patch-from mode (~+50%) (#3545) by @daniellerozenblit\ncli: improve i/o speed (~+10%) when processing lots of small files (#3479) by @felixhandte\ncli: zstd no longer crashes when requested to write into write-protected directory (#3541) by @felixhandte\ncli: fix decompression into block device using -o, reported by @georgmu (#3583)\nbuild: fix zstd CLI compiled with lzma support but not zlib support (#3494) by @Hello71\nbuild: fix cmake does no longer require 3.18 as minimum version (#3510) by @kou\nbuild: fix MSVC+ClangCL linking issue (#3569) by @tru\nbuild: fix zstd-dll, version of zstd CLI that links to the dynamic library (#3496) by @yoniko\nbuild: fix MSVC warnings (#3495) by @embg\ndoc: updated zstd specification to clarify corner cases, by @Cyan4973\ndoc: document how to create fat binaries for macos (#3568) by @rickmark\nmisc: improve seekable format ingestion speed (~+100%) for very small chunk sizes (#3544) by @Cyan4973\nmisc: tests/fullbench can benchmark multiple files (#3516) by @dloidolt\n\nv1.5.4 (Feb 2023)\nperf: +20% faster huffman decompression for targets that can't compile x64 assembly (#3449, @terrelln)\nperf: up to +10% faster streaming compression at levels 1-2 (#3114, @embg)\nperf: +4-13% for levels 5-12 by optimizing function generation (#3295, @terrelln)\npref: +3-11% compression speed for `arm` target (#3199, #3164, #3145, #3141, #3138, @JunHe77 and #3139, #3160, @danlark1)\nperf: +5-30% faster dictionary compression at levels 1-4 (#3086, #3114, #3152, @embg)\nperf: +10-20% cold dict compression speed by prefetching CDict tables (#3177, @embg)\nperf: +1% faster compression by removing a branch in ZSTD_fast_noDict (#3129, @felixhandte)\nperf: Small compression ratio improvements in high compression mode (#2983, #3391, @Cyan4973 and #3285, #3302, @daniellerozenblit)\nperf: small speed improvement by better detecting `STATIC_BMI2` for `clang` (#3080, @TocarIP)\nperf: Improved streaming performance when `ZSTD_c_stableInBuffer` is set (#2974, @Cyan4973)\ncli: Asynchronous I/O for improved cli speed (#2975, #2985, #3021, #3022, @yoniko)\ncli: Change `zstdless` behavior to align with `zless` (#2909, @binhdvo)\ncli: Keep original file if `-c` or `--stdout` is given (#3052, @dirkmueller)\ncli: Keep original files when result is concatenated into a single output with `-o` (#3450, @Cyan4973)\ncli: Preserve Permissions and Ownership of regular files (#3432, @felixhandte)\ncli: Print zlib/lz4/lzma library versions with `-vv` (#3030, @terrelln)\ncli: Print checksum value for single frame files with `-lv`  (#3332, @Cyan4973)\ncli: Print `dictID` when present with `-lv` (#3184, @htnhan)\ncli: when `stderr` is *not* the console, disable status updates, but preserve final summary (#3458, @Cyan4973)\ncli: support `--best` and `--no-name` in `gzip` compatibility mode (#3059, @dirkmueller)\ncli: support for `posix` high resolution timer `clock_gettime()`, for improved benchmark accuracy (#3423, @Cyan4973)\ncli: improved help/usage (`-h`,  `-H`) formatting (#3094, @dirkmueller and #3385, @jonpalmisc)\ncli: Fix better handling of bogus numeric values (#3268, @ctkhanhly)\ncli: Fix input consists of multiple files _and_ `stdin` (#3222, @yoniko)\ncli: Fix tiny files passthrough (#3215, @cgbur)\ncli: Fix for `-r` on empty directory (#3027, @brailovich)\ncli: Fix empty string as argument for `--output-dir-*` (#3220, @embg)\ncli: Fix decompression memory usage reported by `-vv --long` (#3042, @u1f35c, and #3232, @zengyijing)\ncli: Fix infinite loop when empty input is passed to trainer (#3081, @terrelln)\ncli: Fix `--adapt` doesn't work when `--no-progress` is also set (#3354, @terrelln)\napi: Support for Block-Level Sequence Producer (#3333, @embg)\napi: Support for in-place decompression (#3432, @terrelln)\napi: New  `ZSTD_CCtx_setCParams()`  function, set all parameters defined in a  `ZSTD_compressionParameters`  structure (#3403, @Cyan4973)\napi: Streaming decompression detects incorrect header ID sooner (#3175, @Cyan4973)\napi: Window size resizing optimization for edge case (#3345, @daniellerozenblit)\napi: More accurate error codes for busy-loop scenarios (#3413, #3455, @Cyan4973)\napi: Fix limit overflow in `compressBound` and `decompressBound` (#3362, #3373, Cyan4973) reported by @nigeltao\napi: Deprecate several advanced experimental functions: streaming (#3408, @embg), copy (#3196, @mileshu)\nbug: Fix corruption that rarely occurs in 32-bit mode with wlog=25 (#3361, @terrelln)\nbug: Fix for block-splitter (#3033, @Cyan4973)\nbug: Fixes for Sequence Compression API (#3023, #3040, @Cyan4973)\nbug: Fix leaking thread handles on Windows (#3147, @animalize)\nbug: Fix timing issues with cmake/meson builds (#3166, #3167, #3170, @Cyan4973)\nbuild: Allow user to select legacy level for cmake (#3050, @shadchin)\nbuild: Enable legacy support by default in cmake (#3079, @niamster)\nbuild: Meson build script improvements (#3039, #3120, #3122, #3327, #3357, @eli-schwartz and #3276, @neheb)\nbuild: Add aarch64 to supported architectures for zstd_trace (#3054, @ooosssososos)\nbuild: support AIX architecture (#3219, @qiongsiwu)\nbuild: Fix `ZSTD_LIB_MINIFY` build macro, which now reduces static library size by half (#3366, @terrelln)\nbuild: Fix Windows issues with Multithreading translation layer (#3364, #3380, @yoniko) and ARM64 target (#3320, @cwoffenden)\nbuild: Fix `cmake` script (#3382, #3392, @terrelln and #3252 @Tachi107 and #3167 @Cyan4973)\ndoc: Updated man page, providing more details for `--train` mode (#3112, @Cyan4973)\ndoc: Add decompressor errata document (#3092, @terrelln)\nmisc: Enable Intel CET (#2992, #2994, @hjl-tools)\nmisc: Fix `contrib/` seekable format (#3058, @yhoogstrate and #3346, @daniellerozenblit)\nmisc: Improve speed of the one-file library generator (#3241, @wahern and #3005, @cwoffenden)\n\nv1.5.3 (dev version, unpublished)\n\nv1.5.2 (Jan, 2022)\nperf: Regain Minimal memset()-ing During Reuse of Compression Contexts (@Cyan4973, #2969)\nbuild: Build Zstd with `noexecstack` on All Architectures (@felixhandte, #2964)\ndoc: Clarify Licensing (@terrelln, #2981)\n\nv1.5.1 (Dec, 2021)\nperf: rebalanced compression levels, to better match the intended speed/level curve, by @senhuang42\nperf: faster huffman decoder, using x64 assembly, by @terrelln\nperf: slightly faster high speed modes (strategies fast & dfast), by @felixhandte\nperf: improved binary size and faster compilation times, by @terrelln\nperf: new row64 mode, used notably in level 12, by @senhuang42\nperf: faster mid-level compression speed in presence of highly repetitive patterns, by @senhuang42\nperf: minor compression ratio improvements for small data at high levels, by @cyan4973\nperf: reduced stack usage (mostly useful for Linux Kernel), by @terrelln\nperf: faster compression speed on incompressible data, by @bindhvo\nperf: on-demand reduced ZSTD_DCtx state size, using build macro ZSTD_DECODER_INTERNAL_BUFFER, at a small cost of performance, by @bindhvo\nbuild: allows hiding static symbols in the dynamic library, using build macro, by @skitt\nbuild: support for m68k (Motorola 68000's), by @cyan4973\nbuild: improved AIX support, by @Helflym\nbuild: improved meson unofficial build, by @eli-schwartz\ncli : custom memory limit when training dictionary (#2925), by @embg\ncli : report advanced parameters information when compressing in very verbose mode (`-vv`), by @Svetlitski-FB\n\nv1.5.0  (May 11, 2021)\napi: Various functions promoted from experimental to stable API: (#2579-2581, @senhuang42)\n  `ZSTD_defaultCLevel()`\n  `ZSTD_getDictID_fromCDict()`\napi: Several experimental functions have been deprecated and will emit a compiler warning (#2582, @senhuang42)\n  `ZSTD_compress_advanced()`\n  `ZSTD_compress_usingCDict_advanced()`\n  `ZSTD_compressBegin_advanced()`\n  `ZSTD_compressBegin_usingCDict_advanced()`\n  `ZSTD_initCStream_srcSize()`\n  `ZSTD_initCStream_usingDict()`\n  `ZSTD_initCStream_usingCDict()`\n  `ZSTD_initCStream_advanced()`\n  `ZSTD_initCStream_usingCDict_advanced()`\n  `ZSTD_resetCStream()`\napi: ZSTDMT_NBWORKERS_MAX reduced to 64 for 32-bit environments (@Cyan4973)\nperf: Significant speed improvements for middle compression levels (#2494, @senhuang42 @terrelln)\nperf: Block splitter to improve compression ratio, enabled by default for high compression levels (#2447, @senhuang42)\nperf: Decompression loop refactor, speed improvements on `clang` and for `--long` modes (#2614 #2630, @Cyan4973)\nperf: Reduced stack usage during compression and decompression entropy stage (#2522 #2524, @terrelln)\nbug: Improve setting permissions of created files (#2525, @felixhandte)\nbug: Fix large dictionary non-determinism (#2607, @terrelln)\nbug: Fix non-determinism test failures on Linux i686 (#2606, @terrelln)\nbug: Fix various dedicated dictionary search bugs (#2540 #2586, @senhuang42 @felixhandte)\nbug: Ensure `ZSTD_estimateCCtxSize*() `monotonically increases with compression level (#2538, @senhuang42)\nbug: Fix --patch-from mode parameter bound bug with small files (#2637, @occivink)\nbug: Fix UBSAN error in decompression (#2625, @terrelln)\nbug: Fix superblock compression divide by zero bug (#2592, @senhuang42)\nbug: Make the number of physical CPU cores detection more robust (#2517, @PaulBone)\ndoc: Improve `zdict.h` dictionary training API documentation (#2622, @terrelln)\ndoc: Note that public `ZSTD_free*()` functions accept NULL pointers (#2521, @animalize)\ndoc: Add style guide docs for open source contributors (#2626, @Cyan4973)\ntests: Better regression test coverage for different dictionary modes (#2559, @senhuang42)\ntests: Better test coverage of index reduction (#2603, @terrelln)\ntests: OSS-Fuzz coverage for seekable format (#2617, @senhuang42)\ntests: Test coverage for ZSTD threadpool API (#2604, @senhuang42)\nbuild: Dynamic library built multithreaded by default (#2584, @senhuang42)\nbuild: Move  `zstd_errors.h`  and  `zdict.h`  to  `lib/`  root (#2597, @terrelln)\nbuild: Allow `ZSTDMT_JOBSIZE_MIN` to be configured at compile-time, reduce default to 512KB (#2611, @Cyan4973)\nbuild: Single file library build script moved to `build/` directory (#2618, @felixhandte)\nbuild: `ZBUFF_*()` is no longer built by default (#2583, @senhuang42)\nbuild: Fixed Meson build (#2548, @SupervisedThinking @kloczek)\nbuild: Fix excessive compiler warnings with clang-cl and CMake (#2600, @nickhutchinson)\nbuild: Detect presence of `md5` on Darwin (#2609, @felixhandte)\nbuild: Avoid SIGBUS on armv6 (#2633, @bmwiedmann)\ncli: `--progress` flag added to always display progress bar (#2595, @senhuang42)\ncli: Allow reading from block devices with `--force` (#2613, @felixhandte)\ncli: Fix CLI filesize display bug (#2550, @Cyan4973)\ncli: Fix windows CLI `--filelist` end-of-line bug (#2620, @Cyan4973)\ncontrib: Various fixes for linux kernel patch (#2539, @terrelln)\ncontrib: Seekable format - Decompression hanging edge case fix (#2516, @senhuang42)\ncontrib: Seekable format - New seek table-only API  (#2113 #2518, @mdittmer @Cyan4973)\ncontrib: Seekable format - Fix seek table descriptor check when loading (#2534, @foxeng)\ncontrib: Seekable format - Decompression fix for large offsets, (#2594, @azat)\nmisc: Automatically published release tarballs available on Github (#2535, @felixhandte)\n\nv1.4.9  (Mar 1, 2021)\nbug: Use `umask()` to Constrain Created File Permissions (#2495, @felixhandte)\nbug: Make Simple Single-Pass Functions Ignore Advanced Parameters (#2498, @terrelln)\napi: Add (De)Compression Tracing Functionality (#2482, @terrelln)\napi: Support References to Multiple DDicts (#2446, @senhuang42)\napi: Add Function to Generate Skippable Frame (#2439, @senhuang42)\nperf: New Algorithms for the Long Distance Matcher (#2483, @mpu)\nperf: Performance Improvements for Long Distance Matcher (#2464, @mpu)\nperf: Don't Shrink Window Log when Streaming with a Dictionary (#2451, @terrelln)\ncli: Fix `--output-dir-mirror` rejection of `..` -containing paths (#2512, @felixhandte)\ncli: Allow Input From Console When `-f`/`--force` is Passed (#2466, @felixhandte)\ncli: Improve Help Message (#2500, @senhuang42)\ntests: Remove Flaky Tests (#2455, #2486, #2445, @Cyan4973)\ntests: Correctly Invoke md5 Utility on NetBSD (#2492, @niacat)\ntests: Avoid Using `stat -c` on NetBSD (#2513, @felixhandte)\nbuild: Zstd CLI Can Now be Linked to Dynamic `libzstd` (#2457, #2454 @Cyan4973)\nbuild: Hide and Avoid Using Static-Only Symbols (#2501, #2504, @skitt)\nbuild: CMake: Enable Only C for lib/ and programs/ Projects (#2498, @concatime)\nbuild: CMake: Use `configure_file()` to Create the `.pc` File (#2462, @lazka)\nbuild: Fix Fuzzer Compiler Detection & Update UBSAN Flags (#2503, @terrelln)\nbuild: Add Guards for `_LARGEFILE_SOURCE` and `_LARGEFILE64_SOURCE` (#2444, @indygreg)\nbuild: Improve `zlibwrapper` Makefile (#2437, @Cyan4973)\ncontrib: Add `recover_directory` Program (#2473, @terrelln)\ndoc: Change License Year to 2021 (#2452 & #2465, @terrelln & @senhuang42)\ndoc: Fix Typos (#2459, @ThomasWaldmann)\n\nv1.4.8  (Dec 18, 2020)\nhotfix: wrong alignment of an internal buffer\n\nv1.4.7  (Dec 16, 2020)\nperf: stronger --long mode at high compression levels, by @senhuang42\nperf: stronger --patch-from at high compression levels, thanks to --long improvements\nperf: faster dictionary compression at medium compression levels, by @felixhandte\nperf: small speed & memory usage improvements for ZSTD_compress2(), by @terrelln\nperf: improved fast compression speeds with Visual Studio, by @animalize\ncli : Set nb of threads with environment variable ZSTD_NBTHREADS, by @senhuang42\ncli : accept decompressing files with *.zstd suffix\ncli : provide a condensed summary by default when processing multiple files\ncli : fix : stdin input no longer confused as user prompt\ncli : improve accuracy of several error messages\napi : new sequence ingestion API, by @senhuang42\napi : shared thread pool: control total nb of threads used by multiple compression jobs, by @marxin\napi : new ZSTD_getDictID_fromCDict(), by @LuAPi\napi : zlibWrapper only uses public API, and is compatible with dynamic library, by @terrelln\napi : fix : multithreaded compression has predictable output even in special cases (see #2327) (issue not accessible from cli)\napi : fix : dictionary compression correctly respects dictionary compression level (see #2303) (issue not accessible from cli)\nbuild: fix cmake script when using path with spaces, by @terrelln\nbuild: improved compile-time detection of aarch64/neon platforms, by @bsdimp\nbuild: Fix building on AIX 5.1, by @likema\nbuild: compile paramgrill with cmake on Windows, requested by @mirh\ndoc : clarify repcode updates in format specification, by @felixhandte\n\nv1.4.6\nfix : Always return dstSize_tooSmall when that is the case\nfix : Fix ZSTD_initCStream_advanced() with static allocation and no dictionary\nperf: Improve small block decompression speed by 20%+, by @terrelln\nperf: Reduce compression stack usage by 1 KB, by @terrelln\nperf: Improve decompression speed by improving ZSTD_wildcopy, by @helloguo (#2252, #2256)\nperf: Improve histogram construction, by @cyan4973 (#2253)\ncli : Add --output-dir-mirror option, by @xxie24 (#2219)\ncli : Warn when (de)compressing multiple files into a single output, by @senhuang42 (#2279)\ncli : Improved progress bar and status summary when (de)compressing multiple files, by @senhuang42 (#2283)\ncli : Call stat less often, by @felixhandte (#2262)\ncli : Allow --patch-from XXX and --filelist XXX in addition to --patch-from=XXX and --filelist=XXX, by @cyan4973 (#2250)\ncli : Allow --patch-from to compress stdin with --stream-size, by @bimbashrestha (#2206)\napi : Do not install zbuff.h, since it has long been deprecated, by @cyan4973 (#2166).\napi : Fix ZSTD_CCtx_setParameter() with ZSTD_c_compressionLevel to make 0 mean default level, by @i-do-cpp (#2291)\napi : Rename ZSTDMT_NBTHREADS_MAX to ZSTDMT_NBWORKERS_MAX, by @marxin (#2228).\nbuild: Install pkg-config file with CMake and MinGW, by @tonytheodore (#2183)\nbuild: Install DLL with CMake on Windows, by @BioDataAnalysis (#2221)\nbuild: Fix DLL install location with CMake, by @xantares and @bimbashrestha (#2186)\nbuild: Add ZSTD_NO_UNUSED_FUNCTIONS macro to hide unused functions\nbuild: Add ZSTD_NO_INTRINSICS macro to avoid explicit intrinsics\nbuild: Add STATIC_BMI2 macro for compile time detection of BMI2 on MSVC, by @Niadb (#2258)\nbuild: Fix -Wcomma warnings, by @cwoffenden\nbuild: Remove distutils requirement for meson build, by @neheb (#2197)\nbuild: Fix cli compilation with uclibc\nbuild: Fix cli compilation without st_mtime, by @ffontaine (#2246)\nbuild: Fix shadowing warnings in library\nbuild: Fix single file library compilation with Enscripten, by @yoshihitoh (#2227)\nmisc: Improve single file library and include dictBuilder, by @cwoffenden\nmisc: Allow compression dictionaries with missing symbols\nmisc: Add freestanding translation script in contrib/freestanding_lib\nmisc: Collect all of zstd's libc dependencies into zstd_deps.h\ndoc : Add ZSTD_versionString() to manual, by @animalize\ndoc : Fix documentation for ZSTD_CCtxParams_setParameter(), by @felixhandte (#2270)\n\nv1.4.5  (May 22, 2020)\nfix : Compression ratio regression on huge files (> 3 GB) using high levels (--ultra) and multithreading, by @terrelln\nperf: Improved decompression speed: x64 : +10% (clang) / +5% (gcc); ARM : from +15% to +50%, depending on SoC, by @terrelln\nperf: Automatically downsizes ZSTD_DCtx when too large for too long (#2069, by @bimbashreshta)\nperf: Improved fast compression speed on aarch64 (#2040, ~+3%, by @caoyzh)\nperf: Small level 1 compression speed gains (depending on compiler)\ncli : New --patch-from command, create and apply patches from files, by @bimbashreshta\ncli : New --filelist= : Provide a list of files to operate upon from a file\ncli : -b -d command can now benchmark decompression on multiple files\ncli : New --no-content-size command\ncli : New --show-default-cparams information command\napi : ZDICT_finalizeDictionary() is promoted to stable (#2111)\napi : new experimental parameter ZSTD_d_stableOutBuffer (#2094)\nbuild: Generate a single-file libzstd library (#2065, by @cwoffenden)\nbuild: Relative includes no longer require -I compiler flags for zstd lib subdirs (#2103, by @felixhandte)\nbuild: zstd now compiles cleanly under -pedantic (#2099)\nbuild: zstd now compiles with make-4.3\nbuild: Support mingw cross-compilation from Linux, by @Ericson2314\nbuild: Meson multi-thread build fix on windows\nbuild: Some misc icc fixes backed by new ci test on travis\nmisc: bitflip analyzer tool, by @felixhandte\nmisc: Extend largeNbDicts benchmark to compression\nmisc: Edit-distance match finder in contrib/\ndoc : Improved beginner CONTRIBUTING.md docs\ndoc : New issue templates for zstd\n\nv1.4.4  (Nov 6, 2019)\nperf: Improved decompression speed, by > 10%, by @terrelln\nperf: Better compression speed when re-using a context, by @felixhandte\nperf: Fix compression ratio when compressing large files with small dictionary, by @senhuang42\nperf: zstd reference encoder can generate RLE blocks, by @bimbashrestha\nperf: minor generic speed optimization, by @davidbolvansky\napi: new ability to extract sequences from the parser for analysis, by @bimbashrestha\napi: fixed decoding of magic-less frames, by @terrelln\napi: fixed ZSTD_initCStream_advanced() performance with fast modes, reported by @QrczakMK\ncli: Named pipes support, by @bimbashrestha\ncli: short tar's extension support, by @stokito\ncli: command --output-dir-flat= , generates target files into requested directory, by @senhuang42\ncli: commands --stream-size=# and --size-hint=#, by @nmagerko\ncli: command --exclude-compressed, by @shashank0791\ncli: faster `-t` test mode\ncli: improved some error messages, by @vangyzen\ncli: fix command `-D dictionary` on Windows, reported by @artyompetrov\ncli: fix rare deadlock condition within dictionary builder, by @terrelln\nbuild: single-file decoder with emscripten compilation script, by @cwoffenden\nbuild: fixed zlibWrapper compilation on Visual Studio, reported by @bluenlive\nbuild: fixed deprecation warning for certain gcc version, reported by @jasonma163\nbuild: fix compilation on old gcc versions, by @cemeyer\nbuild: improved installation directories for cmake script, by Dmitri Shubin\npack: modified pkgconfig, for better integration into openwrt, requested by @neheb\nmisc: Improved documentation : ZSTD_CLEVEL, DYNAMIC_BMI2, ZSTD_CDict, function deprecation, zstd format\nmisc: fixed educational decoder : accept larger literals section, and removed UNALIGNED() macro\n\nv1.4.3  (Aug 20, 2019)\nbug: Fix Dictionary Compression Ratio Regression by @cyan4973 (#1709)\nbug: Fix Buffer Overflow in legacy v0.3 decompression by @felixhandte (#1722)\nbuild: Add support for IAR C/C++ Compiler for Arm by @joseph0918 (#1705)\n\nv1.4.2  (Jul 26, 2019)\nbug: Fix bug in zstd-0.5 decoder by @terrelln (#1696)\nbug: Fix seekable decompression in-memory API by @iburinoc (#1695)\nmisc: Validate blocks are smaller than size limit by @vivekmg (#1685)\nmisc: Restructure source files by @ephiepark (#1679)\n\nv1.4.1  (Jul 20, 2019)\nbug: Fix data corruption in niche use cases by @terrelln (#1659)\nbug: Fuzz legacy modes, fix uncovered bugs by @terrelln (#1593, #1594, #1595)\nbug: Fix out of bounds read by @terrelln (#1590)\nperf: Improve decode speed by ~7% @mgrice (#1668)\nperf: Slightly improved compression ratio of level 3 and 4 (ZSTD_dfast) by @cyan4973 (#1681)\nperf: Slightly faster compression speed when re-using a context by @cyan4973 (#1658)\nperf: Improve compression ratio for small windowLog by @cyan4973 (#1624)\nperf: Faster compression speed in high compression mode for repetitive data by @terrelln (#1635)\napi: Add parameter to generate smaller dictionaries by @tyler-tran (#1656)\ncli: Recognize symlinks when built in C99 mode by @felixhandte (#1640)\ncli: Expose cpu load indicator for each file on -vv mode by @ephiepark (#1631)\ncli: Restrict read permissions on destination files by @chungy (#1644)\ncli: zstdgrep: handle -f flag by @felixhandte (#1618)\ncli: zstdcat: follow symlinks by @vejnar (#1604)\ndoc: Remove extra size limit on compressed blocks by @felixhandte (#1689)\ndoc: Fix typo by @yk-tanigawa (#1633)\ndoc: Improve documentation on streaming buffer sizes by @cyan4973 (#1629)\nbuild: CMake: support building with LZ4 @leeyoung624 (#1626)\nbuild: CMake: install zstdless and zstdgrep by @leeyoung624 (#1647)\nbuild: CMake: respect existing uninstall target by @j301scott (#1619)\nbuild: Make: skip multithread tests when built without support by @michaelforney (#1620)\nbuild: Make: Fix examples/ test target by @sjnam (#1603)\nbuild: Meson: rename options out of deprecated namespace by @lzutao (#1665)\nbuild: Meson: fix build by @lzutao (#1602)\nbuild: Visual Studio: don't export symbols in static lib by @scharan (#1650)\nbuild: Visual Studio: fix linking by @absotively (#1639)\nbuild: Fix MinGW-W64 build by @myzhang1029 (#1600)\nmisc: Expand decodecorpus coverage by @ephiepark (#1664)\n\nv1.4.0  (Apr 17, 2019)\nperf: Improve level 1 compression speed in most scenarios by 6% by @gbtucker and @terrelln\napi: Move the advanced API, including all functions in the staging section, to the stable section\napi: Make ZSTD_e_flush and ZSTD_e_end block for maximum forward progress\napi: Rename ZSTD_CCtxParam_getParameter to ZSTD_CCtxParams_getParameter\napi: Rename ZSTD_CCtxParam_setParameter to ZSTD_CCtxParams_setParameter\napi: Don't export ZSTDMT functions from the shared library by default\napi: Require ZSTD_MULTITHREAD to be defined to use ZSTDMT\napi: Add ZSTD_decompressBound() to provide an upper bound on decompressed size by @shakeelrao\napi: Fix ZSTD_decompressDCtx() corner cases with a dictionary\napi: Move ZSTD_getDictID_*() functions to the stable section\napi: Add ZSTD_c_literalCompressionMode flag to enable or disable literal compression by @terrelln\napi: Allow compression parameters to be set when a dictionary is used\napi: Allow setting parameters before or after ZSTD_CCtx_loadDictionary() is called\napi: Fix ZSTD_estimateCStreamSize_usingCCtxParams()\napi: Setting ZSTD_d_maxWindowLog to 0 means use the default\ncli: Ensure that a dictionary is not used to compress itself by @shakeelrao\ncli: Add --[no-]compress-literals flag to enable or disable literal compression\ndoc: Update the examples to use the advanced API\ndoc: Explain how to transition from old streaming functions to the advanced API in the header\nbuild: Improve the Windows release packages\nbuild: Improve CMake build by @hjmjohnson\nbuild: Build fixes for FreeBSD by @lwhsu\nbuild: Remove redundant warnings by @thatsafunnyname\nbuild: Fix tests on OpenBSD by @bket\nbuild: Extend fuzzer build system to work with the new clang engine\nbuild: CMake now creates the libzstd.so.1 symlink\nbuild: Improve Menson build by @lzutao\nmisc: Fix symbolic link detection on FreeBSD\nmisc: Use physical core count for -T0 on FreeBSD by @cemeyer\nmisc: Fix zstd --list on truncated files by @kostmo\nmisc: Improve logging in debug mode by @felixhandte\nmisc: Add CirrusCI tests by @lwhsu\nmisc: Optimize dictionary memory usage in corner cases\nmisc: Improve the dictionary builder on small or homogeneous data\nmisc: Fix spelling across the repo by @jsoref\n\nv1.3.8  (Dec 28, 2018)\nperf: better decompression speed on large files (+7%) and cold dictionaries (+15%)\nperf: slightly better compression ratio at high compression modes\napi : finalized advanced API, last stage before \"stable\" status\napi : new --rsyncable mode, by @terrelln\napi : support decompression of empty frames into NULL (used to be an error) (#1385)\nbuild: new set of macros to build a minimal size decoder, by @felixhandte\nbuild: fix compilation on MIPS32, reported by @clbr (#1441)\nbuild: fix compilation with multiple -arch flags, by @ryandesign\nbuild: highly upgraded meson build, by @lzutao\nbuild: improved buck support, by @obelisk\nbuild: fix cmake script : can create debug build, by @pitrou\nbuild: Makefile : grep works on both colored consoles and systems without color support\nbuild: fixed zstd-pgo, by @bmwiedemann\ncli : support ZSTD_CLEVEL environment variable, by @yijinfb (#1423)\ncli : --no-progress flag, preserving final summary (#1371), by @terrelln\ncli : ensure destination file is not source file (#1422)\ncli : clearer error messages, especially when input file not present\ndoc : clarified zstd_compression_format.md, by @ulikunitz\nmisc: fixed zstdgrep, returns 1 on failure, by @lzutao\nmisc: NEWS renamed as CHANGELOG, in accordance with fboss\n\nv1.3.7  (Oct 20, 2018)\nperf: slightly better decompression speed on clang (depending on hardware target)\nfix : performance of dictionary compression for small input < 4 KB at levels 9 and 10\nbuild: no longer build backtrace by default in release mode; restrict further automatic mode\nbuild: control backtrace support through build macro BACKTRACE\nmisc: added man pages for zstdless and zstdgrep, by @samrussell\n\nv1.3.6  (Oct 6, 2018)\nperf: much faster dictionary builder, by @jenniferliu\nperf: faster dictionary compression on small data when using multiple contexts, by @felixhandte\nperf: faster dictionary decompression when using a very large number of dictionaries simultaneously\ncli : fix : does no longer overwrite destination when source does not exist (#1082)\ncli : new command --adapt, for automatic compression level adaptation\napi : fix : block api can be streamed with > 4 GB, reported by @catid\napi : reduced ZSTD_DDict size by 2 KB\napi : minimum negative compression level is defined, and can be queried using ZSTD_minCLevel().\nbuild: support Haiku target, by @korli\nbuild: Read Legacy format is limited to v0.5+ by default. Can be changed at compile time with macro ZSTD_LEGACY_SUPPORT.\ndoc : zstd_compression_format.md updated to match wording in IETF RFC 8478\nmisc: tests/paramgrill, a parameter optimizer, by @GeorgeLu97\n\nv1.3.5  (Jun 29, 2018)\nperf: much faster dictionary compression, by @felixhandte\nperf: small quality improvement for dictionary generation, by @terrelln\nperf: slightly improved high compression levels (notably level 19)\nmem : automatic memory release for long duration contexts\ncli : fix : overlapLog can be manually set\ncli : fix : decoding invalid lz4 frames\napi : fix : performance degradation for dictionary compression when using advanced API, by @terrelln\napi : change : clarify ZSTD_CCtx_reset() vs ZSTD_CCtx_resetParameters(), by @terrelln\nbuild: select custom libzstd scope through control macros, by @GeorgeLu97\nbuild: OpenBSD patch, by @bket\nbuild: make and make all are compatible with -j\ndoc : clarify zstd_compression_format.md, updated for IETF RFC process\nmisc: pzstd compatible with reproducible compilation, by @lamby\n\nv1.3.4  (Mar 27, 2018)\nperf: faster speed (especially decoding speed) on recent cpus (haswell+)\nperf: much better performance associating --long with multi-threading, by @terrelln\nperf: better compression at levels 13-15\ncli : asynchronous compression by default, for faster experience (use --single-thread for former behavior)\ncli : smoother status report in multi-threading mode\ncli : added command --fast=#, for faster compression modes\ncli : fix crash when not overwriting existing files, by Pádraig Brady (@pixelb)\napi : `nbThreads` becomes `nbWorkers` : 1 triggers asynchronous mode\napi : compression levels can be negative, for even more speed\napi : ZSTD_getFrameProgression() : get precise progress status of ZSTDMT anytime\napi : ZSTDMT can accept new compression parameters during compression\napi : implemented all advanced dictionary decompression prototypes\nbuild: improved meson recipe, by Shawn Landden (@shawnl)\nbuild: VS2017 scripts, by @HaydnTrigg\nmisc: all /contrib projects fixed\nmisc: added /contrib/docker script by @gyscos\n\nv1.3.3  (Dec 21, 2017)\nperf: faster zstd_opt strategy (levels 16-19)\nfix : bug #944 : multithreading with shared dictionary and large data, reported by @gsliepen\ncli : fix : content size written in header by default\ncli : fix : improved LZ4 format support, by @felixhandte\ncli : new : hidden command `-S`, to benchmark multiple files while generating one result per file\napi : fix : support large skippable frames, by @terrelln\napi : fix : streaming interface was adding a useless 3-bytes null block to small frames\napi : change : when setting `pledgedSrcSize`, use `ZSTD_CONTENTSIZE_UNKNOWN` macro value to mean \"unknown\"\nbuild: fix : compilation under rhel6 and centos6, reported by @pixelb\nbuild: added `check` target\n\nv1.3.2  (Oct 10, 2017)\nnew : long range mode, using --long command, by Stella Lau (@stellamplau)\nnew : ability to generate and decode magicless frames (#591)\nchanged : maximum nb of threads reduced to 200, to avoid address space exhaustion in 32-bits mode\nfix : multi-threading compression works with custom allocators\nfix : ZSTD_sizeof_CStream() was over-evaluating memory usage\nfix : a rare compression bug when compression generates very large distances and bunch of other conditions (only possible at --ultra -22)\nfix : 32-bits build can now decode large offsets (levels 21+)\ncli : added LZ4 frame support by default, by Felix Handte (@felixhandte)\ncli : improved --list output\ncli : new : can split input file for dictionary training, using command -B#\ncli : new : clean operation artefact on Ctrl-C interruption\ncli : fix : do not change /dev/null permissions when using command -t with root access, reported by @mike155 (#851)\ncli : fix : write file size in header in multiple-files mode\napi : added macro ZSTD_COMPRESSBOUND() for static allocation\napi : experimental : new advanced decompression API\napi : fix : sizeof_CCtx() used to over-estimate\nbuild: fix : no-multithread variant compiles without pool.c dependency, reported by Mitchell Blank Jr (@mitchblank) (#819)\nbuild: better compatibility with reproducible builds, by Bernhard M. Wiedemann (@bmwiedemann) (#818)\nexample : added streaming_memory_usage\nlicense : changed /examples license to BSD + GPLv2\nlicense : fix a few header files to reflect new license (#825)\n\nv1.3.1  (Aug 21, 2017)\nNew license : BSD + GPLv2\nperf: substantially decreased memory usage in Multi-threading mode, thanks to reports by Tino Reichardt (@mcmilk)\nperf: Multi-threading supports up to 256 threads. Cap at 256 when more are requested (#760)\ncli : improved and fixed --list command, by @ib (#772)\ncli : command -vV to list supported formats, by @ib (#771)\nbuild : fixed binary variants, reported by @svenha (#788)\nbuild : fix Visual compilation for non x86/x64 targets, reported by Greg Slazinski (@GregSlazinski) (#718)\nAPI exp : breaking change : ZSTD_getframeHeader() provides more information\nAPI exp : breaking change : pinned down values of error codes\ndoc : fixed huffman example, by Ulrich Kunitz (@ulikunitz)\nnew : contrib/adaptive-compression, I/O driven compression strength, by Paul Cruz (@paulcruz74)\nnew : contrib/long_distance_matching, statistics by Stella Lau (@stellamplau)\nupdated : contrib/linux-kernel, by Nick Terrell (@terrelln)\n\nv1.3.0  (Jul 6, 2017)\ncli : new : `--list` command, by Paul Cruz\ncli : changed : xz/lzma support enabled by default\ncli : changed : `-t *` continue processing list after a decompression error\nAPI : added : ZSTD_versionString()\nAPI : promoted to stable status : ZSTD_getFrameContentSize(), by Sean Purcell\nAPI exp : new advanced API : ZSTD_compress_generic(), ZSTD_CCtx_setParameter()\nAPI exp : new : API for static or external allocation : ZSTD_initStatic?Ctx()\nAPI exp : added : ZSTD_decompressBegin_usingDDict(), requested by Guy Riddle (#700)\nAPI exp : clarified memory estimation / measurement functions.\nAPI exp : changed : strongest strategy renamed ZSTD_btultra, fastest strategy ZSTD_fast set to 1\ntools : decodecorpus can generate random dictionary-compressed samples, by Paul Cruz\nnew : contrib/seekable_format, demo and API, by Sean Purcell\nchanged : contrib/linux-kernel, updated version and license, by Nick Terrell\n\nv1.2.0  (May 5, 2017)\ncli : changed : Multithreading enabled by default (use target zstd-nomt or HAVE_THREAD=0 to disable)\ncli : new : command -T0 means \"detect and use nb of cores\", by Sean Purcell\ncli : new : zstdmt symlink hardwired to `zstd -T0`\ncli : new : command --threads=# (#671)\ncli : changed : cover dictionary builder by default, for improved quality, by Nick Terrell\ncli : new : commands --train-cover and --train-legacy, to select dictionary algorithm and parameters\ncli : experimental targets `zstd4` and `xzstd4`, with support for lz4 format, by Sean Purcell\ncli : fix : does not output compressed data on console\ncli : fix : ignore symbolic links unless --force specified,\nAPI : breaking change : ZSTD_createCDict_advanced(), only use compressionParameters as argument\nAPI : added : prototypes ZSTD_*_usingCDict_advanced(), for direct control over frameParameters.\nAPI : improved: ZSTDMT_compressCCtx() reduced memory usage\nAPI : fix : ZSTDMT_compressCCtx() now provides srcSize in header (#634)\nAPI : fix : src size stored in frame header is controlled at end of frame\nAPI : fix : enforced consistent rules for pledgedSrcSize==0 (#641)\nAPI : fix : error code \"GENERIC\" replaced by \"dstSizeTooSmall\" when appropriate\nbuild: improved cmake script, by @Majlen\nbuild: enabled Multi-threading support for *BSD, by Baptiste Daroussin\ntools: updated Paramgrill. Command -O# provides best parameters for sample and speed target.\nnew : contrib/linux-kernel version, by Nick Terrell\n\nv1.1.4  (Mar 18, 2017)\ncli : new : can compress in *.gz format, using --format=gzip command, by Przemyslaw Skibinski\ncli : new : advanced benchmark command --priority=rt\ncli : fix : write on sparse-enabled file systems in 32-bits mode, by @ds77\ncli : fix : --rm remains silent when input is stdin\ncli : experimental : xzstd, with support for xz/lzma decoding, by Przemyslaw Skibinski\nspeed : improved decompression speed in streaming mode for single shot scenarios (+5%)\nmemory: DDict (decompression dictionary) memory usage down from 150 KB to 20 KB\narch: 32-bits variant able to generate and decode very long matches (>32 MB), by Sean Purcell\nAPI : new : ZSTD_findFrameCompressedSize(), ZSTD_getFrameContentSize(), ZSTD_findDecompressedSize()\nAPI : changed : dropped support of legacy versions <= v0.3 (can be changed by modifying ZSTD_LEGACY_SUPPORT value)\nbuild : new: meson build system in contrib/meson, by Dima Krasner\nbuild : improved cmake script, by @Majlen\nbuild : added -Wformat-security flag, as recommended by Padraig Brady\ndoc : new : educational decoder, by Sean Purcell\n\nv1.1.3  (Feb 7, 2017)\ncli : zstd can decompress .gz files (can be disabled with `make zstd-nogz` or `make HAVE_ZLIB=0`)\ncli : new : experimental target `make zstdmt`, with multi-threading support\ncli : new : improved dictionary builder \"cover\" (experimental), by Nick Terrell, based on prior work by Giuseppe Ottaviano.\ncli : new : advanced commands for detailed parameters, by Przemyslaw Skibinski\ncli : fix zstdless on Mac OS-X, by Andrew Janke\ncli : fix #232 \"compress non-files\"\ndictBuilder : improved dictionary generation quality, thanks to Nick Terrell\nAPI : new : lib/compress/ZSTDMT_compress.h multithreading API (experimental)\nAPI : new : ZSTD_create?Dict_byReference(), requested by Bartosz Taudul\nAPI : new : ZDICT_finalizeDictionary()\nAPI : fix : ZSTD_initCStream_usingCDict() properly writes dictID into frame header, by Gregory Szorc (#511)\nAPI : fix : all symbols properly exposed in libzstd, by Nick Terrell\nbuild : support for Solaris target, by Przemyslaw Skibinski\ndoc : clarified specification, by Sean Purcell\n\nv1.1.2  (Dec 15, 2016)\nAPI : streaming : decompression : changed : automatic implicit reset when chain-decoding new frames without init\nAPI : experimental : added : dictID retrieval functions, and ZSTD_initCStream_srcSize()\nAPI : zbuff : changed : prototypes now generate deprecation warnings\nlib : improved : faster decompression speed at ultra compression settings and 32-bits mode\nlib : changed : only public ZSTD_ symbols are now exposed\nlib : changed : reduced usage  of stack memory\nlib : fixed : several corner case bugs, by Nick Terrell\ncli : new : gzstd, experimental version able to decode .gz files, by Przemyslaw Skibinski\ncli : new : preserve file attributes\ncli : new : added zstdless and zstdgrep tools\ncli : fixed : status displays total amount decoded, even for file consisting of multiple frames (like pzstd)\ncli : fixed : zstdcat\nzlib_wrapper : added support for gz* functions, by Przemyslaw Skibinski\ninstall : better compatibility with FreeBSD, by Dimitry Andric\nsource tree : changed : zbuff source files moved to lib/deprecated\n\nv1.1.1  (Nov 2, 2016)\nNew : command -M#, --memory=, --memlimit=, --memlimit-decompress= to limit allowed memory consumption\nNew : doc/zstd_manual.html, by Przemyslaw Skibinski\nImproved : slightly better compression ratio at --ultra levels (>= 20)\nImproved : better memory usage when using streaming compression API, thanks to @Rogier-5 report\nAdded : API : ZSTD_initCStream_usingCDict(), ZSTD_initDStream_usingDDict() (experimental section)\nAdded : example/multiple_streaming_compression.c\nChanged : zstd_errors.h is now installed within /include (and replaces errors_public.h)\nUpdated man page\nFixed : zstd-small, zstd-compress and zstd-decompress compilation targets\n\nv1.1.0  (Sep 28, 2016)\nNew : contrib/pzstd, parallel version of zstd, by Nick Terrell\nadded : NetBSD install target (#338)\nImproved : speed for batches of small files\nImproved : speed of zlib wrapper, by Przemyslaw Skibinski\nChanged : libzstd on Windows supports legacy formats, by Christophe Chevalier\nFixed : CLI -d output to stdout by default when input is stdin (#322)\nFixed : CLI correctly detects console on Mac OS-X\nFixed : CLI supports recursive mode `-r` on Mac OS-X\nFixed : Legacy decoders use unified error codes, reported by benrg (#341), fixed by Przemyslaw Skibinski\nFixed : compatibility with OpenBSD, reported by Juan Francisco Cantero Hurtado (#319)\nFixed : compatibility with Hurd, by Przemyslaw Skibinski (#365)\nFixed : zstd-pgo, reported by octoploid (#329)\n\nv1.0.0  (Sep 1, 2016)\nChange Licensing, all project is now BSD, Copyright Facebook\nSmall decompression speed improvement\nAPI : Streaming API supports legacy format\nAPI : ZDICT_getDictID(), ZSTD_sizeof_{CCtx, DCtx, CStream, DStream}(), ZSTD_setDStreamParameter()\nCLI supports legacy formats v0.4+\nFixed : compression fails on certain huge files, reported by Jesse McGrew\nEnhanced documentation, by Przemyslaw Skibinski\n\nv0.8.1  (Aug 18, 2016)\nNew streaming API\nChanged : --ultra now enables levels beyond 19\nChanged : -i# now selects benchmark time in second\nFixed : ZSTD_compress* can now compress > 4 GB in a single pass, reported by Nick Terrell\nFixed : speed regression on specific patterns (#272)\nFixed : support for Z_SYNC_FLUSH, by Dmitry Krot (#291)\nFixed : ICC compilation, by Przemyslaw Skibinski\n\nv0.8.0  (Aug 2, 2016)\nImproved : better speed on clang and gcc -O2, thanks to Eric Biggers\nNew : Build on FreeBSD and DragonFly, thanks to JrMarino\nChanged : modified API : ZSTD_compressEnd()\nFixed : legacy mode with ZSTD_HEAPMODE=0, by Christopher Bergqvist\nFixed : premature end of frame when zero-sized raw block, reported by Eric Biggers\nFixed : large dictionaries (> 384 KB), reported by Ilona Papava\nFixed : checksum correctly checked in single-pass mode\nFixed : combined --test amd --rm, reported by Andreas M. Nilsson\nModified : minor compression level adaptations\nUpdated : compression format specification to v0.2.0\nchanged : zstd.h moved to /lib directory\n\nv0.7.5  (Aug 1, 2016)\nTransition version, supporting decoding of v0.8.x\n\nv0.7.4  (Jul 17, 2016)\nAdded : homebrew for Mac, by Daniel Cade\nAdded : more examples\nFixed : segfault when using small dictionaries, reported by Felix Handte\nModified : default compression level for CLI is now 3\nUpdated : specification, to v0.1.1\n\nv0.7.3  (Jul 9, 2016)\nNew : compression format specification\nNew : `--` separator, stating that all following arguments are file names. Suggested by Chip Turner.\nNew : `ZSTD_getDecompressedSize()`\nNew : OpenBSD target, by Juan Francisco Cantero Hurtado\nNew : `examples` directory\nfixed : dictBuilder using HC levels, reported by Bartosz Taudul\nfixed : legacy support from ZSTD_decompress_usingDDict(), reported by Felix Handte\nfixed : multi-blocks decoding with intermediate uncompressed blocks, reported by Greg Slazinski\nmodified : removed \"mem.h\" and \"error_public.h\" dependencies from \"zstd.h\" (experimental section)\nmodified : legacy functions no longer need magic number\n\nv0.7.2  (Jul 4, 2016)\nfixed : ZSTD_decompressBlock() using multiple consecutive blocks. Reported by Greg Slazinski.\nfixed : potential segfault on very large files (many gigabytes). Reported by Chip Turner.\nfixed : CLI displays system error message when destination file cannot be created (#231). Reported by Chip Turner.\n\nv0.7.1  (Jun 23, 2016)\nfixed : ZBUFF_compressEnd() called multiple times with too small `dst` buffer, reported by Christophe Chevalier\nfixed : dictBuilder fails if first sample is too small, reported by Руслан Ковалёв\nfixed : corruption issue, reported by cj\nmodified : checksum enabled by default in command line mode\n\nv0.7.0  (Jun 17, 2016)\nNew : Support for directory compression, using `-r`, thanks to Przemyslaw Skibinski\nNew : Command `--rm`, to remove source file after successful de/compression\nNew : Visual build scripts, by Christophe Chevalier\nNew : Support for Sparse File-systems (do not use space for zero-filled sectors)\nNew : Frame checksum support\nNew : Support pass-through mode (when using `-df`)\nAPI : more efficient Dictionary API : `ZSTD_compress_usingCDict()`, `ZSTD_decompress_usingDDict()`\nAPI : create dictionary files from custom content, by Giuseppe Ottaviano\nAPI : support for custom malloc/free functions\nNew : controllable Dictionary ID\nNew : Support for skippable frames\n\nv0.6.1  (May 13, 2016)\nNew : zlib wrapper API, thanks to Przemyslaw Skibinski\nNew : Ability to compile compressor / decompressor separately\nChanged : new lib directory structure\nFixed : Legacy codec v0.5 compatible with dictionary decompression\nFixed : Decoder corruption error (#173)\nFixed : null-string roundtrip (#176)\nNew : benchmark mode can select directory as input\nExperimental : midipix support, VMS support\n\nv0.6.0  (Apr 13, 2016)\nStronger high compression modes, thanks to Przemyslaw Skibinski\nAPI : ZSTD_getFrameParams() provides size of decompressed content\nNew : highest compression modes require `--ultra` command to fully unleash their capacity\nFixed : zstd cli return error code > 0 and removes dst file artifact when decompression fails, thanks to Chip Turner\n\nv0.5.1  (Feb 18, 2016)\nNew : Optimal parsing => Very high compression modes, thanks to Przemyslaw Skibinski\nChanged : Dictionary builder integrated into libzstd and zstd cli\nChanged (!) : zstd cli now uses \"multiple input files\" as default mode. See `zstd -h`.\nFix : high compression modes for big-endian platforms\nNew : zstd cli : `-t` | `--test` command\n\nv0.5.0  (Feb 5, 2016)\nNew : dictionary builder utility\nChanged : streaming & dictionary API\nImproved : better compression of small data\n\nv0.4.7  (Jan 22, 2016)\nImproved : small compression speed improvement in HC mode\nChanged : `zstd_decompress.c` has ZSTD_LEGACY_SUPPORT to 0 by default\nfix : bt search bug\n\nv0.4.6  (Jan 13, 2016)\nfix : fast compression mode on Windows\nNew : cmake configuration file, thanks to Artyom Dymchenko\nImproved : high compression mode on repetitive data\nNew : block-level API\nNew : ZSTD_duplicateCCtx()\n\nv0.4.5  (Dec 18, 2015)\nnew : -m/--multiple : compress/decompress multiple files\n\nv0.4.4  (Dec 14, 2015)\nFixed : high compression modes for Windows 32 bits\nnew : external dictionary API extended to buffered mode and accessible through command line\nnew : windows DLL project, thanks to Christophe Chevalier\n\nv0.4.3  (Dec 7, 2015)\nnew : external dictionary API\nnew : zstd-frugal\n\nv0.4.2  (Dec 2, 2015)\nGeneric minor improvements for small blocks\nFixed : big-endian compatibility, by Peter Harris (#85)\n\nv0.4.1  (Dec 1, 2015)\nFixed : ZSTD_LEGACY_SUPPORT=0 build mode (reported by Luben)\nremoved `zstd.c`\n\nv0.4.0  (Nov 29, 2015)\nCommand line utility compatible with high compression levels\nRemoved zstdhc => merged into zstd\nAdded : ZBUFF API (see zstd_buffered.h)\nRolling buffer support\n\nv0.3.6  (Nov 10, 2015)\nsmall blocks params\n\nv0.3.5  (Nov 9, 2015)\nminor generic compression improvements\n\nv0.3.4  (Nov 6, 2015)\nFaster fast cLevels\n\nv0.3.3  (Nov 5, 2015)\nSmall compression ratio improvement\n\nv0.3.2  (Nov 2, 2015)\nFixed Visual Studio\n\nv0.3.1  (Nov 2, 2015)\nSmall compression ratio improvement\n\nv0.3  (Oct 30, 2015)\nHC mode : compression levels 2-26\n\nv0.2.2  (Oct 28, 2015)\nFix : Visual Studio 2013 & 2015 release compilation, by Christophe Chevalier\n\nv0.2.1  (Oct 24, 2015)\nFix : Read errors, advanced fuzzer tests, by Hanno Böck\n\nv0.2.0  (Oct 22, 2015)\n**Breaking format change**\nFaster decompression speed\nCan still decode v0.1 format\n\nv0.1.3  (Oct 15, 2015)\nfix uninitialization warning, reported by Evan Nemerson\n\nv0.1.2  (Sep 11, 2015)\nframe concatenation support\n\nv0.1.1  (Aug 27, 2015)\nfix compression bug\ndetects write-flush errors\n\nv0.1.0  (Aug 25, 2015)\nfirst release\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.10)\n\n# Thin wrapper so `cmake -S .` behaves like `cmake -S build/cmake`.\n# Policy lives in build/cmake; keep parent project language-less.\nproject(zstd-superbuild LANGUAGES NONE)\n\nif(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)\n    message(FATAL_ERROR \"In-source builds are not supported. Specify -B <build-dir>.\")\nendif()\n\nadd_subdirectory(build/cmake)\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Code of Conduct\n\nFacebook has adopted a Code of Conduct that we expect project participants to adhere to.\nPlease read the [full text](https://code.fb.com/codeofconduct/)\nso that you can understand what actions will and will not be tolerated.\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to Zstandard\nWe want to make contributing to this project as easy and transparent as\npossible.\n\n## Our Development Process\nNew versions are being developed in the \"dev\" branch,\nor in their own feature branch.\nWhen they are deemed ready for a release, they are merged into \"release\".\n\nAs a consequence, all contributions must stage first through \"dev\"\nor their own feature branch.\n\n## Pull Requests\nWe actively welcome your pull requests.\n\n1. Fork the repo and create your branch from `dev`.\n2. If you've added code that should be tested, add tests.\n3. If you've changed APIs, update the documentation.\n4. Ensure the test suite passes.\n5. Make sure your code lints.\n6. If you haven't already, complete the Contributor License Agreement (\"CLA\").\n\n## Contributor License Agreement (\"CLA\")\nIn order to accept your pull request, we need you to submit a CLA. You only need\nto do this once to work on any of Facebook's open source projects.\n\nComplete your CLA here: <https://code.facebook.com/cla>\n\n## Workflow\nZstd uses a branch-based workflow for making changes to the codebase. Typically, zstd\nwill use a new branch per sizable topic. For smaller changes, it is okay to lump multiple\nrelated changes into a branch.\n\nOur contribution process works in three main stages:\n1. Local development\n    * Update:\n        * Checkout your fork of zstd if you have not already\n        ```\n        git checkout https://github.com/<username>/zstd\n        cd zstd\n        ```\n        * Update your local dev branch\n        ```\n        git pull https://github.com/facebook/zstd dev\n        git push origin dev\n        ```\n    * Topic and development:\n        * Make a new branch on your fork about the topic you're developing for\n        ```\n        # branch names should be concise but sufficiently informative\n        git checkout -b <branch-name>\n        git push origin <branch-name>\n        ```\n        * Make commits and push\n        ```\n        # make some changes =\n        git add -u && git commit -m <message>\n        git push origin <branch-name>\n        ```\n        * Note: run local tests to ensure that your changes didn't break existing functionality\n            * Quick check\n            ```\n            make check\n            ```\n            * Longer check\n            ```\n            make test\n            ```\n2. Code Review and CI tests\n    * Ensure CI tests pass:\n        * Before sharing anything to the community, create a pull request in your own fork against the dev branch\n        and make sure that all GitHub Actions CI tests pass. See the Continuous Integration section below for more information.\n        * Ensure that static analysis passes on your development machine. See the Static Analysis section\n        below to see how to do this.\n    * Create a pull request:\n        * When you are ready to share you changes to the community, create a pull request from your branch\n        to facebook:dev. You can do this very easily by clicking 'Create Pull Request' on your fork's home\n        page.\n        * From there, select the branch where you made changes as your source branch and facebook:dev\n        as the destination.\n        * Examine the diff presented between the two branches to make sure there is nothing unexpected.\n    * Write a good pull request description:\n        * While there is no strict template that our contributors follow, we would like them to\n        sufficiently summarize and motivate the changes they are proposing. We recommend all pull requests,\n        at least indirectly, address the following points.\n            * Is this pull request important and why?\n            * Is it addressing an issue? If so, what issue? (provide links for convenience please)\n            * Is this a new feature? If so, why is it useful and/or necessary?\n            * Are there background references and documents that reviewers should be aware of to properly assess this change?\n        * Note: make sure to point out any design and architectural decisions that you made and the rationale behind them.\n        * Note: if you have been working with a specific user and would like them to review your work, make sure you mention them using (@<username>)\n    * Submit the pull request and iterate with feedback.\n3. Merge and Release\n    * Getting approval:\n        * You will have to iterate on your changes with feedback from other collaborators to reach a point\n        where your pull request can be safely merged.\n        * To avoid too many comments on style and convention, make sure that you have a\n        look at our style section below before creating a pull request.\n        * Eventually, someone from the zstd team will approve your pull request and not long after merge it into\n        the dev branch.\n    * Housekeeping:\n        * Most PRs are linked with one or more Github issues. If this is the case for your PR, make sure\n        the corresponding issue is mentioned. If your change 'fixes' or completely addresses the\n        issue at hand, then please indicate this by requesting that an issue be closed by commenting.\n        * Just because your changes have been merged does not mean the topic or larger issue is complete. Remember\n        that the change must make it to an official zstd release for it to be meaningful. We recommend\n        that contributors track the activity on their pull request and corresponding issue(s) page(s) until\n        their change makes it to the next release of zstd. Users will often discover bugs in your code or\n        suggest ways to refine and improve your initial changes even after the pull request is merged.\n\n## Static Analysis\nStatic analysis is a process for examining the correctness or validity of a program without actually\nexecuting it. It usually helps us find many simple bugs. Zstd uses clang's `scan-build` tool for\nstatic analysis. You can install it by following the instructions for your OS on https://clang-analyzer.llvm.org/scan-build.\n\nOnce installed, you can ensure that our static analysis tests pass on your local development machine\nby running:\n```\nmake staticAnalyze\n```\n\nIn general, you can use `scan-build` to static analyze any build script. For example, to static analyze\njust `contrib/largeNbDicts` and nothing else, you can run:\n\n```\nscan-build make -C contrib/largeNbDicts largeNbDicts\n```\n\n### Pitfalls of static analysis\n`scan-build` is part of our regular CI suite. Other static analyzers are not.\n\nIt can be useful to look at additional static analyzers once in a while (and we do), but it's not a good idea to multiply the nb of analyzers run continuously at each commit and PR. The reasons are :\n\n- Static analyzers are full of false positive. The signal to noise ratio is actually pretty low.\n- A good CI policy is \"zero-warning tolerance\". That means that all issues must be solved, including false positives. This quickly becomes a tedious workload.\n- Multiple static analyzers will feature multiple kind of false positives, sometimes applying to the same code but in different ways leading to :\n   + tortuous code, trying to please multiple constraints, hurting readability and therefore maintenance. Sometimes, such complexity introduce other more subtle bugs, that are just out of scope of the analyzers.\n   + sometimes, these constraints are mutually exclusive : if one try to solve one, the other static analyzer will complain, they can't be both happy at the same time.\n- As if that was not enough, the list of false positives change with each version. It's hard enough to follow one static analyzer, but multiple ones with their own update agenda, this quickly becomes a massive velocity reducer.\n\nThis is different from running a static analyzer once in a while, looking at the output, and __cherry picking__ a few warnings that seem helpful, either because they detected a genuine risk of bug, or because it helps expressing the code in a way which is more readable or more difficult to misuse. These kinds of reports can be useful, and are accepted.\n\n## Continuous Integration\nCI tests run every time a pull request (PR) is created or updated. The exact tests\nthat get run will depend on the destination branch you specify. Some tests take\nlonger to run than others. Currently, our CI is set up to run a short\nseries of tests when creating a PR to the dev branch and a longer series of tests\nwhen creating a PR to the release branch. You can look in the configuration files\nof the respective CI platform for more information on what gets run when.\n\nMost people will just want to create a PR with the destination set to their local dev\nbranch of zstd. You can then find the status of the tests on the PR's page. You can also\nre-run tests and cancel running tests from the PR page or from the respective CI's dashboard.\n\nAlmost all of zstd's CI runs on GitHub Actions (configured at `.github/workflows`), which will automatically run on PRs to your\nown fork. A small number of tests run on other services (e.g. Travis CI, Circle CI, Appveyor).\nThese require work to set up on your local fork, and (at least for Travis CI) cost money.\nTherefore, if the PR on your local fork passes GitHub Actions, feel free to submit a PR\nagainst the main repo.\n\n### Third-party CI\nA small number of tests cannot run on GitHub Actions, or have yet to be migrated.\nFor these, we use a variety of third-party services (listed below). It is not necessary to set\nthese up on your fork in order to contribute to zstd; however, we do link to instructions for those\nwho want earlier signal.\n\n| Service   | Purpose                                                                                                    | Setup Links                                                                                                                                            | Config Path            |\n|-----------|------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------|\n| Travis CI | Used for testing on non-x86 architectures such as PowerPC                                                  | https://docs.travis-ci.com/user/tutorial/#to-get-started-with-travis-ci-using-github <br> https://github.com/marketplace/travis-ci                     | `.travis.yml`          |\n| AppVeyor  | Used for some Windows testing (e.g. cygwin, mingw)                                                         | https://www.appveyor.com/blog/2018/10/02/github-apps-integration/ <br> https://github.com/marketplace/appveyor                                         | `appveyor.yml`         |\n| Cirrus CI | Used for testing on FreeBSD                                                                                | https://github.com/marketplace/cirrus-ci/                                                                                                              | `.cirrus.yml`          |\n| Circle CI | Historically was used to provide faster signal,<br/> but we may be able to migrate these to Github Actions | https://circleci.com/docs/2.0/getting-started/#setting-up-circleci <br> https://youtu.be/Js3hMUsSZ2c <br> https://circleci.com/docs/2.0/enable-checks/ | `.circleci/config.yml` |\n\nNote: the instructions linked above mostly cover how to set up a repository with CI from scratch.\nThe general idea should be the same for setting up CI on your fork of zstd, but you may have to\nfollow slightly different steps. In particular, please ignore any instructions related to setting up\nconfig files (since zstd already has configs for each of these services).\n\n## Performance\nPerformance is extremely important for zstd and we only merge pull requests whose performance\nlandscape and corresponding trade-offs have been adequately analyzed, reproduced, and presented.\nThis high bar for performance means that every PR which has the potential to\nimpact performance takes a very long time for us to properly review. That being said, we\nalways welcome contributions to improve performance (or worsen performance for the trade-off of\nsomething else). Please keep the following in mind before submitting a performance related PR:\n\n1. Zstd isn't as old as gzip but it has been around for time now and its evolution is\nvery well documented via past Github issues and pull requests. It may be the case that your\nparticular performance optimization has already been considered in the past. Please take some\ntime to search through old issues and pull requests using keywords specific to your\nwould-be PR. Of course, just because a topic has already been discussed (and perhaps rejected\non some grounds) in the past, doesn't mean it isn't worth bringing up again. But even in that case,\nit will be helpful for you to have context from that topic's history before contributing.\n2. The distinction between noise and actual performance gains can unfortunately be very subtle\nespecially when microbenchmarking extremely small wins or losses. The only remedy to getting\nsomething subtle merged is extensive benchmarking. You will be doing us a great favor if you\ntake the time to run extensive, long-duration, and potentially cross-(os, platform, process, etc)\nbenchmarks on your end before submitting a PR. Of course, you will not be able to benchmark\nyour changes on every single processor and os out there (and neither will we) but do that best\nyou can:) We've added some things to think about when benchmarking below in the Benchmarking\nPerformance section which might be helpful for you.\n3. Optimizing performance for a certain OS, processor vendor, compiler, or network system is a perfectly\nlegitimate thing to do as long as it does not harm the overall performance health of Zstd.\nThis is a hard balance to strike but please keep in mind other aspects of Zstd when\nsubmitting changes that are clang-specific, windows-specific, etc.\n\n## Benchmarking Performance\nPerformance microbenchmarking is a tricky subject but also essential for Zstd. We value empirical\ntesting over theoretical speculation. This guide it not perfect but for most scenarios, it\nis a good place to start.\n\n### Stability\nUnfortunately, the most important aspect in being able to benchmark reliably is to have a stable\nbenchmarking machine. A virtual machine, a machine with shared resources, or your laptop\nwill typically not be stable enough to obtain reliable benchmark results. If you can get your\nhands on a desktop, this is usually a better scenario.\n\nOf course, benchmarking can be done on non-hyper-stable machines as well. You will just have to\ndo a little more work to ensure that you are in fact measuring the changes you've made and not\nnoise. Here are some things you can do to make your benchmarks more stable:\n\n1. The most simple thing you can do to drastically improve the stability of your benchmark is\nto run it multiple times and then aggregate the results of those runs. As a general rule of\nthumb, the smaller the change you are trying to measure, the more samples of benchmark runs\nyou will have to aggregate over to get reliable results. Here are some additional things to keep in\nmind when running multiple trials:\n    * How you aggregate your samples are important. You might be tempted to use the mean of your\n    results. While this is certainly going to be a more stable number than a raw single sample\n    benchmark number, you might have more luck by taking the median. The mean is not robust to\n    outliers whereas the median is. Better still, you could simply take the fastest speed your\n    benchmark achieved on each run since that is likely the fastest your process will be\n    capable of running your code. In our experience, this (aggregating by just taking the sample\n    with the fastest running time) has been the most stable approach.\n    * The more samples you have, the more stable your benchmarks should be. You can verify\n    your improved stability by looking at the size of your confidence intervals as you\n    increase your sample count. These should get smaller and smaller. Eventually hopefully\n    smaller than the performance win you are expecting.\n    * Most processors will take some time to get `hot` when running anything. The observations\n    you collect during that time period will very different from the true performance number. Having\n    a very large number of sample will help alleviate this problem slightly but you can also\n    address is directly by simply not including the first `n` iterations of your benchmark in\n    your aggregations. You can determine `n` by simply looking at the results from each iteration\n    and then hand picking a good threshold after which the variance in results seems to stabilize.\n2. You cannot really get reliable benchmarks if your host machine is simultaneously running\nanother cpu/memory-intensive application in the background. If you are running benchmarks on your\npersonal laptop for instance, you should close all applications (including your code editor and\nbrowser) before running your benchmarks. You might also have invisible background applications\nrunning. You can see what these are by looking at either Activity Monitor on Mac or Task Manager\non Windows. You will get more stable benchmark results of you end those processes as well.\n    * If you have multiple cores, you can even run your benchmark on a reserved core to prevent\n    pollution from other OS and user processes. There are a number of ways to do this depending\n    on your OS:\n        * On linux boxes, you have use https://github.com/lpechacek/cpuset.\n        * On Windows, you can \"Set Processor Affinity\" using https://www.thewindowsclub.com/processor-affinity-windows\n        * On Mac, you can try to use their dedicated affinity API https://developer.apple.com/library/archive/releasenotes/Performance/RN-AffinityAPI/#//apple_ref/doc/uid/TP40006635-CH1-DontLinkElementID_2\n3. To benchmark, you will likely end up writing a separate c/c++ program that will link libzstd.\nDynamically linking your library will introduce some added variation (not a large amount but\ndefinitely some). Statically linking libzstd will be more stable. Static libraries should\nbe enabled by default when building zstd.\n4. Use a profiler with a good high resolution timer. See the section below on profiling for\ndetails on this.\n5. Disable frequency scaling, turbo boost and address space randomization (this will vary by OS)\n6. Try to avoid storage. On some systems you can use tmpfs. Putting the program, inputs and outputs on\ntmpfs avoids touching a real storage system, which can have a pretty big variability.\n\nAlso check our LLVM's guide on benchmarking here: https://llvm.org/docs/Benchmarking.html\n\n### Zstd benchmark\nThe fastest signal you can get regarding your performance changes is via the in-build zstd cli\nbench option. You can run Zstd as you typically would for your scenario using some set of options\nand then additionally also specify the `-b#` option. Doing this will run our benchmarking pipeline\nfor that options you have just provided. If you want to look at the internals of how this\nbenchmarking script works, you can check out programs/benchzstd.c\n\nFor example: say you have made a change that you believe improves the speed of zstd level 1. The\nvery first thing you should use to assess whether you actually achieved any sort of improvement\nis `zstd -b`. You might try to do something like this. Note: you can use the `-i` option to\nspecify a running time for your benchmark in seconds (default is 3 seconds).\nUsually, the longer the running time, the more stable your results will be.\n\n```\n$ git checkout <commit-before-your-change>\n$ make && cp zstd zstd-old\n$ git checkout <commit-after-your-change>\n$ make && cp zstd zstd-new\n$ zstd-old -i5 -b1 <your-test-data>\n 1<your-test-data>         :      8990 ->      3992 (2.252), 302.6 MB/s , 626.4 MB/s\n$ zstd-new -i5 -b1 <your-test-data>\n 1<your-test-data>         :      8990 ->      3992 (2.252), 302.8 MB/s , 628.4 MB/s\n```\n\nUnless your performance win is large enough to be visible despite the intrinsic noise\non your computer, benchzstd alone will likely not be enough to validate the impact of your\nchanges. For example, the results of the example above indicate that effectively nothing\nchanged but there could be a small <3% improvement that the noise on the host machine\nobscured. So unless you see a large performance win (10-15% consistently) using just\nthis method of evaluation will not be sufficient.\n\n### Profiling\nThere are a number of great profilers out there. We're going to briefly mention how you can\nprofile your code using `instruments` on mac, `perf` on linux and `visual studio profiler`\non Windows.\n\nSay you have an idea for a change that you think will provide some good performance gains\nfor level 1 compression on Zstd. Typically this means, you have identified a section of\ncode that you think can be made to run faster.\n\nThe first thing you will want to do is make sure that the piece of code is actually taking up\na notable amount of time to run. It is usually not worth optimizing something which accounts for less than\n0.0001% of the total running time. Luckily, there are tools to help with this.\nProfilers will let you see how much time your code spends inside a particular function.\nIf your target code snippet is only part of a function, it might be worth trying to\nisolate that snippet by moving it to its own function (this is usually not necessary but\nmight be).\n\nMost profilers (including the profilers discussed below) will generate a call graph of\nfunctions for you. Your goal will be to find your function of interest in this call graph\nand then inspect the time spent inside of it. You might also want to look at the annotated\nassembly which most profilers will provide you with.\n\n#### Instruments\nWe will once again consider the scenario where you think you've identified a piece of code\nwhose performance can be improved upon. Follow these steps to profile your code using\nInstruments.\n\n1. Open Instruments\n2. Select `Time Profiler` from the list of standard templates\n3. Close all other applications except for your instruments window and your terminal\n4. Run your benchmarking script from your terminal window\n    * You will want a benchmark that runs for at least a few seconds (5 seconds will\n    usually be long enough). This way the profiler will have something to work with\n    and you will have ample time to attach your profiler to this process:)\n    * I will just use benchzstd as my benchmarmking script for this example:\n```\n$ zstd -b1 -i5 <my-data> # this will run for 5 seconds\n```\n5. Once you run your benchmarking script, switch back over to instruments and attach your\nprocess to the time profiler. You can do this by:\n    * Clicking on the `All Processes` drop down in the top left of the toolbar.\n    * Selecting your process from the dropdown. In my case, it is just going to be labeled\n    `zstd`\n    * Hitting the bright red record circle button on the top left of the toolbar\n6. You profiler will now start collecting metrics from your benchmarking script. Once\nyou think you have collected enough samples (usually this is the case after 3 seconds of\nrecording), stop your profiler.\n7. Make sure that in toolbar of the bottom window, `profile` is selected.\n8. You should be able to see your call graph.\n    * If you don't see the call graph or an incomplete call graph, make sure you have compiled\n    zstd and your benchmarking script using debug flags. On mac and linux, this just means\n    you will have to supply the `-g` flag alone with your build script. You might also\n    have to provide the `-fno-omit-frame-pointer` flag\n9. Dig down the graph to find your function call and then inspect it by double clicking\nthe list item. You will be able to see the annotated source code and the assembly side by\nside.\n\n#### Perf\n\nThis wiki has a pretty detailed tutorial on getting started working with perf so we'll\nleave you to check that out of you're getting started:\n\nhttps://perf.wiki.kernel.org/index.php/Tutorial\n\nSome general notes on perf:\n* Use `perf stat -r # <bench-program>` to quickly get some relevant timing and\ncounter statistics. Perf uses a high resolution timer and this is likely one\nof the first things your team will run when assessing your PR.\n* Perf has a long list of hardware counters that can be viewed with `perf --list`.\nWhen measuring optimizations, something worth trying is to make sure the hardware\ncounters you expect to be impacted by your change are in fact being so. For example,\nif you expect the L1 cache misses to decrease with your change, you can look at the\ncounter `L1-dcache-load-misses`\n* Perf hardware counters will not work on a virtual machine.\n\n#### Visual Studio\n\nBuild Zstd with symbols first (for example `cmake -B build -S build/cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo && ninja -C build zstd`) so the profiler resolves call stacks.\n\n* Launch Visual Studio’s Performance Profiler (`Alt+F2`), enable CPU Usage (optionally Instrumentation), and point it at the `programs/zstd` benchmark you want to run.\n* If you prefer to start the benchmark from a terminal, use “Attach to running process” to latch onto it mid-run; keep frame pointers (`-fno-omit-frame-pointer`) for clean stacks.\n* When you stop the capture, review the call tree, hot path, and annotated source panes\n* Microsoft’s [Performance Profiling docs](https://learn.microsoft.com/en-us/visualstudio/profiling/?view=vs-2022) cover deeper sampling, ETW, and collection options if required.\n\n## Issues\nWe use GitHub issues to track public bugs. Please ensure your description is\nclear and has sufficient instructions to be able to reproduce the issue.\n\nFacebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe\ndisclosure of security bugs. In those cases, please go through the process\noutlined on that page and do not file a public issue.\n\n## Coding Style\nIt's a pretty long topic, which is difficult to summarize in a single paragraph.\nAs a rule of thumbs, try to imitate the coding style of\nsimilar lines of codes around your contribution.\nThe following is a non-exhaustive list of rules employed in zstd code base:\n\n### C90\nThis code base is following strict C90 standard,\nwith 2 extensions : 64-bit `long long` types, and variadic macros.\nThis rule is applied strictly to code within `lib/` and `programs/`.\nSub-project in `contrib/` are allowed to use other conventions.\n\n### C++ direct compatibility : symbol mangling\nAll public symbol declarations must be wrapped in `extern “C” { … }`,\nso that this project can be compiled as C++98 code,\nand linked into C++ applications.\n\n### Minimal Frugal\nThis design requirement is fundamental to preserve the portability of the code base.\n#### Dependencies\n- Reduce dependencies to the minimum possible level.\n  Any dependency should be considered “bad” by default,\n  and only tolerated because it provides a service in a better way than can be achieved locally.\n  The only external dependencies this repository tolerates are\n  standard C libraries, and in rare cases, system level headers.\n- Within `lib/`, this policy is even more drastic.\n  The only external dependencies allowed are `<assert.h>`, `<stdlib.h>`, `<string.h>`,\n  and even then, not directly.\n  In particular, no function shall ever allocate on heap directly,\n  and must use instead `ZSTD_malloc()` and equivalent.\n  Other accepted non-symbol headers are `<stddef.h>` and `<limits.h>`.\n- Within the project, there is a strict hierarchy of dependencies that must be respected.\n  `programs/` is allowed to depend on `lib/`, but only its public API.\n  Within `lib/`, `lib/common` doesn't depend on any other directory.\n  `lib/compress` and `lib/decompress` shall not depend on each other.\n  `lib/dictBuilder` can depend on `lib/common` and `lib/compress`, but not `lib/decompress`.\n#### Resources\n- Functions in `lib/` must use very little stack space,\n  several dozens of bytes max.\n  Everything larger must use the heap allocator,\n  or require a scratch buffer to be emplaced manually.\n\n### Naming\n* All public symbols are prefixed with `ZSTD_`\n  + private symbols, with a scope limited to their own unit, are free of this restriction.\n    However, since `libzstd` source code can be amalgamated,\n    each symbol name must attempt to be (and remain) unique.\n    Avoid too generic names that could become ground for future collisions.\n    This generally implies usage of some form of prefix.\n* For symbols (functions and variables), naming convention is `PREFIX_camelCase`.\n  + In some advanced cases, one can also find :\n    - `PREFIX_prefix2_camelCase`\n    - `PREFIX_camelCase_extendedQualifier`\n* Multi-words names generally consist of an action followed by object:\n  - for example : `ZSTD_createCCtx()`\n* Prefer positive actions\n  - `goBackward` rather than `notGoForward`\n* Type names (`struct`, etc.) follow similar convention,\n  except that they are allowed and even invited to start by an Uppercase letter.\n  Example : `ZSTD_CCtx`, `ZSTD_CDict`\n* Macro names are all Capital letters.\n  The same composition rules (`PREFIX_NAME_QUALIFIER`) apply.\n* File names are all lowercase letters.\n  The convention is `snake_case`.\n  File names **must** be unique across the entire code base,\n  even when they stand in clearly separated directories.\n\n### Qualifiers\n* This code base is `const` friendly, if not `const` fanatical.\n  Any variable that can be `const` (aka. read-only) **must** be `const`.\n  Any pointer which content will not be modified must be `const`.\n  This property is then controlled at compiler level.\n  `const` variables are an important signal to readers that this variable isn't modified.\n  Conversely, non-const variables are a signal to readers to watch out for modifications later on in the function.\n* If a function must be inlined, mention it explicitly,\n  using project's own portable macros, such as `FORCE_INLINE_ATTR`,\n  defined in `lib/common/compiler.h`.\n\n### Debugging\n* **Assertions** are welcome, and should be used very liberally,\n  to control any condition the code expects for its correct execution.\n  These assertion checks will be run in debug builds, and disabled in production.\n* For traces, this project provides its own debug macros,\n  in particular `DEBUGLOG(level, ...)`, defined in `lib/common/debug.h`.\n\n### Code documentation\n* Avoid code documentation that merely repeats what the code is already stating.\n  Whenever applicable, prefer employing the code as the primary way to convey explanations.\n  Example 1 : `int nbTokens = n;` instead of `int i = n; /* i is a nb of tokens *./`.\n  Example 2 : `assert(size > 0);` instead of `/* here, size should be positive */`.\n* At declaration level, the documentation explains how to use the function or variable\n  and when applicable why it's needed, of the scenarios where it can be useful.\n* At implementation level, the documentation explains the general outline of the algorithm employed,\n  and when applicable why this specific choice was preferred.\n\n### General layout\n* 4 spaces for indentation rather than tabs\n* Code documentation shall directly precede function declaration or implementation\n* Function implementations and its code documentation should be preceded and followed by an empty line\n\n\n## License\nBy contributing to Zstandard, you agree that your contributions will be licensed\nunder both the [LICENSE](LICENSE) file and the [COPYING](COPYING) file in the root directory of this source tree.\n"
  },
  {
    "path": "COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc.,\n 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change free\nsoftware--to make sure the software is free for all its users.  This\nGeneral Public License applies to most of the Free Software\nFoundation's software and to any other program whose authors commit to\nusing it.  (Some other Free Software Foundation software is covered by\nthe GNU Lesser General Public License instead.)  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthis service if you wish), that you receive source code or can get it\nif you want it, that you can change the software or use pieces of it\nin new free programs; and that you know you can do these things.\n\n  To protect your rights, we need to make restrictions that forbid\nanyone to deny you these rights or to ask you to surrender the rights.\nThese restrictions translate to certain responsibilities for you if you\ndistribute copies of the software, or if you modify it.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must give the recipients all the rights that\nyou have.  You must make sure that they, too, receive or can get the\nsource code.  And you must show them these terms so they know their\nrights.\n\n  We protect your rights with two steps: (1) copyright the software, and\n(2) offer you this license which gives you legal permission to copy,\ndistribute and/or modify the software.\n\n  Also, for each author's protection and ours, we want to make certain\nthat everyone understands that there is no warranty for this free\nsoftware.  If the software is modified by someone else and passed on, we\nwant its recipients to know that what they have is not the original, so\nthat any problems introduced by others will not reflect on the original\nauthors' reputations.\n\n  Finally, any free program is threatened constantly by software\npatents.  We wish to avoid the danger that redistributors of a free\nprogram will individually obtain patent licenses, in effect making the\nprogram proprietary.  To prevent this, we have made it clear that any\npatent must be licensed for everyone's free use or not licensed at all.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                    GNU GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License applies to any program or other work which contains\na notice placed by the copyright holder saying it may be distributed\nunder the terms of this General Public License.  The \"Program\", below,\nrefers to any such program or work, and a \"work based on the Program\"\nmeans either the Program or any derivative work under copyright law:\nthat is to say, a work containing the Program or a portion of it,\neither verbatim or with modifications and/or translated into another\nlanguage.  (Hereinafter, translation is included without limitation in\nthe term \"modification\".)  Each licensee is addressed as \"you\".\n\nActivities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning the Program is not restricted, and the output from the Program\nis covered only if its contents constitute a work based on the\nProgram (independent of having been made by running the Program).\nWhether that is true depends on what the Program does.\n\n  1. You may copy and distribute verbatim copies of the Program's\nsource code as you receive it, in any medium, provided that you\nconspicuously and appropriately publish on each copy an appropriate\ncopyright notice and disclaimer of warranty; keep intact all the\nnotices that refer to this License and to the absence of any warranty;\nand give any other recipients of the Program a copy of this License\nalong with the Program.\n\nYou may charge a fee for the physical act of transferring a copy, and\nyou may at your option offer warranty protection in exchange for a fee.\n\n  2. You may modify your copy or copies of the Program or any portion\nof it, thus forming a work based on the Program, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) You must cause the modified files to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    b) You must cause any work that you distribute or publish, that in\n    whole or in part contains or is derived from the Program or any\n    part thereof, to be licensed as a whole at no charge to all third\n    parties under the terms of this License.\n\n    c) If the modified program normally reads commands interactively\n    when run, you must cause it, when started running for such\n    interactive use in the most ordinary way, to print or display an\n    announcement including an appropriate copyright notice and a\n    notice that there is no warranty (or else, saying that you provide\n    a warranty) and that users may redistribute the program under\n    these conditions, and telling the user how to view a copy of this\n    License.  (Exception: if the Program itself is interactive but\n    does not normally print such an announcement, your work based on\n    the Program is not required to print an announcement.)\n\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Program,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Program, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote it.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Program.\n\nIn addition, mere aggregation of another work not based on the Program\nwith the Program (or with a work based on the Program) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may copy and distribute the Program (or a work based on it,\nunder Section 2) in object code or executable form under the terms of\nSections 1 and 2 above provided that you also do one of the following:\n\n    a) Accompany it with the complete corresponding machine-readable\n    source code, which must be distributed under the terms of Sections\n    1 and 2 above on a medium customarily used for software interchange; or,\n\n    b) Accompany it with a written offer, valid for at least three\n    years, to give any third party, for a charge no more than your\n    cost of physically performing source distribution, a complete\n    machine-readable copy of the corresponding source code, to be\n    distributed under the terms of Sections 1 and 2 above on a medium\n    customarily used for software interchange; or,\n\n    c) Accompany it with the information you received as to the offer\n    to distribute corresponding source code.  (This alternative is\n    allowed only for noncommercial distribution and only if you\n    received the program in object code or executable form with such\n    an offer, in accord with Subsection b above.)\n\nThe source code for a work means the preferred form of the work for\nmaking modifications to it.  For an executable work, complete source\ncode means all the source code for all modules it contains, plus any\nassociated interface definition files, plus the scripts used to\ncontrol compilation and installation of the executable.  However, as a\nspecial exception, the source code distributed need not include\nanything that is normally distributed (in either source or binary\nform) with the major components (compiler, kernel, and so on) of the\noperating system on which the executable runs, unless that component\nitself accompanies the executable.\n\nIf distribution of executable or object code is made by offering\naccess to copy from a designated place, then offering equivalent\naccess to copy the source code from the same place counts as\ndistribution of the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\n  4. You may not copy, modify, sublicense, or distribute the Program\nexcept as expressly provided under this License.  Any attempt\notherwise to copy, modify, sublicense or distribute the Program is\nvoid, and will automatically terminate your rights under this License.\nHowever, parties who have received copies, or rights, from you under\nthis License will not have their licenses terminated so long as such\nparties remain in full compliance.\n\n  5. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Program or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Program (or any work based on the\nProgram), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Program or works based on it.\n\n  6. Each time you redistribute the Program (or any work based on the\nProgram), the recipient automatically receives a license from the\noriginal licensor to copy, distribute or modify the Program subject to\nthese terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties to\nthis License.\n\n  7. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Program at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Program by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Program.\n\nIf any portion of this section is held invalid or unenforceable under\nany particular circumstance, the balance of the section is intended to\napply and the section as a whole is intended to apply in other\ncircumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system, which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\n  8. If the distribution and/or use of the Program is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Program under this License\nmay add an explicit geographical distribution limitation excluding\nthose countries, so that distribution is permitted only in or among\ncountries not thus excluded.  In such case, this License incorporates\nthe limitation as if written in the body of this License.\n\n  9. The Free Software Foundation may publish revised and/or new versions\nof the General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies a version number of this License which applies to it and \"any\nlater version\", you have the option of following the terms and conditions\neither of that version or of any later version published by the Free\nSoftware Foundation.  If the Program does not specify a version number of\nthis License, you may choose any version ever published by the Free Software\nFoundation.\n\n  10. If you wish to incorporate parts of the Program into other free\nprograms whose distribution conditions are different, write to the author\nto ask for permission.  For software which is copyrighted by the Free\nSoftware Foundation, write to the Free Software Foundation; we sometimes\nmake exceptions for this.  Our decision will be guided by the two goals\nof preserving the free status of all derivatives of our free software and\nof promoting the sharing and reuse of software generally.\n\n                            NO WARRANTY\n\n  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\nFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\nOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\nTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\nPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\nREPAIR OR CORRECTION.\n\n  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\nTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\nYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nconvey the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License along\n    with this program; if not, write to the Free Software Foundation, Inc.,\n    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program is interactive, make it output a short notice like this\nwhen it starts in an interactive mode:\n\n    Gnomovision version 69, Copyright (C) year name of author\n    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, the commands you use may\nbe called something other than `show w' and `show c'; they could even be\nmouse-clicks or menu items--whatever suits your program.\n\nYou should also get your employer (if you work as a programmer) or your\nschool, if any, to sign a \"copyright disclaimer\" for the program, if\nnecessary.  Here is a sample; alter the names:\n\n  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n  `Gnomovision' (which makes passes at compilers) written by James Hacker.\n\n  <signature of Ty Coon>, 1 April 1989\n  Ty Coon, President of Vice\n\nThis General Public License does not permit incorporating your program into\nproprietary programs.  If your program is a subroutine library, you may\nconsider it more useful to permit linking proprietary applications with the\nlibrary.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License."
  },
  {
    "path": "LICENSE",
    "content": "BSD License\n\nFor Zstandard software\n\nCopyright (c) Meta Platforms, Inc. and affiliates. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n * Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer.\n\n * Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n\n * Neither the name Facebook, nor Meta, nor the names of its contributors may\n   be used to endorse or promote products derived from this software without\n   specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "Makefile",
    "content": "# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ################################################################\n\n# verbose mode (print commands) on V=1 or VERBOSE=1\nQ = $(if $(filter 1,$(V) $(VERBOSE)),,@)\n\nPRGDIR   = programs\nZSTDDIR  = lib\nBUILDIR  = build\nZWRAPDIR = zlibWrapper\nTESTDIR  = tests\nFUZZDIR  = $(TESTDIR)/fuzz\n\n# Define nul output\nVOID = /dev/null\n\n# When cross-compiling from linux to windows, you might\n# need to specify this as \"Windows.\" Fedora build fails\n# without it.\n#\n# Note: mingw-w64 build from linux to windows does not\n# fail on other tested distros (ubuntu, debian) even\n# without manually specifying the TARGET_SYSTEM.\nTARGET_SYSTEM ?= $(OS)\nCP ?= cp\n\nifneq (,$(filter Windows%,$(TARGET_SYSTEM)))\n  EXT =.exe\nelse\n  EXT =\nendif\n\n## default: Build lib-release and zstd-release\n.PHONY: default\ndefault: lib-release zstd-release\n\n.PHONY: all\nall: allmost examples manual contrib\n\n.PHONY: allmost\nallmost: allzstd zlibwrapper\n\n# skip zwrapper, can't build that on alternate architectures without the proper zlib installed\n.PHONY: allzstd\nallzstd: lib\n\t$(Q)$(MAKE) -C $(PRGDIR) all\n\t$(Q)$(MAKE) -C $(TESTDIR) all\n\n.PHONY: all32\nall32:\n\t$(MAKE) -C $(PRGDIR) zstd32\n\t$(MAKE) -C $(TESTDIR) all32\n\n.PHONY: lib lib-release lib-mt lib-nomt\nlib lib-release lib-mt lib-nomt:\n\t$(Q)$(MAKE) -C $(ZSTDDIR) $@\n\n.PHONY: zstd zstd-release\nzstd zstd-release:\n\t$(Q)$(MAKE) -C $(PRGDIR) $@\n\t$(Q)ln -sf $(PRGDIR)/zstd$(EXT) zstd$(EXT)\n\n.PHONY: zstdmt\nzstdmt:\n\t$(Q)$(MAKE) -C $(PRGDIR) $@\n\t$(Q)$(CP) $(PRGDIR)/zstd$(EXT) ./zstdmt$(EXT)\n\n.PHONY: zlibwrapper\nzlibwrapper: lib\n\t$(MAKE) -C $(ZWRAPDIR) all\n\n## test: run long-duration tests\n.PHONY: test\nDEBUGLEVEL ?= 1\ntest: MOREFLAGS += -g -Werror\ntest:\n\tDEBUGLEVEL=$(DEBUGLEVEL) MOREFLAGS=\"$(MOREFLAGS)\" $(MAKE) -j -C $(PRGDIR) allVariants\n\t$(MAKE) -C $(TESTDIR) $@\n\tZSTD=../../programs/zstd $(MAKE) -C doc/educational_decoder $@\n\n## check: run basic tests for `zstd` cli\n.PHONY: check\ncheck:\n\t$(Q)$(MAKE) -C $(TESTDIR) $@\n\n.PHONY: automated_benchmarking\nautomated_benchmarking:\n\t$(MAKE) -C $(TESTDIR) $@\n\n.PHONY: benchmarking\nbenchmarking: automated_benchmarking\n\n## examples: build all examples in `examples/` directory\n.PHONY: examples\nexamples: lib\n\t$(MAKE) -C examples all\n\n## manual: generate API documentation in html format\n.PHONY: manual\nmanual:\n\t$(MAKE) -C contrib/gen_html $@\n\n## man: generate man page\n.PHONY: man\nman:\n\t$(MAKE) -C programs $@\n\n## contrib: build all supported projects in `/contrib` directory\n.PHONY: contrib\ncontrib: lib\n\t$(MAKE) -C contrib/pzstd all\n\t$(MAKE) -C contrib/seekable_format/examples all\n\t$(MAKE) -C contrib/seekable_format/tests test\n\t$(MAKE) -C contrib/largeNbDicts all\n\t$(MAKE) -C contrib/externalSequenceProducer all\n\tcd build/single_file_libs/ ; ./build_decoder_test.sh\n\tcd build/single_file_libs/ ; ./build_library_test.sh\n\n.PHONY: cleanTabs\ncleanTabs:\n\tcd contrib; ./cleanTabs\n\n.PHONY: clean\nclean:\n\t$(Q)$(MAKE) -C $(ZSTDDIR) $@ > $(VOID)\n\t$(Q)$(MAKE) -C $(PRGDIR) $@ > $(VOID)\n\t$(Q)$(MAKE) -C $(TESTDIR) $@ > $(VOID)\n\t$(Q)$(MAKE) -C $(ZWRAPDIR) $@ > $(VOID)\n\t$(Q)$(MAKE) -C examples/ $@ > $(VOID)\n\t$(Q)$(MAKE) -C contrib/gen_html $@ > $(VOID)\n\t$(Q)$(MAKE) -C contrib/pzstd $@ > $(VOID)\n\t$(Q)$(MAKE) -C contrib/seekable_format/examples $@ > $(VOID)\n\t$(Q)$(MAKE) -C contrib/seekable_format/tests $@ > $(VOID)\n\t$(Q)$(MAKE) -C contrib/largeNbDicts $@ > $(VOID)\n\t$(Q)$(MAKE) -C contrib/externalSequenceProducer $@ > $(VOID)\n\t$(Q)$(RM) zstd$(EXT) zstdmt$(EXT) tmp*\n\t$(Q)$(RM) -r lz4 cmakebuild mesonbuild install\n\t@echo Cleaning completed\n\nLIBZSTD_MK_DIR = $(ZSTDDIR)\ninclude $(LIBZSTD_MK_DIR)/install_oses.mk # UNAME, INSTALL_OS_LIST\n\n#------------------------------------------------------------------------------\n# make install is validated only for Linux, macOS, Hurd and some BSD targets\n#------------------------------------------------------------------------------\nifneq (,$(filter $(INSTALL_OS_LIST),$(UNAME)))\n\nHOST_OS = POSIX\n\nMKDIR ?= mkdir -p\n\nHAVE_COLORNEVER = $(shell echo a | egrep --color=never a > /dev/null 2> /dev/null && echo 1 || echo 0)\nEGREP_OPTIONS ?=\nifeq ($(HAVE_COLORNEVER), 1)\nEGREP_OPTIONS += --color=never\nendif\nEGREP = egrep $(EGREP_OPTIONS)\n\n# Print a two column output of targets and their description. To add a target description, put a\n# comment in the Makefile with the format \"## <TARGET>: <DESCRIPTION>\".  For example:\n#\n## list: Print all targets and their descriptions (if provided)\n.PHONY: list\nlist:\n\t$(Q)TARGETS=$$($(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null \\\n\t\t| awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ \"^[#.]\") {print $$1}}' \\\n\t\t| $(EGREP) -v  -e '^[^[:alnum:]]' | sort); \\\n\t{ \\\n\t    printf \"Target Name\\tDescription\\n\"; \\\n\t    printf \"%0.s-\" {1..16}; printf \"\\t\"; printf \"%0.s-\" {1..40}; printf \"\\n\"; \\\n\t    for target in $$TARGETS; do \\\n\t        line=$$($(EGREP) \"^##[[:space:]]+$$target:\" $(lastword $(MAKEFILE_LIST))); \\\n\t        description=$$(echo $$line | awk '{i=index($$0,\":\"); print substr($$0,i+1)}' | xargs); \\\n\t        printf \"$$target\\t$$description\\n\"; \\\n\t    done \\\n\t} | column -t -s $$'\\t'\n\n.PHONY: install armtest usan asan uasan msan asan32\ninstall:\n\t$(Q)$(MAKE) -C $(ZSTDDIR) $@\n\t$(Q)$(MAKE) -C $(PRGDIR) $@\n\n.PHONY: uninstall\nuninstall:\n\t$(Q)$(MAKE) -C $(ZSTDDIR) $@\n\t$(Q)$(MAKE) -C $(PRGDIR) $@\n\n.PHONY: travis-install\ntravis-install:\n\t$(MAKE) install PREFIX=~/install_test_dir\n\n.PHONY: clangbuild-darwin-fat\nclangbuild-darwin-fat: clean\n\tclang -v\n\tCXX=clang++ CC=clang CFLAGS+=\"-Werror -Wconversion -Wno-sign-conversion -Wdocumentation -arch arm64\" $(MAKE) zstd-release\n\tmv programs/zstd programs/zstd_arm64\n\tCXX=clang++ CC=clang CFLAGS+=\"-Werror -Wconversion -Wno-sign-conversion -Wdocumentation -arch x86_64\" $(MAKE) zstd-release\n\tmv programs/zstd programs/zstd_x64\n\tlipo -create programs/zstd_x64 programs/zstd_arm64 -output programs/zstd\n\n.PHONY: gcc5build gcc6build gcc7build clangbuild m32build armbuild aarch64build ppcbuild ppc64build\ngcc5build: clean\n\tgcc-5 -v\n\tCC=gcc-5 $(MAKE) all MOREFLAGS=\"-Werror $(MOREFLAGS)\"\n\ngcc6build: clean\n\tgcc-6 -v\n\tCC=gcc-6 $(MAKE) all MOREFLAGS=\"-Werror $(MOREFLAGS)\"\n\ngcc7build: clean\n\tgcc-7 -v\n\tCC=gcc-7 $(MAKE) all MOREFLAGS=\"-Werror $(MOREFLAGS)\"\n\nclangbuild: clean\n\tclang -v\n\tCXX=clang++ CC=clang CFLAGS=\"-Werror -Wconversion -Wno-sign-conversion -Wdocumentation\" $(MAKE) all\n\nm32build: clean\n\tgcc -v\n\t$(MAKE) all32\n\narmbuild: clean\n\tCC=arm-linux-gnueabi-gcc CFLAGS=\"-Werror\" $(MAKE) allzstd\n\naarch64build: clean\n\tCC=aarch64-linux-gnu-gcc CFLAGS=\"-Werror -O0\" $(MAKE) allzstd\n\nppcbuild: clean\n\tCC=powerpc-linux-gnu-gcc CFLAGS=\"-m32 -Wno-attributes -Werror\" $(MAKE) -j allzstd\n\nppc64build: clean\n\tCC=powerpc-linux-gnu-gcc CFLAGS=\"-m64 -Werror\" $(MAKE) -j allzstd\n\n.PHONY: armfuzz aarch64fuzz ppcfuzz ppc64fuzz\narmfuzz: clean\n\tCC=arm-linux-gnueabi-gcc QEMU_SYS=qemu-arm-static MOREFLAGS=\"-static $(MOREFLAGS)\" FUZZER_FLAGS=\"--no-big-tests $(FUZZER_FLAGS)\" $(MAKE) -C $(TESTDIR) fuzztest\n\naarch64fuzz: clean\n\tld -v\n\tCC=aarch64-linux-gnu-gcc QEMU_SYS=qemu-aarch64-static MOREFLAGS=\"-static $(MOREFLAGS)\" FUZZER_FLAGS=\"--no-big-tests $(FUZZER_FLAGS)\" $(MAKE) -C $(TESTDIR) fuzztest\n\nppcfuzz: clean\n\tCC=powerpc-linux-gnu-gcc QEMU_SYS=qemu-ppc-static MOREFLAGS=\"-static $(MOREFLAGS)\" FUZZER_FLAGS=\"--no-big-tests $(FUZZER_FLAGS)\" $(MAKE) -C $(TESTDIR) fuzztest\n\nppc64fuzz: clean\n\tCC=powerpc-linux-gnu-gcc QEMU_SYS=qemu-ppc64-static MOREFLAGS=\"-m64 -static $(MOREFLAGS)\" FUZZER_FLAGS=\"--no-big-tests $(FUZZER_FLAGS)\" $(MAKE) -C $(TESTDIR) fuzztest\n\n.PHONY: cxxtest gcc5test gcc6test armtest aarch64test ppctest ppc64test\ncxxtest: CXXFLAGS += -Wall -Wextra -Wundef -Wshadow -Wcast-align -Werror\ncxxtest: clean\n\t$(MAKE) -C $(PRGDIR) all CC=\"$(CXX) -Wno-deprecated\" CFLAGS=\"$(CXXFLAGS)\"   # adding -Wno-deprecated to avoid clang++ warning on dealing with C files directly\n\ngcc5test: clean\n\tgcc-5 -v\n\t$(MAKE) all CC=gcc-5 MOREFLAGS=\"-Werror $(MOREFLAGS)\"\n\ngcc6test: clean\n\tgcc-6 -v\n\t$(MAKE) all CC=gcc-6 MOREFLAGS=\"-Werror $(MOREFLAGS)\"\n\narmtest: clean\n\t$(MAKE) -C $(TESTDIR) datagen   # use native, faster\n\t$(MAKE) -C $(TESTDIR) test CC=arm-linux-gnueabi-gcc QEMU_SYS=qemu-arm-static ZSTDRTTEST= MOREFLAGS=\"-Werror -static $(MOREFLAGS)\" FUZZER_FLAGS=\"--no-big-tests $(FUZZER_FLAGS)\"\n\naarch64test:\n\t$(MAKE) -C $(TESTDIR) datagen   # use native, faster\n\t$(MAKE) -C $(TESTDIR) test CC=aarch64-linux-gnu-gcc QEMU_SYS=qemu-aarch64-static ZSTDRTTEST= MOREFLAGS=\"-Werror -static $(MOREFLAGS)\" FUZZER_FLAGS=\"--no-big-tests $(FUZZER_FLAGS)\"\n\nppctest: clean\n\t$(MAKE) -C $(TESTDIR) datagen   # use native, faster\n\t$(MAKE) -C $(TESTDIR) test CC=powerpc-linux-gnu-gcc QEMU_SYS=qemu-ppc-static ZSTDRTTEST= MOREFLAGS=\"-Werror -Wno-attributes -static $(MOREFLAGS)\" FUZZER_FLAGS=\"--no-big-tests $(FUZZER_FLAGS)\"\n\nppc64test: clean\n\t$(MAKE) -C $(TESTDIR) datagen   # use native, faster\n\t$(MAKE) -C $(TESTDIR) test CC=powerpc-linux-gnu-gcc QEMU_SYS=qemu-ppc64-static ZSTDRTTEST= MOREFLAGS=\"-m64 -static $(MOREFLAGS)\" FUZZER_FLAGS=\"--no-big-tests $(FUZZER_FLAGS)\"\n\n.PHONY: arm-ppc-compilation\narm-ppc-compilation:\n\t$(MAKE) -C $(PRGDIR) clean zstd CC=arm-linux-gnueabi-gcc QEMU_SYS=qemu-arm-static ZSTDRTTEST= MOREFLAGS=\"-Werror -static $(MOREFLAGS)\"\n\t$(MAKE) -C $(PRGDIR) clean zstd CC=aarch64-linux-gnu-gcc QEMU_SYS=qemu-aarch64-static ZSTDRTTEST= MOREFLAGS=\"-Werror -static $(MOREFLAGS)\"\n\t$(MAKE) -C $(PRGDIR) clean zstd CC=powerpc-linux-gnu-gcc QEMU_SYS=qemu-ppc-static ZSTDRTTEST= MOREFLAGS=\"-Werror -Wno-attributes -static $(MOREFLAGS)\"\n\t$(MAKE) -C $(PRGDIR) clean zstd CC=powerpc-linux-gnu-gcc QEMU_SYS=qemu-ppc64-static ZSTDRTTEST= MOREFLAGS=\"-m64 -static $(MOREFLAGS)\"\n\nregressiontest:\n\t$(MAKE) -C $(FUZZDIR) regressiontest\n\nuasanregressiontest:\n\t$(MAKE) -C $(FUZZDIR) regressiontest CC=clang CXX=clang++ CFLAGS=\"-O3 -fsanitize=address,undefined -Werror\" CXXFLAGS=\"-O3 -fsanitize=address,undefined -Werror\"\n\nmsanregressiontest:\n\t$(MAKE) -C $(FUZZDIR) regressiontest CC=clang CXX=clang++ CFLAGS=\"-O3 -fsanitize=memory -Werror\" CXXFLAGS=\"-O3 -fsanitize=memory -Werror\"\n\nupdate_regressionResults : REGRESS_RESULTS_DIR := /tmp/regress_results_dir/\nupdate_regressionResults:\n\t$(MAKE) -j -C programs zstd\n\t$(MAKE) -j -C tests/regression test\n\t$(RM) -r $(REGRESS_RESULTS_DIR)\n\t$(MKDIR) $(REGRESS_RESULTS_DIR)\n\t./tests/regression/test                         \\\n        --cache  tests/regression/cache             \\\n        --output $(REGRESS_RESULTS_DIR)/results.csv \\\n        --zstd   programs/zstd\n\techo \"Showing results differences\"\n\t! diff tests/regression/results.csv $(REGRESS_RESULTS_DIR)/results.csv\n\techo \"Updating results.csv\"\n\t$(CP) $(REGRESS_RESULTS_DIR)/results.csv tests/regression/results.csv\n\n\n# run UBsan with -fsanitize-recover=pointer-overflow\n# this only works with recent compilers such as gcc 8+\nusan: clean\n\t$(MAKE) test CC=clang MOREFLAGS=\"-g -fno-sanitize-recover=all -fsanitize=undefined -Werror $(MOREFLAGS)\"\n\nasan: clean\n\t$(MAKE) test CC=clang MOREFLAGS=\"-g -fsanitize=address -Werror $(MOREFLAGS)\"\n\nasan-%: clean\n\tLDFLAGS=-fuse-ld=gold MOREFLAGS=\"-g -fno-sanitize-recover=all -fsanitize=address -Werror $(MOREFLAGS)\" $(MAKE) -C $(TESTDIR) $*\n\nmsan: clean\n\t$(MAKE) test CC=clang MOREFLAGS=\"-g -fsanitize=memory -fno-omit-frame-pointer -Werror $(MOREFLAGS)\" HAVE_LZMA=0   # datagen.c fails this test for no obvious reason\n\nmsan-%:\n\t$(MAKE) clean\n\tLDFLAGS=-fuse-ld=gold MOREFLAGS=\"-g -fno-sanitize-recover=all -fsanitize=memory -fno-omit-frame-pointer -Werror $(MOREFLAGS)\" FUZZER_FLAGS=\"--no-big-tests $(FUZZER_FLAGS)\" $(MAKE) -j -C $(TESTDIR) HAVE_LZMA=0 $*\n\nasan32: clean\n\t$(MAKE) -C $(TESTDIR) test32 CC=clang MOREFLAGS=\"-g -fsanitize=address $(MOREFLAGS)\"\n\nuasan: clean\n\t$(MAKE) test CC=clang MOREFLAGS=\"-g -fno-sanitize-recover=all -fsanitize=address,undefined -Werror $(MOREFLAGS)\"\n\nuasan-%: clean\n\tLDFLAGS=-fuse-ld=gold MOREFLAGS=\"-g -fno-sanitize-recover=all -fsanitize=address,undefined -Werror $(MOREFLAGS)\" $(MAKE) -C $(TESTDIR) $*\n\ntsan-%: clean\n\tLDFLAGS=-fuse-ld=gold MOREFLAGS=\"-g -fno-sanitize-recover=all -fsanitize=thread -Werror $(MOREFLAGS)\" $(MAKE) -C $(TESTDIR) $* FUZZER_FLAGS=\"--no-big-tests $(FUZZER_FLAGS)\"\n\n.PHONY: apt-install\napt-install:\n\t# TODO: uncomment once issue 3011 is resolved and remove hack from Github Actions .yml\n\t# sudo apt-get update\n\tsudo apt-get -yq --no-install-suggests --no-install-recommends --force-yes install $(APT_PACKAGES)\n\n.PHONY: apt-add-repo\napt-add-repo:\n\tsudo add-apt-repository -y ppa:ubuntu-toolchain-r/test\n\tsudo apt-get update -y -qq\n\n.PHONY: ppcinstall arminstall valgrindinstall libc6install gcc6install gcc7install gcc8install gpp6install clang38install\nppcinstall:\n\tAPT_PACKAGES=\"qemu-system-ppc qemu-user-static gcc-powerpc-linux-gnu\" $(MAKE) apt-install\n\narminstall:\n\tAPT_PACKAGES=\"qemu-system-arm qemu-user-static gcc-arm-linux-gnueabi libc6-dev-armel-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross\" $(MAKE) apt-install\n\nvalgrindinstall:\n\tAPT_PACKAGES=\"valgrind\" $(MAKE) apt-install\n\nlibc6install:\n\tAPT_PACKAGES=\"libc6-dev-i386 gcc-multilib\" $(MAKE) apt-install\n\ngcc6install: apt-add-repo\n\tAPT_PACKAGES=\"libc6-dev-i386 gcc-multilib gcc-6 gcc-6-multilib\" $(MAKE) apt-install\n\ngcc7install: apt-add-repo\n\tAPT_PACKAGES=\"libc6-dev-i386 gcc-multilib gcc-7 gcc-7-multilib\" $(MAKE) apt-install\n\ngcc8install: apt-add-repo\n\tAPT_PACKAGES=\"libc6-dev-i386 gcc-multilib gcc-8 gcc-8-multilib\" $(MAKE) apt-install\n\ngpp6install: apt-add-repo\n\tAPT_PACKAGES=\"libc6-dev-i386 g++-multilib gcc-6 g++-6 g++-6-multilib\" $(MAKE) apt-install\n\nclang38install:\n\tAPT_PACKAGES=\"clang-3.8\" $(MAKE) apt-install\n\nendif\n\n\nifneq (,$(filter MSYS%,$(shell sh -c 'MSYSTEM=\"MSYS\" uname') ))\nHOST_OS = MSYS\nendif\n\n#------------------------------------------------------------------------\n# target specific tests\n#------------------------------------------------------------------------\nifneq (,$(filter MSYS POSIX,$(HOST_OS)))\n\nCMAKE ?= cmake\nCMAKE_PARAMS = -DZSTD_BUILD_CONTRIB:BOOL=ON -DZSTD_BUILD_STATIC:BOOL=ON -DZSTD_BUILD_TESTS:BOOL=ON -DZSTD_ZLIB_SUPPORT:BOOL=ON -DZSTD_LZMA_SUPPORT:BOOL=ON\n\nifneq (,$(filter MSYS%,$(shell sh -c 'MSYSTEM=\"MSYS\" uname')))\nCMAKE_PARAMS = -G\"MSYS Makefiles\" -DZSTD_MULTITHREAD_SUPPORT:BOOL=OFF -DZSTD_BUILD_STATIC:BOOL=ON -DZSTD_BUILD_TESTS:BOOL=ON\nendif\n\n.PHONY: cmakebuild\ncmakebuild:\n\t$(CMAKE) --version\n\t$(RM) -r cmakebuild install\n\t$(MKDIR) cmakebuild install\n\tcd cmakebuild; $(CMAKE) -Wdev -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_FLAGS=\"-Werror -O0\" -DCMAKE_INSTALL_PREFIX=install $(CMAKE_PARAMS) ../build/cmake\n\t$(CMAKE) --build cmakebuild --target install -- -j V=1\n\tcd cmakebuild; ctest -V -L Medium\n\nMESON ?= meson\nNINJA ?= ninja\n\n.PHONY: mesonbuild\nmesonbuild:\n\t$(MESON) setup \\\n\t\t--buildtype=debugoptimized \\\n\t\t-Db_lundef=false \\\n\t\t-Dauto_features=enabled \\\n\t\t-Dbin_programs=true \\\n\t\t-Dbin_tests=true \\\n\t\t-Dbin_contrib=true \\\n\t\t-Ddefault_library=both \\\n\t\tbuild/meson mesonbuild\n\t$(NINJA) -C mesonbuild/\n\t$(MESON) test -C mesonbuild/ --print-errorlogs\n\t$(MESON) install -C mesonbuild --destdir staging/\n\n.PHONY: c89build gnu90build c99build gnu99build c11build bmix64build bmix32build bmi32build staticAnalyze\nc89build: clean\n\t$(CC) -v\n\tCFLAGS=\"-std=c89 -Werror -Wno-attributes -Wpedantic -Wno-long-long -Wno-variadic-macros -O0\" $(MAKE) lib zstd\n\ngnu90build: clean\n\t$(CC) -v\n\tCFLAGS=\"-std=gnu90 -Werror -O0\" $(MAKE) allmost\n\nc99build: clean\n\t$(CC) -v\n\tCFLAGS=\"-std=c99 -Werror -O0\" $(MAKE) allmost\n\ngnu99build: clean\n\t$(CC) -v\n\tCFLAGS=\"-std=gnu99 -Werror -O0\" $(MAKE) allmost\n\nc11build: clean\n\t$(CC) -v\n\tCFLAGS=\"-std=c11 -Werror -O0\" $(MAKE) allmost\n\nbmix64build: clean\n\t$(CC) -v\n\tCFLAGS=\"-O3 -mbmi -Werror\" $(MAKE) -C $(TESTDIR) test\n\nbmix32build: clean\n\t$(CC) -v\n\tCFLAGS=\"-O3 -mbmi -mx32 -Werror\" $(MAKE) -C $(TESTDIR) test\n\nbmi32build: clean\n\t$(CC) -v\n\tCFLAGS=\"-O3 -mbmi -m32 -Werror\" $(MAKE) -C $(TESTDIR) test\n\n# static analyzer test uses clang's scan-build\n# does not analyze zlibWrapper, due to detected issues in zlib source code\nstaticAnalyze: SCANBUILD ?= scan-build\nstaticAnalyze:\n\t$(CC) -v\n\tCC=$(CC) CPPFLAGS=-g $(SCANBUILD) --status-bugs -v $(MAKE) zstd\nendif\n"
  },
  {
    "path": "Package.swift",
    "content": "// swift-tools-version:5.0\n// The swift-tools-version declares the minimum version of Swift required to build this package.\n\nimport PackageDescription\n\nlet package = Package(\n    name: \"zstd\",\n    platforms: [\n        .macOS(.v10_10), .iOS(.v9), .tvOS(.v9)\n    ],\n    products: [\n        // Products define the executables and libraries a package produces, and make them visible to other packages.\n        .library(\n            name: \"libzstd\",\n            targets: [ \"libzstd\" ])\n    ],\n    dependencies: [\n        // Dependencies declare other packages that this package depends on.\n        // .package(url: /* package url */, from: \"1.0.0\"),\n    ],\n    targets: [\n        // Targets are the basic building blocks of a package. A target can define a module or a test suite.\n        // Targets can depend on other targets in this package, and on products in packages this package depends on.\n        .target(\n            name: \"libzstd\",\n            path: \"lib\",\n            sources: [ \"common\", \"compress\", \"decompress\", \"dictBuilder\" ],\n            publicHeadersPath: \".\",\n            cSettings: [\n                .headerSearchPath(\".\")\n            ])\n    ],\n    swiftLanguageVersions: [.v5],\n    cLanguageStandard: .gnu11,\n    cxxLanguageStandard: .gnucxx14\n)\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\"><img src=\"https://raw.githubusercontent.com/facebook/zstd/dev/doc/images/zstd_logo86.png\" alt=\"Zstandard\"></p>\n\n__Zstandard__, or `zstd` as short version, is a fast lossless compression algorithm,\ntargeting real-time compression scenarios at zlib-level and better compression ratios.\nIt's backed by a very fast entropy stage, provided by [Huff0 and FSE library](https://github.com/Cyan4973/FiniteStateEntropy).\n\nZstandard's format is stable and documented in [RFC8878](https://datatracker.ietf.org/doc/html/rfc8878). Multiple independent implementations are already available.\nThis repository represents the reference implementation, provided as an open-source dual [BSD](LICENSE) OR [GPLv2](COPYING) licensed **C** library,\nand a command line utility producing and decoding `.zst`, `.gz`, `.xz` and `.lz4` files.\nShould your project require another programming language,\na list of known ports and bindings is provided on [Zstandard homepage](https://facebook.github.io/zstd/#other-languages).\n\n**Development branch status:**\n\n[![Build Status][travisDevBadge]][travisLink]\n[![Build status][CircleDevBadge]][CircleLink]\n[![Build status][CirrusDevBadge]][CirrusLink]\n[![Fuzzing Status][OSSFuzzBadge]][OSSFuzzLink]\n\n[travisDevBadge]: https://api.travis-ci.com/facebook/zstd.svg?branch=dev \"Continuous Integration test suite\"\n[travisLink]: https://travis-ci.com/facebook/zstd\n[CircleDevBadge]: https://circleci.com/gh/facebook/zstd/tree/dev.svg?style=shield \"Short test suite\"\n[CircleLink]: https://circleci.com/gh/facebook/zstd\n[CirrusDevBadge]: https://api.cirrus-ci.com/github/facebook/zstd.svg?branch=dev\n[CirrusLink]: https://cirrus-ci.com/github/facebook/zstd\n[OSSFuzzBadge]: https://oss-fuzz-build-logs.storage.googleapis.com/badges/zstd.svg\n[OSSFuzzLink]: https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:zstd\n\n## Benchmarks\n\nFor reference, several fast compression algorithms were tested and compared\non a desktop featuring a Core i7-9700K CPU @ 4.9GHz\nand running Ubuntu 24.04 (`Linux 6.8.0-53-generic`),\nusing [lzbench], an open-source in-memory benchmark by @inikep\ncompiled with [gcc] 14.2.0,\non the [Silesia compression corpus].\n\n[lzbench]: https://github.com/inikep/lzbench\n[Silesia compression corpus]: https://sun.aei.polsl.pl//~sdeor/index.php?page=silesia\n[gcc]: https://gcc.gnu.org/\n\n| Compressor name         | Ratio | Compression| Decompress.|\n| ---------------         | ------| -----------| ---------- |\n| **zstd 1.5.7 -1**       | 2.896 |   510 MB/s |  1550 MB/s |\n| brotli 1.1.0 -1         | 2.883 |   290 MB/s |   425 MB/s |\n| [zlib] 1.3.1 -1         | 2.743 |   105 MB/s |   390 MB/s |\n| **zstd 1.5.7 --fast=1** | 2.439 |   545 MB/s |  1850 MB/s |\n| quicklz 1.5.0 -1        | 2.238 |   520 MB/s |   750 MB/s |\n| **zstd 1.5.7 --fast=4** | 2.146 |   665 MB/s |  2050 MB/s |\n| lzo1x 2.10 -1           | 2.106 |   650 MB/s |   780 MB/s |\n| [lz4] 1.10.0            | 2.101 |   675 MB/s |  3850 MB/s |\n| snappy 1.2.1            | 2.089 |   520 MB/s |  1500 MB/s |\n| lzf 3.6 -1              | 2.077 |   410 MB/s |   820 MB/s |\n\n[zlib]: https://www.zlib.net/\n[lz4]: https://lz4.github.io/lz4/\n\nThe negative compression levels, specified with `--fast=#`,\noffer faster compression and decompression speed\nat the cost of compression ratio.\n\nZstd can also offer stronger compression ratios at the cost of compression speed.\nSpeed vs Compression trade-off is configurable by small increments.\nDecompression speed is preserved and remains roughly the same at all settings,\na property shared by most LZ compression algorithms, such as [zlib] or lzma.\n\nThe following tests were run\non a server running Linux Debian (`Linux version 4.14.0-3-amd64`)\nwith a Core i7-6700K CPU @ 4.0GHz,\nusing [lzbench], an open-source in-memory benchmark by @inikep\ncompiled with [gcc] 7.3.0,\non the [Silesia compression corpus].\n\nCompression Speed vs Ratio | Decompression Speed\n---------------------------|--------------------\n![Compression Speed vs Ratio](doc/images/CSpeed2.png \"Compression Speed vs Ratio\") | ![Decompression Speed](doc/images/DSpeed3.png \"Decompression Speed\")\n\nA few other algorithms can produce higher compression ratios at slower speeds, falling outside of the graph.\nFor a larger picture including slow modes, [click on this link](doc/images/DCspeed5.png).\n\n\n## The case for Small Data compression\n\nPrevious charts provide results applicable to typical file and stream scenarios (several MB). Small data comes with different perspectives.\n\nThe smaller the amount of data to compress, the more difficult it is to compress. This problem is common to all compression algorithms, and reason is, compression algorithms learn from past data how to compress future data. But at the beginning of a new data set, there is no \"past\" to build upon.\n\nTo solve this situation, Zstd offers a __training mode__, which can be used to tune the algorithm for a selected type of data.\nTraining Zstandard is achieved by providing it with a few samples (one file per sample). The result of this training is stored in a file called \"dictionary\", which must be loaded before compression and decompression.\nUsing this dictionary, the compression ratio achievable on small data improves dramatically.\n\nThe following example uses the `github-users` [sample set](https://github.com/facebook/zstd/releases/tag/v1.1.3), created from [github public API](https://developer.github.com/v3/users/#get-all-users).\nIt consists of roughly 10K records weighing about 1KB each.\n\nCompression Ratio | Compression Speed | Decompression Speed\n------------------|-------------------|--------------------\n![Compression Ratio](doc/images/dict-cr.png \"Compression Ratio\") | ![Compression Speed](doc/images/dict-cs.png \"Compression Speed\") | ![Decompression Speed](doc/images/dict-ds.png \"Decompression Speed\")\n\n\nThese compression gains are achieved while simultaneously providing _faster_ compression and decompression speeds.\n\nTraining works if there is some correlation in a family of small data samples. The more data-specific a dictionary is, the more efficient it is (there is no _universal dictionary_).\nHence, deploying one dictionary per type of data will provide the greatest benefits.\nDictionary gains are mostly effective in the first few KB. Then, the compression algorithm will gradually use previously decoded content to better compress the rest of the file.\n\n### Dictionary compression How To:\n\n1. Create the dictionary\n\n   `zstd --train FullPathToTrainingSet/* -o dictionaryName`\n\n2. Compress with dictionary\n\n   `zstd -D dictionaryName FILE`\n\n3. Decompress with dictionary\n\n   `zstd -D dictionaryName --decompress FILE.zst`\n\n\n## Build instructions\n\n`make` is the main build system of this project.\nIt is the reference, and other build systems are periodically updated to stay compatible.\nHowever, small drifts and feature differences can be present, since perfect synchronization is difficult.\nFor this reason, when your build system allows it, prefer employing `make`.\n\n### Makefile\n\nAssuming your system supports standard `make` (or `gmake`),\njust invoking `make` in root directory generates `zstd` cli at root,\nand also generates `libzstd` into `lib/`.\n\nOther standard targets include:\n- `make install` : install zstd cli, library and man pages\n- `make check` : run `zstd`, test its essential behavior on local platform\n\nThe `Makefile` follows the [GNU Standard Makefile conventions](https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html),\nallowing staged install, standard compilation flags, directory variables and command variables.\n\nFor advanced use cases, specialized flags which control binary generation and installation paths are documented\nin [`lib/README.md`](lib/README.md#modular-build) for the `libzstd` library\nand in [`programs/README.md`](programs/README.md#compilation-variables) for the `zstd` CLI.\n\n### cmake\n\nA `cmake` project generator is available for generating Makefiles or other build scripts\nto create the `zstd` binary as well as `libzstd` dynamic and static libraries.\nThe repository root now contains a minimal `CMakeLists.txt` that forwards to `build/cmake`,\nso you can configure the project with a standard `cmake -S .` invocation,\nwhile the historical `cmake -S build/cmake` entry point remains fully supported.\n\n```bash\ncmake -S . -B build-cmake\ncmake --build build-cmake\n```\n\nBy default, `CMAKE_BUILD_TYPE` is set to `Release`.\n\n#### Support for Fat (Universal2) Output\n\n`zstd` can be built and installed with support for both Apple Silicon (M1/M2) as well as Intel by using CMake's Universal2 support.\nTo perform a Fat/Universal2 build and install use the following commands:\n\n```bash\ncmake -S . -B build-cmake-debug -G Ninja -DCMAKE_OSX_ARCHITECTURES=\"x86_64;x86_64h;arm64\"\ncd build-cmake-debug\nninja\nsudo ninja install\n```\n\n### Meson\n\nA Meson project is provided within [`build/meson`](build/meson). Follow\nbuild instructions in that directory.\n\nYou can also take a look at [`.travis.yml`](.travis.yml) file for an\nexample about how Meson is used to build this project.\n\nNote that default build type is **release**.\n\n### VCPKG\nYou can build and install zstd [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager:\n\n    git clone https://github.com/Microsoft/vcpkg.git\n    cd vcpkg\n    ./bootstrap-vcpkg.sh\n    ./vcpkg integrate install\n    ./vcpkg install zstd\n\nThe zstd port in vcpkg is kept up to date by Microsoft team members and community contributors.\nIf the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.\n\n### Conan\n\nYou can install pre-built binaries for zstd or build it from source using [Conan](https://conan.io/). Use the following command:\n\n```bash\nconan install --requires=\"zstd/[*]\" --build=missing\n```\n\nThe zstd Conan recipe is kept up to date by Conan maintainers and community contributors.\nIf the version is out of date, please [create an issue or pull request](https://github.com/conan-io/conan-center-index) on the ConanCenterIndex repository.\n\n### Visual Studio (Windows)\n\nGoing into `build` directory, you will find additional possibilities:\n- Projects for Visual Studio 2008 and 2010.\n  + VS2010 project is compatible with VS2012, VS2013, VS2015 and VS2017.\n- Automated build scripts for Visual compiler by [@KrzysFR](https://github.com/KrzysFR), in `build/VS_scripts`,\n  which will build `zstd` cli and `libzstd` library without any need to open Visual Studio solution.\n- It is now recommended to generate Visual Studio solutions from `cmake`\n\n### Buck\n\nYou can build the zstd binary via buck by executing: `buck build programs:zstd` from the root of the repo.\nThe output binary will be in `buck-out/gen/programs/`.\n\n### Bazel\n\nYou can integrate zstd into your Bazel project by using the module hosted on the [Bazel Central Repository](https://registry.bazel.build/modules/zstd).\n\n## Testing\n\nYou can run quick local smoke tests by running `make check`.\nIf you can't use `make`, execute the `playTest.sh` script from the `src/tests` directory.\nTwo env variables `$ZSTD_BIN` and `$DATAGEN_BIN` are needed for the test script to locate the `zstd` and `datagen` binary.\nFor information on CI testing, please refer to `TESTING.md`.\n\n## Status\n\nZstandard is deployed within Meta and many other large cloud infrastructures,\nto compress humongous amounts of data in various formats and use cases.\nIt is also continuously fuzzed for security issues by Google's [oss-fuzz](https://github.com/google/oss-fuzz/tree/master/projects/zstd) program.\n\n## License\n\nZstandard is dual-licensed under [BSD](LICENSE) OR [GPLv2](COPYING).\n\n## Contributing\n\nThe `dev` branch is the one where all contributions are merged before reaching `release`.\nDirect commit to `release` are not permitted.\nFor more information, please read [CONTRIBUTING](CONTRIBUTING.md).\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Reporting and Fixing Security Issues\n\nPlease do not open GitHub issues or pull requests - this makes the problem immediately visible to everyone, including malicious actors. Security issues in this open source project can be safely reported via the Meta Bug Bounty program:\n\nhttps://www.facebook.com/whitehat\n\nMeta's security team will triage your report and determine whether or not is it eligible for a bounty under our program.\n\n# Receiving Vulnerability Notifications\n\nIn the case that a significant security vulnerability is reported to us or discovered by us---without being publicly known---we will, at our discretion, notify high-profile, high-exposure users of Zstandard ahead of our public disclosure of the issue and associated fix.\n\nIf you believe your project would benefit from inclusion in this list, please reach out to one of the maintainers.\n\n<!-- Note to maintainers: this list is kept [here](https://fburl.com/wiki/cgc1l62x). -->\n"
  },
  {
    "path": "TESTING.md",
    "content": "Testing\n=======\n\nZstandard CI testing is split up into three sections:\nshort, medium, and long tests.\n\nShort Tests\n-----------\nShort tests run on CircleCI for new commits on every branch and pull request.\nThey consist of the following tests:\n- Compilation on all supported targets (x86, x86_64, ARM, AArch64, PowerPC, and PowerPC64)\n- Compilation on various versions of gcc, clang, and g++\n- `tests/playTests.sh` on x86_64, without the tests on long data (CLI tests)\n- Small tests (`tests/legacy.c`, `tests/longmatch.c`) on x64_64\n\nMedium Tests\n------------\nMedium tests run on every commit and pull request to `dev` branch, on TravisCI.\nThey consist of the following tests:\n- The following tests run with UBsan and Asan on x86_64 and x86, as well as with\n  Msan on x86_64\n  - `tests/playTests.sh --test-large-data`\n  - Fuzzer tests: `tests/fuzzer.c`, `tests/zstreamtest.c`, and `tests/decodecorpus.c`\n- `tests/zstreamtest.c` under Tsan (streaming mode, including multithreaded mode)\n- Valgrind Test (`make -C tests test-valgrind`) (testing CLI and fuzzer under `valgrind`)\n- Fuzzer tests (see above) on ARM, AArch64, PowerPC, and PowerPC64\n\nLong Tests\n----------\nLong tests run on all commits to `release` branch,\nand once a day on the current version of `dev` branch,\non TravisCI.\nThey consist of the following tests:\n- Entire test suite (including fuzzers and some other specialized tests) on:\n  - x86_64 and x86 with UBsan and Asan\n  - x86_64 with Msan\n  - ARM, AArch64, PowerPC, and PowerPC64\n- Streaming mode fuzzer with Tsan (for the `zstdmt` testing)\n- ZlibWrapper tests, including under valgrind\n- Versions test (ensuring `zstd` can decode files from all previous versions)\n- `pzstd` with asan and tsan, as well as in 32-bits mode\n- Testing `zstd` with legacy mode off\n- Entire test suite and make install on macOS\n"
  },
  {
    "path": "contrib/VS2005/README.md",
    "content": "## Project Support Notice\n\nThe VS2005 Project directory has been moved to the contrib directory in order to indicate that it will no longer be supported.\n"
  },
  {
    "path": "contrib/VS2005/fullbench/fullbench.vcproj",
    "content": "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\r\n<VisualStudioProject\r\n\tProjectType=\"Visual C++\"\r\n\tVersion=\"8.00\"\r\n\tName=\"fullbench\"\r\n\tProjectGUID=\"{CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}\"\r\n\tRootNamespace=\"fullbench\"\r\n\tKeyword=\"Win32Proj\"\r\n\t>\r\n\t<Platforms>\r\n\t\t<Platform\r\n\t\t\tName=\"Win32\"\r\n\t\t/>\r\n\t\t<Platform\r\n\t\t\tName=\"x64\"\r\n\t\t/>\r\n\t</Platforms>\r\n\t<ToolFiles>\r\n\t</ToolFiles>\r\n\t<Configurations>\r\n\t\t<Configuration\r\n\t\t\tName=\"Debug|Win32\"\r\n\t\t\tOutputDirectory=\"$(SolutionDir)bin\\$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tIntermediateDirectory=\"$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tConfigurationType=\"1\"\r\n\t\t\tCharacterSet=\"2\"\r\n\t\t\t>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreBuildEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCustomBuildTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCMIDLTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCLCompilerTool\"\r\n\t\t\t\tOptimization=\"0\"\r\n\t\t\t\tAdditionalIncludeDirectories=\"$(SolutionDir)..\\..\\lib;$(SolutionDir)..\\..\\lib\\common;$(SolutionDir)..\\..\\lib\\legacy;$(SolutionDir)..\\..\\programs\"\r\n\t\t\t\tPreprocessorDefinitions=\"WIN32;_DEBUG;_CONSOLE\"\r\n\t\t\t\tMinimalRebuild=\"true\"\r\n\t\t\t\tBasicRuntimeChecks=\"3\"\r\n\t\t\t\tRuntimeLibrary=\"3\"\r\n\t\t\t\tUsePrecompiledHeader=\"0\"\r\n\t\t\t\tWarningLevel=\"4\"\r\n\t\t\t\tWarnAsError=\"true\"\r\n\t\t\t\tDebugInformationFormat=\"4\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreLinkEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCLinkerTool\"\r\n\t\t\t\tLinkIncremental=\"2\"\r\n\t\t\t\tGenerateDebugInformation=\"true\"\r\n\t\t\t\tSubSystem=\"1\"\r\n\t\t\t\tTargetMachine=\"1\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCALinkTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManifestTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXDCMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCBscMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCFxCopTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCAppVerifierTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPostBuildEventTool\"\r\n\t\t\t/>\r\n\t\t</Configuration>\r\n\t\t<Configuration\r\n\t\t\tName=\"Release|Win32\"\r\n\t\t\tOutputDirectory=\"$(SolutionDir)bin\\$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tIntermediateDirectory=\"$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tConfigurationType=\"1\"\r\n\t\t\tCharacterSet=\"2\"\r\n\t\t\tWholeProgramOptimization=\"1\"\r\n\t\t\t>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreBuildEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCustomBuildTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCMIDLTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCLCompilerTool\"\r\n\t\t\t\tOptimization=\"2\"\r\n\t\t\t\tEnableIntrinsicFunctions=\"true\"\r\n\t\t\t\tOmitFramePointers=\"true\"\r\n\t\t\t\tAdditionalIncludeDirectories=\"$(SolutionDir)..\\..\\lib;$(SolutionDir)..\\..\\lib\\common;$(SolutionDir)..\\..\\lib\\legacy;$(SolutionDir)..\\..\\programs\"\r\n\t\t\t\tPreprocessorDefinitions=\"WIN32;NDEBUG;_CONSOLE\"\r\n\t\t\t\tRuntimeLibrary=\"0\"\r\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\r\n\t\t\t\tUsePrecompiledHeader=\"0\"\r\n\t\t\t\tWarningLevel=\"4\"\r\n\t\t\t\tDebugInformationFormat=\"3\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreLinkEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCLinkerTool\"\r\n\t\t\t\tLinkIncremental=\"1\"\r\n\t\t\t\tGenerateDebugInformation=\"true\"\r\n\t\t\t\tSubSystem=\"1\"\r\n\t\t\t\tOptimizeReferences=\"2\"\r\n\t\t\t\tEnableCOMDATFolding=\"2\"\r\n\t\t\t\tTargetMachine=\"1\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCALinkTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManifestTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXDCMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCBscMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCFxCopTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCAppVerifierTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPostBuildEventTool\"\r\n\t\t\t/>\r\n\t\t</Configuration>\r\n\t\t<Configuration\r\n\t\t\tName=\"Debug|x64\"\r\n\t\t\tOutputDirectory=\"$(SolutionDir)bin\\$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tIntermediateDirectory=\"$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tConfigurationType=\"1\"\r\n\t\t\tCharacterSet=\"2\"\r\n\t\t\t>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreBuildEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCustomBuildTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCMIDLTool\"\r\n\t\t\t\tTargetEnvironment=\"3\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCLCompilerTool\"\r\n\t\t\t\tOptimization=\"0\"\r\n\t\t\t\tAdditionalIncludeDirectories=\"$(SolutionDir)..\\..\\lib;$(SolutionDir)..\\..\\lib\\common;$(SolutionDir)..\\..\\lib\\legacy;$(SolutionDir)..\\..\\programs\"\r\n\t\t\t\tPreprocessorDefinitions=\"WIN32;_DEBUG;_CONSOLE\"\r\n\t\t\t\tMinimalRebuild=\"true\"\r\n\t\t\t\tBasicRuntimeChecks=\"3\"\r\n\t\t\t\tRuntimeLibrary=\"3\"\r\n\t\t\t\tUsePrecompiledHeader=\"0\"\r\n\t\t\t\tWarningLevel=\"4\"\r\n\t\t\t\tWarnAsError=\"true\"\r\n\t\t\t\tDebugInformationFormat=\"3\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreLinkEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCLinkerTool\"\r\n\t\t\t\tLinkIncremental=\"2\"\r\n\t\t\t\tGenerateDebugInformation=\"true\"\r\n\t\t\t\tSubSystem=\"1\"\r\n\t\t\t\tTargetMachine=\"17\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCALinkTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManifestTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXDCMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCBscMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCFxCopTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCAppVerifierTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPostBuildEventTool\"\r\n\t\t\t/>\r\n\t\t</Configuration>\r\n\t\t<Configuration\r\n\t\t\tName=\"Release|x64\"\r\n\t\t\tOutputDirectory=\"$(SolutionDir)bin\\$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tIntermediateDirectory=\"$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tConfigurationType=\"1\"\r\n\t\t\tCharacterSet=\"2\"\r\n\t\t\tWholeProgramOptimization=\"1\"\r\n\t\t\t>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreBuildEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCustomBuildTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCMIDLTool\"\r\n\t\t\t\tTargetEnvironment=\"3\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCLCompilerTool\"\r\n\t\t\t\tOptimization=\"2\"\r\n\t\t\t\tEnableIntrinsicFunctions=\"true\"\r\n\t\t\t\tOmitFramePointers=\"true\"\r\n\t\t\t\tAdditionalIncludeDirectories=\"$(SolutionDir)..\\..\\lib;$(SolutionDir)..\\..\\lib\\common;$(SolutionDir)..\\..\\lib\\legacy;$(SolutionDir)..\\..\\programs\"\r\n\t\t\t\tPreprocessorDefinitions=\"WIN32;NDEBUG;_CONSOLE\"\r\n\t\t\t\tRuntimeLibrary=\"0\"\r\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\r\n\t\t\t\tUsePrecompiledHeader=\"0\"\r\n\t\t\t\tWarningLevel=\"4\"\r\n\t\t\t\tDebugInformationFormat=\"3\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreLinkEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCLinkerTool\"\r\n\t\t\t\tLinkIncremental=\"1\"\r\n\t\t\t\tGenerateDebugInformation=\"true\"\r\n\t\t\t\tSubSystem=\"1\"\r\n\t\t\t\tOptimizeReferences=\"2\"\r\n\t\t\t\tEnableCOMDATFolding=\"2\"\r\n\t\t\t\tTargetMachine=\"17\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCALinkTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManifestTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXDCMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCBscMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCFxCopTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCAppVerifierTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPostBuildEventTool\"\r\n\t\t\t/>\r\n\t\t</Configuration>\r\n\t</Configurations>\r\n\t<References>\r\n\t</References>\r\n\t<Files>\r\n\t\t<Filter\r\n\t\t\tName=\"Source Files\"\r\n\t\t\tFilter=\"cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx\"\r\n\t\t\tUniqueIdentifier=\"{4FC737F1-C7A5-4376-A066-2A32D752A2FF}\"\r\n\t\t\t>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\programs\\datagen.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\entropy_common.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\error_private.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\compress\\fse_compress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\fse_decompress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\xxhash.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\tests\\fullbench.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\compress\\huf_compress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\decompress\\huf_decompress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\zstd_common.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\compress\\zstd_compress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\decompress\\zstd_decompress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t</Filter>\r\n\t\t<Filter\r\n\t\t\tName=\"Header Files\"\r\n\t\t\tFilter=\"h;hpp;hxx;hm;inl;inc;xsd\"\r\n\t\t\tUniqueIdentifier=\"{93995380-89BD-4b04-88EB-625FBE52EBFB}\"\r\n\t\t\t>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\bitstream.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\error_private.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\zstd_errors.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\fse.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\fse_static.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\huf.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\huf_static.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\xxhash.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\mem.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\zstd.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\zstd_internal.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\compress\\zstd_opt.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\zstd_static.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t</Filter>\r\n\t</Files>\r\n\t<Globals>\r\n\t</Globals>\r\n</VisualStudioProject>\r\n"
  },
  {
    "path": "contrib/VS2005/fuzzer/fuzzer.vcproj",
    "content": "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\r\n<VisualStudioProject\r\n\tProjectType=\"Visual C++\"\r\n\tVersion=\"8.00\"\r\n\tName=\"fuzzer\"\r\n\tProjectGUID=\"{A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}\"\r\n\tRootNamespace=\"fuzzer\"\r\n\tKeyword=\"Win32Proj\"\r\n\t>\r\n\t<Platforms>\r\n\t\t<Platform\r\n\t\t\tName=\"Win32\"\r\n\t\t/>\r\n\t\t<Platform\r\n\t\t\tName=\"x64\"\r\n\t\t/>\r\n\t</Platforms>\r\n\t<ToolFiles>\r\n\t</ToolFiles>\r\n\t<Configurations>\r\n\t\t<Configuration\r\n\t\t\tName=\"Debug|Win32\"\r\n\t\t\tOutputDirectory=\"$(SolutionDir)bin\\$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tIntermediateDirectory=\"$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tConfigurationType=\"1\"\r\n\t\t\tCharacterSet=\"2\"\r\n\t\t\t>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreBuildEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCustomBuildTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCMIDLTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCLCompilerTool\"\r\n\t\t\t\tOptimization=\"0\"\r\n\t\t\t\tAdditionalIncludeDirectories=\"$(SolutionDir)..\\..\\lib;$(SolutionDir)..\\..\\lib\\common;$(SolutionDir)..\\..\\lib\\dictBuilder;$(SolutionDir)..\\..\\programs\"\r\n\t\t\t\tPreprocessorDefinitions=\"WIN32;_DEBUG;_CONSOLE\"\r\n\t\t\t\tMinimalRebuild=\"true\"\r\n\t\t\t\tBasicRuntimeChecks=\"3\"\r\n\t\t\t\tRuntimeLibrary=\"3\"\r\n\t\t\t\tUsePrecompiledHeader=\"0\"\r\n\t\t\t\tWarningLevel=\"4\"\r\n\t\t\t\tWarnAsError=\"true\"\r\n\t\t\t\tDebugInformationFormat=\"4\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreLinkEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCLinkerTool\"\r\n\t\t\t\tLinkIncremental=\"2\"\r\n\t\t\t\tGenerateDebugInformation=\"true\"\r\n\t\t\t\tSubSystem=\"1\"\r\n\t\t\t\tTargetMachine=\"1\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCALinkTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManifestTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXDCMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCBscMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCFxCopTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCAppVerifierTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPostBuildEventTool\"\r\n\t\t\t/>\r\n\t\t</Configuration>\r\n\t\t<Configuration\r\n\t\t\tName=\"Release|Win32\"\r\n\t\t\tOutputDirectory=\"$(SolutionDir)bin\\$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tIntermediateDirectory=\"$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tConfigurationType=\"1\"\r\n\t\t\tCharacterSet=\"2\"\r\n\t\t\tWholeProgramOptimization=\"1\"\r\n\t\t\t>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreBuildEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCustomBuildTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCMIDLTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCLCompilerTool\"\r\n\t\t\t\tOptimization=\"2\"\r\n\t\t\t\tEnableIntrinsicFunctions=\"true\"\r\n\t\t\t\tOmitFramePointers=\"true\"\r\n\t\t\t\tAdditionalIncludeDirectories=\"$(SolutionDir)..\\..\\lib;$(SolutionDir)..\\..\\lib\\common;$(SolutionDir)..\\..\\lib\\dictBuilder;$(SolutionDir)..\\..\\programs\"\r\n\t\t\t\tPreprocessorDefinitions=\"WIN32;NDEBUG;_CONSOLE\"\r\n\t\t\t\tRuntimeLibrary=\"0\"\r\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\r\n\t\t\t\tUsePrecompiledHeader=\"0\"\r\n\t\t\t\tWarningLevel=\"4\"\r\n\t\t\t\tDebugInformationFormat=\"3\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreLinkEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCLinkerTool\"\r\n\t\t\t\tLinkIncremental=\"1\"\r\n\t\t\t\tGenerateDebugInformation=\"true\"\r\n\t\t\t\tSubSystem=\"1\"\r\n\t\t\t\tOptimizeReferences=\"2\"\r\n\t\t\t\tEnableCOMDATFolding=\"2\"\r\n\t\t\t\tTargetMachine=\"1\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCALinkTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManifestTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXDCMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCBscMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCFxCopTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCAppVerifierTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPostBuildEventTool\"\r\n\t\t\t/>\r\n\t\t</Configuration>\r\n\t\t<Configuration\r\n\t\t\tName=\"Debug|x64\"\r\n\t\t\tOutputDirectory=\"$(SolutionDir)bin\\$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tIntermediateDirectory=\"$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tConfigurationType=\"1\"\r\n\t\t\tCharacterSet=\"2\"\r\n\t\t\t>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreBuildEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCustomBuildTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCMIDLTool\"\r\n\t\t\t\tTargetEnvironment=\"3\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCLCompilerTool\"\r\n\t\t\t\tOptimization=\"0\"\r\n\t\t\t\tAdditionalIncludeDirectories=\"$(SolutionDir)..\\..\\lib;$(SolutionDir)..\\..\\lib\\common;$(SolutionDir)..\\..\\lib\\dictBuilder;$(SolutionDir)..\\..\\programs\"\r\n\t\t\t\tPreprocessorDefinitions=\"WIN32;_DEBUG;_CONSOLE\"\r\n\t\t\t\tMinimalRebuild=\"true\"\r\n\t\t\t\tBasicRuntimeChecks=\"3\"\r\n\t\t\t\tRuntimeLibrary=\"3\"\r\n\t\t\t\tUsePrecompiledHeader=\"0\"\r\n\t\t\t\tWarningLevel=\"4\"\r\n\t\t\t\tWarnAsError=\"true\"\r\n\t\t\t\tDebugInformationFormat=\"3\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreLinkEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCLinkerTool\"\r\n\t\t\t\tLinkIncremental=\"2\"\r\n\t\t\t\tGenerateDebugInformation=\"true\"\r\n\t\t\t\tSubSystem=\"1\"\r\n\t\t\t\tTargetMachine=\"17\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCALinkTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManifestTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXDCMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCBscMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCFxCopTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCAppVerifierTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPostBuildEventTool\"\r\n\t\t\t/>\r\n\t\t</Configuration>\r\n\t\t<Configuration\r\n\t\t\tName=\"Release|x64\"\r\n\t\t\tOutputDirectory=\"$(SolutionDir)bin\\$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tIntermediateDirectory=\"$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tConfigurationType=\"1\"\r\n\t\t\tCharacterSet=\"2\"\r\n\t\t\tWholeProgramOptimization=\"1\"\r\n\t\t\t>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreBuildEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCustomBuildTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCMIDLTool\"\r\n\t\t\t\tTargetEnvironment=\"3\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCLCompilerTool\"\r\n\t\t\t\tOptimization=\"2\"\r\n\t\t\t\tEnableIntrinsicFunctions=\"true\"\r\n\t\t\t\tOmitFramePointers=\"true\"\r\n\t\t\t\tAdditionalIncludeDirectories=\"$(SolutionDir)..\\..\\lib;$(SolutionDir)..\\..\\lib\\common;$(SolutionDir)..\\..\\lib\\dictBuilder;$(SolutionDir)..\\..\\programs\"\r\n\t\t\t\tPreprocessorDefinitions=\"WIN32;NDEBUG;_CONSOLE\"\r\n\t\t\t\tRuntimeLibrary=\"0\"\r\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\r\n\t\t\t\tUsePrecompiledHeader=\"0\"\r\n\t\t\t\tWarningLevel=\"4\"\r\n\t\t\t\tDebugInformationFormat=\"3\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreLinkEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCLinkerTool\"\r\n\t\t\t\tLinkIncremental=\"1\"\r\n\t\t\t\tGenerateDebugInformation=\"true\"\r\n\t\t\t\tSubSystem=\"1\"\r\n\t\t\t\tOptimizeReferences=\"2\"\r\n\t\t\t\tEnableCOMDATFolding=\"2\"\r\n\t\t\t\tTargetMachine=\"17\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCALinkTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManifestTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXDCMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCBscMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCFxCopTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCAppVerifierTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPostBuildEventTool\"\r\n\t\t\t/>\r\n\t\t</Configuration>\r\n\t</Configurations>\r\n\t<References>\r\n\t</References>\r\n\t<Files>\r\n\t\t<Filter\r\n\t\t\tName=\"Source Files\"\r\n\t\t\tFilter=\"cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx\"\r\n\t\t\tUniqueIdentifier=\"{4FC737F1-C7A5-4376-A066-2A32D752A2FF}\"\r\n\t\t\t>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\programs\\datagen.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\dictBuilder\\cover.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\dictBuilder\\divsufsort.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\entropy_common.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\pool.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\threading.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\error_private.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\compress\\zstdmt_compress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\compress\\fse_compress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\fse_decompress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\tests\\fuzzer.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\compress\\huf_compress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\decompress\\huf_decompress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\xxhash.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\dictBuilder\\zdict.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\zstd_common.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\compress\\zstd_compress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\decompress\\zstd_decompress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t</Filter>\r\n\t\t<Filter\r\n\t\t\tName=\"Header Files\"\r\n\t\t\tFilter=\"h;hpp;hxx;hm;inl;inc;xsd\"\r\n\t\t\tUniqueIdentifier=\"{93995380-89BD-4b04-88EB-625FBE52EBFB}\"\r\n\t\t\t>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\pool.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\threading.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\bitstream.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\dictBuilder\\divsufsort.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\error_private.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\zstd_errors.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\fse.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\fse_static.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\huf.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\huf_static.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\mem.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\xxhash.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\zdict.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\dictBuilder\\zdict_static.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\zstd.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\zstd_internal.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\compress\\zstdmt_compress.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\compress\\zstd_opt.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\zstd_static.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t</Filter>\r\n\t</Files>\r\n\t<Globals>\r\n\t</Globals>\r\n</VisualStudioProject>\r\n"
  },
  {
    "path": "contrib/VS2005/zstd/zstd.vcproj",
    "content": "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\r\n<VisualStudioProject\r\n\tProjectType=\"Visual C++\"\r\n\tVersion=\"8.00\"\r\n\tName=\"zstd\"\r\n\tProjectGUID=\"{1A2AB08E-5CE7-4C5B-BE55-458157C14051}\"\r\n\tRootNamespace=\"zstd\"\r\n\tKeyword=\"Win32Proj\"\r\n\t>\r\n\t<Platforms>\r\n\t\t<Platform\r\n\t\t\tName=\"Win32\"\r\n\t\t/>\r\n\t\t<Platform\r\n\t\t\tName=\"x64\"\r\n\t\t/>\r\n\t</Platforms>\r\n\t<ToolFiles>\r\n\t</ToolFiles>\r\n\t<Configurations>\r\n\t\t<Configuration\r\n\t\t\tName=\"Debug|Win32\"\r\n\t\t\tOutputDirectory=\"$(SolutionDir)bin\\$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tIntermediateDirectory=\"$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tConfigurationType=\"1\"\r\n\t\t\tCharacterSet=\"2\"\r\n\t\t\t>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreBuildEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCustomBuildTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCMIDLTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCLCompilerTool\"\r\n\t\t\t\tOptimization=\"0\"\r\n\t\t\t\tAdditionalIncludeDirectories=\"$(SolutionDir)..\\..\\lib;$(SolutionDir)..\\..\\lib\\common;$(SolutionDir)..\\..\\lib\\legacy;$(SolutionDir)..\\..\\lib\\dictBuilder;$(SolutionDir)..\\..\\lib\\compress\"\r\n\t\t\t\tPreprocessorDefinitions=\"ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=4;WIN32;_DEBUG;_CONSOLE\"\r\n\t\t\t\tMinimalRebuild=\"true\"\r\n\t\t\t\tBasicRuntimeChecks=\"3\"\r\n\t\t\t\tRuntimeLibrary=\"3\"\r\n\t\t\t\tUsePrecompiledHeader=\"0\"\r\n\t\t\t\tWarningLevel=\"4\"\r\n\t\t\t\tWarnAsError=\"true\"\r\n\t\t\t\tDebugInformationFormat=\"4\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreLinkEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCLinkerTool\"\r\n\t\t\t\tAdditionalDependencies=\"setargv.obj\"\r\n\t\t\t\tLinkIncremental=\"2\"\r\n\t\t\t\tGenerateDebugInformation=\"true\"\r\n\t\t\t\tSubSystem=\"1\"\r\n\t\t\t\tTargetMachine=\"1\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCALinkTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManifestTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXDCMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCBscMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCFxCopTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCAppVerifierTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPostBuildEventTool\"\r\n\t\t\t/>\r\n\t\t</Configuration>\r\n\t\t<Configuration\r\n\t\t\tName=\"Release|Win32\"\r\n\t\t\tOutputDirectory=\"$(SolutionDir)bin\\$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tIntermediateDirectory=\"$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tConfigurationType=\"1\"\r\n\t\t\tCharacterSet=\"2\"\r\n\t\t\tWholeProgramOptimization=\"1\"\r\n\t\t\t>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreBuildEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCustomBuildTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCMIDLTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCLCompilerTool\"\r\n\t\t\t\tOptimization=\"2\"\r\n\t\t\t\tEnableIntrinsicFunctions=\"true\"\r\n\t\t\t\tOmitFramePointers=\"true\"\r\n\t\t\t\tAdditionalIncludeDirectories=\"$(SolutionDir)..\\..\\lib;$(SolutionDir)..\\..\\lib\\common;$(SolutionDir)..\\..\\lib\\legacy;$(SolutionDir)..\\..\\lib\\dictBuilder;$(SolutionDir)..\\..\\lib\\compress\"\r\n\t\t\t\tPreprocessorDefinitions=\"ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=4;WIN32;NDEBUG;_CONSOLE\"\r\n\t\t\t\tRuntimeLibrary=\"0\"\r\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\r\n\t\t\t\tUsePrecompiledHeader=\"0\"\r\n\t\t\t\tWarningLevel=\"4\"\r\n\t\t\t\tDebugInformationFormat=\"3\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreLinkEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCLinkerTool\"\r\n\t\t\t\tAdditionalDependencies=\"setargv.obj\"\r\n\t\t\t\tLinkIncremental=\"1\"\r\n\t\t\t\tGenerateDebugInformation=\"true\"\r\n\t\t\t\tSubSystem=\"1\"\r\n\t\t\t\tOptimizeReferences=\"2\"\r\n\t\t\t\tEnableCOMDATFolding=\"2\"\r\n\t\t\t\tTargetMachine=\"1\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCALinkTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManifestTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXDCMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCBscMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCFxCopTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCAppVerifierTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPostBuildEventTool\"\r\n\t\t\t/>\r\n\t\t</Configuration>\r\n\t\t<Configuration\r\n\t\t\tName=\"Debug|x64\"\r\n\t\t\tOutputDirectory=\"$(SolutionDir)bin\\$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tIntermediateDirectory=\"$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tConfigurationType=\"1\"\r\n\t\t\tCharacterSet=\"2\"\r\n\t\t\t>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreBuildEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCustomBuildTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCMIDLTool\"\r\n\t\t\t\tTargetEnvironment=\"3\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCLCompilerTool\"\r\n\t\t\t\tOptimization=\"0\"\r\n\t\t\t\tAdditionalIncludeDirectories=\"$(SolutionDir)..\\..\\lib;$(SolutionDir)..\\..\\lib\\common;$(SolutionDir)..\\..\\lib\\legacy;$(SolutionDir)..\\..\\lib\\dictBuilder;$(SolutionDir)..\\..\\lib\\compress\"\r\n\t\t\t\tPreprocessorDefinitions=\"ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=4;WIN32;_DEBUG;_CONSOLE\"\r\n\t\t\t\tMinimalRebuild=\"true\"\r\n\t\t\t\tBasicRuntimeChecks=\"3\"\r\n\t\t\t\tRuntimeLibrary=\"3\"\r\n\t\t\t\tUsePrecompiledHeader=\"0\"\r\n\t\t\t\tWarningLevel=\"4\"\r\n\t\t\t\tWarnAsError=\"true\"\r\n\t\t\t\tDebugInformationFormat=\"3\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreLinkEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCLinkerTool\"\r\n\t\t\t\tAdditionalDependencies=\"setargv.obj\"\r\n\t\t\t\tLinkIncremental=\"2\"\r\n\t\t\t\tGenerateDebugInformation=\"true\"\r\n\t\t\t\tSubSystem=\"1\"\r\n\t\t\t\tTargetMachine=\"17\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCALinkTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManifestTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXDCMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCBscMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCFxCopTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCAppVerifierTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPostBuildEventTool\"\r\n\t\t\t/>\r\n\t\t</Configuration>\r\n\t\t<Configuration\r\n\t\t\tName=\"Release|x64\"\r\n\t\t\tOutputDirectory=\"$(SolutionDir)bin\\$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tIntermediateDirectory=\"$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tConfigurationType=\"1\"\r\n\t\t\tCharacterSet=\"2\"\r\n\t\t\tWholeProgramOptimization=\"1\"\r\n\t\t\t>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreBuildEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCustomBuildTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCMIDLTool\"\r\n\t\t\t\tTargetEnvironment=\"3\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCLCompilerTool\"\r\n\t\t\t\tOptimization=\"2\"\r\n\t\t\t\tEnableIntrinsicFunctions=\"true\"\r\n\t\t\t\tOmitFramePointers=\"true\"\r\n\t\t\t\tAdditionalIncludeDirectories=\"$(SolutionDir)..\\..\\lib;$(SolutionDir)..\\..\\lib\\common;$(SolutionDir)..\\..\\lib\\legacy;$(SolutionDir)..\\..\\lib\\dictBuilder;$(SolutionDir)..\\..\\lib\\compress\"\r\n\t\t\t\tPreprocessorDefinitions=\"ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=4;WIN32;NDEBUG;_CONSOLE\"\r\n\t\t\t\tRuntimeLibrary=\"0\"\r\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\r\n\t\t\t\tUsePrecompiledHeader=\"0\"\r\n\t\t\t\tWarningLevel=\"4\"\r\n\t\t\t\tDebugInformationFormat=\"3\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreLinkEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCLinkerTool\"\r\n\t\t\t\tAdditionalDependencies=\"setargv.obj\"\r\n\t\t\t\tLinkIncremental=\"1\"\r\n\t\t\t\tGenerateDebugInformation=\"true\"\r\n\t\t\t\tSubSystem=\"1\"\r\n\t\t\t\tOptimizeReferences=\"2\"\r\n\t\t\t\tEnableCOMDATFolding=\"2\"\r\n\t\t\t\tTargetMachine=\"17\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCALinkTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManifestTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXDCMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCBscMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCFxCopTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCAppVerifierTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPostBuildEventTool\"\r\n\t\t\t/>\r\n\t\t</Configuration>\r\n\t</Configurations>\r\n\t<References>\r\n\t</References>\r\n\t<Files>\r\n\t\t<Filter\r\n\t\t\tName=\"Source Files\"\r\n\t\t\tFilter=\"cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx\"\r\n\t\t\tUniqueIdentifier=\"{4FC737F1-C7A5-4376-A066-2A32D752A2FF}\"\r\n\t\t\t>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\programs\\bench.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\programs\\datagen.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\programs\\dibio.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\dictBuilder\\cover.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\dictBuilder\\divsufsort.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\entropy_common.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\error_private.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\programs\\fileio.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n                RelativePath=\"..\\..\\..\\programs\\fileio_asyncio.c\"\r\n                >\r\n            </File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\compress\\fse_compress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\fse_decompress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\compress\\huf_compress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\decompress\\huf_decompress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\xxhash.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\dictBuilder\\zdict.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\zstd_common.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\compress\\zstd_compress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\compress\\zstdmt_compress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\decompress\\zstd_decompress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v01.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v02.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v03.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v04.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v05.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v06.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v07.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\programs\\zstdcli.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t</Filter>\r\n\t\t<Filter\r\n\t\t\tName=\"Header Files\"\r\n\t\t\tFilter=\"h;hpp;hxx;hm;inl;inc;xsd\"\r\n\t\t\tUniqueIdentifier=\"{93995380-89BD-4b04-88EB-625FBE52EBFB}\"\r\n\t\t\t>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\bitstream.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\dictBuilder\\divsufsort.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\error_private.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\zstd_errors.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\fse.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\fse_static.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\huf.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\huf_static.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\mem.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\xxhash.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\zdict.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\dictBuilder\\zdict_static.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\zstd.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\zstd_internal.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_legacy.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\compress\\zstd_opt.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\zstd_static.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v01.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v02.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v03.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v04.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v05.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v06.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v07.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\compress\\zstdmt_compress.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t</Filter>\r\n\t</Files>\r\n\t<Globals>\r\n\t</Globals>\r\n</VisualStudioProject>\r\n"
  },
  {
    "path": "contrib/VS2005/zstd.sln",
    "content": "Microsoft Visual Studio Solution File, Format Version 9.00\r\n# Visual C++ Express 2005\r\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"zstd\", \"zstd\\zstd.vcproj\", \"{1A2AB08E-5CE7-4C5B-BE55-458157C14051}\"\r\nEndProject\r\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"fuzzer\", \"fuzzer\\fuzzer.vcproj\", \"{A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}\"\r\nEndProject\r\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"fullbench\", \"fullbench\\fullbench.vcproj\", \"{CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}\"\r\nEndProject\r\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"zstdlib\", \"zstdlib\\zstdlib.vcproj\", \"{99DE2A79-7298-4004-A0ED-030D7A3796CA}\"\r\nEndProject\r\nGlobal\r\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n\t\tDebug|Win32 = Debug|Win32\r\n\t\tDebug|x64 = Debug|x64\r\n\t\tRelease|Win32 = Release|Win32\r\n\t\tRelease|x64 = Release|x64\r\n\tEndGlobalSection\r\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n\t\t{1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Debug|Win32.ActiveCfg = Debug|Win32\r\n\t\t{1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Debug|Win32.Build.0 = Debug|Win32\r\n\t\t{1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Debug|x64.ActiveCfg = Debug|x64\r\n\t\t{1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Debug|x64.Build.0 = Debug|x64\r\n\t\t{1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Release|Win32.ActiveCfg = Release|Win32\r\n\t\t{1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Release|Win32.Build.0 = Release|Win32\r\n\t\t{1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Release|x64.ActiveCfg = Release|x64\r\n\t\t{1A2AB08E-5CE7-4C5B-BE55-458157C14051}.Release|x64.Build.0 = Release|x64\r\n\t\t{A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Debug|Win32.ActiveCfg = Debug|Win32\r\n\t\t{A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Debug|Win32.Build.0 = Debug|Win32\r\n\t\t{A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Debug|x64.ActiveCfg = Debug|x64\r\n\t\t{A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Debug|x64.Build.0 = Debug|x64\r\n\t\t{A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Release|Win32.ActiveCfg = Release|Win32\r\n\t\t{A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Release|Win32.Build.0 = Release|Win32\r\n\t\t{A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Release|x64.ActiveCfg = Release|x64\r\n\t\t{A62E89D2-9DDE-42BA-8F9B-9DA74889A6B0}.Release|x64.Build.0 = Release|x64\r\n\t\t{CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Debug|Win32.ActiveCfg = Debug|Win32\r\n\t\t{CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Debug|Win32.Build.0 = Debug|Win32\r\n\t\t{CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Debug|x64.ActiveCfg = Debug|x64\r\n\t\t{CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Debug|x64.Build.0 = Debug|x64\r\n\t\t{CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Release|Win32.ActiveCfg = Release|Win32\r\n\t\t{CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Release|Win32.Build.0 = Release|Win32\r\n\t\t{CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Release|x64.ActiveCfg = Release|x64\r\n\t\t{CC8F1D1B-BA2F-43E3-A71F-FA415D81AAD3}.Release|x64.Build.0 = Release|x64\r\n\t\t{99DE2A79-7298-4004-A0ED-030D7A3796CA}.Debug|Win32.ActiveCfg = Debug|Win32\r\n\t\t{99DE2A79-7298-4004-A0ED-030D7A3796CA}.Debug|Win32.Build.0 = Debug|Win32\r\n\t\t{99DE2A79-7298-4004-A0ED-030D7A3796CA}.Debug|x64.ActiveCfg = Debug|x64\r\n\t\t{99DE2A79-7298-4004-A0ED-030D7A3796CA}.Debug|x64.Build.0 = Debug|x64\r\n\t\t{99DE2A79-7298-4004-A0ED-030D7A3796CA}.Release|Win32.ActiveCfg = Release|Win32\r\n\t\t{99DE2A79-7298-4004-A0ED-030D7A3796CA}.Release|Win32.Build.0 = Release|Win32\r\n\t\t{99DE2A79-7298-4004-A0ED-030D7A3796CA}.Release|x64.ActiveCfg = Release|x64\r\n\t\t{99DE2A79-7298-4004-A0ED-030D7A3796CA}.Release|x64.Build.0 = Release|x64\r\n\tEndGlobalSection\r\n\tGlobalSection(SolutionProperties) = preSolution\r\n\t\tHideSolutionNode = FALSE\r\n\tEndGlobalSection\r\nEndGlobal\r\n"
  },
  {
    "path": "contrib/VS2005/zstdlib/zstdlib.vcproj",
    "content": "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\r\n<VisualStudioProject\r\n\tProjectType=\"Visual C++\"\r\n\tVersion=\"8.00\"\r\n\tName=\"zstdlib\"\r\n\tProjectGUID=\"{99DE2A79-7298-4004-A0ED-030D7A3796CA}\"\r\n\tRootNamespace=\"zstdlib\"\r\n\tKeyword=\"Win32Proj\"\r\n\t>\r\n\t<Platforms>\r\n\t\t<Platform\r\n\t\t\tName=\"Win32\"\r\n\t\t/>\r\n\t\t<Platform\r\n\t\t\tName=\"x64\"\r\n\t\t/>\r\n\t</Platforms>\r\n\t<ToolFiles>\r\n\t</ToolFiles>\r\n\t<Configurations>\r\n\t\t<Configuration\r\n\t\t\tName=\"Debug|Win32\"\r\n\t\t\tOutputDirectory=\"$(SolutionDir)bin\\$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tIntermediateDirectory=\"$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tConfigurationType=\"2\"\r\n\t\t\tCharacterSet=\"2\"\r\n\t\t\t>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreBuildEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCustomBuildTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCMIDLTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCLCompilerTool\"\r\n\t\t\t\tOptimization=\"0\"\r\n\t\t\t\tAdditionalIncludeDirectories=\"$(SolutionDir)..\\..\\lib;$(SolutionDir)..\\..\\lib\\common;$(SolutionDir)..\\..\\lib\\legacy;$(SolutionDir)..\\..\\programs\\legacy;$(SolutionDir)..\\..\\lib\\dictBuilder\"\r\n\t\t\t\tPreprocessorDefinitions=\"ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=4;WIN32;_DEBUG;_CONSOLE\"\r\n\t\t\t\tMinimalRebuild=\"true\"\r\n\t\t\t\tBasicRuntimeChecks=\"3\"\r\n\t\t\t\tRuntimeLibrary=\"3\"\r\n\t\t\t\tUsePrecompiledHeader=\"0\"\r\n\t\t\t\tWarningLevel=\"4\"\r\n\t\t\t\tWarnAsError=\"true\"\r\n\t\t\t\tDebugInformationFormat=\"4\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreLinkEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCLinkerTool\"\r\n\t\t\t\tLinkIncremental=\"2\"\r\n\t\t\t\tGenerateDebugInformation=\"true\"\r\n\t\t\t\tSubSystem=\"1\"\r\n\t\t\t\tTargetMachine=\"1\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCALinkTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManifestTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXDCMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCBscMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCFxCopTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCAppVerifierTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPostBuildEventTool\"\r\n\t\t\t/>\r\n\t\t</Configuration>\r\n\t\t<Configuration\r\n\t\t\tName=\"Release|Win32\"\r\n\t\t\tOutputDirectory=\"$(SolutionDir)bin\\$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tIntermediateDirectory=\"$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tConfigurationType=\"2\"\r\n\t\t\tCharacterSet=\"2\"\r\n\t\t\tWholeProgramOptimization=\"1\"\r\n\t\t\t>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreBuildEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCustomBuildTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCMIDLTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCLCompilerTool\"\r\n\t\t\t\tOptimization=\"2\"\r\n\t\t\t\tEnableIntrinsicFunctions=\"true\"\r\n\t\t\t\tOmitFramePointers=\"true\"\r\n\t\t\t\tAdditionalIncludeDirectories=\"$(SolutionDir)..\\..\\lib;$(SolutionDir)..\\..\\lib\\common;$(SolutionDir)..\\..\\lib\\legacy;$(SolutionDir)..\\..\\programs\\legacy;$(SolutionDir)..\\..\\lib\\dictBuilder\"\r\n\t\t\t\tPreprocessorDefinitions=\"ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=4;WIN32;NDEBUG;_CONSOLE\"\r\n\t\t\t\tRuntimeLibrary=\"0\"\r\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\r\n\t\t\t\tUsePrecompiledHeader=\"0\"\r\n\t\t\t\tWarningLevel=\"4\"\r\n\t\t\t\tDebugInformationFormat=\"3\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreLinkEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCLinkerTool\"\r\n\t\t\t\tLinkIncremental=\"1\"\r\n\t\t\t\tGenerateDebugInformation=\"true\"\r\n\t\t\t\tSubSystem=\"1\"\r\n\t\t\t\tOptimizeReferences=\"2\"\r\n\t\t\t\tEnableCOMDATFolding=\"2\"\r\n\t\t\t\tTargetMachine=\"1\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCALinkTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManifestTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXDCMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCBscMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCFxCopTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCAppVerifierTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPostBuildEventTool\"\r\n\t\t\t/>\r\n\t\t</Configuration>\r\n\t\t<Configuration\r\n\t\t\tName=\"Debug|x64\"\r\n\t\t\tOutputDirectory=\"$(SolutionDir)bin\\$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tIntermediateDirectory=\"$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tConfigurationType=\"2\"\r\n\t\t\tCharacterSet=\"2\"\r\n\t\t\t>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreBuildEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCustomBuildTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCMIDLTool\"\r\n\t\t\t\tTargetEnvironment=\"3\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCLCompilerTool\"\r\n\t\t\t\tOptimization=\"0\"\r\n\t\t\t\tAdditionalIncludeDirectories=\"$(SolutionDir)..\\..\\lib;$(SolutionDir)..\\..\\lib\\common;$(SolutionDir)..\\..\\lib\\legacy;$(SolutionDir)..\\..\\programs\\legacy;$(SolutionDir)..\\..\\lib\\dictBuilder\"\r\n\t\t\t\tPreprocessorDefinitions=\"ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=4;WIN32;_DEBUG;_CONSOLE\"\r\n\t\t\t\tMinimalRebuild=\"true\"\r\n\t\t\t\tBasicRuntimeChecks=\"3\"\r\n\t\t\t\tRuntimeLibrary=\"3\"\r\n\t\t\t\tUsePrecompiledHeader=\"0\"\r\n\t\t\t\tWarningLevel=\"4\"\r\n\t\t\t\tWarnAsError=\"true\"\r\n\t\t\t\tDebugInformationFormat=\"3\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreLinkEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCLinkerTool\"\r\n\t\t\t\tLinkIncremental=\"2\"\r\n\t\t\t\tGenerateDebugInformation=\"true\"\r\n\t\t\t\tSubSystem=\"1\"\r\n\t\t\t\tTargetMachine=\"17\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCALinkTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManifestTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXDCMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCBscMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCFxCopTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCAppVerifierTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPostBuildEventTool\"\r\n\t\t\t/>\r\n\t\t</Configuration>\r\n\t\t<Configuration\r\n\t\t\tName=\"Release|x64\"\r\n\t\t\tOutputDirectory=\"$(SolutionDir)bin\\$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tIntermediateDirectory=\"$(PlatformName)\\$(ConfigurationName)\"\r\n\t\t\tConfigurationType=\"2\"\r\n\t\t\tCharacterSet=\"2\"\r\n\t\t\tWholeProgramOptimization=\"1\"\r\n\t\t\t>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreBuildEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCustomBuildTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCMIDLTool\"\r\n\t\t\t\tTargetEnvironment=\"3\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCLCompilerTool\"\r\n\t\t\t\tOptimization=\"2\"\r\n\t\t\t\tEnableIntrinsicFunctions=\"true\"\r\n\t\t\t\tOmitFramePointers=\"true\"\r\n\t\t\t\tAdditionalIncludeDirectories=\"$(SolutionDir)..\\..\\lib;$(SolutionDir)..\\..\\lib\\common;$(SolutionDir)..\\..\\lib\\legacy;$(SolutionDir)..\\..\\programs\\legacy;$(SolutionDir)..\\..\\lib\\dictBuilder\"\r\n\t\t\t\tPreprocessorDefinitions=\"ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=4;WIN32;NDEBUG;_CONSOLE\"\r\n\t\t\t\tRuntimeLibrary=\"0\"\r\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\r\n\t\t\t\tUsePrecompiledHeader=\"0\"\r\n\t\t\t\tWarningLevel=\"4\"\r\n\t\t\t\tDebugInformationFormat=\"3\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreLinkEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCLinkerTool\"\r\n\t\t\t\tLinkIncremental=\"1\"\r\n\t\t\t\tGenerateDebugInformation=\"true\"\r\n\t\t\t\tSubSystem=\"1\"\r\n\t\t\t\tOptimizeReferences=\"2\"\r\n\t\t\t\tEnableCOMDATFolding=\"2\"\r\n\t\t\t\tTargetMachine=\"17\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCALinkTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManifestTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXDCMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCBscMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCFxCopTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCAppVerifierTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPostBuildEventTool\"\r\n\t\t\t/>\r\n\t\t</Configuration>\r\n\t</Configurations>\r\n\t<References>\r\n\t</References>\r\n\t<Files>\r\n\t\t<Filter\r\n\t\t\tName=\"Source Files\"\r\n\t\t\tFilter=\"cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx\"\r\n\t\t\tUniqueIdentifier=\"{4FC737F1-C7A5-4376-A066-2A32D752A2FF}\"\r\n\t\t\t>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\dictBuilder\\cover.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\dictBuilder\\divsufsort.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\pool.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\threading.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\entropy_common.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\error_private.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\compress\\fse_compress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\fse_decompress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\compress\\huf_compress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\decompress\\huf_decompress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\xxhash.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\dictBuilder\\zdict.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\zstd_common.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\compress\\zstdmt_compress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\compress\\zstd_compress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\decompress\\zstd_decompress.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v01.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v02.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v03.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v04.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v05.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v06.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v07.c\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t</Filter>\r\n\t\t<Filter\r\n\t\t\tName=\"Header Files\"\r\n\t\t\tFilter=\"h;hpp;hxx;hm;inl;inc;xsd\"\r\n\t\t\tUniqueIdentifier=\"{93995380-89BD-4b04-88EB-625FBE52EBFB}\"\r\n\t\t\t>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\bitstream.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\dictBuilder\\divsufsort.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\pool.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\threading.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\error_private.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\zstd_errors.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\fse.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\fse_static.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\huf.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\huf_static.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\mem.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\xxhash.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\zdict.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\dictBuilder\\zdict_static.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\zstd.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\zstd_internal.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_legacy.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\compress\\zstd_opt.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\compress\\zstdmt_compress.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\common\\zstd_static.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v01.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v02.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v03.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v04.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v05.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v06.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\..\\..\\lib\\legacy\\zstd_v07.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t</Filter>\r\n\t\t<Filter\r\n\t\t\tName=\"Resource Files\"\r\n\t\t\tFilter=\"rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav\"\r\n\t\t\tUniqueIdentifier=\"{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}\"\r\n\t\t\t>\r\n\t\t</Filter>\r\n\t</Files>\r\n\t<Globals>\r\n\t</Globals>\r\n</VisualStudioProject>\r\n"
  },
  {
    "path": "contrib/cleanTabs",
    "content": "#!/bin/sh\nsed -i '' $'s/\\t/    /g' ../lib/**/*.{h,c} ../programs/*.{h,c} ../tests/*.c ./**/*.{h,cpp} ../examples/*.c ../zlibWrapper/*.{h,c}\n"
  },
  {
    "path": "contrib/diagnose_corruption/.gitignore",
    "content": "check_flipped_bits\n"
  },
  {
    "path": "contrib/diagnose_corruption/Makefile",
    "content": "# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# ################################################################\n\n.PHONY: all\nall: check_flipped_bits\n\nZSTDLIBDIR ?= ../../lib\n\nCFLAGS     ?= -O3\nCFLAGS     += -I$(ZSTDLIBDIR) -I$(ZSTDLIBDIR)/common -I$(ZSTDLIBDIR)/compress \\\n              -I$(ZSTDLIBDIR)/decompress\nCFLAGS     += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow                 \\\n              -Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \\\n              -Wstrict-prototypes -Wundef                                     \\\n              -Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings      \\\n              -Wredundant-decls -Wmissing-prototypes\nCFLAGS     += $(DEBUGFLAGS) $(MOREFLAGS)\nFLAGS       = $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)\n\n.PHONY: $(ZSTDLIBDIR)/libzstd.a\n$(ZSTDLIBDIR)/libzstd.a:\n\t$(MAKE) -C $(ZSTDLIBDIR) libzstd.a\n\ncheck_flipped_bits: check_flipped_bits.c $(ZSTDLIBDIR)/libzstd.a\n\t$(CC) $(FLAGS) $< -o $@$(EXT) $(ZSTDLIBDIR)/libzstd.a\n\n.PHONY: clean\nclean:\n\trm -f check_flipped_bits\n"
  },
  {
    "path": "contrib/diagnose_corruption/check_flipped_bits.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#define ZSTD_STATIC_LINKING_ONLY\n#include \"zstd.h\"\n#include \"zstd_errors.h\"\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <unistd.h>\n\ntypedef struct {\n  char *input;\n  size_t input_size;\n\n  char *perturbed; /* same size as input */\n\n  char *output;\n  size_t output_size;\n\n  const char *dict_file_name;\n  const char *dict_file_dir_name;\n  int32_t dict_id;\n  char *dict;\n  size_t dict_size;\n  ZSTD_DDict* ddict;\n\n  ZSTD_DCtx* dctx;\n\n  int success_count;\n  int error_counts[ZSTD_error_maxCode];\n} stuff_t;\n\nstatic void free_stuff(stuff_t* stuff) {\n  free(stuff->input);\n  free(stuff->output);\n  ZSTD_freeDDict(stuff->ddict);\n  free(stuff->dict);\n  ZSTD_freeDCtx(stuff->dctx);\n}\n\nstatic void usage(void) {\n  fprintf(stderr, \"check_flipped_bits input_filename [-d dict] [-D dict_dir]\\n\");\n  fprintf(stderr, \"\\n\");\n  fprintf(stderr, \"Arguments:\\n\");\n  fprintf(stderr, \"    -d file: path to a dictionary file to use.\\n\");\n  fprintf(stderr, \"    -D dir : path to a directory, with files containing dictionaries, of the\\n\"\n                  \"             form DICTID.zstd-dict, e.g., 12345.zstd-dict.\\n\");\n  exit(1);\n}\n\nstatic void print_summary(stuff_t* stuff) {\n  int error_code;\n  fprintf(stderr, \"%9d successful decompressions\\n\", stuff->success_count);\n  for (error_code = 0; error_code < ZSTD_error_maxCode; error_code++) {\n    int count = stuff->error_counts[error_code];\n    if (count) {\n      fprintf(\n          stderr, \"%9d failed decompressions with message: %s\\n\",\n          count, ZSTD_getErrorString(error_code));\n    }\n  }\n}\n\nstatic char* readFile(const char* filename, size_t* size) {\n  struct stat statbuf;\n  int ret;\n  FILE* f;\n  char *buf;\n  size_t bytes_read;\n\n  ret = stat(filename, &statbuf);\n  if (ret != 0) {\n    fprintf(stderr, \"stat failed: %m\\n\");\n    return NULL;\n  }\n  if ((statbuf.st_mode & S_IFREG) != S_IFREG) {\n    fprintf(stderr, \"Input must be regular file\\n\");\n    return NULL;\n  }\n\n  *size = statbuf.st_size;\n\n  f = fopen(filename, \"r\");\n  if (f == NULL) {\n    fprintf(stderr, \"fopen failed: %m\\n\");\n    return NULL;\n  }\n\n  buf = malloc(*size);\n  if (buf == NULL) {\n    fprintf(stderr, \"malloc failed\\n\");\n    fclose(f);\n    return NULL;\n  }\n\n  bytes_read = fread(buf, 1, *size, f);\n  if (bytes_read != *size) {\n    fprintf(stderr, \"failed to read whole file\\n\");\n    fclose(f);\n    free(buf);\n    return NULL;\n  }\n\n  ret = fclose(f);\n  if (ret != 0) {\n    fprintf(stderr, \"fclose failed: %m\\n\");\n    free(buf);\n    return NULL;\n  }\n\n  return buf;\n}\n\nstatic ZSTD_DDict* readDict(const char* filename, char **buf, size_t* size, int32_t* dict_id) {\n  ZSTD_DDict* ddict;\n  *buf = readFile(filename, size);\n  if (*buf == NULL) {\n    fprintf(stderr, \"Opening dictionary file '%s' failed\\n\", filename);\n    return NULL;\n  }\n\n  ddict = ZSTD_createDDict_advanced(*buf, *size, ZSTD_dlm_byRef, ZSTD_dct_auto, ZSTD_defaultCMem);\n  if (ddict == NULL) {\n    fprintf(stderr, \"Failed to create ddict.\\n\");\n    return NULL;\n  }\n  if (dict_id != NULL) {\n    *dict_id = ZSTD_getDictID_fromDDict(ddict);\n  }\n  return ddict;\n}\n\nstatic ZSTD_DDict* readDictByID(stuff_t *stuff, int32_t dict_id, char **buf, size_t* size) {\n  if (stuff->dict_file_dir_name == NULL) {\n    return NULL;\n  } else {\n    size_t dir_name_len = strlen(stuff->dict_file_dir_name);\n    int dir_needs_separator = 0;\n    size_t dict_file_name_alloc_size = dir_name_len + 1 /* '/' */ + 10 /* max int32_t len */ + strlen(\".zstd-dict\") + 1 /* '\\0' */;\n    char *dict_file_name = malloc(dict_file_name_alloc_size);\n    ZSTD_DDict* ddict;\n    int32_t read_dict_id;\n    if (dict_file_name == NULL) {\n      fprintf(stderr, \"malloc failed.\\n\");\n      return 0;\n    }\n\n    if (dir_name_len > 0 && stuff->dict_file_dir_name[dir_name_len - 1] != '/') {\n      dir_needs_separator = 1;\n    }\n\n    snprintf(\n      dict_file_name,\n      dict_file_name_alloc_size,\n      \"%s%s%u.zstd-dict\",\n      stuff->dict_file_dir_name,\n      dir_needs_separator ? \"/\" : \"\",\n      dict_id);\n\n    /* fprintf(stderr, \"Loading dict %u from '%s'.\\n\", dict_id, dict_file_name); */\n\n    ddict = readDict(dict_file_name, buf, size, &read_dict_id);\n    if (ddict == NULL) {\n      fprintf(stderr, \"Failed to create ddict from '%s'.\\n\", dict_file_name);\n      free(dict_file_name);\n      return 0;\n    }\n    if (read_dict_id != dict_id) {\n      fprintf(stderr, \"Read dictID (%u) does not match expected (%u).\\n\", read_dict_id, dict_id);\n      free(dict_file_name);\n      ZSTD_freeDDict(ddict);\n      return 0;\n    }\n\n    free(dict_file_name);\n    return ddict;\n  }\n}\n\nstatic int init_stuff(stuff_t* stuff, int argc, char *argv[]) {\n  const char* input_filename;\n\n  if (argc < 2) {\n    usage();\n  }\n\n  input_filename = argv[1];\n  stuff->input_size = 0;\n  stuff->input = readFile(input_filename, &stuff->input_size);\n  if (stuff->input == NULL) {\n    fprintf(stderr, \"Failed to read input file.\\n\");\n    return 0;\n  }\n\n  stuff->perturbed = malloc(stuff->input_size);\n  if (stuff->perturbed == NULL) {\n    fprintf(stderr, \"malloc failed.\\n\");\n    return 0;\n  }\n  memcpy(stuff->perturbed, stuff->input, stuff->input_size);\n\n  stuff->output_size = ZSTD_DStreamOutSize();\n  stuff->output = malloc(stuff->output_size);\n  if (stuff->output == NULL) {\n    fprintf(stderr, \"malloc failed.\\n\");\n    return 0;\n  }\n\n  stuff->dict_file_name = NULL;\n  stuff->dict_file_dir_name = NULL;\n  stuff->dict_id = 0;\n  stuff->dict = NULL;\n  stuff->dict_size = 0;\n  stuff->ddict = NULL;\n\n  if (argc > 2) {\n    if (!strcmp(argv[2], \"-d\")) {\n      if (argc > 3) {\n        stuff->dict_file_name = argv[3];\n      } else {\n        usage();\n      }\n    } else\n    if (!strcmp(argv[2], \"-D\")) {\n      if (argc > 3) {\n        stuff->dict_file_dir_name = argv[3];\n      } else {\n        usage();\n      }\n    } else {\n      usage();\n    }\n  }\n\n  if (stuff->dict_file_dir_name) {\n    int32_t dict_id = ZSTD_getDictID_fromFrame(stuff->input, stuff->input_size);\n    if (dict_id != 0) {\n      stuff->ddict = readDictByID(stuff, dict_id, &stuff->dict, &stuff->dict_size);\n      if (stuff->ddict == NULL) {\n        fprintf(stderr, \"Failed to create cached ddict.\\n\");\n        return 0;\n      }\n      stuff->dict_id = dict_id;\n    }\n  } else\n  if (stuff->dict_file_name) {\n    stuff->ddict = readDict(stuff->dict_file_name, &stuff->dict, &stuff->dict_size, &stuff->dict_id);\n    if (stuff->ddict == NULL) {\n      fprintf(stderr, \"Failed to create ddict from '%s'.\\n\", stuff->dict_file_name);\n      return 0;\n    }\n  }\n\n  stuff->dctx = ZSTD_createDCtx();\n  if (stuff->dctx == NULL) {\n    return 0;\n  }\n\n  stuff->success_count = 0;\n  memset(stuff->error_counts, 0, sizeof(stuff->error_counts));\n\n  return 1;\n}\n\nstatic int test_decompress(stuff_t* stuff) {\n  size_t ret;\n  ZSTD_inBuffer in = {stuff->perturbed, stuff->input_size, 0};\n  ZSTD_outBuffer out = {stuff->output, stuff->output_size, 0};\n  ZSTD_DCtx* dctx = stuff->dctx;\n  int32_t custom_dict_id = ZSTD_getDictID_fromFrame(in.src, in.size);\n  char *custom_dict = NULL;\n  size_t custom_dict_size = 0;\n  ZSTD_DDict* custom_ddict = NULL;\n\n  if (custom_dict_id != 0 && custom_dict_id != stuff->dict_id) {\n    /* fprintf(stderr, \"Instead of dict %u, this perturbed blob wants dict %u.\\n\", stuff->dict_id, custom_dict_id); */\n    custom_ddict = readDictByID(stuff, custom_dict_id, &custom_dict, &custom_dict_size);\n  }\n\n  ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only);\n\n  if (custom_ddict != NULL) {\n    ZSTD_DCtx_refDDict(dctx, custom_ddict);\n  } else {\n    ZSTD_DCtx_refDDict(dctx, stuff->ddict);\n  }\n\n  while (in.pos != in.size) {\n    out.pos = 0;\n    ret = ZSTD_decompressStream(dctx, &out, &in);\n\n    if (ZSTD_isError(ret)) {\n      unsigned int code = ZSTD_getErrorCode(ret);\n      if (code >= ZSTD_error_maxCode) {\n        fprintf(stderr, \"Received unexpected error code!\\n\");\n        exit(1);\n      }\n      stuff->error_counts[code]++;\n      /*\n      fprintf(\n          stderr, \"Decompression failed: %s\\n\", ZSTD_getErrorName(ret));\n      */\n      if (custom_ddict != NULL) {\n        ZSTD_freeDDict(custom_ddict);\n        free(custom_dict);\n      }\n      return 0;\n    }\n  }\n\n  stuff->success_count++;\n\n  if (custom_ddict != NULL) {\n    ZSTD_freeDDict(custom_ddict);\n    free(custom_dict);\n  }\n  return 1;\n}\n\nstatic int perturb_bits(stuff_t* stuff) {\n  size_t pos;\n  size_t bit;\n  for (pos = 0; pos < stuff->input_size; pos++) {\n    unsigned char old_val = stuff->input[pos];\n    if (pos % 1000 == 0) {\n      fprintf(stderr, \"Perturbing byte %zu / %zu\\n\", pos, stuff->input_size);\n    }\n    for (bit = 0; bit < 8; bit++) {\n      unsigned char new_val = old_val ^ (1 << bit);\n      stuff->perturbed[pos] = new_val;\n      if (test_decompress(stuff)) {\n        fprintf(\n            stderr,\n            \"Flipping byte %zu bit %zu (0x%02x -> 0x%02x) \"\n            \"produced a successful decompression!\\n\",\n            pos, bit, old_val, new_val);\n      }\n    }\n    stuff->perturbed[pos] = old_val;\n  }\n  return 1;\n}\n\nstatic int perturb_bytes(stuff_t* stuff) {\n  size_t pos;\n  size_t new_val;\n  for (pos = 0; pos < stuff->input_size; pos++) {\n    unsigned char old_val = stuff->input[pos];\n    if (pos % 1000 == 0) {\n      fprintf(stderr, \"Perturbing byte %zu / %zu\\n\", pos, stuff->input_size);\n    }\n    for (new_val = 0; new_val < 256; new_val++) {\n      stuff->perturbed[pos] = new_val;\n      if (test_decompress(stuff)) {\n        fprintf(\n            stderr,\n            \"Changing byte %zu (0x%02x -> 0x%02x) \"\n            \"produced a successful decompression!\\n\",\n            pos, old_val, (unsigned char)new_val);\n      }\n    }\n    stuff->perturbed[pos] = old_val;\n  }\n  return 1;\n}\n\nint main(int argc, char* argv[]) {\n  stuff_t stuff;\n\n  if(!init_stuff(&stuff, argc, argv)) {\n    fprintf(stderr, \"Failed to init.\\n\");\n    return 1;\n  }\n\n  if (test_decompress(&stuff)) {\n    fprintf(stderr, \"Blob already decompresses successfully!\\n\");\n    return 1;\n  }\n\n  perturb_bits(&stuff);\n\n  perturb_bytes(&stuff);\n\n  print_summary(&stuff);\n\n  free_stuff(&stuff);\n\n  return 0;\n}\n"
  },
  {
    "path": "contrib/docker/Dockerfile",
    "content": "# Dockerfile\n# First image to build the binary\nFROM alpine@sha256:69665d02cb32192e52e07644d76bc6f25abeb5410edc1c7a81a10ba3f0efb90a as builder\n\nRUN apk --no-cache add make gcc libc-dev\nCOPY . /src\nRUN mkdir /pkg && cd /src && make && make DESTDIR=/pkg install\n\n# Second minimal image to only keep the built binary\nFROM alpine@sha256:69665d02cb32192e52e07644d76bc6f25abeb5410edc1c7a81a10ba3f0efb90a\n\n# Copy the built files\nCOPY --from=builder /pkg /\n\n# Copy the license as well\nRUN mkdir -p /usr/local/share/licenses/zstd\nCOPY --from=builder /src/LICENSE /usr/local/share/licences/zstd/\n\n# Just run `zstd` if no other command is given\nCMD [\"/usr/local/bin/zstd\"]\n"
  },
  {
    "path": "contrib/docker/README.md",
    "content": "\n## Requirement\n\nThe `Dockerfile` script requires a version of `docker` >= 17.05\n\n## Installing docker\n\nThe official docker install docs use a ppa with a modern version available:\nhttps://docs.docker.com/install/linux/docker-ce/ubuntu/\n\n## How to run\n\n`docker build -t zstd .`\n\n## test\n\n```\necho foo | docker run -i --rm zstd | docker run -i --rm zstd zstdcat\nfoo\n```\n"
  },
  {
    "path": "contrib/freestanding_lib/freestanding.py",
    "content": "#!/usr/bin/env python3\n# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ##########################################################################\n\nimport argparse\nimport contextlib\nimport os\nimport re\nimport shutil\nimport sys\nfrom typing import Optional\n\n\nINCLUDED_SUBDIRS = [\"common\", \"compress\", \"decompress\"]\n\nSKIPPED_FILES = [\n    \"common/mem.h\",\n    \"common/zstd_deps.h\",\n    \"common/pool.c\",\n    \"common/pool.h\",\n    \"common/threading.c\",\n    \"common/threading.h\",\n    \"common/zstd_trace.h\",\n    \"compress/zstdmt_compress.h\",\n    \"compress/zstdmt_compress.c\",\n]\n\nXXHASH_FILES = [\n    \"common/xxhash.c\",\n    \"common/xxhash.h\",\n]\n\n\nclass FileLines(object):\n    def __init__(self, filename):\n        self.filename = filename\n        with open(self.filename, \"r\") as f:\n            self.lines = f.readlines()\n\n    def write(self):\n        with open(self.filename, \"w\") as f:\n            f.write(\"\".join(self.lines))\n\n\nclass PartialPreprocessor(object):\n    \"\"\"\n    Looks for simple ifdefs and ifndefs and replaces them.\n    Handles && and ||.\n    Has fancy logic to handle translating elifs to ifs.\n    Only looks for macros in the first part of the expression with no\n    parens.\n    Does not handle multi-line macros (only looks in first line).\n    \"\"\"\n    def __init__(self, defs: [(str, Optional[str])], replaces: [(str, str)], undefs: [str]):\n        MACRO_GROUP = r\"(?P<macro>[a-zA-Z_][a-zA-Z_0-9]*)\"\n        ELIF_GROUP = r\"(?P<elif>el)?\"\n        OP_GROUP = r\"(?P<op>&&|\\|\\|)?\"\n\n        self._defs = {macro:value for macro, value in defs}\n        self._replaces = {macro:value for macro, value in replaces}\n        self._defs.update(self._replaces)\n        self._undefs = set(undefs)\n\n        self._define = re.compile(r\"\\s*#\\s*define\")\n        self._if = re.compile(r\"\\s*#\\s*if\")\n        self._elif = re.compile(r\"\\s*#\\s*(?P<elif>el)if\")\n        self._else = re.compile(r\"\\s*#\\s*(?P<else>else)\")\n        self._endif = re.compile(r\"\\s*#\\s*endif\")\n\n        self._ifdef = re.compile(fr\"\\s*#\\s*if(?P<not>n)?def {MACRO_GROUP}\\s*\")\n        self._if_defined = re.compile(\n            fr\"\\s*#\\s*{ELIF_GROUP}if\\s+(?P<not>!)?\\s*defined\\s*\\(\\s*{MACRO_GROUP}\\s*\\)\\s*{OP_GROUP}\"\n        )\n        self._if_defined_value = re.compile(\n            fr\"\\s*#\\s*{ELIF_GROUP}if\\s+defined\\s*\\(\\s*{MACRO_GROUP}\\s*\\)\\s*\"\n            fr\"(?P<op>&&)\\s*\"\n            fr\"(?P<openp>\\()?\\s*\"\n            fr\"(?P<macro2>[a-zA-Z_][a-zA-Z_0-9]*)\\s*\"\n            fr\"(?P<cmp>[=><!]+)\\s*\"\n            fr\"(?P<value>[0-9]*)\\s*\"\n            fr\"(?P<closep>\\))?\\s*\"\n        )\n        self._if_true = re.compile(\n            fr\"\\s*#\\s*{ELIF_GROUP}if\\s+{MACRO_GROUP}\\s*{OP_GROUP}\"\n        )\n\n        self._c_comment = re.compile(r\"/\\*.*?\\*/\")\n        self._cpp_comment = re.compile(r\"//\")\n\n    def _log(self, *args, **kwargs):\n        print(*args, **kwargs)\n\n    def _strip_comments(self, line):\n        # First strip c-style comments (may include //)\n        while True:\n            m = self._c_comment.search(line)\n            if m is None:\n                break\n            line = line[:m.start()] + line[m.end():]\n\n        # Then strip cpp-style comments\n        m = self._cpp_comment.search(line)\n        if m is not None:\n            line = line[:m.start()]\n\n        return line\n\n    def _fixup_indentation(self, macro, replace: [str]):\n        if len(replace) == 0:\n            return replace\n        if len(replace) == 1 and self._define.match(replace[0]) is None:\n            # If there is only one line, only replace defines\n            return replace\n\n\n        all_pound = True\n        for line in replace:\n            if not line.startswith('#'):\n                all_pound = False\n        if all_pound:\n            replace = [line[1:] for line in replace]\n\n        min_spaces = len(replace[0])\n        for line in replace:\n            spaces = 0\n            for i, c in enumerate(line):\n                if c != ' ':\n                    # Non-preprocessor line ==> skip the fixup\n                    if not all_pound and c != '#':\n                        return replace\n                    spaces = i\n                    break\n            min_spaces = min(min_spaces, spaces)\n\n        replace = [line[min_spaces:] for line in replace]\n\n        if all_pound:\n            replace = [\"#\" + line for line in replace]\n\n        return replace\n\n    def _handle_if_block(self, macro, idx, is_true, prepend):\n        \"\"\"\n        Remove the #if or #elif block starting on this line.\n        \"\"\"\n        REMOVE_ONE = 0\n        KEEP_ONE = 1\n        REMOVE_REST = 2\n\n        if is_true:\n            state = KEEP_ONE\n        else:\n            state = REMOVE_ONE\n\n        line = self._inlines[idx]\n        is_if = self._if.match(line) is not None\n        assert is_if or self._elif.match(line) is not None\n        depth = 0\n\n        start_idx = idx\n\n        idx += 1\n        replace = prepend\n        finished = False\n        while idx < len(self._inlines):\n            line = self._inlines[idx]\n            # Nested if statement\n            if self._if.match(line):\n                depth += 1\n                idx += 1\n                continue\n            # We're inside a nested statement\n            if depth > 0:\n                if self._endif.match(line):\n                    depth -= 1\n                idx += 1\n                continue\n\n            # We're at the original depth\n\n            # Looking only for an endif.\n            # We've found a true statement, but haven't\n            # completely elided the if block, so we just\n            # remove the remainder.\n            if state == REMOVE_REST:\n                if self._endif.match(line):\n                    if is_if:\n                        # Remove the endif because we took the first if\n                        idx += 1\n                    finished = True\n                    break\n                idx += 1\n                continue\n\n            if state == KEEP_ONE:\n                m = self._elif.match(line)\n                if self._endif.match(line):\n                    replace += self._inlines[start_idx + 1:idx]\n                    idx += 1\n                    finished = True\n                    break\n                if self._elif.match(line) or self._else.match(line):\n                    replace += self._inlines[start_idx + 1:idx]\n                    state = REMOVE_REST\n                idx += 1\n                continue\n\n            if state == REMOVE_ONE:\n                m = self._elif.match(line)\n                if m is not None:\n                    if is_if:\n                        idx += 1\n                        b = m.start('elif')\n                        e = m.end('elif')\n                        assert e - b == 2\n                        replace.append(line[:b] + line[e:])\n                    finished = True\n                    break\n                m = self._else.match(line)\n                if m is not None:\n                    if is_if:\n                        idx += 1\n                        while self._endif.match(self._inlines[idx]) is None:\n                            replace.append(self._inlines[idx])\n                            idx += 1\n                        idx += 1\n                    finished = True\n                    break\n                if self._endif.match(line):\n                    if is_if:\n                        # Remove the endif because no other elifs\n                        idx += 1\n                    finished = True\n                    break\n                idx += 1\n                continue\n        if not finished:\n            raise RuntimeError(\"Unterminated if block!\")\n\n        replace = self._fixup_indentation(macro, replace)\n\n        self._log(f\"\\tHardwiring {macro}\")\n        if start_idx > 0:\n            self._log(f\"\\t\\t  {self._inlines[start_idx - 1][:-1]}\")\n        for x in range(start_idx, idx):\n            self._log(f\"\\t\\t- {self._inlines[x][:-1]}\")\n        for line in replace:\n            self._log(f\"\\t\\t+ {line[:-1]}\")\n        if idx < len(self._inlines):\n            self._log(f\"\\t\\t  {self._inlines[idx][:-1]}\")\n\n        return idx, replace\n\n    def _preprocess_once(self):\n        outlines = []\n        idx = 0\n        changed = False\n        while idx < len(self._inlines):\n            line = self._inlines[idx]\n            sline = self._strip_comments(line)\n            m = self._ifdef.fullmatch(sline)\n            if_true = False\n            if m is None:\n                m = self._if_defined_value.fullmatch(sline)\n            if m is None:\n                m = self._if_defined.match(sline)\n            if m is None:\n                m = self._if_true.match(sline)\n                if_true = (m is not None)\n            if m is None:\n                outlines.append(line)\n                idx += 1\n                continue\n\n            groups = m.groupdict()\n            macro = groups['macro']\n            op = groups.get('op')\n\n            if not (macro in self._defs or macro in self._undefs):\n                outlines.append(line)\n                idx += 1\n                continue\n\n            defined = macro in self._defs\n\n            # Needed variables set:\n            # resolved: Is the statement fully resolved?\n            # is_true: If resolved, is the statement true?\n            ifdef = False\n            if if_true:\n                if not defined:\n                    outlines.append(line)\n                    idx += 1\n                    continue\n\n                defined_value = self._defs[macro]\n                is_int = True\n                try:\n                    defined_value = int(defined_value)\n                except TypeError:\n                    is_int = False\n                except ValueError:\n                    is_int = False\n\n                resolved = is_int\n                is_true = (defined_value != 0)\n\n                if resolved and op is not None:\n                    if op == '&&':\n                        resolved = not is_true\n                    else:\n                        assert op == '||'\n                        resolved = is_true\n\n            else:\n                ifdef = groups.get('not') is None\n                elseif = groups.get('elif') is not None\n\n                macro2 = groups.get('macro2')\n                cmp = groups.get('cmp')\n                value = groups.get('value')\n                openp = groups.get('openp')\n                closep = groups.get('closep')\n\n                is_true = (ifdef == defined)\n                resolved = True\n                if op is not None:\n                    if op == '&&':\n                        resolved = not is_true\n                    else:\n                        assert op == '||'\n                        resolved = is_true\n\n                if macro2 is not None and not resolved:\n                    assert ifdef and defined and op == '&&' and cmp is not None\n                    # If the statement is true, but we have a single value check, then\n                    # check the value.\n                    defined_value = self._defs[macro]\n                    are_ints = True\n                    try:\n                        defined_value = int(defined_value)\n                        value = int(value)\n                    except TypeError:\n                        are_ints = False\n                    except ValueError:\n                        are_ints = False\n                    if (\n                            macro == macro2 and\n                            ((openp is None) == (closep is None)) and\n                            are_ints\n                    ):\n                        resolved = True\n                        if cmp == '<':\n                            is_true = defined_value < value\n                        elif cmp == '<=':\n                            is_true = defined_value <= value\n                        elif cmp == '==':\n                            is_true = defined_value == value\n                        elif cmp == '!=':\n                            is_true = defined_value != value\n                        elif cmp == '>=':\n                            is_true = defined_value >= value\n                        elif cmp == '>':\n                            is_true = defined_value > value\n                        else:\n                            resolved = False\n\n                if op is not None and not resolved:\n                    # Remove the first op in the line + spaces\n                    if op == '&&':\n                        opre = op\n                    else:\n                        assert op == '||'\n                        opre = r'\\|\\|'\n                    needle = re.compile(fr\"(?P<if>\\s*#\\s*(el)?if\\s+).*?(?P<op>{opre}\\s*)\")\n                    match = needle.match(line)\n                    assert match is not None\n                    newline = line[:match.end('if')] + line[match.end('op'):]\n\n                    self._log(f\"\\tHardwiring partially resolved {macro}\")\n                    self._log(f\"\\t\\t- {line[:-1]}\")\n                    self._log(f\"\\t\\t+ {newline[:-1]}\")\n\n                    outlines.append(newline)\n                    idx += 1\n                    continue\n\n            # Skip any statements we cannot fully compute\n            if not resolved:\n                outlines.append(line)\n                idx += 1\n                continue\n\n            prepend = []\n            if macro in self._replaces:\n                assert not ifdef\n                assert op is None\n                value = self._replaces.pop(macro)\n                prepend = [f\"#define {macro} {value}\\n\"]\n\n            idx, replace = self._handle_if_block(macro, idx, is_true, prepend)\n            outlines += replace\n            changed = True\n\n        return changed, outlines\n\n    def preprocess(self, filename):\n        with open(filename, 'r') as f:\n            self._inlines = f.readlines()\n        changed = True\n        iters = 0\n        while changed:\n            iters += 1\n            changed, outlines = self._preprocess_once()\n            self._inlines = outlines\n\n        with open(filename, 'w') as f:\n            f.write(''.join(self._inlines))\n\n\nclass Freestanding(object):\n    def __init__(\n            self, zstd_deps: str, mem: str, source_lib: str, output_lib: str,\n            external_xxhash: bool, xxh64_state: Optional[str],\n            xxh64_prefix: Optional[str], rewritten_includes: [(str, str)],\n            defs: [(str, Optional[str])], replaces: [(str, str)],\n            undefs: [str], excludes: [str], seds: [str], spdx: bool,\n    ):\n        self._zstd_deps = zstd_deps\n        self._mem = mem\n        self._src_lib = source_lib\n        self._dst_lib = output_lib\n        self._external_xxhash = external_xxhash\n        self._xxh64_state = xxh64_state\n        self._xxh64_prefix = xxh64_prefix\n        self._rewritten_includes = rewritten_includes\n        self._defs = defs\n        self._replaces = replaces\n        self._undefs = undefs\n        self._excludes = excludes\n        self._seds = seds\n        self._spdx = spdx\n\n    def _dst_lib_file_paths(self):\n        \"\"\"\n        Yields all the file paths in the dst_lib.\n        \"\"\"\n        for root, dirname, filenames in os.walk(self._dst_lib):\n            for filename in filenames:\n                filepath = os.path.join(root, filename)\n                yield filepath\n\n    def _log(self, *args, **kwargs):\n        print(*args, **kwargs)\n\n    def _copy_file(self, lib_path):\n        suffixes = [\".c\", \".h\", \".S\"]\n        if not any((lib_path.endswith(suffix) for suffix in suffixes)):\n            return\n        if lib_path in SKIPPED_FILES:\n            self._log(f\"\\tSkipping file: {lib_path}\")\n            return\n        if self._external_xxhash and lib_path in XXHASH_FILES:\n            self._log(f\"\\tSkipping xxhash file: {lib_path}\")\n            return\n\n        src_path = os.path.join(self._src_lib, lib_path)\n        dst_path = os.path.join(self._dst_lib, lib_path)\n        self._log(f\"\\tCopying: {src_path} -> {dst_path}\")\n        shutil.copyfile(src_path, dst_path)\n\n    def _copy_source_lib(self):\n        self._log(\"Copying source library into output library\")\n\n        assert os.path.exists(self._src_lib)\n        os.makedirs(self._dst_lib, exist_ok=True)\n        self._copy_file(\"zstd.h\")\n        self._copy_file(\"zstd_errors.h\")\n        for subdir in INCLUDED_SUBDIRS:\n            src_dir = os.path.join(self._src_lib, subdir)\n            dst_dir = os.path.join(self._dst_lib, subdir)\n\n            assert os.path.exists(src_dir)\n            os.makedirs(dst_dir, exist_ok=True)\n\n            for filename in os.listdir(src_dir):\n                lib_path = os.path.join(subdir, filename)\n                self._copy_file(lib_path)\n\n    def _copy_zstd_deps(self):\n        dst_zstd_deps = os.path.join(self._dst_lib, \"common\", \"zstd_deps.h\")\n        self._log(f\"Copying zstd_deps: {self._zstd_deps} -> {dst_zstd_deps}\")\n        shutil.copyfile(self._zstd_deps, dst_zstd_deps)\n\n    def _copy_mem(self):\n        dst_mem = os.path.join(self._dst_lib, \"common\", \"mem.h\")\n        self._log(f\"Copying mem: {self._mem} -> {dst_mem}\")\n        shutil.copyfile(self._mem, dst_mem)\n\n    def _hardwire_preprocessor(self, name: str, value: Optional[str] = None, undef=False):\n        \"\"\"\n        If value=None then hardwire that it is defined, but not what the value is.\n        If undef=True then value must be None.\n        If value='' then the macro is defined to '' exactly.\n        \"\"\"\n        assert not (undef and value is not None)\n        for filepath in self._dst_lib_file_paths():\n            file = FileLines(filepath)\n\n    def _hardwire_defines(self):\n        self._log(\"Hardwiring macros\")\n        partial_preprocessor = PartialPreprocessor(self._defs, self._replaces, self._undefs)\n        for filepath in self._dst_lib_file_paths():\n            partial_preprocessor.preprocess(filepath)\n\n    def _remove_excludes(self):\n        self._log(\"Removing excluded sections\")\n        for exclude in self._excludes:\n            self._log(f\"\\tRemoving excluded sections for: {exclude}\")\n            begin_re = re.compile(f\"BEGIN {exclude}\")\n            end_re = re.compile(f\"END {exclude}\")\n            for filepath in self._dst_lib_file_paths():\n                file = FileLines(filepath)\n                outlines = []\n                skipped = []\n                emit = True\n                for line in file.lines:\n                    if emit and begin_re.search(line) is not None:\n                        assert end_re.search(line) is None\n                        emit = False\n                    if emit:\n                        outlines.append(line)\n                    else:\n                        skipped.append(line)\n                        if end_re.search(line) is not None:\n                            assert begin_re.search(line) is None\n                            self._log(f\"\\t\\tRemoving excluded section: {exclude}\")\n                            for s in skipped:\n                                self._log(f\"\\t\\t\\t- {s}\")\n                            emit = True\n                            skipped = []\n                if not emit:\n                    raise RuntimeError(\"Excluded section unfinished!\")\n                file.lines = outlines\n                file.write()\n\n    def _rewrite_include(self, original, rewritten):\n        self._log(f\"\\tRewriting include: {original} -> {rewritten}\")\n        regex = re.compile(f\"\\\\s*#\\\\s*include\\\\s*(?P<include>{original})\")\n        for filepath in self._dst_lib_file_paths():\n            file = FileLines(filepath)\n            for i, line in enumerate(file.lines):\n                match = regex.match(line)\n                if match is None:\n                    continue\n                s = match.start('include')\n                e = match.end('include')\n                file.lines[i] = line[:s] + rewritten + line[e:]\n            file.write()\n\n    def _rewrite_includes(self):\n        self._log(\"Rewriting includes\")\n        for original, rewritten in self._rewritten_includes:\n            self._rewrite_include(original, rewritten)\n\n    def _replace_xxh64_prefix(self):\n        if self._xxh64_prefix is None:\n            return\n        self._log(f\"Replacing XXH64 prefix with {self._xxh64_prefix}\")\n        replacements = []\n        if self._xxh64_state is not None:\n            replacements.append(\n                (re.compile(r\"([^\\w]|^)(?P<orig>XXH64_state_t)([^\\w]|$)\"), self._xxh64_state)\n            )\n        if self._xxh64_prefix is not None:\n            replacements.append(\n                (re.compile(r\"([^\\w]|^)(?P<orig>XXH64)[\\(_]\"), self._xxh64_prefix)\n            )\n        for filepath in self._dst_lib_file_paths():\n            file = FileLines(filepath)\n            for i, line in enumerate(file.lines):\n                modified = False\n                for regex, replacement in replacements:\n                    match = regex.search(line)\n                    while match is not None:\n                        modified = True\n                        b = match.start('orig')\n                        e = match.end('orig')\n                        line = line[:b] + replacement + line[e:]\n                        match = regex.search(line)\n                if modified:\n                    self._log(f\"\\t- {file.lines[i][:-1]}\")\n                    self._log(f\"\\t+ {line[:-1]}\")\n                file.lines[i] = line\n            file.write()\n\n    def _parse_sed(self, sed):\n        assert sed[0] == 's'\n        delim = sed[1]\n        match = re.fullmatch(f's{delim}(.+){delim}(.*){delim}(.*)', sed)\n        assert match is not None\n        regex = re.compile(match.group(1))\n        format_str = match.group(2)\n        is_global = match.group(3) == 'g'\n        return regex, format_str, is_global\n\n    def _process_sed(self, sed):\n        self._log(f\"Processing sed: {sed}\")\n        regex, format_str, is_global = self._parse_sed(sed)\n\n        for filepath in self._dst_lib_file_paths():\n            file = FileLines(filepath)\n            for i, line in enumerate(file.lines):\n                modified = False\n                while True:\n                    match = regex.search(line)\n                    if match is None:\n                        break\n                    replacement = format_str.format(match.groups(''), match.groupdict(''))\n                    b = match.start()\n                    e = match.end()\n                    line = line[:b] + replacement + line[e:]\n                    modified = True\n                    if not is_global:\n                        break\n                if modified:\n                    self._log(f\"\\t- {file.lines[i][:-1]}\")\n                    self._log(f\"\\t+ {line[:-1]}\")\n                file.lines[i] = line\n            file.write()\n\n    def _process_seds(self):\n        self._log(\"Processing seds\")\n        for sed in self._seds:\n            self._process_sed(sed)\n\n    def _process_spdx(self):\n        if not self._spdx:\n            return\n        self._log(\"Processing spdx\")\n        SPDX_C = \"// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause\\n\"\n        SPDX_H_S = \"/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */\\n\"\n        for filepath in self._dst_lib_file_paths():\n            file = FileLines(filepath)\n            if file.lines[0] == SPDX_C or file.lines[0] == SPDX_H_S:\n                continue\n            for line in file.lines:\n                if \"SPDX-License-Identifier\" in line:\n                    raise RuntimeError(f\"Unexpected SPDX license identifier: {file.filename} {repr(line)}\")\n            if file.filename.endswith(\".c\"):\n                file.lines.insert(0, SPDX_C)\n            elif file.filename.endswith(\".h\") or file.filename.endswith(\".S\"):\n                file.lines.insert(0, SPDX_H_S)\n            else:\n                raise RuntimeError(f\"Unexpected file extension: {file.filename}\")\n            file.write()\n\n\n\n    def go(self):\n        self._copy_source_lib()\n        self._copy_zstd_deps()\n        self._copy_mem()\n        self._hardwire_defines()\n        self._remove_excludes()\n        self._rewrite_includes()\n        self._replace_xxh64_prefix()\n        self._process_seds()\n        self._process_spdx()\n\n\ndef parse_optional_pair(defines: [str]) -> [(str, Optional[str])]:\n    output = []\n    for define in defines:\n        parsed = define.split('=')\n        if len(parsed) == 1:\n            output.append((parsed[0], None))\n        elif len(parsed) == 2:\n            output.append((parsed[0], parsed[1]))\n        else:\n            raise RuntimeError(f\"Bad define: {define}\")\n    return output\n\n\ndef parse_pair(rewritten_includes: [str]) -> [(str, str)]:\n    output = []\n    for rewritten_include in rewritten_includes:\n        parsed = rewritten_include.split('=')\n        if len(parsed) == 2:\n            output.append((parsed[0], parsed[1]))\n        else:\n            raise RuntimeError(f\"Bad rewritten include: {rewritten_include}\")\n    return output\n\n\n\ndef main(name, args):\n    parser = argparse.ArgumentParser(prog=name)\n    parser.add_argument(\"--zstd-deps\", default=\"zstd_deps.h\", help=\"Zstd dependencies file\")\n    parser.add_argument(\"--mem\", default=\"mem.h\", help=\"Memory module\")\n    parser.add_argument(\"--source-lib\", default=\"../../lib\", help=\"Location of the zstd library\")\n    parser.add_argument(\"--output-lib\", default=\"./freestanding_lib\", help=\"Where to output the freestanding zstd library\")\n    parser.add_argument(\"--xxhash\", default=None, help=\"Alternate external xxhash include e.g. --xxhash='<xxhash.h>'. If set xxhash is not included.\")\n    parser.add_argument(\"--xxh64-state\", default=None, help=\"Alternate XXH64 state type (excluding _) e.g. --xxh64-state='struct xxh64_state'\")\n    parser.add_argument(\"--xxh64-prefix\", default=None, help=\"Alternate XXH64 function prefix (excluding _) e.g. --xxh64-prefix=xxh64\")\n    parser.add_argument(\"--rewrite-include\", default=[], dest=\"rewritten_includes\", action=\"append\", help=\"Rewrite an include REGEX=NEW (e.g. '<stddef\\\\.h>=<linux/types.h>')\")\n    parser.add_argument(\"--sed\", default=[], dest=\"seds\", action=\"append\", help=\"Apply a sed replacement. Format: `s/REGEX/FORMAT/[g]`. REGEX is a Python regex. FORMAT is a Python format string formatted by the regex dict.\")\n    parser.add_argument(\"--spdx\", action=\"store_true\", help=\"Add SPDX License Identifiers\")\n    parser.add_argument(\"-D\", \"--define\", default=[], dest=\"defs\", action=\"append\", help=\"Pre-define this macro (can be passed multiple times)\")\n    parser.add_argument(\"-U\", \"--undefine\", default=[], dest=\"undefs\", action=\"append\", help=\"Pre-undefine this macro (can be passed multiple times)\")\n    parser.add_argument(\"-R\", \"--replace\", default=[], dest=\"replaces\", action=\"append\", help=\"Pre-define this macro and replace the first ifndef block with its definition\")\n    parser.add_argument(\"-E\", \"--exclude\", default=[], dest=\"excludes\", action=\"append\", help=\"Exclude all lines between 'BEGIN <EXCLUDE>' and 'END <EXCLUDE>'\")\n    args = parser.parse_args(args)\n\n    # Always remove threading\n    if \"ZSTD_MULTITHREAD\" not in args.undefs:\n        args.undefs.append(\"ZSTD_MULTITHREAD\")\n\n    args.defs = parse_optional_pair(args.defs)\n    for name, _ in args.defs:\n        if name in args.undefs:\n            raise RuntimeError(f\"{name} is both defined and undefined!\")\n\n    # Always set tracing to 0\n    if \"ZSTD_NO_TRACE\" not in (arg[0] for arg in args.defs):\n        args.defs.append((\"ZSTD_NO_TRACE\", None))\n        args.defs.append((\"ZSTD_TRACE\", \"0\"))\n\n    args.replaces = parse_pair(args.replaces)\n    for name, _ in args.replaces:\n        if name in args.undefs or name in args.defs:\n            raise RuntimeError(f\"{name} is both replaced and (un)defined!\")\n\n    args.rewritten_includes = parse_pair(args.rewritten_includes)\n\n    external_xxhash = False\n    if args.xxhash is not None:\n        external_xxhash = True\n        args.rewritten_includes.append(('\"(\\\\.\\\\./common/)?xxhash.h\"', args.xxhash))\n\n    if args.xxh64_prefix is not None:\n        if not external_xxhash:\n            raise RuntimeError(\"--xxh64-prefix may only be used with --xxhash provided\")\n\n    if args.xxh64_state is not None:\n        if not external_xxhash:\n            raise RuntimeError(\"--xxh64-state may only be used with --xxhash provided\")\n\n    Freestanding(\n        args.zstd_deps,\n        args.mem,\n        args.source_lib,\n        args.output_lib,\n        external_xxhash,\n        args.xxh64_state,\n        args.xxh64_prefix,\n        args.rewritten_includes,\n        args.defs,\n        args.replaces,\n        args.undefs,\n        args.excludes,\n        args.seds,\n        args.spdx,\n    ).go()\n\nif __name__ == \"__main__\":\n    main(sys.argv[0], sys.argv[1:])\n"
  },
  {
    "path": "contrib/linux-kernel/.gitignore",
    "content": "!lib/zstd\n!lib/zstd/*\n*.o\n*.a\n"
  },
  {
    "path": "contrib/linux-kernel/Makefile",
    "content": "# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ################################################################\n\n.PHONY: libzstd\nlibzstd:\n\trm -rf linux\n\tmkdir -p linux\n\tmkdir -p linux/include/linux\n\tmkdir -p linux/lib/zstd\n\t../freestanding_lib/freestanding.py \\\n\t\t--source-lib ../../lib \\\n\t\t--output-lib linux/lib/zstd \\\n\t\t--xxhash '<linux/xxhash.h>' \\\n\t\t--xxh64-state 'struct xxh64_state' \\\n\t\t--xxh64-prefix 'xxh64' \\\n\t\t--rewrite-include '<limits\\.h>=<linux/limits.h>' \\\n\t\t--rewrite-include '<stddef\\.h>=<linux/types.h>' \\\n\t\t--rewrite-include '\"\\.\\./zstd.h\"=<linux/zstd.h>' \\\n\t\t--rewrite-include '\"(\\.\\./)?zstd_errors.h\"=<linux/zstd_errors.h>' \\\n\t\t--sed 's,/\\*\\*\\*,/* *,g' \\\n\t\t--sed 's,/\\*\\*,/*,g' \\\n\t\t--spdx \\\n\t\t-DZSTD_NO_INTRINSICS \\\n\t\t-DZSTD_NO_UNUSED_FUNCTIONS \\\n\t\t-DZSTD_LEGACY_SUPPORT=0 \\\n\t\t-DZSTD_STATIC_LINKING_ONLY \\\n\t\t-DFSE_STATIC_LINKING_ONLY \\\n\t\t-DXXH_STATIC_LINKING_ONLY \\\n\t\t-D__GNUC__ \\\n\t\t-D__linux__=1 \\\n\t\t-DSTATIC_BMI2=0 \\\n\t\t-DZSTD_ADDRESS_SANITIZER=0 \\\n\t\t-DZSTD_MEMORY_SANITIZER=0 \\\n\t\t-DZSTD_DATAFLOW_SANITIZER=0 \\\n\t\t-DZSTD_COMPRESS_HEAPMODE=1 \\\n\t\t-UNO_PREFETCH \\\n\t\t-U__cplusplus \\\n\t\t-UZSTD_DLL_EXPORT \\\n\t\t-UZSTD_DLL_IMPORT \\\n\t\t-U__ICCARM__ \\\n\t\t-UZSTD_MULTITHREAD \\\n\t\t-U_MSC_VER \\\n\t\t-U_WIN32 \\\n\t\t-RZSTDLIB_VISIBLE= \\\n\t\t-RZSTDERRORLIB_VISIBLE= \\\n\t\t-RZSTD_FALLTHROUGH=fallthrough \\\n\t\t-DZSTD_HAVE_WEAK_SYMBOLS=0 \\\n\t\t-DZSTD_TRACE=0 \\\n\t\t-DZSTD_NO_TRACE \\\n\t\t-DZSTD_DISABLE_ASM \\\n\t\t-DZSTD_LINUX_KERNEL\n\trm linux/lib/zstd/decompress/huf_decompress_amd64.S\n\tmv linux/lib/zstd/zstd.h linux/include/linux/zstd_lib.h\n\tmv linux/lib/zstd/zstd_errors.h linux/include/linux/\n\tcp linux_zstd.h linux/include/linux/zstd.h\n\tcp zstd_common_module.c linux/lib/zstd\n\tcp zstd_compress_module.c linux/lib/zstd\n\tcp zstd_decompress_module.c linux/lib/zstd\n\tcp decompress_sources.h linux/lib/zstd\n\tcp linux.mk linux/lib/zstd/Makefile\n\nLINUX ?= $(HOME)/repos/linux\n\n.PHONY: import\nimport: libzstd\n\trm -f $(LINUX)/include/linux/zstd.h\n\trm -f $(LINUX)/include/linux/zstd_errors.h\n\trm -rf $(LINUX)/lib/zstd\n\tcp linux/include/linux/zstd.h $(LINUX)/include/linux\n\tcp linux/include/linux/zstd_lib.h $(LINUX)/include/linux\n\tcp linux/include/linux/zstd_errors.h $(LINUX)/include/linux\n\tcp -r linux/lib/zstd $(LINUX)/lib\n\nimport-upstream:\n\trm -rf $(LINUX)/lib/zstd\n\tmkdir $(LINUX)/lib/zstd\n\tcp ../../lib/zstd.h $(LINUX)/include/linux/zstd_lib.h\n\tcp -r ../../lib/common $(LINUX)/lib/zstd\n\tcp -r ../../lib/compress $(LINUX)/lib/zstd\n\tcp -r ../../lib/decompress $(LINUX)/lib/zstd\n\tmv $(LINUX)/lib/zstd/zstd_errors.h $(LINUX)/include/linux\n\trm $(LINUX)/lib/zstd/common/threading.*\n\trm $(LINUX)/lib/zstd/common/pool.*\n\trm $(LINUX)/lib/zstd/common/xxhash.*\n\trm $(LINUX)/lib/zstd/compress/zstdmt_*\n\nDEBUGFLAGS= -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \\\n            -Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \\\n            -Wstrict-prototypes -Wundef -Wpointer-arith \\\n            -Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \\\n            -Wredundant-decls -Wmissing-prototypes -Wc++-compat \\\n\t    -Wimplicit-fallthrough\n\n.PHONY: test\ntest: libzstd\n\t$(MAKE) -C test run-test CFLAGS=\"-O3 $(CFLAGS) $(DEBUGFLAGS) -Werror\" -j\n\n.PHONY: clean\nclean:\n\t$(RM) -rf linux\n\t$(MAKE) -C test clean\n"
  },
  {
    "path": "contrib/linux-kernel/README.md",
    "content": "# Zstd in the Linux Kernel\n\nThis directory contains the scripts needed to transform upstream zstd into the version imported into the kernel. All the transforms are automated and tested by our continuous integration.\n\n## Upgrading Zstd in the Linux Kernel\n\n1. `cd` into this directory.\n2. Run `make libzstd` and read the output. Make sure that all the diffs printed and changes made by the script are correct.\n3. Run `make test` and ensure that it passes.\n4. Import zstd into the Linux Kernel `make import LINUX=/path/to/linux/repo`\n5. Inspect the diff for sanity.\n6. Check the Linux Kernel history for zstd. If any patches were made to the kernel version of zstd, but not to upstream zstd, then port them upstream if necessary.\n7. Test the diff. Benchmark if necessary. Make sure to test multiple architectures: At least x86, i386, and arm.\n8. Submit the patch to the LKML.\n"
  },
  {
    "path": "contrib/linux-kernel/btrfs-benchmark.sh",
    "content": "# !/bin/sh\nset -e\n\n# Benchmarks run on a Ubuntu 14.04 VM with 2 cores and 4 GiB of RAM.\n# The VM is running on a Macbook Pro with a 3.1 GHz Intel Core i7 processor and\n# 16 GB of RAM and an SSD.\n\n# silesia is a directory that can be downloaded from\n# http://mattmahoney.net/dc/silesia.html\n# ls -l silesia/\n# total 203M\n# -rwxr-xr-x 1 terrelln 9.8M Apr 12  2002 dickens\n# -rwxr-xr-x 1 terrelln  49M May 31  2002 mozilla\n# -rwxr-xr-x 1 terrelln 9.6M Mar 20  2003 mr\n# -rwxr-xr-x 1 terrelln  32M Apr  2  2002 nci\n# -rwxr-xr-x 1 terrelln 5.9M Jul  4  2002 ooffice\n# -rwxr-xr-x 1 terrelln 9.7M Apr 11  2002 osdb\n# -rwxr-xr-x 1 terrelln 6.4M Apr  2  2002 reymont\n# -rwxr-xr-x 1 terrelln  21M Mar 25  2002 samba\n# -rwxr-xr-x 1 terrelln 7.0M Mar 24  2002 sao\n# -rwxr-xr-x 1 terrelln  40M Mar 25  2002 webster\n# -rwxr-xr-x 1 terrelln 8.1M Apr  4  2002 x-ray\n# -rwxr-xr-x 1 terrelln 5.1M Nov 30  2000 xml\n\n# $HOME is on a ext4 filesystem\nBENCHMARK_DIR=\"$HOME/silesia/\"\nN=10\n\n# Normalize the environment\nsudo umount /mnt/btrfs 2> /dev/null > /dev/null || true\nsudo mount -t btrfs $@ /dev/sda3 /mnt/btrfs\nsudo rm -rf /mnt/btrfs/*\nsync\nsudo umount /mnt/btrfs\nsudo mount -t btrfs $@ /dev/sda3 /mnt/btrfs\n\n# Run the benchmark\necho \"Compression\"\ntime sh -c \"for i in \\$(seq $N); do sudo cp -r $BENCHMARK_DIR /mnt/btrfs/\\$i; done; sync\"\n\necho \"Approximate compression ratio\"\nprintf \"%d / %d\\n\"                                                             \\\n  $(df /mnt/btrfs --output=used -B 1 | tail -n 1)                              \\\n  $(sudo du /mnt/btrfs -b -d 0 | tr '\\t' '\\n' | head -n 1);\n\n# Unmount and remount to avoid any caching\nsudo umount /mnt/btrfs\nsudo mount -t btrfs $@ /dev/sda3 /mnt/btrfs\n\necho \"Decompression\"\ntime sudo tar -c /mnt/btrfs 2> /dev/null | wc -c > /dev/null\n\nsudo rm -rf /mnt/btrfs/*\nsudo umount /mnt/btrfs\n\n# Run for each of -o compress-force={none, lzo, zlib, zstd} 5 times and take the\n# min time and ratio.\n# Ran zstd with compression levels {1, 3, 6, 9, 12, 15}.\n# Original size: 2119415342 B (using du /mnt/btrfs)\n\n# none\n# compress: 4.205 s\n# decompress: 3.090 s\n# ratio: 0.99\n\n# lzo\n# compress: 5.328 s\n# decompress: 4.793 s\n# ratio: 1.66\n\n# zlib\n# compress: 32.588 s\n# decompress: 8.791 s\n# ratio : 2.58\n\n# zstd 1\n# compress: 8.147 s\n# decompress: 5.527 s\n# ratio : 2.57\n\n# zstd 3\n# compress: 12.207 s\n# decompress: 5.195 s\n# ratio : 2.71\n\n# zstd 6\n# compress: 30.253 s\n# decompress: 5.324 s\n# ratio : 2.87\n\n# zstd 9\n# compress: 49.659 s\n# decompress: 5.220 s\n# ratio : 2.92\n\n# zstd 12\n# compress: 99.245 s\n# decompress: 5.193 s\n# ratio : 2.93\n\n# zstd 15\n# compress: 196.997 s\n# decompress: 5.992 s\n# ratio : 3.01\n"
  },
  {
    "path": "contrib/linux-kernel/btrfs-extract-benchmark.sh",
    "content": "# !/bin/sh\nset -e\n\n# Benchmarks run on a Ubuntu 14.04 VM with 2 cores and 4 GiB of RAM.\n# The VM is running on a Macbook Pro with a 3.1 GHz Intel Core i7 processor and\n# 16 GB of RAM and an SSD.\n\n# silesia is a directory that can be downloaded from\n# http://mattmahoney.net/dc/silesia.html\n# ls -l silesia/\n# total 203M\n# -rwxr-xr-x 1 terrelln 9.8M Apr 12  2002 dickens\n# -rwxr-xr-x 1 terrelln  49M May 31  2002 mozilla\n# -rwxr-xr-x 1 terrelln 9.6M Mar 20  2003 mr\n# -rwxr-xr-x 1 terrelln  32M Apr  2  2002 nci\n# -rwxr-xr-x 1 terrelln 5.9M Jul  4  2002 ooffice\n# -rwxr-xr-x 1 terrelln 9.7M Apr 11  2002 osdb\n# -rwxr-xr-x 1 terrelln 6.4M Apr  2  2002 reymont\n# -rwxr-xr-x 1 terrelln  21M Mar 25  2002 samba\n# -rwxr-xr-x 1 terrelln 7.0M Mar 24  2002 sao\n# -rwxr-xr-x 1 terrelln  40M Mar 25  2002 webster\n# -rwxr-xr-x 1 terrelln 8.1M Apr  4  2002 x-ray\n# -rwxr-xr-x 1 terrelln 5.1M Nov 30  2000 xml\n\n# $HOME is on a ext4 filesystem\nBENCHMARK_FILE=\"linux-4.11.6.tar\"\nBENCHMARK_DIR=\"$HOME/$BENCHMARK_FILE\"\n\n# Normalize the environment\nsudo umount /mnt/btrfs 2> /dev/null > /dev/null || true\nsudo mount -t btrfs $@ /dev/sda3 /mnt/btrfs\nsudo rm -rf /mnt/btrfs/*\nsync\nsudo umount /mnt/btrfs\nsudo mount -t btrfs $@ /dev/sda3 /mnt/btrfs\n\n# Run the benchmark\necho \"Copy\"\ntime sh -c \"sudo cp -r $BENCHMARK_DIR /mnt/btrfs/$BENCHMARK_FILE && sync\"\n\necho \"Approximate tarred compression ratio\"\nprintf \"%d / %d\\n\"                                                             \\\n  $(df /mnt/btrfs --output=used -B 1 | tail -n 1)                              \\\n  $(sudo du /mnt/btrfs -b -d 0 | tr '\\t' '\\n' | head -n 1);\n\n# Unmount and remount to avoid any caching\nsudo umount /mnt/btrfs\nsudo mount -t btrfs $@ /dev/sda3 /mnt/btrfs\n\necho \"Extract\"\ntime sh -c \"sudo tar -C /mnt/btrfs -xf /mnt/btrfs/$BENCHMARK_FILE && sync\"\n\n# Remove the tarball, leaving only the extracted data\nsudo rm /mnt/btrfs/$BENCHMARK_FILE\n# Unmount and remount to avoid any caching\nsudo umount /mnt/btrfs\nsudo mount -t btrfs $@ /dev/sda3 /mnt/btrfs\n\necho \"Approximate extracted compression ratio\"\nprintf \"%d / %d\\n\"                                                             \\\n  $(df /mnt/btrfs --output=used -B 1 | tail -n 1)                              \\\n  $(sudo du /mnt/btrfs -b -d 0 | tr '\\t' '\\n' | head -n 1);\n\necho \"Read\"\ntime sudo tar -c /mnt/btrfs 2> /dev/null | wc -c > /dev/null\n\nsudo rm -rf /mnt/btrfs/*\nsudo umount /mnt/btrfs\n\n# Run for each of -o compress-force={none, lzo, zlib, zstd} 5 times and take the\n# min time and ratio.\n\n# none\n# copy: 0.981 s\n# extract: 5.501 s\n# read: 8.807 s\n# tarball ratio: 0.97\n# extracted ratio: 0.78\n\n# lzo\n# copy: 1.631 s\n# extract: 8.458 s\n# read: 8.585 s\n# tarball ratio: 2.06\n# extracted ratio: 1.38\n\n# zlib\n# copy: 7.750 s\n# extract: 21.544 s\n# read: 11.744 s\n# tarball ratio : 3.40\n# extracted ratio: 1.86\n\n# zstd 1\n# copy: 2.579 s\n# extract: 11.479 s\n# read: 9.389 s\n# tarball ratio : 3.57\n# extracted ratio: 1.85\n"
  },
  {
    "path": "contrib/linux-kernel/decompress_sources.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */\n/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/*\n * This file includes every .c file needed for decompression.\n * It is used by lib/decompress_unzstd.c to include the decompression\n * source into the translation-unit, so it can be used for kernel\n * decompression.\n */\n\n/*\n * Disable the ASM Huffman implementation because we need to\n * include all the sources.\n */\n#define ZSTD_DISABLE_ASM 1\n\n#include \"common/debug.c\"\n#include \"common/entropy_common.c\"\n#include \"common/error_private.c\"\n#include \"common/fse_decompress.c\"\n#include \"common/zstd_common.c\"\n#include \"decompress/huf_decompress.c\"\n#include \"decompress/zstd_ddict.c\"\n#include \"decompress/zstd_decompress.c\"\n#include \"decompress/zstd_decompress_block.c\"\n#include \"zstd_decompress_module.c\"\n"
  },
  {
    "path": "contrib/linux-kernel/linux.mk",
    "content": "# SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause\n# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ################################################################\nobj-$(CONFIG_ZSTD_COMPRESS) += zstd_compress.o\nobj-$(CONFIG_ZSTD_DECOMPRESS) += zstd_decompress.o\nobj-$(CONFIG_ZSTD_COMMON) += zstd_common.o\n\nzstd_compress-y := \\\n\t\tzstd_compress_module.o \\\n\t\tcompress/fse_compress.o \\\n\t\tcompress/hist.o \\\n\t\tcompress/huf_compress.o \\\n\t\tcompress/zstd_compress.o \\\n\t\tcompress/zstd_compress_literals.o \\\n\t\tcompress/zstd_compress_sequences.o \\\n\t\tcompress/zstd_compress_superblock.o \\\n\t\tcompress/zstd_double_fast.o \\\n\t\tcompress/zstd_fast.o \\\n\t\tcompress/zstd_lazy.o \\\n\t\tcompress/zstd_ldm.o \\\n\t\tcompress/zstd_opt.o \\\n\t\tcompress/zstd_preSplit.o \\\n\nzstd_decompress-y := \\\n\t\tzstd_decompress_module.o \\\n\t\tdecompress/huf_decompress.o \\\n\t\tdecompress/zstd_ddict.o \\\n\t\tdecompress/zstd_decompress.o \\\n\t\tdecompress/zstd_decompress_block.o \\\n\nzstd_common-y := \\\n\t\tzstd_common_module.o \\\n\t\tcommon/debug.o \\\n\t\tcommon/entropy_common.o \\\n\t\tcommon/error_private.o \\\n\t\tcommon/fse_decompress.o \\\n\t\tcommon/zstd_common.o \\\n"
  },
  {
    "path": "contrib/linux-kernel/linux_zstd.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */\n/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of https://github.com/facebook/zstd) and\n * the GPLv2 (found in the COPYING file in the root directory of\n * https://github.com/facebook/zstd). You may select, at your option, one of the\n * above-listed licenses.\n */\n\n#ifndef LINUX_ZSTD_H\n#define LINUX_ZSTD_H\n\n/**\n * This is a kernel-style API that wraps the upstream zstd API, which cannot be\n * used directly because the symbols aren't exported. It exposes the minimal\n * functionality which is currently required by users of zstd in the kernel.\n * Expose extra functions from lib/zstd/zstd.h as needed.\n */\n\n/* ======   Dependency   ====== */\n#include <linux/types.h>\n#include <linux/zstd_errors.h>\n#include <linux/zstd_lib.h>\n\n/* ======   Helper Functions   ====== */\n/**\n * zstd_compress_bound() - maximum compressed size in worst case scenario\n * @src_size: The size of the data to compress.\n *\n * Return:    The maximum compressed size in the worst case scenario.\n */\nsize_t zstd_compress_bound(size_t src_size);\n\n/**\n * zstd_is_error() - tells if a size_t function result is an error code\n * @code:  The function result to check for error.\n *\n * Return: Non-zero iff the code is an error.\n */\nunsigned int zstd_is_error(size_t code);\n\n/**\n * enum zstd_error_code - zstd error codes\n */\ntypedef ZSTD_ErrorCode zstd_error_code;\n\n/**\n * zstd_get_error_code() - translates an error function result to an error code\n * @code:  The function result for which zstd_is_error(code) is true.\n *\n * Return: A unique error code for this error.\n */\nzstd_error_code zstd_get_error_code(size_t code);\n\n/**\n * zstd_get_error_name() - translates an error function result to a string\n * @code:  The function result for which zstd_is_error(code) is true.\n *\n * Return: An error string corresponding to the error code.\n */\nconst char *zstd_get_error_name(size_t code);\n\n/**\n * zstd_min_clevel() - minimum allowed compression level\n *\n * Return: The minimum allowed compression level.\n */\nint zstd_min_clevel(void);\n\n/**\n * zstd_max_clevel() - maximum allowed compression level\n *\n * Return: The maximum allowed compression level.\n */\nint zstd_max_clevel(void);\n\n/**\n * zstd_default_clevel() - default compression level\n *\n * Return: Default compression level.\n */\nint zstd_default_clevel(void);\n\n/**\n * struct zstd_custom_mem - custom memory allocation\n */\ntypedef ZSTD_customMem zstd_custom_mem;\n\n/**\n * struct zstd_dict_load_method - Dictionary load method.\n * See zstd_lib.h.\n */\ntypedef ZSTD_dictLoadMethod_e zstd_dict_load_method;\n\n/**\n * struct zstd_dict_content_type - Dictionary context type.\n * See zstd_lib.h.\n */\ntypedef ZSTD_dictContentType_e zstd_dict_content_type;\n\n/* ======   Parameter Selection   ====== */\n\n/**\n * enum zstd_strategy - zstd compression search strategy\n *\n * From faster to stronger. See zstd_lib.h.\n */\ntypedef ZSTD_strategy zstd_strategy;\n\n/**\n * struct zstd_compression_parameters - zstd compression parameters\n * @windowLog:    Log of the largest match distance. Larger means more\n *                compression, and more memory needed during decompression.\n * @chainLog:     Fully searched segment. Larger means more compression,\n *                slower, and more memory (useless for fast).\n * @hashLog:      Dispatch table. Larger means more compression,\n *                slower, and more memory.\n * @searchLog:    Number of searches. Larger means more compression and slower.\n * @searchLength: Match length searched. Larger means faster decompression,\n *                sometimes less compression.\n * @targetLength: Acceptable match size for optimal parser (only). Larger means\n *                more compression, and slower.\n * @strategy:     The zstd compression strategy.\n *\n * See zstd_lib.h.\n */\ntypedef ZSTD_compressionParameters zstd_compression_parameters;\n\n/**\n * struct zstd_frame_parameters - zstd frame parameters\n * @contentSizeFlag: Controls whether content size will be present in the\n *                   frame header (when known).\n * @checksumFlag:    Controls whether a 32-bit checksum is generated at the\n *                   end of the frame for error detection.\n * @noDictIDFlag:    Controls whether dictID will be saved into the frame\n *                   header when using dictionary compression.\n *\n * The default value is all fields set to 0. See zstd_lib.h.\n */\ntypedef ZSTD_frameParameters zstd_frame_parameters;\n\n/**\n * struct zstd_parameters - zstd parameters\n * @cParams: The compression parameters.\n * @fParams: The frame parameters.\n */\ntypedef ZSTD_parameters zstd_parameters;\n\n/**\n * zstd_get_params() - returns zstd_parameters for selected level\n * @level:              The compression level\n * @estimated_src_size: The estimated source size to compress or 0\n *                      if unknown.\n *\n * Return:              The selected zstd_parameters.\n */\nzstd_parameters zstd_get_params(int level,\n\tunsigned long long estimated_src_size);\n\n/**\n * zstd_get_cparams() - returns zstd_compression_parameters for selected level\n * @level:              The compression level\n * @estimated_src_size: The estimated source size to compress or 0\n *                      if unknown.\n * @dict_size:          Dictionary size.\n *\n * Return:              The selected zstd_compression_parameters.\n */\nzstd_compression_parameters zstd_get_cparams(int level,\n\tunsigned long long estimated_src_size, size_t dict_size);\n\ntypedef ZSTD_CCtx zstd_cctx;\ntypedef ZSTD_cParameter zstd_cparameter;\n\n/**\n * zstd_cctx_set_param() - sets a compression parameter\n * @cctx:         The context. Must have been initialized with zstd_init_cctx().\n * @param:        The parameter to set.\n * @value:        The value to set the parameter to.\n *\n * Return:        Zero or an error, which can be checked using zstd_is_error().\n */\nsize_t zstd_cctx_set_param(zstd_cctx *cctx, zstd_cparameter param, int value);\n\n/* ======   Single-pass Compression   ====== */\n\n/**\n * zstd_cctx_workspace_bound() - max memory needed to initialize a zstd_cctx\n * @parameters: The compression parameters to be used.\n *\n * If multiple compression parameters might be used, the caller must call\n * zstd_cctx_workspace_bound() for each set of parameters and use the maximum\n * size.\n *\n * Return:      A lower bound on the size of the workspace that is passed to\n *              zstd_init_cctx().\n */\nsize_t zstd_cctx_workspace_bound(const zstd_compression_parameters *parameters);\n\n/**\n * zstd_cctx_workspace_bound_with_ext_seq_prod() - max memory needed to\n * initialize a zstd_cctx when using the block-level external sequence\n * producer API.\n * @parameters: The compression parameters to be used.\n *\n * If multiple compression parameters might be used, the caller must call\n * this function for each set of parameters and use the maximum size.\n *\n * Return:      A lower bound on the size of the workspace that is passed to\n *              zstd_init_cctx().\n */\nsize_t zstd_cctx_workspace_bound_with_ext_seq_prod(const zstd_compression_parameters *parameters);\n\n/**\n * zstd_init_cctx() - initialize a zstd compression context\n * @workspace:      The workspace to emplace the context into. It must outlive\n *                  the returned context.\n * @workspace_size: The size of workspace. Use zstd_cctx_workspace_bound() to\n *                  determine how large the workspace must be.\n *\n * Return:          A zstd compression context or NULL on error.\n */\nzstd_cctx *zstd_init_cctx(void *workspace, size_t workspace_size);\n\n/**\n * zstd_compress_cctx() - compress src into dst with the initialized parameters\n * @cctx:         The context. Must have been initialized with zstd_init_cctx().\n * @dst:          The buffer to compress src into.\n * @dst_capacity: The size of the destination buffer. May be any size, but\n *                ZSTD_compressBound(srcSize) is guaranteed to be large enough.\n * @src:          The data to compress.\n * @src_size:     The size of the data to compress.\n * @parameters:   The compression parameters to be used.\n *\n * Return:        The compressed size or an error, which can be checked using\n *                zstd_is_error().\n */\nsize_t zstd_compress_cctx(zstd_cctx *cctx, void *dst, size_t dst_capacity,\n\tconst void *src, size_t src_size, const zstd_parameters *parameters);\n\n/**\n * zstd_create_cctx_advanced() - Create compression context\n * @custom_mem:   Custom allocator.\n *\n * Return:        NULL on error, pointer to compression context otherwise.\n */\nzstd_cctx *zstd_create_cctx_advanced(zstd_custom_mem custom_mem);\n\n/**\n * zstd_free_cctx() - Free compression context\n * @cdict:        Pointer to compression context.\n *\n * Return:        Always 0.\n */\nsize_t zstd_free_cctx(zstd_cctx* cctx);\n\n/**\n * struct zstd_cdict - Compression dictionary.\n * See zstd_lib.h.\n */\ntypedef ZSTD_CDict zstd_cdict;\n\n/**\n * zstd_create_cdict_byreference() - Create compression dictionary\n * @dict:              Pointer to dictionary buffer.\n * @dict_size:         Size of the dictionary buffer.\n * @dict_load_method:  Dictionary load method.\n * @dict_content_type: Dictionary content type.\n * @custom_mem:        Memory allocator.\n *\n * Note, this uses @dict by reference (ZSTD_dlm_byRef), so it should be\n * free before zstd_cdict is destroyed.\n *\n * Return:             NULL on error, pointer to compression dictionary\n *                     otherwise.\n */\nzstd_cdict *zstd_create_cdict_byreference(const void *dict, size_t dict_size,\n\t\t\t\t\t  zstd_compression_parameters cparams,\n\t\t\t\t\t  zstd_custom_mem custom_mem);\n\n/**\n * zstd_free_cdict() - Free compression dictionary\n * @cdict:        Pointer to compression dictionary.\n *\n * Return:        Always 0.\n */\nsize_t zstd_free_cdict(zstd_cdict* cdict);\n\n/**\n * zstd_compress_using_cdict() - compress src into dst using a dictionary\n * @cctx:         The context. Must have been initialized with zstd_init_cctx().\n * @dst:          The buffer to compress src into.\n * @dst_capacity: The size of the destination buffer. May be any size, but\n *                ZSTD_compressBound(srcSize) is guaranteed to be large enough.\n * @src:          The data to compress.\n * @src_size:     The size of the data to compress.\n * @cdict:        The dictionary to be used.\n *\n * Return:        The compressed size or an error, which can be checked using\n *                zstd_is_error().\n */\nsize_t zstd_compress_using_cdict(zstd_cctx *cctx, void *dst,\n\tsize_t dst_capacity, const void *src, size_t src_size,\n\tconst zstd_cdict *cdict);\n\n/* ======   Single-pass Decompression   ====== */\n\ntypedef ZSTD_DCtx zstd_dctx;\n\n/**\n * zstd_dctx_workspace_bound() - max memory needed to initialize a zstd_dctx\n *\n * Return: A lower bound on the size of the workspace that is passed to\n *         zstd_init_dctx().\n */\nsize_t zstd_dctx_workspace_bound(void);\n\n/**\n * zstd_init_dctx() - initialize a zstd decompression context\n * @workspace:      The workspace to emplace the context into. It must outlive\n *                  the returned context.\n * @workspace_size: The size of workspace. Use zstd_dctx_workspace_bound() to\n *                  determine how large the workspace must be.\n *\n * Return:          A zstd decompression context or NULL on error.\n */\nzstd_dctx *zstd_init_dctx(void *workspace, size_t workspace_size);\n\n/**\n * zstd_decompress_dctx() - decompress zstd compressed src into dst\n * @dctx:         The decompression context.\n * @dst:          The buffer to decompress src into.\n * @dst_capacity: The size of the destination buffer. Must be at least as large\n *                as the decompressed size. If the caller cannot upper bound the\n *                decompressed size, then it's better to use the streaming API.\n * @src:          The zstd compressed data to decompress. Multiple concatenated\n *                frames and skippable frames are allowed.\n * @src_size:     The exact size of the data to decompress.\n *\n * Return:        The decompressed size or an error, which can be checked using\n *                zstd_is_error().\n */\nsize_t zstd_decompress_dctx(zstd_dctx *dctx, void *dst, size_t dst_capacity,\n\tconst void *src, size_t src_size);\n\n/**\n * struct zstd_ddict - Decompression dictionary.\n * See zstd_lib.h.\n */\ntypedef ZSTD_DDict zstd_ddict;\n\n/**\n * zstd_create_ddict_byreference() - Create decompression dictionary\n * @dict:              Pointer to dictionary buffer.\n * @dict_size:         Size of the dictionary buffer.\n * @dict_load_method:  Dictionary load method.\n * @dict_content_type: Dictionary content type.\n * @custom_mem:        Memory allocator.\n *\n * Note, this uses @dict by reference (ZSTD_dlm_byRef), so it should be\n * free before zstd_ddict is destroyed.\n *\n * Return:             NULL on error, pointer to decompression dictionary\n *                     otherwise.\n */\nzstd_ddict *zstd_create_ddict_byreference(const void *dict, size_t dict_size,\n\t\t\t\t\t  zstd_custom_mem custom_mem);\n/**\n * zstd_free_ddict() - Free decompression dictionary\n * @dict:         Pointer to the dictionary.\n *\n * Return:        Always 0.\n */\nsize_t zstd_free_ddict(zstd_ddict *ddict);\n\n/**\n * zstd_create_dctx_advanced() - Create decompression context\n * @custom_mem:   Custom allocator.\n *\n * Return:        NULL on error, pointer to decompression context otherwise.\n */\nzstd_dctx *zstd_create_dctx_advanced(zstd_custom_mem custom_mem);\n\n/**\n * zstd_free_dctx() -- Free decompression context\n * @dctx:         Pointer to decompression context.\n * Return:        Always 0.\n */\nsize_t zstd_free_dctx(zstd_dctx *dctx);\n\n/**\n * zstd_decompress_using_ddict() - decompress src into dst using a dictionary\n * @dctx:         The decompression context.\n * @dst:          The buffer to decompress src into.\n * @dst_capacity: The size of the destination buffer. Must be at least as large\n *                as the decompressed size. If the caller cannot upper bound the\n *                decompressed size, then it's better to use the streaming API.\n * @src:          The zstd compressed data to decompress. Multiple concatenated\n *                frames and skippable frames are allowed.\n * @src_size:     The exact size of the data to decompress.\n * @ddict:        The dictionary to be used.\n *\n * Return:        The decompressed size or an error, which can be checked using\n *                zstd_is_error().\n */\nsize_t zstd_decompress_using_ddict(zstd_dctx *dctx,\n\tvoid *dst, size_t dst_capacity, const void *src, size_t src_size,\n\tconst zstd_ddict *ddict);\n\n\n/* ======   Streaming Buffers   ====== */\n\n/**\n * struct zstd_in_buffer - input buffer for streaming\n * @src:  Start of the input buffer.\n * @size: Size of the input buffer.\n * @pos:  Position where reading stopped. Will be updated.\n *        Necessarily 0 <= pos <= size.\n *\n * See zstd_lib.h.\n */\ntypedef ZSTD_inBuffer zstd_in_buffer;\n\n/**\n * struct zstd_out_buffer - output buffer for streaming\n * @dst:  Start of the output buffer.\n * @size: Size of the output buffer.\n * @pos:  Position where writing stopped. Will be updated.\n *        Necessarily 0 <= pos <= size.\n *\n * See zstd_lib.h.\n */\ntypedef ZSTD_outBuffer zstd_out_buffer;\n\n/* ======   Streaming Compression   ====== */\n\ntypedef ZSTD_CStream zstd_cstream;\n\n/**\n * zstd_cstream_workspace_bound() - memory needed to initialize a zstd_cstream\n * @cparams: The compression parameters to be used for compression.\n *\n * Return:   A lower bound on the size of the workspace that is passed to\n *           zstd_init_cstream().\n */\nsize_t zstd_cstream_workspace_bound(const zstd_compression_parameters *cparams);\n\n/**\n * zstd_cstream_workspace_bound_with_ext_seq_prod() - memory needed to initialize\n * a zstd_cstream when using the block-level external sequence producer API.\n * @cparams: The compression parameters to be used for compression.\n *\n * Return:   A lower bound on the size of the workspace that is passed to\n *           zstd_init_cstream().\n */\nsize_t zstd_cstream_workspace_bound_with_ext_seq_prod(const zstd_compression_parameters *cparams);\n\n/**\n * zstd_init_cstream() - initialize a zstd streaming compression context\n * @parameters        The zstd parameters to use for compression.\n * @pledged_src_size: If params.fParams.contentSizeFlag == 1 then the caller\n *                    must pass the source size (zero means empty source).\n *                    Otherwise, the caller may optionally pass the source\n *                    size, or zero if unknown.\n * @workspace:        The workspace to emplace the context into. It must outlive\n *                    the returned context.\n * @workspace_size:   The size of workspace.\n *                    Use zstd_cstream_workspace_bound(params->cparams) to\n *                    determine how large the workspace must be.\n *\n * Return:            The zstd streaming compression context or NULL on error.\n */\nzstd_cstream *zstd_init_cstream(const zstd_parameters *parameters,\n\tunsigned long long pledged_src_size, void *workspace, size_t workspace_size);\n\n/**\n * zstd_reset_cstream() - reset the context using parameters from creation\n * @cstream:          The zstd streaming compression context to reset.\n * @pledged_src_size: Optionally the source size, or zero if unknown.\n *\n * Resets the context using the parameters from creation. Skips dictionary\n * loading, since it can be reused. If `pledged_src_size` is non-zero the frame\n * content size is always written into the frame header.\n *\n * Return:            Zero or an error, which can be checked using\n *                    zstd_is_error().\n */\nsize_t zstd_reset_cstream(zstd_cstream *cstream,\n\tunsigned long long pledged_src_size);\n\n/**\n * zstd_compress_stream() - streaming compress some of input into output\n * @cstream: The zstd streaming compression context.\n * @output:  Destination buffer. `output->pos` is updated to indicate how much\n *           compressed data was written.\n * @input:   Source buffer. `input->pos` is updated to indicate how much data\n *           was read. Note that it may not consume the entire input, in which\n *           case `input->pos < input->size`, and it's up to the caller to\n *           present remaining data again.\n *\n * The `input` and `output` buffers may be any size. Guaranteed to make some\n * forward progress if `input` and `output` are not empty.\n *\n * Return:   A hint for the number of bytes to use as the input for the next\n *           function call or an error, which can be checked using\n *           zstd_is_error().\n */\nsize_t zstd_compress_stream(zstd_cstream *cstream, zstd_out_buffer *output,\n\tzstd_in_buffer *input);\n\n/**\n * zstd_flush_stream() - flush internal buffers into output\n * @cstream: The zstd streaming compression context.\n * @output:  Destination buffer. `output->pos` is updated to indicate how much\n *           compressed data was written.\n *\n * zstd_flush_stream() must be called until it returns 0, meaning all the data\n * has been flushed. Since zstd_flush_stream() causes a block to be ended,\n * calling it too often will degrade the compression ratio.\n *\n * Return:   The number of bytes still present within internal buffers or an\n *           error, which can be checked using zstd_is_error().\n */\nsize_t zstd_flush_stream(zstd_cstream *cstream, zstd_out_buffer *output);\n\n/**\n * zstd_end_stream() - flush internal buffers into output and end the frame\n * @cstream: The zstd streaming compression context.\n * @output:  Destination buffer. `output->pos` is updated to indicate how much\n *           compressed data was written.\n *\n * zstd_end_stream() must be called until it returns 0, meaning all the data has\n * been flushed and the frame epilogue has been written.\n *\n * Return:   The number of bytes still present within internal buffers or an\n *           error, which can be checked using zstd_is_error().\n */\nsize_t zstd_end_stream(zstd_cstream *cstream, zstd_out_buffer *output);\n\n/* ======   Streaming Decompression   ====== */\n\ntypedef ZSTD_DStream zstd_dstream;\n\n/**\n * zstd_dstream_workspace_bound() - memory needed to initialize a zstd_dstream\n * @max_window_size: The maximum window size allowed for compressed frames.\n *\n * Return:           A lower bound on the size of the workspace that is passed\n *                   to zstd_init_dstream().\n */\nsize_t zstd_dstream_workspace_bound(size_t max_window_size);\n\n/**\n * zstd_init_dstream() - initialize a zstd streaming decompression context\n * @max_window_size: The maximum window size allowed for compressed frames.\n * @workspace:       The workspace to emplace the context into. It must outlive\n *                   the returned context.\n * @workspaceSize:   The size of workspace.\n *                   Use zstd_dstream_workspace_bound(max_window_size) to\n *                   determine how large the workspace must be.\n *\n * Return:           The zstd streaming decompression context.\n */\nzstd_dstream *zstd_init_dstream(size_t max_window_size, void *workspace,\n\tsize_t workspace_size);\n\n/**\n * zstd_reset_dstream() - reset the context using parameters from creation\n * @dstream: The zstd streaming decompression context to reset.\n *\n * Resets the context using the parameters from creation. Skips dictionary\n * loading, since it can be reused.\n *\n * Return:   Zero or an error, which can be checked using zstd_is_error().\n */\nsize_t zstd_reset_dstream(zstd_dstream *dstream);\n\n/**\n * zstd_decompress_stream() - streaming decompress some of input into output\n * @dstream: The zstd streaming decompression context.\n * @output:  Destination buffer. `output.pos` is updated to indicate how much\n *           decompressed data was written.\n * @input:   Source buffer. `input.pos` is updated to indicate how much data was\n *           read. Note that it may not consume the entire input, in which case\n *           `input.pos < input.size`, and it's up to the caller to present\n *           remaining data again.\n *\n * The `input` and `output` buffers may be any size. Guaranteed to make some\n * forward progress if `input` and `output` are not empty.\n * zstd_decompress_stream() will not consume the last byte of the frame until\n * the entire frame is flushed.\n *\n * Return:   Returns 0 iff a frame is completely decoded and fully flushed.\n *           Otherwise returns a hint for the number of bytes to use as the\n *           input for the next function call or an error, which can be checked\n *           using zstd_is_error(). The size hint will never load more than the\n *           frame.\n */\nsize_t zstd_decompress_stream(zstd_dstream *dstream, zstd_out_buffer *output,\n\tzstd_in_buffer *input);\n\n/* ======   Frame Inspection Functions ====== */\n\n/**\n * zstd_find_frame_compressed_size() - returns the size of a compressed frame\n * @src:      Source buffer. It should point to the start of a zstd encoded\n *            frame or a skippable frame.\n * @src_size: The size of the source buffer. It must be at least as large as the\n *            size of the frame.\n *\n * Return:    The compressed size of the frame pointed to by `src` or an error,\n *            which can be check with zstd_is_error().\n *            Suitable to pass to ZSTD_decompress() or similar functions.\n */\nsize_t zstd_find_frame_compressed_size(const void *src, size_t src_size);\n\n/**\n * zstd_register_sequence_producer() - exposes the zstd library function\n * ZSTD_registerSequenceProducer(). This is used for the block-level external\n * sequence producer API. See upstream zstd.h for detailed documentation.\n */\ntypedef ZSTD_sequenceProducer_F zstd_sequence_producer_f;\nvoid zstd_register_sequence_producer(\n  zstd_cctx *cctx,\n  void* sequence_producer_state,\n  zstd_sequence_producer_f sequence_producer\n);\n\n/**\n * struct zstd_frame_params - zstd frame parameters stored in the frame header\n * @frameContentSize: The frame content size, or ZSTD_CONTENTSIZE_UNKNOWN if not\n *                    present.\n * @windowSize:       The window size, or 0 if the frame is a skippable frame.\n * @blockSizeMax:     The maximum block size.\n * @frameType:        The frame type (zstd or skippable)\n * @headerSize:       The size of the frame header.\n * @dictID:           The dictionary id, or 0 if not present.\n * @checksumFlag:     Whether a checksum was used.\n *\n * See zstd_lib.h.\n */\ntypedef ZSTD_FrameHeader zstd_frame_header;\n\n/**\n * zstd_get_frame_header() - extracts parameters from a zstd or skippable frame\n * @params:   On success the frame parameters are written here.\n * @src:      The source buffer. It must point to a zstd or skippable frame.\n * @src_size: The size of the source buffer.\n *\n * Return:    0 on success. If more data is required it returns how many bytes\n *            must be provided to make forward progress. Otherwise it returns\n *            an error, which can be checked using zstd_is_error().\n */\nsize_t zstd_get_frame_header(zstd_frame_header *params, const void *src,\n\tsize_t src_size);\n\n/**\n * struct zstd_sequence - a sequence of literals or a match\n *\n * @offset: The offset of the match\n * @litLength: The literal length of the sequence\n * @matchLength: The match length of the sequence\n * @rep: Represents which repeat offset is used\n */\ntypedef ZSTD_Sequence zstd_sequence;\n\n/**\n * zstd_compress_sequences_and_literals() - compress an array of zstd_sequence and literals\n *\n * @cctx: The zstd compression context.\n * @dst: The buffer to compress the data into.\n * @dst_capacity: The size of the destination buffer.\n * @in_seqs: The array of zstd_sequence to compress.\n * @in_seqs_size: The number of sequences in in_seqs.\n * @literals: The literals associated to the sequences to be compressed.\n * @lit_size: The size of the literals in the literals buffer.\n * @lit_capacity: The size of the literals buffer.\n * @decompressed_size: The size of the input data\n *\n * Return: The compressed size or an error, which can be checked using\n * \t   zstd_is_error().\n */\nsize_t zstd_compress_sequences_and_literals(zstd_cctx *cctx, void* dst, size_t dst_capacity,\n\t\t\t\t\t    const zstd_sequence *in_seqs, size_t in_seqs_size,\n\t\t\t\t\t    const void* literals, size_t lit_size, size_t lit_capacity,\n\t\t\t\t\t    size_t decompressed_size);\n\n#endif  /* LINUX_ZSTD_H */\n"
  },
  {
    "path": "contrib/linux-kernel/mem.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */\n/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef MEM_H_MODULE\n#define MEM_H_MODULE\n\n/*-****************************************\n*  Dependencies\n******************************************/\n#include <linux/unaligned.h>  /* get_unaligned, put_unaligned* */\n#include <linux/compiler.h>  /* inline */\n#include <linux/swab.h>  /* swab32, swab64 */\n#include <linux/types.h>  /* size_t, ptrdiff_t */\n#include \"debug.h\"  /* DEBUG_STATIC_ASSERT */\n\n/*-****************************************\n*  Compiler specifics\n******************************************/\n#undef MEM_STATIC /* may be already defined from common/compiler.h */\n#define MEM_STATIC static inline\n\n/*-**************************************************************\n*  Basic Types\n*****************************************************************/\ntypedef uint8_t  BYTE;\ntypedef uint8_t  U8;\ntypedef int8_t   S8;\ntypedef uint16_t U16;\ntypedef int16_t  S16;\ntypedef uint32_t U32;\ntypedef int32_t  S32;\ntypedef uint64_t U64;\ntypedef int64_t  S64;\n\n/*-**************************************************************\n*  Memory I/O API\n*****************************************************************/\n/*=== Static platform detection ===*/\nMEM_STATIC unsigned MEM_32bits(void);\nMEM_STATIC unsigned MEM_64bits(void);\nMEM_STATIC unsigned MEM_isLittleEndian(void);\n\n/*=== Native unaligned read/write ===*/\nMEM_STATIC U16 MEM_read16(const void* memPtr);\nMEM_STATIC U32 MEM_read32(const void* memPtr);\nMEM_STATIC U64 MEM_read64(const void* memPtr);\nMEM_STATIC size_t MEM_readST(const void* memPtr);\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value);\nMEM_STATIC void MEM_write32(void* memPtr, U32 value);\nMEM_STATIC void MEM_write64(void* memPtr, U64 value);\n\n/*=== Little endian unaligned read/write ===*/\nMEM_STATIC U16 MEM_readLE16(const void* memPtr);\nMEM_STATIC U32 MEM_readLE24(const void* memPtr);\nMEM_STATIC U32 MEM_readLE32(const void* memPtr);\nMEM_STATIC U64 MEM_readLE64(const void* memPtr);\nMEM_STATIC size_t MEM_readLEST(const void* memPtr);\n\nMEM_STATIC void MEM_writeLE16(void* memPtr, U16 val);\nMEM_STATIC void MEM_writeLE24(void* memPtr, U32 val);\nMEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32);\nMEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64);\nMEM_STATIC void MEM_writeLEST(void* memPtr, size_t val);\n\n/*=== Big endian unaligned read/write ===*/\nMEM_STATIC U32 MEM_readBE32(const void* memPtr);\nMEM_STATIC U64 MEM_readBE64(const void* memPtr);\nMEM_STATIC size_t MEM_readBEST(const void* memPtr);\n\nMEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32);\nMEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64);\nMEM_STATIC void MEM_writeBEST(void* memPtr, size_t val);\n\n/*=== Byteswap ===*/\nMEM_STATIC U32 MEM_swap32(U32 in);\nMEM_STATIC U64 MEM_swap64(U64 in);\nMEM_STATIC size_t MEM_swapST(size_t in);\n\n/*-**************************************************************\n*  Memory I/O Implementation\n*****************************************************************/\nMEM_STATIC unsigned MEM_32bits(void)\n{\n    return sizeof(size_t) == 4;\n}\n\nMEM_STATIC unsigned MEM_64bits(void)\n{\n    return sizeof(size_t) == 8;\n}\n\n#if defined(__LITTLE_ENDIAN)\n#define MEM_LITTLE_ENDIAN 1\n#else\n#define MEM_LITTLE_ENDIAN 0\n#endif\n\nMEM_STATIC unsigned MEM_isLittleEndian(void)\n{\n    return MEM_LITTLE_ENDIAN;\n}\n\nMEM_STATIC U16 MEM_read16(const void *memPtr)\n{\n    return get_unaligned((const U16 *)memPtr);\n}\n\nMEM_STATIC U32 MEM_read32(const void *memPtr)\n{\n    return get_unaligned((const U32 *)memPtr);\n}\n\nMEM_STATIC U64 MEM_read64(const void *memPtr)\n{\n    return get_unaligned((const U64 *)memPtr);\n}\n\nMEM_STATIC size_t MEM_readST(const void *memPtr)\n{\n    return get_unaligned((const size_t *)memPtr);\n}\n\nMEM_STATIC void MEM_write16(void *memPtr, U16 value)\n{\n    put_unaligned(value, (U16 *)memPtr);\n}\n\nMEM_STATIC void MEM_write32(void *memPtr, U32 value)\n{\n    put_unaligned(value, (U32 *)memPtr);\n}\n\nMEM_STATIC void MEM_write64(void *memPtr, U64 value)\n{\n    put_unaligned(value, (U64 *)memPtr);\n}\n\n/*=== Little endian r/w ===*/\n\nMEM_STATIC U16 MEM_readLE16(const void *memPtr)\n{\n    return get_unaligned_le16(memPtr);\n}\n\nMEM_STATIC void MEM_writeLE16(void *memPtr, U16 val)\n{\n    put_unaligned_le16(val, memPtr);\n}\n\nMEM_STATIC U32 MEM_readLE24(const void *memPtr)\n{\n    return MEM_readLE16(memPtr) + (((const BYTE *)memPtr)[2] << 16);\n}\n\nMEM_STATIC void MEM_writeLE24(void *memPtr, U32 val)\n{\n\tMEM_writeLE16(memPtr, (U16)val);\n\t((BYTE *)memPtr)[2] = (BYTE)(val >> 16);\n}\n\nMEM_STATIC U32 MEM_readLE32(const void *memPtr)\n{\n    return get_unaligned_le32(memPtr);\n}\n\nMEM_STATIC void MEM_writeLE32(void *memPtr, U32 val32)\n{\n    put_unaligned_le32(val32, memPtr);\n}\n\nMEM_STATIC U64 MEM_readLE64(const void *memPtr)\n{\n    return get_unaligned_le64(memPtr);\n}\n\nMEM_STATIC void MEM_writeLE64(void *memPtr, U64 val64)\n{\n    put_unaligned_le64(val64, memPtr);\n}\n\nMEM_STATIC size_t MEM_readLEST(const void *memPtr)\n{\n\tif (MEM_32bits())\n\t\treturn (size_t)MEM_readLE32(memPtr);\n\telse\n\t\treturn (size_t)MEM_readLE64(memPtr);\n}\n\nMEM_STATIC void MEM_writeLEST(void *memPtr, size_t val)\n{\n\tif (MEM_32bits())\n\t\tMEM_writeLE32(memPtr, (U32)val);\n\telse\n\t\tMEM_writeLE64(memPtr, (U64)val);\n}\n\n/*=== Big endian r/w ===*/\n\nMEM_STATIC U32 MEM_readBE32(const void *memPtr)\n{\n    return get_unaligned_be32(memPtr);\n}\n\nMEM_STATIC void MEM_writeBE32(void *memPtr, U32 val32)\n{\n    put_unaligned_be32(val32, memPtr);\n}\n\nMEM_STATIC U64 MEM_readBE64(const void *memPtr)\n{\n    return get_unaligned_be64(memPtr);\n}\n\nMEM_STATIC void MEM_writeBE64(void *memPtr, U64 val64)\n{\n    put_unaligned_be64(val64, memPtr);\n}\n\nMEM_STATIC size_t MEM_readBEST(const void *memPtr)\n{\n\tif (MEM_32bits())\n\t\treturn (size_t)MEM_readBE32(memPtr);\n\telse\n\t\treturn (size_t)MEM_readBE64(memPtr);\n}\n\nMEM_STATIC void MEM_writeBEST(void *memPtr, size_t val)\n{\n\tif (MEM_32bits())\n\t\tMEM_writeBE32(memPtr, (U32)val);\n\telse\n\t\tMEM_writeBE64(memPtr, (U64)val);\n}\n\nMEM_STATIC U32 MEM_swap32(U32 in)\n{\n    return swab32(in);\n}\n\nMEM_STATIC U64 MEM_swap64(U64 in)\n{\n    return swab64(in);\n}\n\nMEM_STATIC size_t MEM_swapST(size_t in)\n{\n    if (MEM_32bits())\n        return (size_t)MEM_swap32((U32)in);\n    else\n        return (size_t)MEM_swap64((U64)in);\n}\n\n#endif /* MEM_H_MODULE */\n"
  },
  {
    "path": "contrib/linux-kernel/squashfs-benchmark.sh",
    "content": "# !/bin/sh\nset -e\n\n# Benchmarks run on a Ubuntu 14.04 VM with 2 cores and 4 GiB of RAM.\n# The VM is running on a Macbook Pro with a 3.1 GHz Intel Core i7 processor and\n# 16 GB of RAM and an SSD.\n\n# $BENCHMARK_DIR is generated with the following commands, from the Ubuntu image\n# ubuntu-16.10-desktop-amd64.iso.\n# > mkdir mnt\n# > sudo mount -o loop ubuntu-16.10-desktop-amd64.iso mnt\n# > cp mnt/casper/filesystem.squashfs .\n# > sudo unsquashfs filesystem.squashfs\n\n# $HOME is on a ext4 filesystem\nBENCHMARK_DIR=\"$HOME/squashfs-root/\"\nBENCHMARK_FS=\"$HOME/filesystem.squashfs\"\n\n# Normalize the environment\nsudo rm -f $BENCHMARK_FS 2> /dev/null > /dev/null || true\nsudo umount /mnt/squashfs 2> /dev/null > /dev/null || true\n\n# Run the benchmark\necho \"Compression\"\necho \"sudo mksquashfs $BENCHMARK_DIR $BENCHMARK_FS $@\"\ntime sudo mksquashfs $BENCHMARK_DIR $BENCHMARK_FS $@ 2> /dev/null > /dev/null\n\necho \"Approximate compression ratio\"\nprintf \"%d / %d\\n\"                                                             \\\n  $(sudo du -sx --block-size=1 $BENCHMARK_DIR | cut -f1)                       \\\n  $(sudo du -sx --block-size=1 $BENCHMARK_FS  | cut -f1);\n\n# Mount the filesystem\nsudo mount -t squashfs $BENCHMARK_FS /mnt/squashfs\n\necho \"Decompression\"\ntime sudo tar -c /mnt/squashfs 2> /dev/null | wc -c > /dev/null\n\nsudo umount /mnt/squashfs\n"
  },
  {
    "path": "contrib/linux-kernel/test/Makefile",
    "content": "# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ################################################################\n\nLINUX := ../linux\nLINUX_ZSTDLIB := $(LINUX)/lib/zstd\n\nCPPFLAGS += -I$(LINUX)/include -I$(LINUX_ZSTDLIB) -Iinclude -DNDEBUG -Wno-deprecated-declarations\n# Don't poison the workspace, it currently doesn't work with static allocation and workspace reuse\nCPPFLAGS += -DZSTD_ASAN_DONT_POISON_WORKSPACE\n\nLINUX_ZSTD_MODULE     := $(wildcard $(LINUX_ZSTDLIB)/*.c)\nLINUX_ZSTD_COMMON     := $(wildcard $(LINUX_ZSTDLIB)/common/*.c)\nLINUX_ZSTD_COMPRESS   := $(wildcard $(LINUX_ZSTDLIB)/compress/*.c)\nLINUX_ZSTD_DECOMPRESS := $(wildcard $(LINUX_ZSTDLIB)/decompress/*.c $(LINUX_ZSTDLIB)/decompress/*.S)\nLINUX_ZSTD_FILES      := $(LINUX_ZSTD_MODULE) $(LINUX_ZSTD_COMMON) $(LINUX_ZSTD_COMPRESS) $(LINUX_ZSTD_DECOMPRESS)\nLINUX_ZSTD_OBJECTS0   := $(LINUX_ZSTD_FILES:.c=.o)\nLINUX_ZSTD_OBJECTS    := $(LINUX_ZSTD_OBJECTS0:.S=.o)\n\n%.o: %.S\n\t$(COMPILE.S) $(OUTPUT_OPTION) $<\n\nliblinuxzstd.a: $(LINUX_ZSTD_OBJECTS)\n\t$(AR) $(ARFLAGS) $@ $^\n\ntest: test.c liblinuxzstd.a\n\t$(CC) $(LDFLAGS) $(CPPFLAGS) $(CFLAGS) $^ -o $@\n\nstatic_test: static_test.c\n\t$(CC) $(LDFLAGS) $(CPPFLAGS) $(CFLAGS) $^ -o $@\n\nrun-test: test static_test\n\t./macro-test.sh\n\t./test\n\t./static_test\n\n.PHONY:\nclean:\n\t$(RM) -f $(LINUX_ZSTDLIB)/*.o\n\t$(RM) -f $(LINUX_ZSTDLIB)/**/*.o\n\t$(RM) -f *.o *.a\n\t$(RM) -f static_test\n\t$(RM) -f test\n"
  },
  {
    "path": "contrib/linux-kernel/test/include/linux/compiler.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n#ifndef LINUX_COMPILER_H\n#define LINUX_COMPILER_H\n\n#ifndef inline\n#define inline __inline __attribute__((unused))\n#endif\n\n#ifndef noinline\n#define noinline __attribute__((noinline))\n#endif\n\n#define fallthrough __attribute__((__fallthrough__))\n\n#endif\n"
  },
  {
    "path": "contrib/linux-kernel/test/include/linux/errno.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n#ifndef LINUX_ERRNO_H\n#define LINUX_ERRNO_H\n\n#define EINVAL 22\n\n#endif\n"
  },
  {
    "path": "contrib/linux-kernel/test/include/linux/kernel.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n#ifndef LINUX_KERNEL_H\n#define LINUX_KERNEL_H\n\n#define WARN_ON(x)\n\n#define PTR_ALIGN(p, a) (typeof(p))ALIGN((unsigned long long)(p), (a))\n#define ALIGN(x, a)         ALIGN_MASK((x), (a) - 1)\n#define ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))\n\n#endif\n"
  },
  {
    "path": "contrib/linux-kernel/test/include/linux/limits.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n#ifndef LINUX_LIMITS_H\n#define LINUX_LIMITS_H\n\n#include <limits.h>\n\n#endif\n"
  },
  {
    "path": "contrib/linux-kernel/test/include/linux/math64.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n#ifndef LINUX_MATH64_H\n#define LINUX_MATH64_H\n\n#define div_u64(dividend, divisor) ((dividend) / (divisor))\n\n#endif\n"
  },
  {
    "path": "contrib/linux-kernel/test/include/linux/module.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n#ifndef LINUX_MODULE_H\n#define LINUX_MODULE_H\n\n#define EXPORT_SYMBOL(symbol)                                                  \\\n  void* __##symbol = symbol\n#define EXPORT_SYMBOL_GPL(symbol)                                              \\\n  void* __##symbol = symbol\n#define MODULE_LICENSE(license)\n#define MODULE_DESCRIPTION(description)\n\n#endif\n"
  },
  {
    "path": "contrib/linux-kernel/test/include/linux/printk.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n#ifndef LINUX_PRINTK_H\n#define LINUX_PRINTK_H\n\n#define pr_debug(...)\n\n#endif\n"
  },
  {
    "path": "contrib/linux-kernel/test/include/linux/stddef.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n#ifndef LINUX_STDDEF_H\n#define LINUX_STDDEF_H\n\n#include <stddef.h>\n\n#endif\n"
  },
  {
    "path": "contrib/linux-kernel/test/include/linux/swab.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n#ifndef LINUX_SWAB_H\n#define LINUX_SWAB_H\n\n#define swab32(x) __builtin_bswap32((x))\n#define swab64(x) __builtin_bswap64((x))\n\n#endif\n"
  },
  {
    "path": "contrib/linux-kernel/test/include/linux/types.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n#ifndef LINUX_TYPES_H\n#define LINUX_TYPES_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n#endif\n"
  },
  {
    "path": "contrib/linux-kernel/test/include/linux/unaligned.h",
    "content": "#ifndef ASM_UNALIGNED_H\n#define ASM_UNALIGNED_H\n\n#include <assert.h>\n#include <linux/types.h>\n\n#ifndef __LITTLE_ENDIAN\n# if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || defined(__LITTLE_ENDIAN__)\n#  define __LITTLE_ENDIAN 1\n# endif\n#endif\n\n#ifdef __LITTLE_ENDIAN\n# define _IS_LITTLE_ENDIAN 1\n#else\n# define _IS_LITTLE_ENDIAN 0\n#endif\n\nstatic unsigned _isLittleEndian(void)\n{\n    const union { uint32_t u; uint8_t c[4]; } one = { 1 };\n    assert(_IS_LITTLE_ENDIAN == one.c[0]);\n    (void)one;\n    return _IS_LITTLE_ENDIAN;\n}\n\nstatic uint16_t _swap16(uint16_t in)\n{\n    return ((in & 0xF) << 8) + ((in & 0xF0) >> 8);\n}\n\nstatic uint32_t _swap32(uint32_t in)\n{\n    return __builtin_bswap32(in);\n}\n\nstatic uint64_t _swap64(uint64_t in)\n{\n    return __builtin_bswap64(in);\n}\n\n/* Little endian */\nstatic uint16_t get_unaligned_le16(const void* memPtr)\n{\n    uint16_t val;\n    __builtin_memcpy(&val, memPtr, sizeof(val));\n    if (!_isLittleEndian()) _swap16(val);\n    return val;\n}\n\nstatic uint32_t get_unaligned_le32(const void* memPtr)\n{\n    uint32_t val;\n    __builtin_memcpy(&val, memPtr, sizeof(val));\n    if (!_isLittleEndian()) _swap32(val);\n    return val;\n}\n\nstatic uint64_t get_unaligned_le64(const void* memPtr)\n{\n    uint64_t val;\n    __builtin_memcpy(&val, memPtr, sizeof(val));\n    if (!_isLittleEndian()) _swap64(val);\n    return val;\n}\n\nstatic void put_unaligned_le16(uint16_t value, void* memPtr)\n{\n    if (!_isLittleEndian()) value = _swap16(value);\n    __builtin_memcpy(memPtr, &value, sizeof(value));\n}\n\nstatic void put_unaligned_le32(uint32_t value, void* memPtr)\n{\n    if (!_isLittleEndian()) value = _swap32(value);\n    __builtin_memcpy(memPtr, &value, sizeof(value));\n}\n\nstatic void put_unaligned_le64(uint64_t value, void* memPtr)\n{\n    if (!_isLittleEndian()) value = _swap64(value);\n    __builtin_memcpy(memPtr, &value, sizeof(value));\n}\n\n/* big endian */\nstatic uint32_t get_unaligned_be32(const void* memPtr)\n{\n    uint32_t val;\n    __builtin_memcpy(&val, memPtr, sizeof(val));\n    if (_isLittleEndian()) _swap32(val);\n    return val;\n}\n\nstatic uint64_t get_unaligned_be64(const void* memPtr)\n{\n    uint64_t val;\n    __builtin_memcpy(&val, memPtr, sizeof(val));\n    if (_isLittleEndian()) _swap64(val);\n    return val;\n}\n\nstatic void put_unaligned_be32(uint32_t value, void* memPtr)\n{\n    if (_isLittleEndian()) value = _swap32(value);\n    __builtin_memcpy(memPtr, &value, sizeof(value));\n}\n\nstatic void put_unaligned_be64(uint64_t value, void* memPtr)\n{\n    if (_isLittleEndian()) value = _swap64(value);\n    __builtin_memcpy(memPtr, &value, sizeof(value));\n}\n\n/* generic */\nextern void __bad_unaligned_access_size(void);\n\n#define __get_unaligned_le(ptr) ((typeof(*(ptr)))({                            \\\n    __builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr),                         \\\n    __builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_le16((ptr)),      \\\n    __builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_le32((ptr)),      \\\n    __builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_le64((ptr)),      \\\n    __bad_unaligned_access_size()))));                                         \\\n    }))\n\n#define __get_unaligned_be(ptr) ((typeof(*(ptr)))({                            \\\n    __builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr),                         \\\n    __builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_be16((ptr)),      \\\n    __builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_be32((ptr)),      \\\n    __builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_be64((ptr)),      \\\n    __bad_unaligned_access_size()))));                                         \\\n    }))\n\n#define __put_unaligned_le(val, ptr)                                           \\\n  ({                                                                           \\\n    void *__gu_p = (ptr);                                                      \\\n    switch (sizeof(*(ptr))) {                                                  \\\n    case 1:                                                                    \\\n      *(uint8_t *)__gu_p = (uint8_t)(val);                                     \\\n      break;                                                                   \\\n    case 2:                                                                    \\\n      put_unaligned_le16((uint16_t)(val), __gu_p);                             \\\n      break;                                                                   \\\n    case 4:                                                                    \\\n      put_unaligned_le32((uint32_t)(val), __gu_p);                             \\\n      break;                                                                   \\\n    case 8:                                                                    \\\n      put_unaligned_le64((uint64_t)(val), __gu_p);                             \\\n      break;                                                                   \\\n    default:                                                                   \\\n      __bad_unaligned_access_size();                                           \\\n      break;                                                                   \\\n    }                                                                          \\\n    (void)0;                                                                   \\\n  })\n\n#define __put_unaligned_be(val, ptr)                                           \\\n  ({                                                                           \\\n    void *__gu_p = (ptr);                                                      \\\n    switch (sizeof(*(ptr))) {                                                  \\\n    case 1:                                                                    \\\n      *(uint8_t *)__gu_p = (uint8_t)(val);                                     \\\n      break;                                                                   \\\n    case 2:                                                                    \\\n      put_unaligned_be16((uint16_t)(val), __gu_p);                             \\\n      break;                                                                   \\\n    case 4:                                                                    \\\n      put_unaligned_be32((uint32_t)(val), __gu_p);                             \\\n      break;                                                                   \\\n    case 8:                                                                    \\\n      put_unaligned_be64((uint64_t)(val), __gu_p);                             \\\n      break;                                                                   \\\n    default:                                                                   \\\n      __bad_unaligned_access_size();                                           \\\n      break;                                                                   \\\n    }                                                                          \\\n    (void)0;                                                                   \\\n  })\n\n#if _IS_LITTLE_ENDIAN\n#  define get_unaligned __get_unaligned_le\n#  define put_unaligned __put_unaligned_le\n#else\n#  define get_unaligned __get_unaligned_be\n#  define put_unaligned __put_unaligned_be\n#endif\n\n#endif // ASM_UNALIGNED_H\n"
  },
  {
    "path": "contrib/linux-kernel/test/include/linux/xxhash.h",
    "content": "/*\n * xxHash - Extremely Fast Hash algorithm\n * Copyright (C) 2012-2016, Yann Collet.\n *\n * BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n *   * Redistributions of source code must retain the above copyright\n *     notice, this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above\n *     copyright notice, this list of conditions and the following disclaimer\n *     in the documentation and/or other materials provided with the\n *     distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * This program is free software; you can redistribute it and/or modify it under\n * the terms of the GNU General Public License version 2 as published by the\n * Free Software Foundation. This program is dual-licensed; you may select\n * either version 2 of the GNU General Public License (\"GPL\") or BSD license\n * (\"BSD\").\n *\n * You can contact the author at:\n * - xxHash homepage: https://cyan4973.github.io/xxHash/\n * - xxHash source repository: https://github.com/Cyan4973/xxHash\n */\n\n/*\n * Notice extracted from xxHash homepage:\n *\n * xxHash is an extremely fast Hash algorithm, running at RAM speed limits.\n * It also successfully passes all tests from the SMHasher suite.\n *\n * Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2\n * Duo @3GHz)\n *\n * Name            Speed       Q.Score   Author\n * xxHash          5.4 GB/s     10\n * CrapWow         3.2 GB/s      2       Andrew\n * MumurHash 3a    2.7 GB/s     10       Austin Appleby\n * SpookyHash      2.0 GB/s     10       Bob Jenkins\n * SBox            1.4 GB/s      9       Bret Mulvey\n * Lookup3         1.2 GB/s      9       Bob Jenkins\n * SuperFastHash   1.2 GB/s      1       Paul Hsieh\n * CityHash64      1.05 GB/s    10       Pike & Alakuijala\n * FNV             0.55 GB/s     5       Fowler, Noll, Vo\n * CRC32           0.43 GB/s     9\n * MD5-32          0.33 GB/s    10       Ronald L. Rivest\n * SHA1-32         0.28 GB/s    10\n *\n * Q.Score is a measure of quality of the hash function.\n * It depends on successfully passing SMHasher test set.\n * 10 is a perfect score.\n *\n * A 64-bits version, named xxh64 offers much better speed,\n * but for 64-bits applications only.\n * Name     Speed on 64 bits    Speed on 32 bits\n * xxh64       13.8 GB/s            1.9 GB/s\n * xxh32        6.8 GB/s            6.0 GB/s\n */\n\n#ifndef XXHASH_H\n#define XXHASH_H\n\n#include <linux/types.h>\n\n#define XXH_API static inline __attribute__((unused))\n/*-****************************\n * Simple Hash Functions\n *****************************/\n\n/**\n * xxh32() - calculate the 32-bit hash of the input with a given seed.\n *\n * @input:  The data to hash.\n * @length: The length of the data to hash.\n * @seed:   The seed can be used to alter the result predictably.\n *\n * Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s\n *\n * Return:  The 32-bit hash of the data.\n */\nXXH_API uint32_t xxh32(const void *input, size_t length, uint32_t seed);\n\n/**\n * xxh64() - calculate the 64-bit hash of the input with a given seed.\n *\n * @input:  The data to hash.\n * @length: The length of the data to hash.\n * @seed:   The seed can be used to alter the result predictably.\n *\n * This function runs 2x faster on 64-bit systems, but slower on 32-bit systems.\n *\n * Return:  The 64-bit hash of the data.\n */\nXXH_API uint64_t xxh64(const void *input, size_t length, uint64_t seed);\n\n/**\n * xxhash() - calculate wordsize hash of the input with a given seed\n * @input:  The data to hash.\n * @length: The length of the data to hash.\n * @seed:   The seed can be used to alter the result predictably.\n *\n * If the hash does not need to be comparable between machines with\n * different word sizes, this function will call whichever of xxh32()\n * or xxh64() is faster.\n *\n * Return:  wordsize hash of the data.\n */\n\nstatic inline unsigned long xxhash(const void *input, size_t length,\n\t\t\t\t   uint64_t seed)\n{\n\tif (sizeof(size_t) == 8)\n\t\treturn xxh64(input, length, seed);\n\telse\n\t\treturn xxh32(input, length, seed);\n}\n\n/*-****************************\n * Streaming Hash Functions\n *****************************/\n\n/*\n * These definitions are only meant to allow allocation of XXH state\n * statically, on stack, or in a struct for example.\n * Do not use members directly.\n */\n\n/**\n * struct xxh32_state - private xxh32 state, do not use members directly\n */\nstruct xxh32_state {\n\tuint32_t total_len_32;\n\tuint32_t large_len;\n\tuint32_t v1;\n\tuint32_t v2;\n\tuint32_t v3;\n\tuint32_t v4;\n\tuint32_t mem32[4];\n\tuint32_t memsize;\n};\n\n/**\n * struct xxh32_state - private xxh64 state, do not use members directly\n */\nstruct xxh64_state {\n\tuint64_t total_len;\n\tuint64_t v1;\n\tuint64_t v2;\n\tuint64_t v3;\n\tuint64_t v4;\n\tuint64_t mem64[4];\n\tuint32_t memsize;\n};\n\n/**\n * xxh32_reset() - reset the xxh32 state to start a new hashing operation\n *\n * @state: The xxh32 state to reset.\n * @seed:  Initialize the hash state with this seed.\n *\n * Call this function on any xxh32_state to prepare for a new hashing operation.\n */\nXXH_API void xxh32_reset(struct xxh32_state *state, uint32_t seed);\n\n/**\n * xxh32_update() - hash the data given and update the xxh32 state\n *\n * @state:  The xxh32 state to update.\n * @input:  The data to hash.\n * @length: The length of the data to hash.\n *\n * After calling xxh32_reset() call xxh32_update() as many times as necessary.\n *\n * Return:  Zero on success, otherwise an error code.\n */\nXXH_API int xxh32_update(struct xxh32_state *state, const void *input, size_t length);\n\n/**\n * xxh32_digest() - produce the current xxh32 hash\n *\n * @state: Produce the current xxh32 hash of this state.\n *\n * A hash value can be produced at any time. It is still possible to continue\n * inserting input into the hash state after a call to xxh32_digest(), and\n * generate new hashes later on, by calling xxh32_digest() again.\n *\n * Return: The xxh32 hash stored in the state.\n */\nXXH_API uint32_t xxh32_digest(const struct xxh32_state *state);\n\n/**\n * xxh64_reset() - reset the xxh64 state to start a new hashing operation\n *\n * @state: The xxh64 state to reset.\n * @seed:  Initialize the hash state with this seed.\n */\nXXH_API void xxh64_reset(struct xxh64_state *state, uint64_t seed);\n\n/**\n * xxh64_update() - hash the data given and update the xxh64 state\n * @state:  The xxh64 state to update.\n * @input:  The data to hash.\n * @length: The length of the data to hash.\n *\n * After calling xxh64_reset() call xxh64_update() as many times as necessary.\n *\n * Return:  Zero on success, otherwise an error code.\n */\nXXH_API int xxh64_update(struct xxh64_state *state, const void *input, size_t length);\n\n/**\n * xxh64_digest() - produce the current xxh64 hash\n *\n * @state: Produce the current xxh64 hash of this state.\n *\n * A hash value can be produced at any time. It is still possible to continue\n * inserting input into the hash state after a call to xxh64_digest(), and\n * generate new hashes later on, by calling xxh64_digest() again.\n *\n * Return: The xxh64 hash stored in the state.\n */\nXXH_API uint64_t xxh64_digest(const struct xxh64_state *state);\n\n/*-**************************\n * Utils\n ***************************/\n\n/**\n * xxh32_copy_state() - copy the source state into the destination state\n *\n * @src: The source xxh32 state.\n * @dst: The destination xxh32 state.\n */\nXXH_API void xxh32_copy_state(struct xxh32_state *dst, const struct xxh32_state *src);\n\n/**\n * xxh64_copy_state() - copy the source state into the destination state\n *\n * @src: The source xxh64 state.\n * @dst: The destination xxh64 state.\n */\nXXH_API void xxh64_copy_state(struct xxh64_state *dst, const struct xxh64_state *src);\n\n/*\n * xxHash - Extremely Fast Hash algorithm\n * Copyright (C) 2012-2016, Yann Collet.\n *\n * BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n *   * Redistributions of source code must retain the above copyright\n *     notice, this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above\n *     copyright notice, this list of conditions and the following disclaimer\n *     in the documentation and/or other materials provided with the\n *     distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * This program is free software; you can redistribute it and/or modify it under\n * the terms of the GNU General Public License version 2 as published by the\n * Free Software Foundation. This program is dual-licensed; you may select\n * either version 2 of the GNU General Public License (\"GPL\") or BSD license\n * (\"BSD\").\n *\n * You can contact the author at:\n * - xxHash homepage: https://cyan4973.github.io/xxHash/\n * - xxHash source repository: https://github.com/Cyan4973/xxHash\n */\n\n#include <linux/unaligned.h>\n#include <linux/errno.h>\n#include <linux/kernel.h>\n#include <linux/module.h>\n#include <linux/xxhash.h>\n\n/*-*************************************\n * Macros\n **************************************/\n#define xxh_rotl32(x, r) ((x << r) | (x >> (32 - r)))\n#define xxh_rotl64(x, r) ((x << r) | (x >> (64 - r)))\n\n#ifdef __LITTLE_ENDIAN\n# define XXH_CPU_LITTLE_ENDIAN 1\n#else\n# define XXH_CPU_LITTLE_ENDIAN 0\n#endif\n\n/*-*************************************\n * Constants\n **************************************/\nstatic const uint32_t PRIME32_1 = 2654435761U;\nstatic const uint32_t PRIME32_2 = 2246822519U;\nstatic const uint32_t PRIME32_3 = 3266489917U;\nstatic const uint32_t PRIME32_4 =  668265263U;\nstatic const uint32_t PRIME32_5 =  374761393U;\n\nstatic const uint64_t PRIME64_1 = 11400714785074694791ULL;\nstatic const uint64_t PRIME64_2 = 14029467366897019727ULL;\nstatic const uint64_t PRIME64_3 =  1609587929392839161ULL;\nstatic const uint64_t PRIME64_4 =  9650029242287828579ULL;\nstatic const uint64_t PRIME64_5 =  2870177450012600261ULL;\n\n/*-**************************\n *  Utils\n ***************************/\nXXH_API void xxh32_copy_state(struct xxh32_state *dst, const struct xxh32_state *src)\n{\n\t__builtin_memcpy(dst, src, sizeof(*dst));\n}\n\nXXH_API void xxh64_copy_state(struct xxh64_state *dst, const struct xxh64_state *src)\n{\n\t__builtin_memcpy(dst, src, sizeof(*dst));\n}\n\n/*-***************************\n * Simple Hash Functions\n ****************************/\nstatic uint32_t xxh32_round(uint32_t seed, const uint32_t input)\n{\n\tseed += input * PRIME32_2;\n\tseed = xxh_rotl32(seed, 13);\n\tseed *= PRIME32_1;\n\treturn seed;\n}\n\nXXH_API uint32_t xxh32(const void *input, const size_t len, const uint32_t seed)\n{\n\tconst uint8_t *p = (const uint8_t *)input;\n\tconst uint8_t *b_end = p + len;\n\tuint32_t h32;\n\n\tif (len >= 16) {\n\t\tconst uint8_t *const limit = b_end - 16;\n\t\tuint32_t v1 = seed + PRIME32_1 + PRIME32_2;\n\t\tuint32_t v2 = seed + PRIME32_2;\n\t\tuint32_t v3 = seed + 0;\n\t\tuint32_t v4 = seed - PRIME32_1;\n\n\t\tdo {\n\t\t\tv1 = xxh32_round(v1, get_unaligned_le32(p));\n\t\t\tp += 4;\n\t\t\tv2 = xxh32_round(v2, get_unaligned_le32(p));\n\t\t\tp += 4;\n\t\t\tv3 = xxh32_round(v3, get_unaligned_le32(p));\n\t\t\tp += 4;\n\t\t\tv4 = xxh32_round(v4, get_unaligned_le32(p));\n\t\t\tp += 4;\n\t\t} while (p <= limit);\n\n\t\th32 = xxh_rotl32(v1, 1) + xxh_rotl32(v2, 7) +\n\t\t\txxh_rotl32(v3, 12) + xxh_rotl32(v4, 18);\n\t} else {\n\t\th32 = seed + PRIME32_5;\n\t}\n\n\th32 += (uint32_t)len;\n\n\twhile (p + 4 <= b_end) {\n\t\th32 += get_unaligned_le32(p) * PRIME32_3;\n\t\th32 = xxh_rotl32(h32, 17) * PRIME32_4;\n\t\tp += 4;\n\t}\n\n\twhile (p < b_end) {\n\t\th32 += (*p) * PRIME32_5;\n\t\th32 = xxh_rotl32(h32, 11) * PRIME32_1;\n\t\tp++;\n\t}\n\n\th32 ^= h32 >> 15;\n\th32 *= PRIME32_2;\n\th32 ^= h32 >> 13;\n\th32 *= PRIME32_3;\n\th32 ^= h32 >> 16;\n\n\treturn h32;\n}\n\nstatic uint64_t xxh64_round(uint64_t acc, const uint64_t input)\n{\n\tacc += input * PRIME64_2;\n\tacc = xxh_rotl64(acc, 31);\n\tacc *= PRIME64_1;\n\treturn acc;\n}\n\nstatic uint64_t xxh64_merge_round(uint64_t acc, uint64_t val)\n{\n\tval = xxh64_round(0, val);\n\tacc ^= val;\n\tacc = acc * PRIME64_1 + PRIME64_4;\n\treturn acc;\n}\n\nXXH_API uint64_t xxh64(const void *input, const size_t len, const uint64_t seed)\n{\n\tconst uint8_t *p = (const uint8_t *)input;\n\tconst uint8_t *const b_end = p + len;\n\tuint64_t h64;\n\n\tif (len >= 32) {\n\t\tconst uint8_t *const limit = b_end - 32;\n\t\tuint64_t v1 = seed + PRIME64_1 + PRIME64_2;\n\t\tuint64_t v2 = seed + PRIME64_2;\n\t\tuint64_t v3 = seed + 0;\n\t\tuint64_t v4 = seed - PRIME64_1;\n\n\t\tdo {\n\t\t\tv1 = xxh64_round(v1, get_unaligned_le64(p));\n\t\t\tp += 8;\n\t\t\tv2 = xxh64_round(v2, get_unaligned_le64(p));\n\t\t\tp += 8;\n\t\t\tv3 = xxh64_round(v3, get_unaligned_le64(p));\n\t\t\tp += 8;\n\t\t\tv4 = xxh64_round(v4, get_unaligned_le64(p));\n\t\t\tp += 8;\n\t\t} while (p <= limit);\n\n\t\th64 = xxh_rotl64(v1, 1) + xxh_rotl64(v2, 7) +\n\t\t\txxh_rotl64(v3, 12) + xxh_rotl64(v4, 18);\n\t\th64 = xxh64_merge_round(h64, v1);\n\t\th64 = xxh64_merge_round(h64, v2);\n\t\th64 = xxh64_merge_round(h64, v3);\n\t\th64 = xxh64_merge_round(h64, v4);\n\n\t} else {\n\t\th64  = seed + PRIME64_5;\n\t}\n\n\th64 += (uint64_t)len;\n\n\twhile (p + 8 <= b_end) {\n\t\tconst uint64_t k1 = xxh64_round(0, get_unaligned_le64(p));\n\n\t\th64 ^= k1;\n\t\th64 = xxh_rotl64(h64, 27) * PRIME64_1 + PRIME64_4;\n\t\tp += 8;\n\t}\n\n\tif (p + 4 <= b_end) {\n\t\th64 ^= (uint64_t)(get_unaligned_le32(p)) * PRIME64_1;\n\t\th64 = xxh_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;\n\t\tp += 4;\n\t}\n\n\twhile (p < b_end) {\n\t\th64 ^= (*p) * PRIME64_5;\n\t\th64 = xxh_rotl64(h64, 11) * PRIME64_1;\n\t\tp++;\n\t}\n\n\th64 ^= h64 >> 33;\n\th64 *= PRIME64_2;\n\th64 ^= h64 >> 29;\n\th64 *= PRIME64_3;\n\th64 ^= h64 >> 32;\n\n\treturn h64;\n}\n\n/*-**************************************************\n * Advanced Hash Functions\n ***************************************************/\nXXH_API void xxh32_reset(struct xxh32_state *statePtr, const uint32_t seed)\n{\n\t/* use a local state for memcpy() to avoid strict-aliasing warnings */\n\tstruct xxh32_state state;\n\n\t__builtin_memset(&state, 0, sizeof(state));\n\tstate.v1 = seed + PRIME32_1 + PRIME32_2;\n\tstate.v2 = seed + PRIME32_2;\n\tstate.v3 = seed + 0;\n\tstate.v4 = seed - PRIME32_1;\n\t__builtin_memcpy(statePtr, &state, sizeof(state));\n}\n\nXXH_API void xxh64_reset(struct xxh64_state *statePtr, const uint64_t seed)\n{\n\t/* use a local state for memcpy() to avoid strict-aliasing warnings */\n\tstruct xxh64_state state;\n\n\t__builtin_memset(&state, 0, sizeof(state));\n\tstate.v1 = seed + PRIME64_1 + PRIME64_2;\n\tstate.v2 = seed + PRIME64_2;\n\tstate.v3 = seed + 0;\n\tstate.v4 = seed - PRIME64_1;\n\t__builtin_memcpy(statePtr, &state, sizeof(state));\n}\n\nXXH_API int xxh32_update(struct xxh32_state *state, const void *input, const size_t len)\n{\n\tconst uint8_t *p = (const uint8_t *)input;\n\tconst uint8_t *const b_end = p + len;\n\n\tif (input == NULL)\n\t\treturn -EINVAL;\n\n\tstate->total_len_32 += (uint32_t)len;\n\tstate->large_len |= (len >= 16) | (state->total_len_32 >= 16);\n\n\tif (state->memsize + len < 16) { /* fill in tmp buffer */\n\t\t__builtin_memcpy((uint8_t *)(state->mem32) + state->memsize, input, len);\n\t\tstate->memsize += (uint32_t)len;\n\t\treturn 0;\n\t}\n\n\tif (state->memsize) { /* some data left from previous update */\n\t\tconst uint32_t *p32 = state->mem32;\n\n\t\t__builtin_memcpy((uint8_t *)(state->mem32) + state->memsize, input,\n\t\t\t16 - state->memsize);\n\n\t\tstate->v1 = xxh32_round(state->v1, get_unaligned_le32(p32));\n\t\tp32++;\n\t\tstate->v2 = xxh32_round(state->v2, get_unaligned_le32(p32));\n\t\tp32++;\n\t\tstate->v3 = xxh32_round(state->v3, get_unaligned_le32(p32));\n\t\tp32++;\n\t\tstate->v4 = xxh32_round(state->v4, get_unaligned_le32(p32));\n\t\tp32++;\n\n\t\tp += 16-state->memsize;\n\t\tstate->memsize = 0;\n\t}\n\n\tif (p <= b_end - 16) {\n\t\tconst uint8_t *const limit = b_end - 16;\n\t\tuint32_t v1 = state->v1;\n\t\tuint32_t v2 = state->v2;\n\t\tuint32_t v3 = state->v3;\n\t\tuint32_t v4 = state->v4;\n\n\t\tdo {\n\t\t\tv1 = xxh32_round(v1, get_unaligned_le32(p));\n\t\t\tp += 4;\n\t\t\tv2 = xxh32_round(v2, get_unaligned_le32(p));\n\t\t\tp += 4;\n\t\t\tv3 = xxh32_round(v3, get_unaligned_le32(p));\n\t\t\tp += 4;\n\t\t\tv4 = xxh32_round(v4, get_unaligned_le32(p));\n\t\t\tp += 4;\n\t\t} while (p <= limit);\n\n\t\tstate->v1 = v1;\n\t\tstate->v2 = v2;\n\t\tstate->v3 = v3;\n\t\tstate->v4 = v4;\n\t}\n\n\tif (p < b_end) {\n\t\t__builtin_memcpy(state->mem32, p, (size_t)(b_end-p));\n\t\tstate->memsize = (uint32_t)(b_end-p);\n\t}\n\n\treturn 0;\n}\n\nXXH_API uint32_t xxh32_digest(const struct xxh32_state *state)\n{\n\tconst uint8_t *p = (const uint8_t *)state->mem32;\n\tconst uint8_t *const b_end = (const uint8_t *)(state->mem32) +\n\t\tstate->memsize;\n\tuint32_t h32;\n\n\tif (state->large_len) {\n\t\th32 = xxh_rotl32(state->v1, 1) + xxh_rotl32(state->v2, 7) +\n\t\t\txxh_rotl32(state->v3, 12) + xxh_rotl32(state->v4, 18);\n\t} else {\n\t\th32 = state->v3 /* == seed */ + PRIME32_5;\n\t}\n\n\th32 += state->total_len_32;\n\n\twhile (p + 4 <= b_end) {\n\t\th32 += get_unaligned_le32(p) * PRIME32_3;\n\t\th32 = xxh_rotl32(h32, 17) * PRIME32_4;\n\t\tp += 4;\n\t}\n\n\twhile (p < b_end) {\n\t\th32 += (*p) * PRIME32_5;\n\t\th32 = xxh_rotl32(h32, 11) * PRIME32_1;\n\t\tp++;\n\t}\n\n\th32 ^= h32 >> 15;\n\th32 *= PRIME32_2;\n\th32 ^= h32 >> 13;\n\th32 *= PRIME32_3;\n\th32 ^= h32 >> 16;\n\n\treturn h32;\n}\n\nXXH_API int xxh64_update(struct xxh64_state *state, const void *input, const size_t len)\n{\n\tconst uint8_t *p = (const uint8_t *)input;\n\tconst uint8_t *const b_end = p + len;\n\n\tif (input == NULL)\n\t\treturn -EINVAL;\n\n\tstate->total_len += len;\n\n\tif (state->memsize + len < 32) { /* fill in tmp buffer */\n\t\t__builtin_memcpy(((uint8_t *)state->mem64) + state->memsize, input, len);\n\t\tstate->memsize += (uint32_t)len;\n\t\treturn 0;\n\t}\n\n\tif (state->memsize) { /* tmp buffer is full */\n\t\tuint64_t *p64 = state->mem64;\n\n\t\t__builtin_memcpy(((uint8_t *)p64) + state->memsize, input,\n\t\t\t32 - state->memsize);\n\n\t\tstate->v1 = xxh64_round(state->v1, get_unaligned_le64(p64));\n\t\tp64++;\n\t\tstate->v2 = xxh64_round(state->v2, get_unaligned_le64(p64));\n\t\tp64++;\n\t\tstate->v3 = xxh64_round(state->v3, get_unaligned_le64(p64));\n\t\tp64++;\n\t\tstate->v4 = xxh64_round(state->v4, get_unaligned_le64(p64));\n\n\t\tp += 32 - state->memsize;\n\t\tstate->memsize = 0;\n\t}\n\n\tif (p + 32 <= b_end) {\n\t\tconst uint8_t *const limit = b_end - 32;\n\t\tuint64_t v1 = state->v1;\n\t\tuint64_t v2 = state->v2;\n\t\tuint64_t v3 = state->v3;\n\t\tuint64_t v4 = state->v4;\n\n\t\tdo {\n\t\t\tv1 = xxh64_round(v1, get_unaligned_le64(p));\n\t\t\tp += 8;\n\t\t\tv2 = xxh64_round(v2, get_unaligned_le64(p));\n\t\t\tp += 8;\n\t\t\tv3 = xxh64_round(v3, get_unaligned_le64(p));\n\t\t\tp += 8;\n\t\t\tv4 = xxh64_round(v4, get_unaligned_le64(p));\n\t\t\tp += 8;\n\t\t} while (p <= limit);\n\n\t\tstate->v1 = v1;\n\t\tstate->v2 = v2;\n\t\tstate->v3 = v3;\n\t\tstate->v4 = v4;\n\t}\n\n\tif (p < b_end) {\n\t\t__builtin_memcpy(state->mem64, p, (size_t)(b_end-p));\n\t\tstate->memsize = (uint32_t)(b_end - p);\n\t}\n\n\treturn 0;\n}\n\nXXH_API uint64_t xxh64_digest(const struct xxh64_state *state)\n{\n\tconst uint8_t *p = (const uint8_t *)state->mem64;\n\tconst uint8_t *const b_end = (const uint8_t *)state->mem64 +\n\t\tstate->memsize;\n\tuint64_t h64;\n\n\tif (state->total_len >= 32) {\n\t\tconst uint64_t v1 = state->v1;\n\t\tconst uint64_t v2 = state->v2;\n\t\tconst uint64_t v3 = state->v3;\n\t\tconst uint64_t v4 = state->v4;\n\n\t\th64 = xxh_rotl64(v1, 1) + xxh_rotl64(v2, 7) +\n\t\t\txxh_rotl64(v3, 12) + xxh_rotl64(v4, 18);\n\t\th64 = xxh64_merge_round(h64, v1);\n\t\th64 = xxh64_merge_round(h64, v2);\n\t\th64 = xxh64_merge_round(h64, v3);\n\t\th64 = xxh64_merge_round(h64, v4);\n\t} else {\n\t\th64  = state->v3 + PRIME64_5;\n\t}\n\n\th64 += (uint64_t)state->total_len;\n\n\twhile (p + 8 <= b_end) {\n\t\tconst uint64_t k1 = xxh64_round(0, get_unaligned_le64(p));\n\n\t\th64 ^= k1;\n\t\th64 = xxh_rotl64(h64, 27) * PRIME64_1 + PRIME64_4;\n\t\tp += 8;\n\t}\n\n\tif (p + 4 <= b_end) {\n\t\th64 ^= (uint64_t)(get_unaligned_le32(p)) * PRIME64_1;\n\t\th64 = xxh_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;\n\t\tp += 4;\n\t}\n\n\twhile (p < b_end) {\n\t\th64 ^= (*p) * PRIME64_5;\n\t\th64 = xxh_rotl64(h64, 11) * PRIME64_1;\n\t\tp++;\n\t}\n\n\th64 ^= h64 >> 33;\n\th64 *= PRIME64_2;\n\th64 ^= h64 >> 29;\n\th64 *= PRIME64_3;\n\th64 ^= h64 >> 32;\n\n\treturn h64;\n}\n\n#endif /* XXHASH_H */\n"
  },
  {
    "path": "contrib/linux-kernel/test/macro-test.sh",
    "content": "#!/usr/bin/env sh\n\nset -e\n\nSCRIPT_DIR=$(cd \"$(dirname \"$0\")\" && pwd)\nINCLUDE_DIR=\"$SCRIPT_DIR/../linux/include\"\nLIB_DIR=\"$SCRIPT_DIR/../linux/lib\"\n\n\nprint() {\n    printf '%b' \"${*}\"\n}\n\nprintln() {\n    printf '%b\\n' \"${*}\"\n}\n\ndie() {\n    println \"$@\" 1>&2\n    exit 1\n}\n\ntest_not_present() {\n    print \"Testing that '$1' is not present... \"\n    grep -r $1 \"$INCLUDE_DIR\" \"$LIB_DIR\" && die \"Fail!\"\n    println \"Okay\"\n}\n\nprintln \"This test checks that the macro removal process worked as expected\"\nprintln \"If this test fails, then freestanding.py wasn't able to remove one of these\"\nprintln \"macros from the source code completely. You'll either need to rewrite the check\"\nprintln \"or improve freestanding.py.\"\nprintln \"\"\n\ntest_not_present \"ZSTD_NO_INTRINSICS\"\ntest_not_present \"ZSTD_NO_UNUSED_FUNCTIONS\"\ntest_not_present \"ZSTD_LEGACY_SUPPORT\"\ntest_not_present \"STATIC_BMI2\"\ntest_not_present \"ZSTD_DLL_EXPORT\"\ntest_not_present \"ZSTD_DLL_IMPORT\"\ntest_not_present \"__ICCARM__\"\ntest_not_present \"_MSC_VER\"\ntest_not_present \"_WIN32\"\ntest_not_present \"__linux__\"\n"
  },
  {
    "path": "contrib/linux-kernel/test/static_test.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n#include <stddef.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"decompress_sources.h\"\n#include <linux/zstd.h>\n\n#define CONTROL(x)                                                             \\\n  do {                                                                         \\\n    if (!(x)) {                                                                \\\n      fprintf(stderr, \"%s:%u: %s failed!\\n\", __FUNCTION__, __LINE__, #x);      \\\n      abort();                                                                 \\\n    }                                                                          \\\n  } while (0)\n\n\nstatic const char kEmptyZstdFrame[] = {\n    0x28, 0xb5, 0x2f, 0xfd, 0x24, 0x00, 0x01, 0x00, 0x00, 0x99, 0xe9, 0xd8, 0x51\n};\n\nstatic void test_decompress_unzstd(void) {\n    fprintf(stderr, \"Testing decompress unzstd... \");\n    {\n        size_t const wkspSize = zstd_dctx_workspace_bound();\n        void* wksp = malloc(wkspSize);\n        ZSTD_DCtx* dctx = zstd_init_dctx(wksp, wkspSize);\n        CONTROL(wksp != NULL);\n        CONTROL(dctx != NULL);\n        {\n          size_t const dSize = zstd_decompress_dctx(dctx, NULL, 0, kEmptyZstdFrame, sizeof(kEmptyZstdFrame));\n          CONTROL(!zstd_is_error(dSize));\n          CONTROL(dSize == 0);\n        }\n        free(wksp);\n    }\n    fprintf(stderr, \"Ok\\n\");\n}\n\nint main(void) {\n  test_decompress_unzstd();\n  return 0;\n}\n"
  },
  {
    "path": "contrib/linux-kernel/test/test.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n#include <stddef.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include <linux/zstd.h>\n\n#define CONTROL(x)                                                             \\\n  do {                                                                         \\\n    if (!(x)) {                                                                \\\n      fprintf(stderr, \"%s:%u: %s failed!\\n\", __FUNCTION__, __LINE__, #x);      \\\n      abort();                                                                 \\\n    }                                                                          \\\n  } while (0)\n\ntypedef struct {\n  char *data;\n  char *data2;\n  size_t dataSize;\n  char *comp;\n  size_t compSize;\n} test_data_t;\n\nstatic test_data_t create_test_data(void) {\n  test_data_t data;\n  data.dataSize = 128 * 1024;\n  data.data = (char*)malloc(data.dataSize);\n  CONTROL(data.data != NULL);\n  data.data2 = (char*)malloc(data.dataSize);\n  CONTROL(data.data2 != NULL);\n  data.compSize = zstd_compress_bound(data.dataSize);\n  data.comp = (char*)malloc(data.compSize);\n  CONTROL(data.comp != NULL);\n  memset(data.data, 0, data.dataSize);\n  return data;\n}\n\nstatic void free_test_data(test_data_t const *data) {\n  free(data->data);\n  free(data->data2);\n  free(data->comp);\n}\n\n#define MIN(a, b) ((a) < (b) ? (a) : (b))\n#define MAX(a, b) ((a) > (b) ? (a) : (b))\n\nstatic void test_btrfs(test_data_t const *data) {\n  size_t const size = MIN(data->dataSize, 128 * 1024);\n  fprintf(stderr, \"testing btrfs use cases... \");\n  for (int level = -1; level < 16; ++level) {\n    zstd_parameters params = zstd_get_params(level, size);\n    size_t const workspaceSize =\n        MAX(zstd_cstream_workspace_bound(&params.cParams),\n            zstd_dstream_workspace_bound(size));\n    void *workspace = malloc(workspaceSize);\n\n    char const *ip = data->data;\n    char const *iend = ip + size;\n    char *op = data->comp;\n    char *oend = op + data->compSize;\n\n    CONTROL(params.cParams.windowLog <= 17);\n    CONTROL(workspace != NULL);\n    {\n      zstd_cstream *cctx = zstd_init_cstream(&params, size, workspace, workspaceSize);\n      zstd_out_buffer out = {NULL, 0, 0};\n      zstd_in_buffer in = {NULL, 0, 0};\n      CONTROL(cctx != NULL);\n      for (;;) {\n        if (in.pos == in.size) {\n          in.src = ip;\n          in.size = MIN(4096, iend - ip);\n          in.pos = 0;\n          ip += in.size;\n        }\n\n        if (out.pos == out.size) {\n          out.dst = op;\n          out.size = MIN(4096, oend - op);\n          out.pos = 0;\n          op += out.size;\n        }\n\n        if (ip != iend || in.pos < in.size) {\n          CONTROL(!zstd_is_error(zstd_compress_stream(cctx, &out, &in)));\n        } else {\n          size_t const ret = zstd_end_stream(cctx, &out);\n          CONTROL(!zstd_is_error(ret));\n          if (ret == 0) {\n            break;\n          }\n        }\n      }\n      op += out.pos;\n    }\n\n    ip = data->comp;\n    iend = op;\n    op = data->data2;\n    oend = op + size;\n    {\n      zstd_dstream *dctx = zstd_init_dstream(1ULL << params.cParams.windowLog, workspace, workspaceSize);\n      zstd_out_buffer out = {NULL, 0, 0};\n      zstd_in_buffer in = {NULL, 0, 0};\n      CONTROL(dctx != NULL);\n      for (;;) {\n        if (in.pos == in.size) {\n          in.src = ip;\n          in.size = MIN(4096, iend - ip);\n          in.pos = 0;\n          ip += in.size;\n        }\n\n        if (out.pos == out.size) {\n          out.dst = op;\n          out.size = MIN(4096, oend - op);\n          out.pos = 0;\n          op += out.size;\n        }\n        {\n          size_t const ret = zstd_decompress_stream(dctx, &out, &in);\n          CONTROL(!zstd_is_error(ret));\n          if (ret == 0) {\n            break;\n          }\n        }\n      }\n    }\n    CONTROL((size_t)(op - data->data2) == data->dataSize);\n    CONTROL(!memcmp(data->data, data->data2, data->dataSize));\n    free(workspace);\n  }\n  fprintf(stderr, \"Ok\\n\");\n}\n\nstatic void test_decompress_unzstd(test_data_t const *data) {\n    size_t cSize;\n    fprintf(stderr, \"Testing decompress unzstd... \");\n    {\n        zstd_parameters params = zstd_get_params(19, 0);\n        size_t const wkspSize = zstd_cctx_workspace_bound(&params.cParams);\n        void* wksp = malloc(wkspSize);\n        zstd_cctx* cctx = zstd_init_cctx(wksp, wkspSize);\n        CONTROL(wksp != NULL);\n        CONTROL(cctx != NULL);\n        cSize = zstd_compress_cctx(cctx, data->comp, data->compSize, data->data, data->dataSize, &params);\n        CONTROL(!zstd_is_error(cSize));\n        free(wksp);\n    }\n    {\n        size_t const wkspSize = zstd_dctx_workspace_bound();\n        void* wksp = malloc(wkspSize);\n        zstd_dctx* dctx = zstd_init_dctx(wksp, wkspSize);\n        CONTROL(wksp != NULL);\n        CONTROL(dctx != NULL);\n        {\n          size_t const dSize = zstd_decompress_dctx(dctx, data->data2, data->dataSize, data->comp, cSize);\n          CONTROL(!zstd_is_error(dSize));\n          CONTROL(dSize == data->dataSize);\n        }\n        CONTROL(!memcmp(data->data, data->data2, data->dataSize));\n        free(wksp);\n    }\n    fprintf(stderr, \"Ok\\n\");\n}\n\nstatic void test_f2fs(void) {\n  fprintf(stderr, \"testing f2fs uses... \");\n  CONTROL(zstd_min_clevel() < 0);\n  CONTROL(zstd_max_clevel() == 22);\n  fprintf(stderr, \"Ok\\n\");\n}\n\nstatic char *g_stack = NULL;\n\nstatic void __attribute__((noinline)) use(void *x) {\n  asm volatile(\"\" : \"+r\"(x));\n}\n\nstatic void __attribute__((noinline)) fill_stack(void) {\n  memset(g_stack, 0x33, 8192);\n}\n\nstatic void __attribute__((noinline)) set_stack(void) {\n\n  char stack[8192];\n  g_stack = stack;\n  use(g_stack);\n}\n\nstatic void __attribute__((noinline)) check_stack(void) {\n  size_t cleanStack = 0;\n  while (cleanStack < 8192 && g_stack[cleanStack] == 0x33) {\n    ++cleanStack;\n  }\n  {\n    size_t const stackSize = 8192 - cleanStack;\n    fprintf(stderr, \"Maximum stack size: %zu\\n\", stackSize);\n    CONTROL(stackSize <= 2048 + 512);\n  }\n}\n\nstatic void test_stack_usage(test_data_t const *data) {\n  set_stack();\n  fill_stack();\n  test_f2fs();\n  test_btrfs(data);\n  test_decompress_unzstd(data);\n  check_stack();\n}\n\nint main(void) {\n  test_data_t data = create_test_data();\n  test_f2fs();\n  test_btrfs(&data);\n  test_decompress_unzstd(&data);\n  test_stack_usage(&data);\n  free_test_data(&data);\n  return 0;\n}\n"
  },
  {
    "path": "contrib/linux-kernel/zstd_common_module.c",
    "content": "// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause\n/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include <linux/module.h>\n\n#include \"common/huf.h\"\n#include \"common/fse.h\"\n#include \"common/zstd_internal.h\"\n\n// Export symbols shared by compress and decompress into a common module\n\n#undef ZSTD_isError   /* defined within zstd_internal.h */\nEXPORT_SYMBOL_GPL(FSE_readNCount);\nEXPORT_SYMBOL_GPL(HUF_readStats);\nEXPORT_SYMBOL_GPL(HUF_readStats_wksp);\nEXPORT_SYMBOL_GPL(ZSTD_isError);\nEXPORT_SYMBOL_GPL(ZSTD_getErrorName);\nEXPORT_SYMBOL_GPL(ZSTD_getErrorCode);\n\nMODULE_LICENSE(\"Dual BSD/GPL\");\nMODULE_DESCRIPTION(\"Zstd Common\");\n"
  },
  {
    "path": "contrib/linux-kernel/zstd_compress_module.c",
    "content": "// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause\n/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include <linux/kernel.h>\n#include <linux/module.h>\n#include <linux/string.h>\n#include <linux/zstd.h>\n\n#include \"common/zstd_deps.h\"\n#include \"common/zstd_internal.h\"\n#include \"compress/zstd_compress_internal.h\"\n\n#define ZSTD_FORWARD_IF_ERR(ret)            \\\n\tdo {                                \\\n\t\tsize_t const __ret = (ret); \\\n\t\tif (ZSTD_isError(__ret))    \\\n\t\t\treturn __ret;       \\\n\t} while (0)\n\nstatic size_t zstd_cctx_init(zstd_cctx *cctx, const zstd_parameters *parameters,\n\tunsigned long long pledged_src_size)\n{\n\tZSTD_FORWARD_IF_ERR(ZSTD_CCtx_reset(\n\t\tcctx, ZSTD_reset_session_and_parameters));\n\tZSTD_FORWARD_IF_ERR(ZSTD_CCtx_setPledgedSrcSize(\n\t\tcctx, pledged_src_size));\n\tZSTD_FORWARD_IF_ERR(ZSTD_CCtx_setParameter(\n\t\tcctx, ZSTD_c_windowLog, parameters->cParams.windowLog));\n\tZSTD_FORWARD_IF_ERR(ZSTD_CCtx_setParameter(\n\t\tcctx, ZSTD_c_hashLog, parameters->cParams.hashLog));\n\tZSTD_FORWARD_IF_ERR(ZSTD_CCtx_setParameter(\n\t\tcctx, ZSTD_c_chainLog, parameters->cParams.chainLog));\n\tZSTD_FORWARD_IF_ERR(ZSTD_CCtx_setParameter(\n\t\tcctx, ZSTD_c_searchLog, parameters->cParams.searchLog));\n\tZSTD_FORWARD_IF_ERR(ZSTD_CCtx_setParameter(\n\t\tcctx, ZSTD_c_minMatch, parameters->cParams.minMatch));\n\tZSTD_FORWARD_IF_ERR(ZSTD_CCtx_setParameter(\n\t\tcctx, ZSTD_c_targetLength, parameters->cParams.targetLength));\n\tZSTD_FORWARD_IF_ERR(ZSTD_CCtx_setParameter(\n\t\tcctx, ZSTD_c_strategy, parameters->cParams.strategy));\n\tZSTD_FORWARD_IF_ERR(ZSTD_CCtx_setParameter(\n\t\tcctx, ZSTD_c_contentSizeFlag, parameters->fParams.contentSizeFlag));\n\tZSTD_FORWARD_IF_ERR(ZSTD_CCtx_setParameter(\n\t\tcctx, ZSTD_c_checksumFlag, parameters->fParams.checksumFlag));\n\tZSTD_FORWARD_IF_ERR(ZSTD_CCtx_setParameter(\n\t\tcctx, ZSTD_c_dictIDFlag, !parameters->fParams.noDictIDFlag));\n\treturn 0;\n}\n\nint zstd_min_clevel(void)\n{\n\treturn ZSTD_minCLevel();\n}\nEXPORT_SYMBOL(zstd_min_clevel);\n\nint zstd_max_clevel(void)\n{\n\treturn ZSTD_maxCLevel();\n}\nEXPORT_SYMBOL(zstd_max_clevel);\n\nint zstd_default_clevel(void)\n{\n\treturn ZSTD_defaultCLevel();\n}\nEXPORT_SYMBOL(zstd_default_clevel);\n\nsize_t zstd_compress_bound(size_t src_size)\n{\n\treturn ZSTD_compressBound(src_size);\n}\nEXPORT_SYMBOL(zstd_compress_bound);\n\nzstd_parameters zstd_get_params(int level,\n\tunsigned long long estimated_src_size)\n{\n\treturn ZSTD_getParams(level, estimated_src_size, 0);\n}\nEXPORT_SYMBOL(zstd_get_params);\n\nzstd_compression_parameters zstd_get_cparams(int level,\n\tunsigned long long estimated_src_size, size_t dict_size)\n{\n\treturn ZSTD_getCParams(level, estimated_src_size, dict_size);\n}\nEXPORT_SYMBOL(zstd_get_cparams);\n\nsize_t zstd_cctx_set_param(zstd_cctx *cctx, ZSTD_cParameter param, int value)\n{\n\treturn ZSTD_CCtx_setParameter(cctx, param, value);\n}\nEXPORT_SYMBOL(zstd_cctx_set_param);\n\nsize_t zstd_cctx_workspace_bound(const zstd_compression_parameters *cparams)\n{\n\treturn ZSTD_estimateCCtxSize_usingCParams(*cparams);\n}\nEXPORT_SYMBOL(zstd_cctx_workspace_bound);\n\n// Used by zstd_cctx_workspace_bound_with_ext_seq_prod()\nstatic size_t dummy_external_sequence_producer(\n\tvoid *sequenceProducerState,\n\tZSTD_Sequence *outSeqs, size_t outSeqsCapacity,\n\tconst void *src, size_t srcSize,\n\tconst void *dict, size_t dictSize,\n\tint compressionLevel,\n\tsize_t windowSize)\n{\n\t(void)sequenceProducerState;\n\t(void)outSeqs; (void)outSeqsCapacity;\n\t(void)src; (void)srcSize;\n\t(void)dict; (void)dictSize;\n\t(void)compressionLevel;\n\t(void)windowSize;\n\treturn ZSTD_SEQUENCE_PRODUCER_ERROR;\n}\n\nstatic void init_cctx_params_from_compress_params(\n\tZSTD_CCtx_params *cctx_params,\n\tconst zstd_compression_parameters *compress_params)\n{\n\tZSTD_parameters zstd_params;\n\tmemset(&zstd_params, 0, sizeof(zstd_params));\n\tzstd_params.cParams = *compress_params;\n\tZSTD_CCtxParams_init_advanced(cctx_params, zstd_params);\n}\n\nsize_t zstd_cctx_workspace_bound_with_ext_seq_prod(const zstd_compression_parameters *compress_params)\n{\n\tZSTD_CCtx_params cctx_params;\n\tinit_cctx_params_from_compress_params(&cctx_params, compress_params);\n\tZSTD_CCtxParams_registerSequenceProducer(&cctx_params, NULL, dummy_external_sequence_producer);\n\treturn ZSTD_estimateCCtxSize_usingCCtxParams(&cctx_params);\n}\nEXPORT_SYMBOL(zstd_cctx_workspace_bound_with_ext_seq_prod);\n\nsize_t zstd_cstream_workspace_bound_with_ext_seq_prod(const zstd_compression_parameters *compress_params)\n{\n\tZSTD_CCtx_params cctx_params;\n\tinit_cctx_params_from_compress_params(&cctx_params, compress_params);\n\tZSTD_CCtxParams_registerSequenceProducer(&cctx_params, NULL, dummy_external_sequence_producer);\n\treturn ZSTD_estimateCStreamSize_usingCCtxParams(&cctx_params);\n}\nEXPORT_SYMBOL(zstd_cstream_workspace_bound_with_ext_seq_prod);\n\nzstd_cctx *zstd_init_cctx(void *workspace, size_t workspace_size)\n{\n\tif (workspace == NULL)\n\t\treturn NULL;\n\treturn ZSTD_initStaticCCtx(workspace, workspace_size);\n}\nEXPORT_SYMBOL(zstd_init_cctx);\n\nzstd_cctx *zstd_create_cctx_advanced(zstd_custom_mem custom_mem)\n{\n\treturn ZSTD_createCCtx_advanced(custom_mem);\n}\nEXPORT_SYMBOL(zstd_create_cctx_advanced);\n\nsize_t zstd_free_cctx(zstd_cctx *cctx)\n{\n\treturn ZSTD_freeCCtx(cctx);\n}\nEXPORT_SYMBOL(zstd_free_cctx);\n\nzstd_cdict *zstd_create_cdict_byreference(const void *dict, size_t dict_size,\n\t\t\t\t\t  zstd_compression_parameters cparams,\n\t\t\t\t\t  zstd_custom_mem custom_mem)\n{\n\treturn ZSTD_createCDict_advanced(dict, dict_size, ZSTD_dlm_byRef,\n\t\t\t\t\t ZSTD_dct_auto, cparams, custom_mem);\n}\nEXPORT_SYMBOL(zstd_create_cdict_byreference);\n\nsize_t zstd_free_cdict(zstd_cdict *cdict)\n{\n\treturn ZSTD_freeCDict(cdict);\n}\nEXPORT_SYMBOL(zstd_free_cdict);\n\nsize_t zstd_compress_cctx(zstd_cctx *cctx, void *dst, size_t dst_capacity,\n\tconst void *src, size_t src_size, const zstd_parameters *parameters)\n{\n\tZSTD_FORWARD_IF_ERR(zstd_cctx_init(cctx, parameters, src_size));\n\treturn ZSTD_compress2(cctx, dst, dst_capacity, src, src_size);\n}\nEXPORT_SYMBOL(zstd_compress_cctx);\n\nsize_t zstd_compress_using_cdict(zstd_cctx *cctx, void *dst,\n\tsize_t dst_capacity, const void *src, size_t src_size,\n\tconst ZSTD_CDict *cdict)\n{\n\treturn ZSTD_compress_usingCDict(cctx, dst, dst_capacity,\n\t\t\t\t\tsrc, src_size, cdict);\n}\nEXPORT_SYMBOL(zstd_compress_using_cdict);\n\nsize_t zstd_cstream_workspace_bound(const zstd_compression_parameters *cparams)\n{\n\treturn ZSTD_estimateCStreamSize_usingCParams(*cparams);\n}\nEXPORT_SYMBOL(zstd_cstream_workspace_bound);\n\nzstd_cstream *zstd_init_cstream(const zstd_parameters *parameters,\n\tunsigned long long pledged_src_size, void *workspace, size_t workspace_size)\n{\n\tzstd_cstream *cstream;\n\n\tif (workspace == NULL)\n\t\treturn NULL;\n\n\tcstream = ZSTD_initStaticCStream(workspace, workspace_size);\n\tif (cstream == NULL)\n\t\treturn NULL;\n\n\t/* 0 means unknown in linux zstd API but means 0 in new zstd API */\n\tif (pledged_src_size == 0)\n\t\tpledged_src_size = ZSTD_CONTENTSIZE_UNKNOWN;\n\n\tif (ZSTD_isError(zstd_cctx_init(cstream, parameters, pledged_src_size)))\n\t\treturn NULL;\n\n\treturn cstream;\n}\nEXPORT_SYMBOL(zstd_init_cstream);\n\nsize_t zstd_reset_cstream(zstd_cstream *cstream,\n\tunsigned long long pledged_src_size)\n{\n\tif (pledged_src_size == 0)\n\t\tpledged_src_size = ZSTD_CONTENTSIZE_UNKNOWN;\n\tZSTD_FORWARD_IF_ERR( ZSTD_CCtx_reset(cstream, ZSTD_reset_session_only) );\n\tZSTD_FORWARD_IF_ERR( ZSTD_CCtx_setPledgedSrcSize(cstream, pledged_src_size) );\n\treturn 0;\n}\nEXPORT_SYMBOL(zstd_reset_cstream);\n\nsize_t zstd_compress_stream(zstd_cstream *cstream, zstd_out_buffer *output,\n\tzstd_in_buffer *input)\n{\n\treturn ZSTD_compressStream(cstream, output, input);\n}\nEXPORT_SYMBOL(zstd_compress_stream);\n\nsize_t zstd_flush_stream(zstd_cstream *cstream, zstd_out_buffer *output)\n{\n\treturn ZSTD_flushStream(cstream, output);\n}\nEXPORT_SYMBOL(zstd_flush_stream);\n\nsize_t zstd_end_stream(zstd_cstream *cstream, zstd_out_buffer *output)\n{\n\treturn ZSTD_endStream(cstream, output);\n}\nEXPORT_SYMBOL(zstd_end_stream);\n\nvoid zstd_register_sequence_producer(\n  zstd_cctx *cctx,\n  void* sequence_producer_state,\n  zstd_sequence_producer_f sequence_producer\n) {\n\tZSTD_registerSequenceProducer(cctx, sequence_producer_state, sequence_producer);\n}\nEXPORT_SYMBOL(zstd_register_sequence_producer);\n\nsize_t zstd_compress_sequences_and_literals(zstd_cctx *cctx, void* dst, size_t dst_capacity,\n\t\t\t\t\t    const zstd_sequence *in_seqs, size_t in_seqs_size,\n\t\t\t\t\t    const void* literals, size_t lit_size, size_t lit_capacity,\n\t\t\t\t\t    size_t decompressed_size)\n{\n\treturn ZSTD_compressSequencesAndLiterals(cctx, dst, dst_capacity, in_seqs,\n\t\t\t\t\t\t in_seqs_size, literals, lit_size,\n\t\t\t\t\t\t lit_capacity, decompressed_size);\n}\nEXPORT_SYMBOL(zstd_compress_sequences_and_literals);\n\nMODULE_LICENSE(\"Dual BSD/GPL\");\nMODULE_DESCRIPTION(\"Zstd Compressor\");\n"
  },
  {
    "path": "contrib/linux-kernel/zstd_decompress_module.c",
    "content": "// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause\n/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include <linux/kernel.h>\n#include <linux/module.h>\n#include <linux/string.h>\n#include <linux/zstd.h>\n\n#include \"common/zstd_deps.h\"\n\n/* Common symbols. zstd_compress must depend on zstd_decompress. */\n\nunsigned int zstd_is_error(size_t code)\n{\n\treturn ZSTD_isError(code);\n}\nEXPORT_SYMBOL(zstd_is_error);\n\nzstd_error_code zstd_get_error_code(size_t code)\n{\n\treturn ZSTD_getErrorCode(code);\n}\nEXPORT_SYMBOL(zstd_get_error_code);\n\nconst char *zstd_get_error_name(size_t code)\n{\n\treturn ZSTD_getErrorName(code);\n}\nEXPORT_SYMBOL(zstd_get_error_name);\n\n/* Decompression symbols. */\n\nsize_t zstd_dctx_workspace_bound(void)\n{\n\treturn ZSTD_estimateDCtxSize();\n}\nEXPORT_SYMBOL(zstd_dctx_workspace_bound);\n\nzstd_dctx *zstd_create_dctx_advanced(zstd_custom_mem custom_mem)\n{\n\treturn ZSTD_createDCtx_advanced(custom_mem);\n}\nEXPORT_SYMBOL(zstd_create_dctx_advanced);\n\nsize_t zstd_free_dctx(zstd_dctx *dctx)\n{\n\treturn ZSTD_freeDCtx(dctx);\n}\nEXPORT_SYMBOL(zstd_free_dctx);\n\nzstd_ddict *zstd_create_ddict_byreference(const void *dict, size_t dict_size,\n\t\t\t\t\t  zstd_custom_mem custom_mem)\n{\n\treturn ZSTD_createDDict_advanced(dict, dict_size, ZSTD_dlm_byRef,\n\t\t\t\t\t ZSTD_dct_auto, custom_mem);\n\n}\nEXPORT_SYMBOL(zstd_create_ddict_byreference);\n\nsize_t zstd_free_ddict(zstd_ddict *ddict)\n{\n\treturn ZSTD_freeDDict(ddict);\n}\nEXPORT_SYMBOL(zstd_free_ddict);\n\nzstd_dctx *zstd_init_dctx(void *workspace, size_t workspace_size)\n{\n\tif (workspace == NULL)\n\t\treturn NULL;\n\treturn ZSTD_initStaticDCtx(workspace, workspace_size);\n}\nEXPORT_SYMBOL(zstd_init_dctx);\n\nsize_t zstd_decompress_dctx(zstd_dctx *dctx, void *dst, size_t dst_capacity,\n\tconst void *src, size_t src_size)\n{\n\treturn ZSTD_decompressDCtx(dctx, dst, dst_capacity, src, src_size);\n}\nEXPORT_SYMBOL(zstd_decompress_dctx);\n\nsize_t zstd_decompress_using_ddict(zstd_dctx *dctx,\n\tvoid *dst, size_t dst_capacity, const void* src, size_t src_size,\n\tconst zstd_ddict* ddict)\n{\n\treturn ZSTD_decompress_usingDDict(dctx, dst, dst_capacity, src,\n\t\t\t\t\t  src_size, ddict);\n}\nEXPORT_SYMBOL(zstd_decompress_using_ddict);\n\nsize_t zstd_dstream_workspace_bound(size_t max_window_size)\n{\n\treturn ZSTD_estimateDStreamSize(max_window_size);\n}\nEXPORT_SYMBOL(zstd_dstream_workspace_bound);\n\nzstd_dstream *zstd_init_dstream(size_t max_window_size, void *workspace,\n\tsize_t workspace_size)\n{\n\tif (workspace == NULL)\n\t\treturn NULL;\n\t(void)max_window_size;\n\treturn ZSTD_initStaticDStream(workspace, workspace_size);\n}\nEXPORT_SYMBOL(zstd_init_dstream);\n\nsize_t zstd_reset_dstream(zstd_dstream *dstream)\n{\n\treturn ZSTD_DCtx_reset(dstream, ZSTD_reset_session_only);\n}\nEXPORT_SYMBOL(zstd_reset_dstream);\n\nsize_t zstd_decompress_stream(zstd_dstream *dstream, zstd_out_buffer *output,\n\tzstd_in_buffer *input)\n{\n\treturn ZSTD_decompressStream(dstream, output, input);\n}\nEXPORT_SYMBOL(zstd_decompress_stream);\n\nsize_t zstd_find_frame_compressed_size(const void *src, size_t src_size)\n{\n\treturn ZSTD_findFrameCompressedSize(src, src_size);\n}\nEXPORT_SYMBOL(zstd_find_frame_compressed_size);\n\nsize_t zstd_get_frame_header(zstd_frame_header *header, const void *src,\n\tsize_t src_size)\n{\n\treturn ZSTD_getFrameHeader(header, src, src_size);\n}\nEXPORT_SYMBOL(zstd_get_frame_header);\n\nMODULE_LICENSE(\"Dual BSD/GPL\");\nMODULE_DESCRIPTION(\"Zstd Decompressor\");\n"
  },
  {
    "path": "contrib/linux-kernel/zstd_deps.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */\n/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/*\n * This file provides common libc dependencies that zstd requires.\n * The purpose is to allow replacing this file with a custom implementation\n * to compile zstd without libc support.\n */\n\n/* Need:\n * NULL\n * INT_MAX\n * UINT_MAX\n * ZSTD_memcpy()\n * ZSTD_memset()\n * ZSTD_memmove()\n */\n#ifndef ZSTD_DEPS_COMMON\n#define ZSTD_DEPS_COMMON\n\n#include <linux/limits.h>\n#include <linux/stddef.h>\n\n#define ZSTD_memcpy(d,s,n) __builtin_memcpy((d),(s),(n))\n#define ZSTD_memmove(d,s,n) __builtin_memmove((d),(s),(n))\n#define ZSTD_memset(d,s,n) __builtin_memset((d),(s),(n))\n\n#endif /* ZSTD_DEPS_COMMON */\n\n/*\n * Define malloc as always failing. That means the user must\n * either use ZSTD_customMem or statically allocate memory.\n * Need:\n * ZSTD_malloc()\n * ZSTD_free()\n * ZSTD_calloc()\n */\n#ifdef ZSTD_DEPS_NEED_MALLOC\n#ifndef ZSTD_DEPS_MALLOC\n#define ZSTD_DEPS_MALLOC\n\n#define ZSTD_malloc(s) ({ (void)(s); NULL; })\n#define ZSTD_free(p) ((void)(p))\n#define ZSTD_calloc(n,s) ({ (void)(n); (void)(s); NULL; })\n\n#endif /* ZSTD_DEPS_MALLOC */\n#endif /* ZSTD_DEPS_NEED_MALLOC */\n\n/*\n * Provides 64-bit math support.\n * Need:\n * U64 ZSTD_div64(U64 dividend, U32 divisor)\n */\n#ifdef ZSTD_DEPS_NEED_MATH64\n#ifndef ZSTD_DEPS_MATH64\n#define ZSTD_DEPS_MATH64\n\n#include <linux/math64.h>\n\nstatic uint64_t ZSTD_div64(uint64_t dividend, uint32_t divisor) {\n  return div_u64(dividend, divisor);\n}\n\n#endif /* ZSTD_DEPS_MATH64 */\n#endif /* ZSTD_DEPS_NEED_MATH64 */\n\n/*\n * This is only requested when DEBUGLEVEL >= 1, meaning\n * it is disabled in production.\n * Need:\n * assert()\n */\n#ifdef ZSTD_DEPS_NEED_ASSERT\n#ifndef ZSTD_DEPS_ASSERT\n#define ZSTD_DEPS_ASSERT\n\n#include <linux/kernel.h>\n\n#define assert(x) WARN_ON(!(x))\n\n#endif /* ZSTD_DEPS_ASSERT */\n#endif /* ZSTD_DEPS_NEED_ASSERT */\n\n/*\n * This is only requested when DEBUGLEVEL >= 2, meaning\n * it is disabled in production.\n * Need:\n * ZSTD_DEBUG_PRINT()\n */\n#ifdef ZSTD_DEPS_NEED_IO\n#ifndef ZSTD_DEPS_IO\n#define ZSTD_DEPS_IO\n\n#include <linux/printk.h>\n\n#define ZSTD_DEBUG_PRINT(...) pr_debug(__VA_ARGS__)\n\n#endif /* ZSTD_DEPS_IO */\n#endif /* ZSTD_DEPS_NEED_IO */\n\n/*\n * Only requested when MSAN is enabled.\n * Need:\n * intptr_t\n */\n#ifdef ZSTD_DEPS_NEED_STDINT\n#ifndef ZSTD_DEPS_STDINT\n#define ZSTD_DEPS_STDINT\n\n/* intptr_t already provided by ZSTD_DEPS_COMMON */\n\n#endif /* ZSTD_DEPS_STDINT */\n#endif /* ZSTD_DEPS_NEED_STDINT */\n"
  },
  {
    "path": "contrib/match_finders/README.md",
    "content": "## Edit Distance Match Finder\n\n```\n/* This match finder leverages techniques used in file comparison algorithms\n * to find matches between a dictionary and a source file.\n * \n * The original motivation for studying this approach was to try and optimize \n * Zstandard for the use case of patching: the most common scenario being \n * updating an existing software package with the next version. When patching,\n * the difference between the old version of the package and the new version \n * is generally tiny (most of the new file will be identical to \n * the old one). In more technical terms, the edit distance (the minimal number \n * of changes required to take one sequence of bytes to another) between the \n * files would be small relative to the size of the file. \n * \n * Various 'diffing' algorithms utilize this notion of edit distance and \n * the corresponding concept of a minimal edit script between two \n * sequences to identify the regions within two files where they differ. \n * The core algorithm used in this match finder is described in: \n * \n * \"An O(ND) Difference Algorithm and its Variations\", Eugene W. Myers,\n *    Algorithmica Vol. 1, 1986, pp. 251-266,\n *    <https://doi.org/10.1007/BF01840446>.\n * \n * Additional algorithmic heuristics for speed improvement have also been included.\n * These we inspired from implementations of various regular and binary diffing \n * algorithms such as GNU diff, bsdiff, and Xdelta. \n * \n * Note: after some experimentation, this approach proved to not provide enough \n * utility to justify the additional CPU used in finding matches. The one area\n * where this approach consistently outperforms Zstandard even on level 19 is \n * when compressing small files (<10 KB) using an equally small dictionary that \n * is very similar to the source file. For the use case that this was intended,\n * (large similar files) this approach by itself took 5-10X longer than zstd-19 and \n * generally resulted in 2-3X larger files. The core advantage that zstd-19 has \n * over this approach for match finding is the overlapping matches. This approach \n * cannot find any. \n * \n * I'm leaving this in the contrib section in case this ever becomes interesting \n * to explore again.\n * */\n```\n"
  },
  {
    "path": "contrib/match_finders/zstd_edist.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/*-*************************************\n*  Dependencies\n***************************************/\n\n/* Currently relies on qsort when combining contiguous matches. This can probably \n * be avoided but would require changes to the algorithm. The qsort is far from \n * the bottleneck in this algorithm even for medium sized files so it's probably \n * not worth trying to address */ \n#include <stdlib.h>\n#include <assert.h>\n\n#include \"zstd_edist.h\"\n#include \"mem.h\"\n\n/*-*************************************\n*  Constants\n***************************************/\n\n/* Just a sential for the entries of the diagonal matrix */\n#define ZSTD_EDIST_DIAG_MAX (S32)(1 << 30)\n\n/* How large should a snake be to be considered a 'big' snake. \n * For an explanation of what a 'snake' is with respect to the \n * edit distance matrix, see the linked paper in zstd_edist.h */\n#define ZSTD_EDIST_SNAKE_THRESH 20\n\n/* After how many iterations should we start to use the heuristic\n * based on 'big' snakes */\n#define ZSTD_EDIST_SNAKE_ITER_THRESH 200\n\n/* After how many iterations should be just give up and take \n * the best available edit script for this round */ \n#define ZSTD_EDIST_EXPENSIVE_THRESH 1024\n\n/*-*************************************\n*  Structures\n***************************************/\n\ntypedef struct {\n    U32 dictIdx;\n    U32 srcIdx;\n    U32 matchLength;\n} ZSTD_eDist_match;\n\ntypedef struct {\n    const BYTE* dict;\n    const BYTE* src;\n    size_t dictSize;\n    size_t srcSize;\n    S32* forwardDiag;            /* Entries of the forward diagonal stored here */\n    S32* backwardDiag;           /* Entries of the backward diagonal stored here.\n                                  *   Note: this buffer and the 'forwardDiag' buffer \n                                  *   are contiguous. See the ZSTD_eDist_genSequences */\n    ZSTD_eDist_match* matches;   /* Accumulate matches of length 1 in this buffer. \n                                  *   In a subsequence post-processing step, we combine \n                                  *   contiguous matches. */\n    U32 nbMatches;\n} ZSTD_eDist_state;\n\ntypedef struct {\n    S32 dictMid;           /* The mid diagonal for the dictionary */\n    S32 srcMid;            /* The mid diagonal for the source */ \n    int lowUseHeuristics;  /* Should we use heuristics for the low part */\n    int highUseHeuristics; /* Should we use heuristics for the high part */ \n} ZSTD_eDist_partition;\n\n/*-*************************************\n*  Internal\n***************************************/\n\nstatic void ZSTD_eDist_diag(ZSTD_eDist_state* state,\n                    ZSTD_eDist_partition* partition,\n                    S32 dictLow, S32 dictHigh, S32 srcLow, \n                    S32 srcHigh, int useHeuristics)\n{\n    S32* const forwardDiag = state->forwardDiag;\n    S32* const backwardDiag = state->backwardDiag;\n    const BYTE* const dict = state->dict;\n    const BYTE* const src = state->src;\n\n    S32 const diagMin = dictLow - srcHigh;\n    S32 const diagMax = dictHigh - srcLow;\n    S32 const forwardMid = dictLow - srcLow;\n    S32 const backwardMid = dictHigh - srcHigh;\n\n    S32 forwardMin = forwardMid;\n    S32 forwardMax = forwardMid;\n    S32 backwardMin = backwardMid;\n    S32 backwardMax = backwardMid;\n    int odd = (forwardMid - backwardMid) & 1;\n    U32 iterations;\n\n    forwardDiag[forwardMid] = dictLow;\n    backwardDiag[backwardMid] = dictHigh;\n\n    /* Main loop for updating diag entries. Unless useHeuristics is \n     * set to false, this loop will run until it finds the minimal \n     * edit script */ \n    for (iterations = 1;;iterations++) {\n        S32 diag;\n        int bigSnake = 0;\n        \n        if (forwardMin > diagMin) {\n            forwardMin--;\n            forwardDiag[forwardMin - 1] = -1;\n        } else {\n            forwardMin++;\n        }\n\n        if (forwardMax < diagMax) {\n            forwardMax++;\n            forwardDiag[forwardMax + 1] = -1;\n        } else {\n            forwardMax--;\n        }\n\n        for (diag = forwardMax; diag >= forwardMin; diag -= 2) {\n            S32 dictIdx;\n            S32 srcIdx;\n            S32 low = forwardDiag[diag - 1];\n            S32 high = forwardDiag[diag + 1];\n            S32 dictIdx0 = low < high ? high : low + 1;\n\n            for (dictIdx = dictIdx0, srcIdx = dictIdx0 - diag;\n                dictIdx < dictHigh && srcIdx < srcHigh && dict[dictIdx] == src[srcIdx];\n                dictIdx++, srcIdx++) continue;\n\n            if (dictIdx - dictIdx0 > ZSTD_EDIST_SNAKE_THRESH)\n                bigSnake = 1;\n\n            forwardDiag[diag] = dictIdx;\n\n            if (odd && backwardMin <= diag && diag <= backwardMax && backwardDiag[diag] <= dictIdx) {\n                partition->dictMid = dictIdx;\n                partition->srcMid = srcIdx;\n                partition->lowUseHeuristics = 0;\n                partition->highUseHeuristics = 0;\n                return;\n            }\n        }\n\n        if (backwardMin > diagMin) {\n            backwardMin--;\n            backwardDiag[backwardMin - 1] = ZSTD_EDIST_DIAG_MAX;\n        } else {\n            backwardMin++;\n        }\n\n        if (backwardMax < diagMax) {\n            backwardMax++;\n            backwardDiag[backwardMax + 1] = ZSTD_EDIST_DIAG_MAX;\n        } else {\n            backwardMax--;\n        }\n\n\n        for (diag = backwardMax; diag >= backwardMin; diag -= 2) {\n            S32 dictIdx;\n            S32 srcIdx;\n            S32 low = backwardDiag[diag - 1];\n            S32 high = backwardDiag[diag + 1];\n            S32 dictIdx0 = low < high ? low : high - 1;\n\n            for (dictIdx = dictIdx0, srcIdx = dictIdx0 - diag;\n                dictLow < dictIdx && srcLow < srcIdx && dict[dictIdx - 1] == src[srcIdx - 1];\n                dictIdx--, srcIdx--) continue;\n\n            if (dictIdx0 - dictIdx > ZSTD_EDIST_SNAKE_THRESH)\n                bigSnake = 1;\n\n            backwardDiag[diag] = dictIdx;\n\n            if (!odd && forwardMin <= diag && diag <= forwardMax && dictIdx <= forwardDiag[diag]) {\n                partition->dictMid = dictIdx;\n                partition->srcMid = srcIdx;\n                partition->lowUseHeuristics = 0;\n                partition->highUseHeuristics = 0;\n                return;\n            }\n        }\n\n        if (!useHeuristics)\n            continue;\n\n        /* Everything under this point is a heuristic. Using these will \n         * substantially speed up the match finding. In some cases, taking \n         * the total match finding time from several minutes to seconds.\n         * Of course, the caveat is that the edit script found may no longer \n         * be optimal */ \n\n        /* Big snake heuristic */ \n        if (iterations > ZSTD_EDIST_SNAKE_ITER_THRESH && bigSnake) {\n            {\n                S32 best = 0;\n                \n                for (diag = forwardMax; diag >= forwardMin; diag -= 2) {\n                    S32 diagDiag = diag - forwardMid;\n                    S32 dictIdx = forwardDiag[diag];\n                    S32 srcIdx = dictIdx - diag;\n                    S32 v = (dictIdx - dictLow) * 2 - diagDiag;\n\n                    if (v > 12 * (iterations + (diagDiag < 0 ? -diagDiag : diagDiag))) {\n                        if (v > best \n                          && dictLow + ZSTD_EDIST_SNAKE_THRESH <= dictIdx && dictIdx <= dictHigh\n                          && srcLow + ZSTD_EDIST_SNAKE_THRESH <= srcIdx && srcIdx <= srcHigh) {\n                            S32 k;\n                            for (k = 1; dict[dictIdx - k] == src[srcIdx - k]; k++) {\n                                if (k == ZSTD_EDIST_SNAKE_THRESH) {\n                                    best = v;\n                                    partition->dictMid = dictIdx;\n                                    partition->srcMid = srcIdx;\n                                    break;\n                                }\n                            }\n                        }\n                    }\n                }\n\n                if (best > 0) {\n                    partition->lowUseHeuristics = 0;\n                    partition->highUseHeuristics = 1;\n                    return;\n                }\n            }\n\n            {\n                S32 best = 0;\n\n                for (diag = backwardMax; diag >= backwardMin; diag -= 2) {\n                    S32 diagDiag = diag - backwardMid;\n                    S32 dictIdx = backwardDiag[diag];\n                    S32 srcIdx = dictIdx - diag;\n                    S32 v = (dictHigh - dictIdx) * 2 + diagDiag;\n\n                    if (v > 12 * (iterations + (diagDiag < 0 ? -diagDiag : diagDiag))) {\n                        if (v > best \n                          && dictLow < dictIdx && dictIdx <= dictHigh - ZSTD_EDIST_SNAKE_THRESH\n                          && srcLow < srcIdx && srcIdx <= srcHigh - ZSTD_EDIST_SNAKE_THRESH) {\n                            int k;\n                            for (k = 0; dict[dictIdx + k] == src[srcIdx + k]; k++) {\n                                if (k == ZSTD_EDIST_SNAKE_THRESH - 1) { \n                                    best = v;\n                                    partition->dictMid = dictIdx;\n                                    partition->srcMid = srcIdx;\n                                    break; \n                                }\n                            }\n                        }\n                    }\n                }\n\n                if (best > 0) {\n                    partition->lowUseHeuristics = 1;\n                    partition->highUseHeuristics = 0;\n                    return;\n                }\n            }\n        }\n\n        /* More general 'too expensive' heuristic */ \n        if (iterations >= ZSTD_EDIST_EXPENSIVE_THRESH) {\n            S32 forwardDictSrcBest;\n            S32 forwardDictBest = 0;\n            S32 backwardDictSrcBest;\n            S32 backwardDictBest = 0;\n\n            forwardDictSrcBest = -1;\n            for (diag = forwardMax; diag >= forwardMin; diag -= 2) {\n                S32 dictIdx = MIN(forwardDiag[diag], dictHigh);\n                S32 srcIdx = dictIdx - diag;\n\n                if (srcHigh < srcIdx) {\n                    dictIdx = srcHigh + diag;\n                    srcIdx = srcHigh;\n                }\n\n                if (forwardDictSrcBest < dictIdx + srcIdx) {\n                    forwardDictSrcBest = dictIdx + srcIdx;\n                    forwardDictBest = dictIdx;\n                }\n            }\n\n            backwardDictSrcBest = ZSTD_EDIST_DIAG_MAX;\n            for (diag = backwardMax; diag >= backwardMin; diag -= 2) {\n                S32 dictIdx = MAX(dictLow, backwardDiag[diag]);\n                S32 srcIdx = dictIdx - diag;\n\n                if (srcIdx < srcLow) {\n                    dictIdx = srcLow + diag;\n                    srcIdx = srcLow;\n                }\n\n                if (dictIdx + srcIdx < backwardDictSrcBest) {\n                    backwardDictSrcBest = dictIdx + srcIdx;\n                    backwardDictBest = dictIdx;\n                }\n            }\n\n            if ((dictHigh + srcHigh) - backwardDictSrcBest < forwardDictSrcBest - (dictLow + srcLow)) {\n                partition->dictMid = forwardDictBest;\n                partition->srcMid = forwardDictSrcBest - forwardDictBest;\n                partition->lowUseHeuristics = 0;\n                partition->highUseHeuristics = 1;\n            } else {\n                partition->dictMid = backwardDictBest;\n                partition->srcMid = backwardDictSrcBest - backwardDictBest;\n                partition->lowUseHeuristics = 1;\n                partition->highUseHeuristics = 0;\n            }\n            return;\n        }\n    }\n}\n\nstatic void ZSTD_eDist_insertMatch(ZSTD_eDist_state* state, \n                    S32 const dictIdx, S32 const srcIdx)\n{\n    state->matches[state->nbMatches].dictIdx = dictIdx;\n    state->matches[state->nbMatches].srcIdx = srcIdx;\n    state->matches[state->nbMatches].matchLength = 1;\n    state->nbMatches++;\n}\n\nstatic int ZSTD_eDist_compare(ZSTD_eDist_state* state,\n                    S32 dictLow, S32 dictHigh, S32 srcLow,\n                    S32 srcHigh, int useHeuristics)\n{\n    const BYTE* const dict = state->dict;\n    const BYTE* const src = state->src;\n\n    /* Found matches while traversing from the low end */ \n    while (dictLow < dictHigh && srcLow < srcHigh && dict[dictLow] == src[srcLow]) {\n        ZSTD_eDist_insertMatch(state, dictLow, srcLow);\n        dictLow++;\n        srcLow++;\n    }\n\n    /* Found matches while traversing from the high end */\n    while (dictLow < dictHigh && srcLow < srcHigh && dict[dictHigh - 1] == src[srcHigh - 1]) {\n        ZSTD_eDist_insertMatch(state, dictHigh - 1, srcHigh - 1);\n        dictHigh--;\n        srcHigh--;\n    }\n    \n    /* If the low and high end end up touching. If we wanted to make \n     * note of the differences like most diffing algorithms do, we would \n     * do so here. In our case, we're only concerned with matches \n     * Note: if you wanted to find the edit distance of the algorithm, \n     *   you could just accumulate the cost for an insertion/deletion \n     *   below. */ \n    if (dictLow == dictHigh) {\n        while (srcLow < srcHigh) {\n            /* Reaching this point means inserting src[srcLow] into \n             * the current position of dict */ \n            srcLow++;\n        }\n    } else if (srcLow == srcHigh) {\n        while (dictLow < dictHigh) {\n            /* Reaching this point means deleting dict[dictLow] from \n             * the current position of dict */ \n            dictLow++;\n        }\n    } else {\n        ZSTD_eDist_partition partition;\n        partition.dictMid = 0;\n        partition.srcMid = 0;\n        ZSTD_eDist_diag(state, &partition, dictLow, dictHigh, \n            srcLow, srcHigh, useHeuristics);\n        if (ZSTD_eDist_compare(state, dictLow, partition.dictMid, \n          srcLow, partition.srcMid, partition.lowUseHeuristics))\n            return 1;\n        if (ZSTD_eDist_compare(state, partition.dictMid, dictHigh,\n          partition.srcMid, srcHigh, partition.highUseHeuristics))\n            return 1;\n    }\n\n    return 0;\n}\n\nstatic int ZSTD_eDist_matchComp(const void* p, const void* q)\n{\n    S32 const l = ((ZSTD_eDist_match*)p)->srcIdx;\n    S32 const r = ((ZSTD_eDist_match*)q)->srcIdx;\n    return (l - r);\n}\n\n/* The matches from the approach above will all be of the form \n * (dictIdx, srcIdx, 1). This method combines contiguous matches \n * of length MINMATCH or greater. Matches less than MINMATCH \n * are discarded */ \nstatic void ZSTD_eDist_combineMatches(ZSTD_eDist_state* state)\n{\n    /* Create a new buffer to put the combined matches into \n     * and memcpy to state->matches after */ \n    ZSTD_eDist_match* combinedMatches = \n        ZSTD_malloc(state->nbMatches * sizeof(ZSTD_eDist_match), \n        ZSTD_defaultCMem);\n\n    U32 nbCombinedMatches = 1;\n    size_t i;\n\n    /* Make sure that the srcIdx and dictIdx are in sorted order.\n     * The combination step won't work otherwise */ \n    qsort(state->matches, state->nbMatches, sizeof(ZSTD_eDist_match), ZSTD_eDist_matchComp);\n\n    memcpy(combinedMatches, state->matches, sizeof(ZSTD_eDist_match));\n    for (i = 1; i < state->nbMatches; i++) {\n        ZSTD_eDist_match const match = state->matches[i];\n        ZSTD_eDist_match const combinedMatch = \n            combinedMatches[nbCombinedMatches - 1];\n        if (combinedMatch.srcIdx + combinedMatch.matchLength == match.srcIdx && \n          combinedMatch.dictIdx + combinedMatch.matchLength == match.dictIdx) {\n            combinedMatches[nbCombinedMatches - 1].matchLength++;\n        } else {\n            /* Discard matches that are less than MINMATCH */\n            if (combinedMatches[nbCombinedMatches - 1].matchLength < MINMATCH) {\n                nbCombinedMatches--;\n            }\n\n            memcpy(combinedMatches + nbCombinedMatches, \n                state->matches + i, sizeof(ZSTD_eDist_match));\n            nbCombinedMatches++;\n        }\n    }\n    memcpy(state->matches, combinedMatches, nbCombinedMatches * sizeof(ZSTD_eDist_match));\n    state->nbMatches = nbCombinedMatches;\n    ZSTD_free(combinedMatches, ZSTD_defaultCMem);\n}\n\nstatic size_t ZSTD_eDist_convertMatchesToSequences(ZSTD_Sequence* sequences, \n    ZSTD_eDist_state* state)\n{\n    const ZSTD_eDist_match* matches = state->matches;\n    size_t const nbMatches = state->nbMatches;\n    size_t const dictSize = state->dictSize;\n    size_t nbSequences = 0;\n    size_t i;\n    for (i = 0; i < nbMatches; i++) {\n        ZSTD_eDist_match const match = matches[i];\n        U32 const litLength = !i ? match.srcIdx : \n            match.srcIdx - (matches[i - 1].srcIdx + matches[i - 1].matchLength);\n        U32 const offset = (match.srcIdx + dictSize) - match.dictIdx;\n        U32 const matchLength = match.matchLength;\n        sequences[nbSequences].offset = offset;\n        sequences[nbSequences].litLength = litLength;\n        sequences[nbSequences].matchLength = matchLength;\n        nbSequences++;\n    }\n    return nbSequences;\n}\n\n/*-*************************************\n*  Internal utils\n***************************************/\n\nstatic size_t ZSTD_eDist_hamingDist(const BYTE* const a,\n                        const BYTE* const b, size_t n)\n{\n    size_t i;\n    size_t dist = 0;\n    for (i = 0; i < n; i++)\n        dist += a[i] != b[i];\n    return dist; \n}\n\n/* This is a pretty naive recursive implementation that should only\n * be used for quick tests obviously. Don't try and run this on a \n * GB file or something. There are faster implementations. Use those\n * if you need to run it for large files. */\nstatic size_t ZSTD_eDist_levenshteinDist(const BYTE* const s,\n                        size_t const sn, const BYTE* const t,\n                        size_t const tn)\n{\n    size_t a, b, c;\n\n    if (!sn)\n        return tn;\n    if (!tn)\n        return sn;\n    \n    if (s[sn - 1] == t[tn - 1])\n        return ZSTD_eDist_levenshteinDist(\n            s, sn - 1, t, tn - 1);\n    \n    a = ZSTD_eDist_levenshteinDist(s, sn - 1, t, tn - 1);\n    b = ZSTD_eDist_levenshteinDist(s, sn, t, tn - 1);\n    c = ZSTD_eDist_levenshteinDist(s, sn - 1, t, tn);\n\n    if (a > b)\n        a = b;\n    if (a > c)\n        a = c;\n    \n    return a + 1;\n}\n\nstatic void ZSTD_eDist_validateMatches(ZSTD_eDist_match* matches,\n                        size_t const nbMatches, const BYTE* const dict,\n                        size_t const dictSize, const BYTE* const src,\n                        size_t const srcSize)\n{\n    size_t i;\n    for (i = 0; i < nbMatches; i++) {\n        ZSTD_eDist_match match = matches[i];\n        U32 const dictIdx = match.dictIdx;\n        U32 const srcIdx = match.srcIdx;\n        U32 const matchLength = match.matchLength;\n        \n        assert(dictIdx + matchLength < dictSize);\n        assert(srcIdx + matchLength < srcSize);\n        assert(!memcmp(dict + dictIdx, src + srcIdx, matchLength));\n    }\n}\n\n/*-*************************************\n*  API\n***************************************/\n\nsize_t ZSTD_eDist_genSequences(ZSTD_Sequence* sequences, \n                        const void* dict, size_t dictSize,\n                        const void* src, size_t srcSize,\n                        int useHeuristics)\n{\n    size_t const nbDiags = dictSize + srcSize + 3;\n    S32* buffer = ZSTD_malloc(nbDiags * 2 * sizeof(S32), ZSTD_defaultCMem);\n    ZSTD_eDist_state state;\n    size_t nbSequences = 0;\n\n    state.dict = (const BYTE*)dict;\n    state.src = (const BYTE*)src;\n    state.dictSize = dictSize;\n    state.srcSize = srcSize;\n    state.forwardDiag = buffer;\n    state.backwardDiag = buffer + nbDiags;\n    state.forwardDiag += srcSize + 1;\n    state.backwardDiag += srcSize + 1;\n    state.matches = ZSTD_malloc(srcSize * sizeof(ZSTD_eDist_match), ZSTD_defaultCMem);\n    state.nbMatches = 0;\n\n    ZSTD_eDist_compare(&state, 0, dictSize, 0, srcSize, 1);\n    ZSTD_eDist_combineMatches(&state);\n    nbSequences = ZSTD_eDist_convertMatchesToSequences(sequences, &state);\n\n    ZSTD_free(buffer, ZSTD_defaultCMem);\n    ZSTD_free(state.matches, ZSTD_defaultCMem);\n\n    return nbSequences;\n}\n"
  },
  {
    "path": "contrib/match_finders/zstd_edist.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* This match finder leverages techniques used in file comparison algorithms\n * to find matches between a dictionary and a source file.\n * \n * The original motivation for studying this approach was to try and optimize \n * Zstandard for the use case of patching: the most common scenario being \n * updating an existing software package with the next version. When patching,\n * the difference between the old version of the package and the new version \n * is generally tiny (most of the new file will be identical to \n * the old one). In more technical terms, the edit distance (the minimal number \n * of changes required to take one sequence of bytes to another) between the \n * files would be small relative to the size of the file. \n * \n * Various 'diffing' algorithms utilize this notion of edit distance and \n * the corresponding concept of a minimal edit script between two \n * sequences to identify the regions within two files where they differ. \n * The core algorithm used in this match finder is described in: \n * \n * \"An O(ND) Difference Algorithm and its Variations\", Eugene W. Myers,\n *    Algorithmica Vol. 1, 1986, pp. 251-266,\n *    <https://doi.org/10.1007/BF01840446>.\n * \n * Additional algorithmic heuristics for speed improvement have also been included.\n * These we inspired from implementations of various regular and binary diffing \n * algorithms such as GNU diff, bsdiff, and Xdelta. \n * \n * Note: after some experimentation, this approach proved to not provide enough \n * utility to justify the additional CPU used in finding matches. The one area\n * where this approach consistently outperforms Zstandard even on level 19 is \n * when compressing small files (<10 KB) using an equally small dictionary that \n * is very similar to the source file. For the use case that this was intended,\n * (large similar files) this approach by itself took 5-10X longer than zstd-19 and \n * generally resulted in 2-3X larger files. The core advantage that zstd-19 has \n * over this approach for match finding is the overlapping matches. This approach \n * cannot find any. \n * \n * I'm leaving this in the contrib section in case this ever becomes interesting \n * to explore again.\n * */\n\n#ifndef ZSTD_EDIST_H\n#define ZSTD_EDIST_H\n\n/*-*************************************\n*  Dependencies\n***************************************/\n\n#include <stddef.h>\n#include \"zstd_internal.h\" /* ZSTD_Sequence */\n\n/*! ZSTD_eDist_genSequences() : \n * Will populate the provided ZSTD_Sequence buffer with sequences \n * based on the optimal or near-optimal (depending on 'useHeuristics')\n * edit script between 'dict' and 'src.' \n * @return : the number of sequences found */ \nsize_t ZSTD_eDist_genSequences(ZSTD_Sequence* sequences, \n                        const void* dict, size_t dictSize,\n                        const void* src, size_t srcSize,\n                        int useHeuristics);\n\n#endif\n"
  },
  {
    "path": "contrib/premake/premake4.lua",
    "content": "-- Include zstd.lua in your GENie or premake4 file, which exposes a project_zstd function\ndofile('zstd.lua')\n\nsolution 'example'\n\tconfigurations { 'Debug', 'Release' }\n\tproject_zstd('../../lib/')\n"
  },
  {
    "path": "contrib/premake/zstd.lua",
    "content": "-- This GENie/premake file copies the behavior of the Makefile in the lib folder.\n-- Basic usage: project_zstd(ZSTD_DIR)\n\nfunction project_zstd(dir, compression, decompression, deprecated, dictbuilder, legacy)\n\tif string.sub(dir, -1, 1) ~= '/' then dir = dir .. '/' end\n\tif compression == nil then compression = true end\n\tif decompression == nil then decompression = true end\n\tif deprecated == nil then deprecated = false end\n\tif dictbuilder == nil then dictbuilder = false end\n\n\tif legacy == nil then legacy = 0 end\n\n\tif not compression then\n\t\tdictbuilder = false\n\t\tdeprecated = false\n\tend\n\n\tif not decompression then\n\t\tlegacy = 0\n\t\tdeprecated = false\n\tend\n\n\tproject 'zstd'\n\t\tkind 'StaticLib'\n\t\tlanguage 'C'\n\n\t\tfiles {\n\t\t\tdir .. 'zstd.h',\n\t\t\tdir .. 'common/**.c',\n\t\t\tdir .. 'common/**.h'\n\t\t}\n\n\t\tif compression then\n\t\t\tfiles {\n\t\t\t\tdir .. 'compress/**.c',\n\t\t\t\tdir .. 'compress/**.h'\n\t\t\t}\n\t\tend\n\n\t\tif decompression then\n\t\t\tfiles {\n\t\t\t\tdir .. 'decompress/**.c',\n\t\t\t\tdir .. 'decompress/**.h'\n\t\t\t}\n\t\tend\n\n\t\tif dictbuilder then\n\t\t\tfiles {\n\t\t\t\tdir .. 'dictBuilder/**.c',\n\t\t\t\tdir .. 'dictBuilder/**.h'\n\t\t\t}\n\t\tend\n\n\t\tif deprecated then\n\t\t\tfiles {\n\t\t\t\tdir .. 'deprecated/**.c',\n\t\t\t\tdir .. 'deprecated/**.h'\n\t\t\t}\n\t\tend\n\n\t\tif legacy ~= 0 then\n\t\t\tif legacy >= 8 then\n\t\t\t\tfiles {\n\t\t\t\t\tdir .. 'legacy/zstd_v0' .. (legacy - 7) .. '.*'\n\t\t\t\t}\n\t\t\tend\n\t\t\tincludedirs {\n\t\t\t\tdir .. 'legacy'\n\t\t\t}\n\t\tend\n\n\t\tincludedirs {\n\t\t\tdir,\n\t\t\tdir .. 'common'\n\t\t}\n\n\t\tdefines {\n\t\t\t'XXH_NAMESPACE=ZSTD_',\n\t\t\t'ZSTD_LEGACY_SUPPORT=' .. legacy\n\t\t}\nend\n"
  },
  {
    "path": "contrib/recovery/Makefile",
    "content": "# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# ################################################################\n\n.PHONY: all\nall: recover_directory\n\nZSTDLIBDIR ?= ../../lib\nPROGRAMDIR ?= ../../programs\n\nCFLAGS     ?= -O3\nCFLAGS     += -I$(ZSTDLIBDIR) -I$(PROGRAMDIR)\nCFLAGS     += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow                 \\\n              -Wstrict-aliasing=1 -Wswitch-enum                               \\\n              -Wstrict-prototypes -Wundef                                     \\\n              -Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings      \\\n              -Wredundant-decls -Wmissing-prototypes\nCFLAGS     += $(DEBUGFLAGS) $(MOREFLAGS)\nFLAGS       = $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)\n\n.PHONY: $(ZSTDLIBDIR)/libzstd.a\n$(ZSTDLIBDIR)/libzstd.a:\n\t$(MAKE) -C $(ZSTDLIBDIR) libzstd.a\n\nrecover_directory: recover_directory.c $(ZSTDLIBDIR)/libzstd.a $(PROGRAMDIR)/util.c\n\t$(CC) $(FLAGS) $^ -o $@$(EXT)\n\n.PHONY: clean\nclean:\n\trm -f recover_directory\n"
  },
  {
    "path": "contrib/recovery/recover_directory.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include <string.h>\n#include <stdio.h>\n#include <stdlib.h>\n\n#define ZSTD_STATIC_LINKING_ONLY\n#include \"util.h\"\n#include \"zstd.h\"\n\n#define CHECK(cond, ...)                                                       \\\n  do {                                                                         \\\n    if (!(cond)) {                                                             \\\n      fprintf(stderr, \"%s:%d CHECK(%s) failed: \", __FILE__, __LINE__, #cond);  \\\n      fprintf(stderr, \"\" __VA_ARGS__);                                         \\\n      fprintf(stderr, \"\\n\");                                                   \\\n      exit(1);                                                                 \\\n    }                                                                          \\\n  } while (0)\n\nstatic void usage(char const *program) {\n  fprintf(stderr, \"USAGE: %s FILE.zst PREFIX\\n\", program);\n  fprintf(stderr, \"FILE.zst: A zstd compressed file with multiple frames\\n\");\n  fprintf(stderr, \"PREFIX:   The output prefix. Uncompressed files will be \"\n                  \"created named ${PREFIX}0 ${PREFIX}1...\\n\\n\");\n  fprintf(stderr, \"This program takes concatenated zstd frames and \"\n                  \"decompresses them into individual files.\\n\");\n  fprintf(stderr, \"E.g. files created with a command like: zstd -r directory \"\n                  \"-o file.zst\\n\");\n}\n\ntypedef struct {\n  char *data;\n  size_t size;\n  size_t frames;\n  size_t maxFrameSize;\n} ZstdFrames;\n\nstatic ZstdFrames readFile(char const *fileName) {\n  U64 const fileSize = UTIL_getFileSize(fileName);\n  CHECK(fileSize != UTIL_FILESIZE_UNKNOWN, \"Unknown file size!\");\n\n  char *const data = (char *)malloc(fileSize);\n  CHECK(data != NULL, \"Allocation failed\");\n\n  FILE *file = fopen(fileName, \"rb\");\n  CHECK(file != NULL, \"fopen failed\");\n\n  size_t const readSize = fread(data, 1, fileSize, file);\n  CHECK(readSize == fileSize, \"fread failed\");\n\n  fclose(file);\n  ZstdFrames frames;\n  frames.data = (char *)data;\n  frames.size = fileSize;\n  frames.frames = 0;\n\n  size_t index;\n  size_t maxFrameSize = 0;\n  for (index = 0; index < fileSize;) {\n    size_t const frameSize =\n        ZSTD_findFrameCompressedSize(data + index, fileSize - index);\n    CHECK(!ZSTD_isError(frameSize), \"Bad zstd frame: %s\",\n          ZSTD_getErrorName(frameSize));\n    if (frameSize > maxFrameSize)\n      maxFrameSize = frameSize;\n    frames.frames += 1;\n    index += frameSize;\n  }\n  CHECK(index == fileSize, \"Zstd file corrupt!\");\n  frames.maxFrameSize = maxFrameSize;\n\n  return frames;\n}\n\nstatic int computePadding(size_t numFrames) {\n  return snprintf(NULL, 0, \"%u\", (unsigned)numFrames);\n}\n\nint main(int argc, char **argv) {\n  if (argc != 3) {\n    usage(argv[0]);\n    exit(1);\n  }\n  char const *const zstdFile = argv[1];\n  char const *const prefix = argv[2];\n\n  ZstdFrames frames = readFile(zstdFile);\n\n  if (frames.frames <= 1) {\n    fprintf(\n        stderr,\n        \"%s only has %u zstd frame. Simply use `zstd -d` to decompress it.\\n\",\n        zstdFile, (unsigned)frames.frames);\n    exit(1);\n  }\n\n  int const padding = computePadding(frames.frames - 1);\n\n  size_t const outFileNameSize = strlen(prefix) + padding + 1;\n  char* outFileName = malloc(outFileNameSize);\n  CHECK(outFileName != NULL, \"Allocation failure\");\n\n  size_t const bufferSize = 128 * 1024;\n  void *buffer = malloc(bufferSize);\n  CHECK(buffer != NULL, \"Allocation failure\");\n\n  ZSTD_DCtx* dctx = ZSTD_createDCtx();\n  CHECK(dctx != NULL, \"Allocation failure\");\n\n  fprintf(stderr, \"Recovering %u files...\\n\", (unsigned)frames.frames);\n\n  size_t index;\n  size_t frame = 0;\n  for (index = 0; index < frames.size; ++frame) {\n    size_t const frameSize =\n        ZSTD_findFrameCompressedSize(frames.data + index, frames.size - index);\n\n    int const ret = snprintf(outFileName, outFileNameSize, \"%s%0*u\", prefix, padding, (unsigned)frame);\n    CHECK(ret >= 0 && (size_t)ret <= outFileNameSize, \"snprintf failed!\");\n\n    FILE* outFile = fopen(outFileName, \"wb\");\n    CHECK(outFile != NULL, \"fopen failed\");\n\n    ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only);\n    ZSTD_inBuffer in = {frames.data + index, frameSize, 0};\n    while (in.pos < in.size) {\n        ZSTD_outBuffer out = {buffer, bufferSize, 0};\n        CHECK(!ZSTD_isError(ZSTD_decompressStream(dctx, &out, &in)), \"decompression failed\");\n        size_t const writeSize = fwrite(out.dst, 1, out.pos, outFile);\n        CHECK(writeSize == out.pos, \"fwrite failed\");\n    }\n    fclose(outFile);\n    fprintf(stderr, \"Recovered %s\\n\", outFileName);\n    index += frameSize;\n  }\n  fprintf(stderr, \"Complete\\n\");\n\n  free(outFileName);\n  ZSTD_freeDCtx(dctx);\n  free(buffer);\n  free(frames.data);\n  return 0;\n}\n"
  },
  {
    "path": "contrib/seekable_format/README.md",
    "content": "# Zstandard Seekable Format\n\nThe seekable format splits compressed data into a series of independent \"frames\",\neach compressed individually,\nso that decompression of a section in the middle of an archive\nonly requires zstd to decompress at most a frame's worth of extra data,\ninstead of the entire archive.\n\nThe frames are appended, so that the decompression of the entire payload\nstill regenerates the original content, using any compliant zstd decoder.\n\nOn top of that, the seekable format generates a jump table,\nwhich makes it possible to jump directly to the position of the relevant frame\nwhen requesting only a segment of the data.\nThe jump table is simply ignored by zstd decoders unaware of the seekable format.\n\nThe format is delivered with an API to create seekable archives\nand to retrieve arbitrary segments inside the archive.\n\n### Maximum Frame Size parameter\n\nWhen creating a seekable archive, the main parameter is the maximum frame size.\n\nAt compression time, user can manually select the boundaries between segments,\nbut they don't have to: long segments will be automatically split\nwhen larger than selected maximum frame size.\n\nSmall frame sizes reduce decompression cost when requesting small segments,\nbecause the decoder will nonetheless have to decompress an entire frame\nto recover just a single byte from it.\n\nA good rule of thumb is to select a maximum frame size roughly equivalent\nto the access pattern when it's known.\nFor example, if the application tends to request 4KB blocks,\nthen it's a good idea to set a maximum frame size in the vicinity of 4 KB.\n\nBut small frame sizes also reduce compression ratio,\nand increase the cost for the jump table,\nso there is a balance to find.\n\nIn general, try to avoid really tiny frame sizes (<1 KB),\nwhich would have a large negative impact on compression ratio.\n"
  },
  {
    "path": "contrib/seekable_format/examples/.gitignore",
    "content": "seekable_compression\nseekable_decompression\nseekable_decompression_mem\nparallel_processing\nparallel_compression\n"
  },
  {
    "path": "contrib/seekable_format/examples/Makefile",
    "content": "# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# ################################################################\n\n# This Makefile presumes libzstd is built, using `make` in / or /lib/\n\nZSTDLIB_PATH = ../../../lib\nZSTDLIB_NAME = libzstd.a\n# Parallel tools only make sense against multi-threaded libzstd\nZSTDLIB_TARGET = $(ZSTDLIB_NAME)-mt\nZSTDLIB = $(ZSTDLIB_PATH)/$(ZSTDLIB_NAME)\n\nCPPFLAGS += -DXXH_NAMESPACE=ZSTD_ -I../ -I../../../lib -I../../../lib/common\n\nCFLAGS ?= -O3\nCFLAGS += -g\n\nSEEKABLE_OBJS = ../zstdseek_compress.c ../zstdseek_decompress.c $(ZSTDLIB)\n\n.PHONY: default all clean test\n\ndefault: all\n\nall: seekable_compression seekable_decompression seekable_decompression_mem \\\n\tparallel_processing\n\n$(ZSTDLIB):\n\t$(MAKE) -C $(ZSTDLIB_PATH) $(ZSTDLIB_TARGET)\n\nseekable_compression : seekable_compression.c $(SEEKABLE_OBJS)\n\t$(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@\n\nseekable_decompression : seekable_decompression.c $(SEEKABLE_OBJS)\n\t$(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@\n\nseekable_decompression_mem : seekable_decompression_mem.c $(SEEKABLE_OBJS)\n\t$(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@\n\nparallel_processing : parallel_processing.c $(SEEKABLE_OBJS)\n\t$(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@ -pthread\n\nparallel_compression : parallel_compression.c $(SEEKABLE_OBJS)\n\t$(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@ -pthread\n\nclean:\n\t@rm -f core *.o tmp* result* *.zst \\\n\t\tseekable_compression seekable_decompression \\\n\t\tseekable_decompression_mem \\\n\t\tparallel_processing parallel_compression\n\t@echo Cleaning completed\n"
  },
  {
    "path": "contrib/seekable_format/examples/parallel_compression.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n */\n\n#include <stdlib.h>    // malloc, free, exit, atoi\n#include <stdio.h>     // fprintf, perror, feof, fopen, etc.\n#include <string.h>    // strlen, memset, strcat\n#define ZSTD_STATIC_LINKING_ONLY\n#include <zstd.h>      // presumes zstd library is installed\n#include <zstd_errors.h>\n#if defined(WIN32) || defined(_WIN32)\n#  include <windows.h>\n#  define SLEEP(x) Sleep(x)\n#else\n#  include <unistd.h>\n#  define SLEEP(x) usleep(x * 1000)\n#endif\n\n#include \"xxhash.h\"\n\n#define ZSTD_MULTITHREAD 1\n#include \"threading.h\"\n#include \"pool.h\"      // use zstd thread pool for demo\n\n#include \"../zstd_seekable.h\"\n\nstatic void* malloc_orDie(size_t size)\n{\n    void* const buff = malloc(size);\n    if (buff) return buff;\n    /* error */\n    perror(\"malloc:\");\n    exit(1);\n}\n\nstatic FILE* fopen_orDie(const char *filename, const char *instruction)\n{\n    FILE* const inFile = fopen(filename, instruction);\n    if (inFile) return inFile;\n    /* error */\n    perror(filename);\n    exit(3);\n}\n\nstatic size_t fread_orDie(void* buffer, size_t sizeToRead, FILE* file)\n{\n    size_t const readSize = fread(buffer, 1, sizeToRead, file);\n    if (readSize == sizeToRead) return readSize;   /* good */\n    if (feof(file)) return readSize;   /* good, reached end of file */\n    /* error */\n    perror(\"fread\");\n    exit(4);\n}\n\nstatic size_t fwrite_orDie(const void* buffer, size_t sizeToWrite, FILE* file)\n{\n    size_t const writtenSize = fwrite(buffer, 1, sizeToWrite, file);\n    if (writtenSize == sizeToWrite) return sizeToWrite;   /* good */\n    /* error */\n    perror(\"fwrite\");\n    exit(5);\n}\n\nstatic size_t fclose_orDie(FILE* file)\n{\n    if (!fclose(file)) return 0;\n    /* error */\n    perror(\"fclose\");\n    exit(6);\n}\n\nstruct state {\n    FILE* fout;\n    ZSTD_pthread_mutex_t mutex;\n    size_t nextID;\n    struct job* pending;\n    ZSTD_frameLog* frameLog;\n    const int compressionLevel;\n};\n\nstruct job {\n    size_t id;\n    struct job* next;\n    struct state* state;\n\n    void* src;\n    size_t srcSize;\n    void* dst;\n    size_t dstSize;\n\n    unsigned checksum;\n};\n\nstatic void addPending_inmutex(struct state* state, struct job* job)\n{\n    struct job** p = &state->pending;\n    while (*p && (*p)->id < job->id)\n        p = &(*p)->next;\n    job->next = *p;\n    *p = job;\n}\n\nstatic void flushFrame(struct state* state, struct job* job)\n{\n    fwrite_orDie(job->dst, job->dstSize, state->fout);\n    free(job->dst);\n\n    size_t ret = ZSTD_seekable_logFrame(state->frameLog, (unsigned)job->dstSize, (unsigned)job->srcSize, job->checksum);\n    if (ZSTD_isError(ret)) {\n        fprintf(stderr, \"ZSTD_seekable_logFrame() error : %s \\n\", ZSTD_getErrorName(ret));\n        exit(12);\n    }\n}\n\nstatic void flushPending_inmutex(struct state* state)\n{\n    while (state->pending && state->pending->id == state->nextID) {\n        struct job* p = state->pending;\n        state->pending = p->next;\n        flushFrame(state, p);\n        free(p);\n        state->nextID++;\n    }\n}\n\nstatic void finishFrame(struct job* job)\n{\n    struct state *state = job->state;\n    ZSTD_pthread_mutex_lock(&state->mutex);\n    addPending_inmutex(state, job);\n    flushPending_inmutex(state);\n    ZSTD_pthread_mutex_unlock(&state->mutex);\n}\n\nstatic void compressFrame(void* opaque)\n{\n    struct job* job = opaque;\n\n    job->checksum = (unsigned)XXH64(job->src, job->srcSize, 0);\n\n    size_t ret = ZSTD_compress(job->dst, job->dstSize, job->src, job->srcSize, job->state->compressionLevel);\n    if (ZSTD_isError(ret)) {\n        fprintf(stderr, \"ZSTD_compress() error : %s \\n\", ZSTD_getErrorName(ret));\n        exit(20);\n    }\n    job->dstSize = ret;\n\n    // No longer need\n    free(job->src);\n    job->src = NULL;\n\n    finishFrame(job);\n}\n\nstatic const char* createOutFilename_orDie(const char* filename)\n{\n    size_t const inL = strlen(filename);\n    size_t const outL = inL + 5;\n    void* outSpace = malloc_orDie(outL);\n    memset(outSpace, 0, outL);\n    strcat(outSpace, filename);\n    strcat(outSpace, \".zst\");\n    return (const char*)outSpace;\n}\n\nstatic void openInOut_orDie(const char* fname, FILE** fin, FILE** fout) {\n    if (strcmp(fname, \"-\") == 0) {\n        *fin = stdin;\n        *fout = stdout;\n    } else {\n        *fin = fopen_orDie(fname, \"rb\");\n        const char* outName = createOutFilename_orDie(fname);\n        *fout = fopen_orDie(outName, \"wb\");\n    }\n}\n\nstatic void compressFile_orDie(const char* fname, int cLevel, unsigned frameSize, size_t nbThreads)\n{\n    struct state state = {\n        .nextID = 0,\n        .pending = NULL,\n        .compressionLevel = cLevel,\n    };\n    ZSTD_pthread_mutex_init(&state.mutex, NULL);\n    state.frameLog = ZSTD_seekable_createFrameLog(1);\n    if (state.frameLog == NULL) { fprintf(stderr, \"ZSTD_seekable_createFrameLog() failed \\n\"); exit(11); }\n\n    POOL_ctx* pool = POOL_create(nbThreads, nbThreads);\n    if (pool == NULL) { fprintf(stderr, \"POOL_create() error \\n\"); exit(9); }\n\n    FILE* fin;\n    openInOut_orDie(fname, &fin, &state.fout);\n\n    if (ZSTD_compressBound(frameSize) > 0xFFFFFFFFU) { fprintf(stderr, \"Frame size too large \\n\"); exit(10); }\n    size_t dstSize = ZSTD_compressBound(frameSize);\n\n    for (size_t id = 0; 1; id++) {\n        struct job* job = malloc_orDie(sizeof(struct job));\n        job->id = id;\n        job->next = NULL;\n        job->state = &state;\n        job->src = malloc_orDie(frameSize);\n        job->dst = malloc_orDie(dstSize);\n        job->srcSize = fread_orDie(job->src, frameSize, fin);\n        job->dstSize = dstSize; \n        POOL_add(pool, compressFrame, job);\n        if (feof(fin))\n            break;\n    }\n\n    POOL_joinJobs(pool);\n    POOL_free(pool);\n    if (state.pending) {\n        fprintf(stderr, \"Unexpected leftover output blocks!\\n\");\n        exit(13);\n    }\n\n    {   unsigned char seekTableBuff[1024];\n        ZSTD_outBuffer out = {seekTableBuff, 1024, 0};\n        while (ZSTD_seekable_writeSeekTable(state.frameLog, &out) != 0) {\n            fwrite_orDie(seekTableBuff, out.pos, state.fout);\n            out.pos = 0;\n        }\n        fwrite_orDie(seekTableBuff, out.pos, state.fout);\n    }\n\n    ZSTD_seekable_freeFrameLog(state.frameLog);\n    fclose_orDie(state.fout);\n    fclose_orDie(fin);\n}\n\nint main(int argc, const char** argv) {\n    const char* const exeName = argv[0];\n    if (argc!=4) {\n        printf(\"wrong arguments\\n\");\n        printf(\"usage:\\n\");\n        printf(\"%s FILE FRAME_SIZE NB_THREADS\\n\", exeName);\n        return 1;\n    }\n\n    {   const char* const inFileName = argv[1];\n        unsigned const frameSize = (unsigned)atoi(argv[2]);\n        size_t const nbThreads = (size_t)atoi(argv[3]);\n\n        compressFile_orDie(inFileName, 5, frameSize, nbThreads);\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "contrib/seekable_format/examples/parallel_processing.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n */\n\n/*\n * A simple demo that sums up all the bytes in the file in parallel using\n * seekable decompression and the zstd thread pool\n */\n\n#include <stdlib.h>    // malloc, exit\n#include <stdio.h>     // fprintf, perror, feof\n#include <string.h>    // strerror\n#include <errno.h>     // errno\n#define ZSTD_STATIC_LINKING_ONLY\n#include <zstd.h>      // presumes zstd library is installed\n#include <zstd_errors.h>\n#if defined(_WIN32)\n#  include <windows.h>\n#  define SLEEP(x) Sleep(x)\n#else\n#  include <unistd.h>\n#  define SLEEP(x) usleep(x * 1000)\n#endif\n\n#include \"pool.h\"      // use zstd thread pool for demo\n\n#include \"../zstd_seekable.h\"\n\n#define MIN(a, b) ((a) < (b) ? (a) : (b))\n\nstatic void* malloc_orDie(size_t size)\n{\n    void* const buff = malloc(size);\n    if (buff) return buff;\n    /* error */\n    perror(\"malloc\");\n    exit(1);\n}\n\nstatic void* realloc_orDie(void* ptr, size_t size)\n{\n    ptr = realloc(ptr, size);\n    if (ptr) return ptr;\n    /* error */\n    perror(\"realloc\");\n    exit(1);\n}\n\nstatic FILE* fopen_orDie(const char *filename, const char *instruction)\n{\n    FILE* const inFile = fopen(filename, instruction);\n    if (inFile) return inFile;\n    /* error */\n    perror(filename);\n    exit(3);\n}\n\nstatic size_t fread_orDie(void* buffer, size_t sizeToRead, FILE* file)\n{\n    size_t const readSize = fread(buffer, 1, sizeToRead, file);\n    if (readSize == sizeToRead) return readSize;   /* good */\n    if (feof(file)) return readSize;   /* good, reached end of file */\n    /* error */\n    perror(\"fread\");\n    exit(4);\n}\n\nstatic size_t fwrite_orDie(const void* buffer, size_t sizeToWrite, FILE* file)\n{\n    size_t const writtenSize = fwrite(buffer, 1, sizeToWrite, file);\n    if (writtenSize == sizeToWrite) return sizeToWrite;   /* good */\n    /* error */\n    perror(\"fwrite\");\n    exit(5);\n}\n\nstatic size_t fclose_orDie(FILE* file)\n{\n    if (!fclose(file)) return 0;\n    /* error */\n    perror(\"fclose\");\n    exit(6);\n}\n\nstatic void fseek_orDie(FILE* file, long int offset, int origin) {\n    if (!fseek(file, offset, origin)) {\n        if (!fflush(file)) return;\n    }\n    /* error */\n    perror(\"fseek\");\n    exit(7);\n}\n\nstruct sum_job {\n    const char* fname;\n    unsigned long long sum;\n    unsigned frameNb;\n};\n\nstatic void sumFrame(void* opaque)\n{\n    struct sum_job* job = (struct sum_job*)opaque;\n\n    FILE* const fin = fopen_orDie(job->fname, \"rb\");\n\n    ZSTD_seekable* const seekable = ZSTD_seekable_create();\n    if (seekable==NULL) { fprintf(stderr, \"ZSTD_seekable_create() error \\n\"); exit(10); }\n\n    size_t const initResult = ZSTD_seekable_initFile(seekable, fin);\n    if (ZSTD_isError(initResult)) { fprintf(stderr, \"ZSTD_seekable_init() error : %s \\n\", ZSTD_getErrorName(initResult)); exit(11); }\n\n    size_t const frameSize = ZSTD_seekable_getFrameDecompressedSize(seekable, job->frameNb);\n    unsigned char* data = malloc_orDie(frameSize);\n\n    size_t result = ZSTD_seekable_decompressFrame(seekable, data, frameSize, job->frameNb);\n    if (ZSTD_isError(result)) { fprintf(stderr, \"ZSTD_seekable_decompressFrame() error : %s \\n\", ZSTD_getErrorName(result)); exit(12); }\n\n    unsigned long long sum = 0;\n    size_t i;\n    for (i = 0; i < frameSize; i++) {\n        sum += data[i];\n    }\n    job->sum = sum;\n\n    fclose(fin);\n    ZSTD_seekable_free(seekable);\n    free(data);\n}\n\nstatic void sumFile_orDie(const char* fname, int nbThreads)\n{\n    POOL_ctx* pool = POOL_create(nbThreads, nbThreads);\n    if (pool == NULL) { fprintf(stderr, \"POOL_create() error \\n\"); exit(9); }\n\n    FILE* const fin = fopen_orDie(fname, \"rb\");\n\n    ZSTD_seekable* const seekable = ZSTD_seekable_create();\n    if (seekable==NULL) { fprintf(stderr, \"ZSTD_seekable_create() error \\n\"); exit(10); }\n\n    size_t const initResult = ZSTD_seekable_initFile(seekable, fin);\n    if (ZSTD_isError(initResult)) { fprintf(stderr, \"ZSTD_seekable_init() error : %s \\n\", ZSTD_getErrorName(initResult)); exit(11); }\n\n    unsigned const numFrames = ZSTD_seekable_getNumFrames(seekable);\n    struct sum_job* jobs = (struct sum_job*)malloc(numFrames * sizeof(struct sum_job));\n\n    unsigned fnb;\n    for (fnb = 0; fnb < numFrames; fnb++) {\n        jobs[fnb] = (struct sum_job){ fname, 0, fnb };\n        POOL_add(pool, sumFrame, &jobs[fnb]);\n    }\n    POOL_joinJobs(pool);\n\n    unsigned long long total = 0;\n\n    for (fnb = 0; fnb < numFrames; fnb++) {\n        total += jobs[fnb].sum;\n    }\n\n    printf(\"Sum: %llu\\n\", total);\n\n    POOL_free(pool);\n    ZSTD_seekable_free(seekable);\n    fclose(fin);\n    free(jobs);\n}\n\n\nint main(int argc, const char** argv)\n{\n    const char* const exeName = argv[0];\n\n    if (argc!=3) {\n        fprintf(stderr, \"wrong arguments\\n\");\n        fprintf(stderr, \"usage:\\n\");\n        fprintf(stderr, \"%s FILE NB_THREADS\\n\", exeName);\n        return 1;\n    }\n\n    {\n        const char* const inFilename = argv[1];\n        int const nbThreads = atoi(argv[2]);\n        sumFile_orDie(inFilename, nbThreads);\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "contrib/seekable_format/examples/seekable_compression.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n */\n\n#include <stdlib.h>    // malloc, free, exit, atoi\n#include <stdio.h>     // fprintf, perror, feof, fopen, etc.\n#include <string.h>    // strlen, memset, strcat\n#define ZSTD_STATIC_LINKING_ONLY\n#include <zstd.h>      // presumes zstd library is installed\n\n#include \"../zstd_seekable.h\"\n\nstatic void* malloc_orDie(size_t size)\n{\n    void* const buff = malloc(size);\n    if (buff) return buff;\n    /* error */\n    perror(\"malloc:\");\n    exit(1);\n}\n\nstatic FILE* fopen_orDie(const char *filename, const char *instruction)\n{\n    FILE* const inFile = fopen(filename, instruction);\n    if (inFile) return inFile;\n    /* error */\n    perror(filename);\n    exit(3);\n}\n\nstatic size_t fread_orDie(void* buffer, size_t sizeToRead, FILE* file)\n{\n    size_t const readSize = fread(buffer, 1, sizeToRead, file);\n    if (readSize == sizeToRead) return readSize;   /* good */\n    if (feof(file)) return readSize;   /* good, reached end of file */\n    /* error */\n    perror(\"fread\");\n    exit(4);\n}\n\nstatic size_t fwrite_orDie(const void* buffer, size_t sizeToWrite, FILE* file)\n{\n    size_t const writtenSize = fwrite(buffer, 1, sizeToWrite, file);\n    if (writtenSize == sizeToWrite) return sizeToWrite;   /* good */\n    /* error */\n    perror(\"fwrite\");\n    exit(5);\n}\n\nstatic size_t fclose_orDie(FILE* file)\n{\n    if (!fclose(file)) return 0;\n    /* error */\n    perror(\"fclose\");\n    exit(6);\n}\n\nstatic void compressFile_orDie(const char* fname, const char* outName, int cLevel, unsigned frameSize)\n{\n    FILE* const fin  = fopen_orDie(fname, \"rb\");\n    FILE* const fout = fopen_orDie(outName, \"wb\");\n    size_t const buffInSize = ZSTD_CStreamInSize();    /* can always read one full block */\n    void*  const buffIn  = malloc_orDie(buffInSize);\n    size_t const buffOutSize = ZSTD_CStreamOutSize();  /* can always flush a full block */\n    void*  const buffOut = malloc_orDie(buffOutSize);\n\n    ZSTD_seekable_CStream* const cstream = ZSTD_seekable_createCStream();\n    if (cstream==NULL) { fprintf(stderr, \"ZSTD_seekable_createCStream() error \\n\"); exit(10); }\n    size_t const initResult = ZSTD_seekable_initCStream(cstream, cLevel, 1, frameSize);\n    if (ZSTD_isError(initResult)) { fprintf(stderr, \"ZSTD_seekable_initCStream() error : %s \\n\", ZSTD_getErrorName(initResult)); exit(11); }\n\n    size_t read, toRead = buffInSize;\n    while( (read = fread_orDie(buffIn, toRead, fin)) ) {\n        ZSTD_inBuffer input = { buffIn, read, 0 };\n        while (input.pos < input.size) {\n            ZSTD_outBuffer output = { buffOut, buffOutSize, 0 };\n            toRead = ZSTD_seekable_compressStream(cstream, &output , &input);   /* toRead is guaranteed to be <= ZSTD_CStreamInSize() */\n            if (ZSTD_isError(toRead)) { fprintf(stderr, \"ZSTD_seekable_compressStream() error : %s \\n\", ZSTD_getErrorName(toRead)); exit(12); }\n            if (toRead > buffInSize) toRead = buffInSize;   /* Safely handle case when `buffInSize` is manually changed to a value < ZSTD_CStreamInSize()*/\n            fwrite_orDie(buffOut, output.pos, fout);\n        }\n    }\n\n    while (1) {\n        ZSTD_outBuffer output = { buffOut, buffOutSize, 0 };\n        size_t const remainingToFlush = ZSTD_seekable_endStream(cstream, &output);   /* close stream */\n        if (ZSTD_isError(remainingToFlush)) { fprintf(stderr, \"ZSTD_seekable_endStream() error : %s \\n\", ZSTD_getErrorName(remainingToFlush)); exit(13); }\n        fwrite_orDie(buffOut, output.pos, fout);\n        if (!remainingToFlush) break;\n    }\n\n    ZSTD_seekable_freeCStream(cstream);\n    fclose_orDie(fout);\n    fclose_orDie(fin);\n    free(buffIn);\n    free(buffOut);\n}\n\nstatic char* createOutFilename_orDie(const char* filename)\n{\n    size_t const inL = strlen(filename);\n    size_t const outL = inL + 5;\n    void* outSpace = malloc_orDie(outL);\n    memset(outSpace, 0, outL);\n    strcat(outSpace, filename);\n    strcat(outSpace, \".zst\");\n    return (char*)outSpace;\n}\n\n#define CLEVEL_DEFAULT 5\nint main(int argc, const char** argv)\n{\n    const char* const exeName = argv[0];\n    if (argc<3 || argc>4) {\n        printf(\"wrong arguments \\n\");\n        printf(\"usage: \\n\");\n        printf(\"%s FILE FRAME_SIZE [LEVEL] \\n\", exeName);\n        return 1;\n    }\n\n    {   const char* const inFileName = argv[1];\n        unsigned const frameSize = (unsigned)atoi(argv[2]);\n        int const cLevel = (argc==4) ? atoi(argv[3]) : CLEVEL_DEFAULT;\n\n        char* const outFileName = createOutFilename_orDie(inFileName);\n        compressFile_orDie(inFileName, outFileName, cLevel, frameSize);\n        free(outFileName);\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "contrib/seekable_format/examples/seekable_decompression.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n */\n\n\n#include <stdlib.h>    // malloc, exit\n#include <stdio.h>     // fprintf, perror, feof\n#include <string.h>    // strerror\n#include <errno.h>     // errno\n#define ZSTD_STATIC_LINKING_ONLY\n#include <zstd.h>      // presumes zstd library is installed\n#include <zstd_errors.h>\n\n#include \"../zstd_seekable.h\"\n\n#define MIN(a, b) ((a) < (b) ? (a) : (b))\n\nstatic void* malloc_orDie(size_t size)\n{\n    void* const buff = malloc(size);\n    if (buff) return buff;\n    /* error */\n    perror(\"malloc\");\n    exit(1);\n}\n\nstatic void* realloc_orDie(void* ptr, size_t size)\n{\n    ptr = realloc(ptr, size);\n    if (ptr) return ptr;\n    /* error */\n    perror(\"realloc\");\n    exit(1);\n}\n\nstatic FILE* fopen_orDie(const char *filename, const char *instruction)\n{\n    FILE* const inFile = fopen(filename, instruction);\n    if (inFile) return inFile;\n    /* error */\n    perror(filename);\n    exit(3);\n}\n\nstatic size_t fread_orDie(void* buffer, size_t sizeToRead, FILE* file)\n{\n    size_t const readSize = fread(buffer, 1, sizeToRead, file);\n    if (readSize == sizeToRead) return readSize;   /* good */\n    if (feof(file)) return readSize;   /* good, reached end of file */\n    /* error */\n    perror(\"fread\");\n    exit(4);\n}\n\nstatic size_t fwrite_orDie(const void* buffer, size_t sizeToWrite, FILE* file)\n{\n    size_t const writtenSize = fwrite(buffer, 1, sizeToWrite, file);\n    if (writtenSize == sizeToWrite) return sizeToWrite;   /* good */\n    /* error */\n    perror(\"fwrite\");\n    exit(5);\n}\n\nstatic size_t fclose_orDie(FILE* file)\n{\n    if (!fclose(file)) return 0;\n    /* error */\n    perror(\"fclose\");\n    exit(6);\n}\n\nstatic void fseek_orDie(FILE* file, long int offset, int origin) {\n    if (!fseek(file, offset, origin)) {\n        if (!fflush(file)) return;\n    }\n    /* error */\n    perror(\"fseek\");\n    exit(7);\n}\n\n\nstatic void decompressFile_orDie(const char* fname, off_t startOffset, off_t endOffset)\n{\n    FILE* const fin  = fopen_orDie(fname, \"rb\");\n    FILE* const fout = stdout;\n    size_t const buffOutSize = ZSTD_DStreamOutSize();  /* Guarantee to successfully flush at least one complete compressed block in all circumstances. */\n    void*  const buffOut = malloc_orDie(buffOutSize);\n\n    ZSTD_seekable* const seekable = ZSTD_seekable_create();\n    if (seekable==NULL) { fprintf(stderr, \"ZSTD_seekable_create() error \\n\"); exit(10); }\n\n    size_t const initResult = ZSTD_seekable_initFile(seekable, fin);\n    if (ZSTD_isError(initResult)) { fprintf(stderr, \"ZSTD_seekable_init() error : %s \\n\", ZSTD_getErrorName(initResult)); exit(11); }\n\n    while (startOffset < endOffset) {\n        size_t const result = ZSTD_seekable_decompress(seekable, buffOut, MIN(endOffset - startOffset, buffOutSize), startOffset);\n        if (!result) {\n            break;\n        }\n\n        if (ZSTD_isError(result)) {\n            fprintf(stderr, \"ZSTD_seekable_decompress() error : %s \\n\",\n                    ZSTD_getErrorName(result));\n            exit(12);\n        }\n        fwrite_orDie(buffOut, result, fout);\n        startOffset += result;\n    }\n\n    ZSTD_seekable_free(seekable);\n    fclose_orDie(fin);\n    fclose_orDie(fout);\n    free(buffOut);\n}\n\n\nint main(int argc, const char** argv)\n{\n    const char* const exeName = argv[0];\n\n    if (argc!=4) {\n        fprintf(stderr, \"wrong arguments\\n\");\n        fprintf(stderr, \"usage:\\n\");\n        fprintf(stderr, \"%s FILE START END\\n\", exeName);\n        return 1;\n    }\n\n    {\n        const char* const inFilename = argv[1];\n        off_t const startOffset = atoll(argv[2]);\n        off_t const endOffset = atoll(argv[3]);\n        decompressFile_orDie(inFilename, startOffset, endOffset);\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "contrib/seekable_format/examples/seekable_decompression_mem.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n */\n\n\n#include <stdlib.h>    // malloc, exit\n#include <stdio.h>     // fprintf, perror, feof\n#include <string.h>    // strerror\n#include <errno.h>     // errno\n#define ZSTD_STATIC_LINKING_ONLY\n#include <zstd.h>      // presumes zstd library is installed\n#include <zstd_errors.h>\n\n#include \"zstd_seekable.h\"\n\n#define MIN(a, b) ((a) < (b) ? (a) : (b))\n\n#define MAX_FILE_SIZE (8 * 1024 * 1024)\n\nstatic void* malloc_orDie(size_t size)\n{\n    void* const buff = malloc(size);\n    if (buff) return buff;\n    /* error */\n    perror(\"malloc\");\n    exit(1);\n}\n\nstatic void* realloc_orDie(void* ptr, size_t size)\n{\n    ptr = realloc(ptr, size);\n    if (ptr) return ptr;\n    /* error */\n    perror(\"realloc\");\n    exit(1);\n}\n\nstatic FILE* fopen_orDie(const char *filename, const char *instruction)\n{\n    FILE* const inFile = fopen(filename, instruction);\n    if (inFile) return inFile;\n    /* error */\n    perror(filename);\n    exit(3);\n}\n\nstatic size_t fread_orDie(void* buffer, size_t sizeToRead, FILE* file)\n{\n    size_t const readSize = fread(buffer, 1, sizeToRead, file);\n    if (readSize == sizeToRead) return readSize;   /* good */\n    if (feof(file)) return readSize;   /* good, reached end of file */\n    /* error */\n    perror(\"fread\");\n    exit(4);\n}\n\nstatic size_t fwrite_orDie(const void* buffer, size_t sizeToWrite, FILE* file)\n{\n    size_t const writtenSize = fwrite(buffer, 1, sizeToWrite, file);\n    if (writtenSize == sizeToWrite) return sizeToWrite;   /* good */\n    /* error */\n    perror(\"fwrite\");\n    exit(5);\n}\n\nstatic size_t fclose_orDie(FILE* file)\n{\n    if (!fclose(file)) return 0;\n    /* error */\n    perror(\"fclose\");\n    exit(6);\n}\n\nstatic void fseek_orDie(FILE* file, long int offset, int origin) {\n    if (!fseek(file, offset, origin)) {\n        if (!fflush(file)) return;\n    }\n    /* error */\n    perror(\"fseek\");\n    exit(7);\n}\n\n\nstatic void decompressFile_orDie(const char* fname, off_t startOffset, off_t endOffset)\n{\n    FILE* const fin  = fopen_orDie(fname, \"rb\");\n    FILE* const fout = stdout;\n    // Just for demo purposes, assume file is <= MAX_FILE_SIZE\n    void*  const buffIn = malloc_orDie(MAX_FILE_SIZE);\n    size_t const inSize = fread_orDie(buffIn, MAX_FILE_SIZE, fin);\n    size_t const buffOutSize = ZSTD_DStreamOutSize();  /* Guarantee to successfully flush at least one complete compressed block in all circumstances. */\n    void*  const buffOut = malloc_orDie(buffOutSize);\n\n    ZSTD_seekable* const seekable = ZSTD_seekable_create();\n    if (seekable==NULL) { fprintf(stderr, \"ZSTD_seekable_create() error \\n\"); exit(10); }\n\n    size_t const initResult = ZSTD_seekable_initBuff(seekable, buffIn, inSize);\n    if (ZSTD_isError(initResult)) { fprintf(stderr, \"ZSTD_seekable_init() error : %s \\n\", ZSTD_getErrorName(initResult)); exit(11); }\n\n    while (startOffset < endOffset) {\n        size_t const result = ZSTD_seekable_decompress(seekable, buffOut, MIN(endOffset - startOffset, buffOutSize), startOffset);\n        if (!result) {\n            break;\n        }\n\n        if (ZSTD_isError(result)) {\n            fprintf(stderr, \"ZSTD_seekable_decompress() error : %s \\n\",\n                    ZSTD_getErrorName(result));\n            exit(12);\n        }\n        fwrite_orDie(buffOut, result, fout);\n        startOffset += result;\n    }\n\n    ZSTD_seekable_free(seekable);\n    fclose_orDie(fin);\n    fclose_orDie(fout);\n    free(buffIn);\n    free(buffOut);\n}\n\n\nint main(int argc, const char** argv)\n{\n    const char* const exeName = argv[0];\n\n    if (argc!=4) {\n        fprintf(stderr, \"wrong arguments\\n\");\n        fprintf(stderr, \"usage:\\n\");\n        fprintf(stderr, \"%s FILE START END\\n\", exeName);\n        return 1;\n    }\n\n    {\n        const char* const inFilename = argv[1];\n        off_t const startOffset = atoll(argv[2]);\n        off_t const endOffset = atoll(argv[3]);\n        decompressFile_orDie(inFilename, startOffset, endOffset);\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "contrib/seekable_format/tests/.gitignore",
    "content": "seekable_tests\ndata.txt\n"
  },
  {
    "path": "contrib/seekable_format/tests/Makefile",
    "content": "# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# ################################################################\n\n# This Makefile presumes libzstd is built, using `make` in / or /lib/\n\nZSTDLIB_PATH = ../../../lib\nZSTDLIB_NAME = libzstd.a\nZSTDLIB = $(ZSTDLIB_PATH)/$(ZSTDLIB_NAME)\n\nCPPFLAGS += -DXXH_NAMESPACE=ZSTD_ -I../ -I$(ZSTDLIB_PATH) -I$(ZSTDLIB_PATH)/common\n\nCFLAGS ?= -O3\nCFLAGS += -g -Wall -Wextra -Wcast-qual -Wcast-align -Wconversion \\\n          -Wformat=2 -Wstrict-aliasing=1\n\nSEEKABLE_OBJS = ../zstdseek_compress.c ../zstdseek_decompress.c $(ZSTDLIB)\n\n.PHONY: default clean test\ndefault: test\n\ntest: seekable_tests parallel_compression_test\n\t./seekable_tests\n\n$(ZSTDLIB):\n\t$(MAKE) -C $(ZSTDLIB_PATH) $(ZSTDLIB_NAME)\n\nseekable_tests : $(SEEKABLE_OBJS)\n\nEXAMPLES_PATH = ../examples\nPARALLEL_COMPRESSION = $(EXAMPLES_PATH)/parallel_compression\n\nDATAGEN_PATH = ../../../tests\nDATAGEN = $(DATAGEN_PATH)/datagen\n\n$(PARALLEL_COMPRESSION):\n\t$(MAKE) -C $(EXAMPLES_PATH) parallel_compression\n\n$(DATAGEN):\n\t$(MAKE) -C $(DATAGEN_PATH) datagen\n\ndata.txt: $(DATAGEN)\n\t$(DATAGEN) -g100M > $@\n\nparallel_compression_test: $(PARALLEL_COMPRESSION) data.txt\n\tulimit -Sv 102400; $(PARALLEL_COMPRESSION) data.txt 1048576 2\n\n.PHONY: parallel_compression_test parallel_comp\n\nclean:\n\t@$(RM) core *.o tmp* result* *.zst \\\n\t\tseekable_tests data.txt\n\t@echo Cleaning completed\n"
  },
  {
    "path": "contrib/seekable_format/tests/seekable_tests.c",
    "content": "#include <stddef.h>\n#include <stdint.h>\n#include <stdlib.h>  // malloc\n#include <stdio.h>\n#include <assert.h>\n#include <string.h>\n\n#include \"../zstd_seekable.h\"\n\n\n/* ZSTD_seekable_customFile implementation that reads/seeks a buffer while keeping track of total bytes read */\ntypedef struct {\n    const void *ptr;\n    size_t size;\n    size_t pos;\n    size_t totalRead;\n} buffWrapperWithTotal_t;\n\nstatic int readBuffWithTotal(void* opaque, void* buffer, size_t n)\n{\n    buffWrapperWithTotal_t* const buff = (buffWrapperWithTotal_t*)opaque;\n    assert(buff != NULL);\n    if (buff->pos + n > buff->size) return -1;\n    memcpy(buffer, (const char*)buff->ptr + buff->pos, n);\n    buff->pos += n;\n    buff->totalRead += n;\n    return 0;\n}\n\nstatic int seekBuffWithTotal(void* opaque, long long offset, int origin)\n{\n    buffWrapperWithTotal_t* const buff = (buffWrapperWithTotal_t*) opaque;\n    unsigned long long newOffset;\n    assert(buff != NULL);\n    switch (origin) {\n    case SEEK_SET:\n        assert(offset >= 0);\n        newOffset = (unsigned long long)offset;\n        break;\n    case SEEK_CUR:\n        newOffset = (unsigned long long)((long long)buff->pos + offset);\n        break;\n    case SEEK_END:\n        newOffset = (unsigned long long)((long long)buff->size + offset);\n        break;\n    default:\n        assert(0);  /* not possible */\n    }\n    if (newOffset > buff->size) {\n        return -1;\n    }\n    buff->pos = newOffset;\n    return 0;\n}\n\n/* Basic unit tests for zstd seekable format */\nint main(int argc, const char** argv)\n{\n    unsigned testNb = 1;\n    (void)argc; (void)argv;\n    printf(\"Beginning zstd seekable format tests...\\n\");\n\n    printf(\"Test %u - simple round trip: \", testNb++);\n    {   size_t const inSize = 4000;\n        void* const inBuffer = malloc(inSize);\n        assert(inBuffer != NULL);\n\n        size_t const seekCapacity = 5000;\n        void* const seekBuffer = malloc(seekCapacity);\n        assert(seekBuffer != NULL);\n        size_t seekSize;\n\n        size_t const outCapacity = inSize;\n        void* const outBuffer = malloc(outCapacity);\n        assert(outBuffer != NULL);\n\n        ZSTD_seekable_CStream* const zscs = ZSTD_seekable_createCStream();\n        assert(zscs != NULL);\n\n        { size_t const initStatus = ZSTD_seekable_initCStream(zscs, 9, 0 /* checksumFlag */, (unsigned)inSize /* maxFrameSize */);\n          assert(!ZSTD_isError(initStatus));\n        }\n\n        {   ZSTD_outBuffer outb = { .dst=seekBuffer, .pos=0, .size=seekCapacity };\n            ZSTD_inBuffer inb = { .src=inBuffer, .pos=0, .size=inSize };\n\n            size_t const cStatus = ZSTD_seekable_compressStream(zscs, &outb, &inb);\n            assert(!ZSTD_isError(cStatus));\n            assert(inb.pos == inb.size);\n\n            size_t const endStatus = ZSTD_seekable_endStream(zscs, &outb);\n            assert(!ZSTD_isError(endStatus));\n            seekSize = outb.pos;\n        }\n\n        ZSTD_seekable* const stream = ZSTD_seekable_create();\n        assert(stream != NULL);\n        { size_t const initStatus = ZSTD_seekable_initBuff(stream, seekBuffer, seekSize);\n          assert(!ZSTD_isError(initStatus)); }\n\n        { size_t const decStatus = ZSTD_seekable_decompress(stream, outBuffer, outCapacity, 0);\n          assert(decStatus == inSize); }\n\n        /* unit test ZSTD_seekTable functions */\n        ZSTD_seekTable* const zst = ZSTD_seekTable_create_fromSeekable(stream);\n        assert(zst != NULL);\n\n        unsigned const nbFrames = ZSTD_seekTable_getNumFrames(zst);\n        assert(nbFrames > 0);\n\n        unsigned long long const frame0Offset = ZSTD_seekTable_getFrameCompressedOffset(zst, 0);\n        assert(frame0Offset == 0);\n\n        unsigned long long const content0Offset = ZSTD_seekTable_getFrameDecompressedOffset(zst, 0);\n        assert(content0Offset == 0);\n\n        size_t const cSize = ZSTD_seekTable_getFrameCompressedSize(zst, 0);\n        assert(!ZSTD_isError(cSize));\n        assert(cSize <= seekCapacity);\n\n        size_t const origSize = ZSTD_seekTable_getFrameDecompressedSize(zst, 0);\n        assert(origSize == inSize);\n\n        unsigned const fo1idx = ZSTD_seekTable_offsetToFrameIndex(zst, 1);\n        assert(fo1idx == 0);\n\n        free(inBuffer);\n        free(seekBuffer);\n        free(outBuffer);\n        ZSTD_seekable_freeCStream(zscs);\n        ZSTD_seekTable_free(zst);\n        ZSTD_seekable_free(stream);\n    }\n    printf(\"Success!\\n\");\n\n\n    printf(\"Test %u - check that seekable decompress does not hang: \", testNb++);\n    {   /* Github issue #2335 */\n        const size_t compressed_size = 17;\n        const uint8_t compressed_data[17] = {\n            '^',\n            '*',\n            'M',\n            '\\x18',\n            '\\t',\n            '\\x00',\n            '\\x00',\n            '\\x00',\n            '\\x00',\n            '\\x00',\n            '\\x00',\n            '\\x00',\n            (uint8_t)('\\x03'),\n            (uint8_t)('\\xb1'),\n            (uint8_t)('\\xea'),\n            (uint8_t)('\\x92'),\n            (uint8_t)('\\x8f'),\n        };\n        const size_t uncompressed_size = 32;\n        uint8_t uncompressed_data[32];\n\n        ZSTD_seekable* const stream = ZSTD_seekable_create();\n        assert(stream != NULL);\n        {   size_t const status = ZSTD_seekable_initBuff(stream, compressed_data, compressed_size);\n            if (ZSTD_isError(status)) {\n                ZSTD_seekable_free(stream);\n                goto _test_error;\n        }   }\n\n        /* Should return an error, but not hang */\n        {   const size_t offset = 2;\n            size_t const status = ZSTD_seekable_decompress(stream, uncompressed_data, uncompressed_size, offset);\n            if (!ZSTD_isError(status)) {\n                ZSTD_seekable_free(stream);\n                goto _test_error;\n        }   }\n\n        ZSTD_seekable_free(stream);\n    }\n    printf(\"Success!\\n\");\n\n    printf(\"Test %u - check #2 that seekable decompress does not hang: \", testNb++);\n    {   /* Github issue #FIXME */\n        const size_t compressed_size = 27;\n        const uint8_t compressed_data[27] = {\n            (uint8_t)'\\x28',\n            (uint8_t)'\\xb5',\n            (uint8_t)'\\x2f',\n            (uint8_t)'\\xfd',\n            (uint8_t)'\\x00',\n            (uint8_t)'\\x32',\n            (uint8_t)'\\x91',\n            (uint8_t)'\\x00',\n            (uint8_t)'\\x00',\n            (uint8_t)'\\x00',\n            (uint8_t)'\\x5e',\n            (uint8_t)'\\x2a',\n            (uint8_t)'\\x4d',\n            (uint8_t)'\\x18',\n            (uint8_t)'\\x09',\n            (uint8_t)'\\x00',\n            (uint8_t)'\\x00',\n            (uint8_t)'\\x00',\n            (uint8_t)'\\x00',\n            (uint8_t)'\\x00',\n            (uint8_t)'\\x00',\n            (uint8_t)'\\x00',\n            (uint8_t)'\\x00',\n            (uint8_t)'\\xb1',\n            (uint8_t)'\\xea',\n            (uint8_t)'\\x92',\n            (uint8_t)'\\x8f',\n        };\n        const size_t uncompressed_size = 400;\n        uint8_t uncompressed_data[400];\n\n        ZSTD_seekable* stream = ZSTD_seekable_create();\n        size_t status = ZSTD_seekable_initBuff(stream, compressed_data, compressed_size);\n        if (ZSTD_isError(status)) {\n            ZSTD_seekable_free(stream);\n            goto _test_error;\n        }\n\n        const size_t offset = 2;\n        /* Should return an error, but not hang */\n        status = ZSTD_seekable_decompress(stream, uncompressed_data, uncompressed_size, offset);\n        if (!ZSTD_isError(status)) {\n            ZSTD_seekable_free(stream);\n            goto _test_error;\n        }\n\n        ZSTD_seekable_free(stream);\n    }\n    printf(\"Success!\\n\");\n\n\n    printf(\"Test %u - check ZSTD magic in compressing empty string: \", testNb++);\n    { // compressing empty string should return a zstd header\n        size_t const capacity = 255;\n        char* inBuffer = malloc(capacity);\n        assert(inBuffer != NULL);\n        inBuffer[0] = '\\0';\n        void* const outBuffer = malloc(capacity);\n        assert(outBuffer != NULL);\n\n        ZSTD_seekable_CStream *s = ZSTD_seekable_createCStream();\n        ZSTD_seekable_initCStream(s, 1, 1, 255);\n\n        ZSTD_inBuffer input = { .src=inBuffer, .pos=0, .size=0 };\n        ZSTD_outBuffer output = { .dst=outBuffer, .pos=0, .size=capacity };\n\n        ZSTD_seekable_compressStream(s, &output, &input);\n        ZSTD_seekable_endStream(s, &output);\n\n        if((((char*)output.dst)[0] != '\\x28') | (((char*)output.dst)[1] != '\\xb5') | (((char*)output.dst)[2] != '\\x2f') | (((char*)output.dst)[3] != '\\xfd')) {\n            printf(\"%#02x %#02x %#02x %#02x\\n\", ((char*)output.dst)[0], ((char*)output.dst)[1] , ((char*)output.dst)[2] , ((char*)output.dst)[3] );\n\n            free(inBuffer);\n            free(outBuffer);\n            ZSTD_seekable_freeCStream(s);\n            goto _test_error;\n        }\n\n        free(inBuffer);\n        free(outBuffer);\n        ZSTD_seekable_freeCStream(s);\n    }\n    printf(\"Success!\\n\");\n\n\n    printf(\"Test %u - multiple decompress calls: \", testNb++);\n    {   char const inBuffer[] = \"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt\";\n        size_t const inSize = sizeof(inBuffer);\n\n        size_t const seekCapacity = 5000;\n        void* const seekBuffer = malloc(seekCapacity);\n        assert(seekBuffer != NULL);\n        size_t seekSize;\n\n        size_t const outCapacity = inSize;\n        char* const outBuffer = malloc(outCapacity);\n        assert(outBuffer != NULL);\n\n        ZSTD_seekable_CStream* const zscs = ZSTD_seekable_createCStream();\n        assert(zscs != NULL);\n\n        /* compress test data with a small frame size to ensure multiple frames in the output */\n        unsigned const maxFrameSize = 40;\n        { size_t const initStatus = ZSTD_seekable_initCStream(zscs, 9, 0 /* checksumFlag */, maxFrameSize);\n          assert(!ZSTD_isError(initStatus));\n        }\n\n        {   ZSTD_outBuffer outb = { .dst=seekBuffer, .pos=0, .size=seekCapacity };\n            ZSTD_inBuffer inb = { .src=inBuffer, .pos=0, .size=inSize };\n\n            while (inb.pos < inb.size) {\n                size_t const cStatus = ZSTD_seekable_compressStream(zscs, &outb, &inb);\n                assert(!ZSTD_isError(cStatus));\n            }\n\n            size_t const endStatus = ZSTD_seekable_endStream(zscs, &outb);\n            assert(!ZSTD_isError(endStatus));\n            seekSize = outb.pos;\n        }\n\n        ZSTD_seekable* const stream = ZSTD_seekable_create();\n        assert(stream != NULL);\n        buffWrapperWithTotal_t buffWrapper = {seekBuffer, seekSize, 0, 0};\n        { ZSTD_seekable_customFile srcFile = {&buffWrapper, &readBuffWithTotal, &seekBuffWithTotal};\n          size_t const initStatus = ZSTD_seekable_initAdvanced(stream, srcFile);\n          assert(!ZSTD_isError(initStatus)); }\n\n        /* Perform a series of small reads and seeks (repeatedly read 1 byte and skip 1 byte)\n           and check that we didn't reread input data unnecessarily */\n        size_t pos;\n        for (pos = 0; pos < inSize; pos += 2) {\n            size_t const decStatus = ZSTD_seekable_decompress(stream, outBuffer, 1, pos);\n            if (decStatus != 1 || outBuffer[0] != inBuffer[pos]) {\n                free(seekBuffer);\n                free(outBuffer);\n                ZSTD_seekable_freeCStream(zscs);\n                ZSTD_seekable_free(stream);\n                goto _test_error;\n            }\n        }\n        if (buffWrapper.totalRead > seekSize) {\n            /* We read more than the compressed size, meaning there were some rereads.\n               This is unneeded because we only seeked forward. */\n            printf(\"Too much data read: %zu read, with compressed size %zu\\n\", buffWrapper.totalRead, seekSize);\n            free(seekBuffer);\n            free(outBuffer);\n            ZSTD_seekable_freeCStream(zscs);\n            ZSTD_seekable_free(stream);\n            goto _test_error;\n        }\n\n        /* Perform some reads and seeks to ensure correctness */\n        struct {\n            size_t offset;\n            size_t size;\n        } const tests[] = {  /* Assume the frame size is 40 */\n            {20, 40}, /* read partial data from two frames */\n            {60, 10}, /* continue reading from the same offset */\n            {50, 20}, /* seek backward within the same frame */\n            {10, 10}, /* seek backward to a different frame */\n            {25, 10}, /* seek forward within the same frame */\n            {60, 10}, /* seek forward to a different frame */\n        };\n        size_t idx;\n        for (idx = 0; idx < sizeof(tests) / sizeof(tests[0]); idx++) {\n            size_t const decStatus = ZSTD_seekable_decompress(stream, outBuffer, tests[idx].size, tests[idx].offset);\n            if (decStatus != tests[idx].size || memcmp(outBuffer, inBuffer + tests[idx].offset, tests[idx].size) != 0) {\n                free(seekBuffer);\n                free(outBuffer);\n                ZSTD_seekable_freeCStream(zscs);\n                ZSTD_seekable_free(stream);\n                goto _test_error;\n            }\n        }\n\n        free(seekBuffer);\n        free(outBuffer);\n        ZSTD_seekable_freeCStream(zscs);\n        ZSTD_seekable_free(stream);\n    }\n    printf(\"Success!\\n\");\n\n    /* TODO: Add more tests */\n    printf(\"Finished tests\\n\");\n    return 0;\n\n_test_error:\n    printf(\"test failed! Exiting..\\n\");\n    return 1;\n}\n"
  },
  {
    "path": "contrib/seekable_format/zstd_seekable.h",
    "content": "#ifndef SEEKABLE_H\n#define SEEKABLE_H\n\n#include <stdio.h>\n#include \"zstd.h\"   /* ZSTDLIB_API */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n#define ZSTD_seekTableFooterSize 9\n\n#define ZSTD_SEEKABLE_MAGICNUMBER 0x8F92EAB1\n\n#define ZSTD_SEEKABLE_MAXFRAMES 0x8000000U\n\n/* Limit maximum size to avoid potential issues storing the compressed size */\n#define ZSTD_SEEKABLE_MAX_FRAME_DECOMPRESSED_SIZE 0x40000000U\n\n/*-****************************************************************************\n*  Seekable Format\n*\n*  The seekable format splits the compressed data into a series of \"frames\",\n*  each compressed individually so that decompression of a section in the\n*  middle of an archive only requires zstd to decompress at most a frame's\n*  worth of extra data, instead of the entire archive.\n******************************************************************************/\n\ntypedef struct ZSTD_seekable_CStream_s ZSTD_seekable_CStream;\ntypedef struct ZSTD_seekable_s ZSTD_seekable;\ntypedef struct ZSTD_seekTable_s ZSTD_seekTable;\n\n/*-****************************************************************************\n*  Seekable compression - HowTo\n*  A ZSTD_seekable_CStream object is required to tracking streaming operation.\n*  Use ZSTD_seekable_createCStream() and ZSTD_seekable_freeCStream() to create/\n*  release resources.\n*\n*  Streaming objects are reusable to avoid allocation and deallocation,\n*  to start a new compression operation call ZSTD_seekable_initCStream() on the\n*  compressor.\n*\n*  Data streamed to the seekable compressor will automatically be split into\n*  frames of size `maxFrameSize` (provided in ZSTD_seekable_initCStream()),\n*  or if none is provided, will be cut off whenever ZSTD_seekable_endFrame() is\n*  called or when the default maximum frame size (2GB) is reached.\n*\n*  Use ZSTD_seekable_initCStream() to initialize a ZSTD_seekable_CStream object\n*  for a new compression operation.\n*  - `maxFrameSize` indicates the size at which to automatically start a new\n*            seekable frame.\n*            `maxFrameSize == 0` implies the default maximum size.\n*            Smaller frame sizes allow faster decompression of small segments,\n*            since retrieving a single byte requires decompression of\n*            the full frame where the byte belongs.\n*            In general, size the frames to roughly correspond to\n*            the access granularity (when it's known).\n*            But small sizes also reduce compression ratio.\n*            Avoid really tiny frame sizes (< 1 KB),\n*            that would hurt compression ratio considerably.\n*  - `checksumFlag` indicates whether or not the seek table should include frame\n*            checksums on the uncompressed data for verification.\n*  @return : a size hint for input to provide for compression, or an error code\n*            checkable with ZSTD_isError()\n*\n*  Use ZSTD_seekable_compressStream() repetitively to consume input stream.\n*  The function will automatically update both `pos` fields.\n*  Note that it may not consume the entire input, in which case `pos < size`,\n*  and it's up to the caller to present again remaining data.\n*  @return : a size hint, preferred nb of bytes to use as input for next\n*            function call or an error code, which can be tested using\n*            ZSTD_isError().\n*            Note 1 : it's just a hint, to help latency a little, any other\n*                     value will work fine.\n*\n*  At any time, call ZSTD_seekable_endFrame() to end the current frame and\n*  start a new one.\n*\n*  ZSTD_seekable_endStream() will end the current frame, and then write the seek\n*  table so that decompressors can efficiently find compressed frames.\n*  ZSTD_seekable_endStream() may return a number > 0 if it was unable to flush\n*  all the necessary data to `output`.  In this case, it should be called again\n*  until all remaining data is flushed out and 0 is returned.\n******************************************************************************/\n\n/*===== Seekable compressor management =====*/\nZSTDLIB_API ZSTD_seekable_CStream* ZSTD_seekable_createCStream(void);\nZSTDLIB_API size_t ZSTD_seekable_freeCStream(ZSTD_seekable_CStream* zcs);\n\n/*===== Seekable compression functions =====*/\nZSTDLIB_API size_t ZSTD_seekable_initCStream(ZSTD_seekable_CStream* zcs, int compressionLevel, int checksumFlag, unsigned maxFrameSize);\nZSTDLIB_API size_t ZSTD_seekable_compressStream(ZSTD_seekable_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input);\nZSTDLIB_API size_t ZSTD_seekable_endFrame(ZSTD_seekable_CStream* zcs, ZSTD_outBuffer* output);\nZSTDLIB_API size_t ZSTD_seekable_endStream(ZSTD_seekable_CStream* zcs, ZSTD_outBuffer* output);\n\n/*= Raw seek table API\n *  These functions allow for the seek table to be constructed directly.\n *  This table can then be appended to a file of concatenated frames.\n *  This allows the frames to be compressed independently, even in parallel,\n *  and compiled together afterward into a seekable archive.\n *\n *  Use ZSTD_seekable_createFrameLog() to allocate and initialize a tracking\n *  structure.\n *\n *  Call ZSTD_seekable_logFrame() once for each frame in the archive.\n *  checksum is optional, and will not be used if checksumFlag was 0 when the\n *  frame log was created.  If present, it should be the least significant 32\n *  bits of the XXH64 hash of the uncompressed data.\n *\n *  Call ZSTD_seekable_writeSeekTable to serialize the data into a seek table.\n *  If the entire table was written, the return value will be 0.  Otherwise,\n *  it will be equal to the number of bytes left to write. */\ntypedef struct ZSTD_frameLog_s ZSTD_frameLog;\nZSTDLIB_API ZSTD_frameLog* ZSTD_seekable_createFrameLog(int checksumFlag);\nZSTDLIB_API size_t ZSTD_seekable_freeFrameLog(ZSTD_frameLog* fl);\nZSTDLIB_API size_t ZSTD_seekable_logFrame(ZSTD_frameLog* fl, unsigned compressedSize, unsigned decompressedSize, unsigned checksum);\nZSTDLIB_API size_t ZSTD_seekable_writeSeekTable(ZSTD_frameLog* fl, ZSTD_outBuffer* output);\n\n\n/*-****************************************************************************\n*  Seekable decompression - HowTo\n*  A ZSTD_seekable object is required to tracking the seekTable.\n*\n*  Call ZSTD_seekable_init* to initialize a ZSTD_seekable object with the\n*  the seek table provided in the input.\n*  There are three modes for ZSTD_seekable_init:\n*    - ZSTD_seekable_initBuff() : An in-memory API.  The data contained in\n*      `src` should be the entire seekable file, including the seek table.\n*      `src` should be kept alive and unmodified until the ZSTD_seekable object\n*      is freed or reset.\n*    - ZSTD_seekable_initFile() : A simplified file API using stdio.  fread and\n*      fseek will be used to access the required data for building the seek\n*      table and doing decompression operations.  `src` should not be closed\n*      or modified until the ZSTD_seekable object is freed or reset.\n*    - ZSTD_seekable_initAdvanced() : A general API allowing the client to\n*      provide its own read and seek callbacks.\n*        + ZSTD_seekable_read() : read exactly `n` bytes into `buffer`.\n*                                 Premature EOF should be treated as an error.\n*        + ZSTD_seekable_seek() : seek the read head to `offset` from `origin`,\n*                                 where origin is either SEEK_SET (beginning of\n*                                 file), or SEEK_END (end of file).\n*  Both functions should return a non-negative value in case of success, and a\n*  negative value in case of failure.  If implementing using this API and\n*  stdio, be careful with files larger than 4GB and fseek.  All of these\n*  functions return an error code checkable with ZSTD_isError().\n*\n*  Call ZSTD_seekable_decompress to decompress `dstSize` bytes at decompressed\n*  offset `offset`.  ZSTD_seekable_decompress may have to decompress the entire\n*  prefix of the frame before the desired data if it has not already processed\n*  this section. If ZSTD_seekable_decompress is called multiple times for a\n*  consecutive range of data, it will efficiently retain the decompressor object\n*  and avoid redecompressing frame prefixes.  The return value is the number of\n*  bytes decompressed, or an error code checkable with ZSTD_isError().\n*\n*  The seek table access functions can be used to obtain the data contained\n*  in the seek table.  If frameIndex is larger than the value returned by\n*  ZSTD_seekable_getNumFrames(), they will return error codes checkable with\n*  ZSTD_isError().  Note that since the offset access functions return\n*  unsigned long long instead of size_t, in this case they will instead return\n*  the value ZSTD_SEEKABLE_FRAMEINDEX_TOOLARGE.\n******************************************************************************/\n\n/*===== Seekable decompressor management =====*/\nZSTDLIB_API ZSTD_seekable* ZSTD_seekable_create(void);\nZSTDLIB_API size_t ZSTD_seekable_free(ZSTD_seekable* zs);\n\n/*===== Seekable decompression functions =====*/\nZSTDLIB_API size_t ZSTD_seekable_initBuff(ZSTD_seekable* zs, const void* src, size_t srcSize);\nZSTDLIB_API size_t ZSTD_seekable_initFile(ZSTD_seekable* zs, FILE* src);\nZSTDLIB_API size_t ZSTD_seekable_decompress(ZSTD_seekable* zs, void* dst, size_t dstSize, unsigned long long offset);\nZSTDLIB_API size_t ZSTD_seekable_decompressFrame(ZSTD_seekable* zs, void* dst, size_t dstSize, unsigned frameIndex);\n\n#define ZSTD_SEEKABLE_FRAMEINDEX_TOOLARGE (0ULL-2)\n/*===== Seekable seek table access functions =====*/\nZSTDLIB_API unsigned ZSTD_seekable_getNumFrames(const ZSTD_seekable* zs);\nZSTDLIB_API unsigned long long ZSTD_seekable_getFrameCompressedOffset(const ZSTD_seekable* zs, unsigned frameIndex);\nZSTDLIB_API unsigned long long ZSTD_seekable_getFrameDecompressedOffset(const ZSTD_seekable* zs, unsigned frameIndex);\nZSTDLIB_API size_t ZSTD_seekable_getFrameCompressedSize(const ZSTD_seekable* zs, unsigned frameIndex);\nZSTDLIB_API size_t ZSTD_seekable_getFrameDecompressedSize(const ZSTD_seekable* zs, unsigned frameIndex);\nZSTDLIB_API unsigned ZSTD_seekable_offsetToFrameIndex(const ZSTD_seekable* zs, unsigned long long offset);\n\n\n/*-****************************************************************************\n*  Direct exploitation of the seekTable\n*\n*  Memory constrained use cases that manage multiple archives\n*  benefit from retaining multiple archive seek tables\n*  without retaining a ZSTD_seekable instance for each.\n*\n*  Below API allow the above-mentioned use cases\n*  to initialize a ZSTD_seekable, extract its (smaller) ZSTD_seekTable,\n*  then throw the ZSTD_seekable away to save memory.\n*\n*  Standard ZSTD operations can then be used\n*  to decompress frames based on seek table offsets.\n******************************************************************************/\n\n/*===== Independent seek table management =====*/\nZSTDLIB_API ZSTD_seekTable* ZSTD_seekTable_create_fromSeekable(const ZSTD_seekable* zs);\nZSTDLIB_API size_t ZSTD_seekTable_free(ZSTD_seekTable* st);\n\n/*===== Direct seek table access functions =====*/\nZSTDLIB_API unsigned ZSTD_seekTable_getNumFrames(const ZSTD_seekTable* st);\nZSTDLIB_API unsigned long long ZSTD_seekTable_getFrameCompressedOffset(const ZSTD_seekTable* st, unsigned frameIndex);\nZSTDLIB_API unsigned long long ZSTD_seekTable_getFrameDecompressedOffset(const ZSTD_seekTable* st, unsigned frameIndex);\nZSTDLIB_API size_t ZSTD_seekTable_getFrameCompressedSize(const ZSTD_seekTable* st, unsigned frameIndex);\nZSTDLIB_API size_t ZSTD_seekTable_getFrameDecompressedSize(const ZSTD_seekTable* st, unsigned frameIndex);\nZSTDLIB_API unsigned ZSTD_seekTable_offsetToFrameIndex(const ZSTD_seekTable* st, unsigned long long offset);\n\n\n/*===== Seekable advanced I/O API =====*/\ntypedef int(ZSTD_seekable_read)(void* opaque, void* buffer, size_t n);\ntypedef int(ZSTD_seekable_seek)(void* opaque, long long offset, int origin);\ntypedef struct {\n    void* opaque;\n    ZSTD_seekable_read* read;\n    ZSTD_seekable_seek* seek;\n} ZSTD_seekable_customFile;\nZSTDLIB_API size_t ZSTD_seekable_initAdvanced(ZSTD_seekable* zs, ZSTD_seekable_customFile src);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "contrib/seekable_format/zstd_seekable_compression_format.md",
    "content": "# Zstandard Seekable Format\n\n### Notices\n\nCopyright (c) Meta Platforms, Inc. and affiliates.\n\nPermission is granted to copy and distribute this document\nfor any purpose and without charge,\nincluding translations into other languages\nand incorporation into compilations,\nprovided that the copyright notice and this notice are preserved,\nand that any substantive changes or deletions from the original\nare clearly marked.\nDistribution of this document is unlimited.\n\n### Version\n0.1.0 (11/04/17)\n\n## Introduction\nThis document defines a format for compressed data to be stored so that subranges of the data can be efficiently decompressed without requiring the entire document to be decompressed.\nThis is done by splitting up the input data into frames,\neach of which are compressed independently,\nand so can be decompressed independently.\nDecompression then takes advantage of a provided 'seek table', which allows the decompressor to immediately jump to the desired data.  This is done in a way that is compatible with the original Zstandard format by placing the seek table in a Zstandard skippable frame.\n\n### Overall conventions\nIn this document:\n- square brackets i.e. `[` and `]` are used to indicate optional fields or parameters.\n- the naming convention for identifiers is `Mixed_Case_With_Underscores`\n- All numeric fields are little-endian unless specified otherwise\n\n## Format\n\nThe format consists of a number of frames (Zstandard compressed frames and skippable frames), followed by a final skippable frame at the end containing the seek table.\n\n### Seek Table Format\nThe structure of the seek table frame is as follows:\n\n|`Skippable_Magic_Number`|`Frame_Size`|`[Seek_Table_Entries]`|`Seek_Table_Footer`|\n|------------------------|------------|----------------------|-------------------|\n| 4 bytes                | 4 bytes    | 8-12 bytes each      | 9 bytes           |\n\n__`Skippable_Magic_Number`__\n\nValue : 0x184D2A5E.\nThis is for compatibility with [Zstandard skippable frames].\nSince it is legal for other Zstandard skippable frames to use the same\nmagic number, it is not recommended for a decoder to recognize frames\nsolely on this.\n\n__`Frame_Size`__\n\nThe total size of the skippable frame, not including the `Skippable_Magic_Number` or `Frame_Size`.\nThis is for compatibility with [Zstandard skippable frames].\n\n[Zstandard skippable frames]: https://github.com/facebook/zstd/blob/release/doc/zstd_compression_format.md#skippable-frames\n\n#### `Seek_Table_Footer`\nThe seek table footer format is as follows:\n\n|`Number_Of_Frames`|`Seek_Table_Descriptor`|`Seekable_Magic_Number`|\n|------------------|-----------------------|-----------------------|\n| 4 bytes          | 1 byte                | 4 bytes               |\n\n__`Seekable_Magic_Number`__\n\nValue : 0x8F92EAB1.\nThis value must be the last bytes present in the compressed file so that decoders\ncan efficiently find it and determine if there is an actual seek table present.\n\n__`Number_Of_Frames`__\n\nThe number of stored frames in the data.\n\n__`Seek_Table_Descriptor`__\n\nA bitfield describing the format of the seek table.\n\n| Bit number | Field name                |\n| ---------- | ----------                |\n| 7          | `Checksum_Flag`           |\n| 6-2        | `Reserved_Bits`           |\n| 1-0        | `Unused_Bits`             |\n\nWhile only `Checksum_Flag` currently exists, there are 7 other bits in this field that can be used for future changes to the format,\nfor example the addition of inline dictionaries.\n\n__`Checksum_Flag`__\n\nIf the checksum flag is set, each of the seek table entries contains a 4 byte checksum of the uncompressed data contained in its frame.\n\n`Reserved_Bits` are not currently used but may be used in the future for breaking changes, so a compliant decoder should ensure they are set to 0.  `Unused_Bits` may be used in the future for non-breaking changes, so a compliant decoder should not interpret these bits.\n\n#### __`Seek_Table_Entries`__\n\n`Seek_Table_Entries` consists of `Number_Of_Frames` (one for each frame in the data, not including the seek table frame) entries of the following form, in sequence:\n\n|`Compressed_Size`|`Decompressed_Size`|`[Checksum]`|\n|-----------------|-------------------|------------|\n| 4 bytes         | 4 bytes           | 4 bytes    |\n\n__`Compressed_Size`__\n\nThe compressed size of the frame.\nThe cumulative sum of the `Compressed_Size` fields of frames `0` to `i` gives the offset in the compressed file of frame `i+1`.\n\n__`Decompressed_Size`__\n\nThe size of the decompressed data contained in the frame.  For skippable or otherwise empty frames, this value is 0.\n\n__`Checksum`__\n\nOnly present if `Checksum_Flag` is set in the `Seek_Table_Descriptor`.  Value : the least significant 32 bits of the XXH64 digest of the uncompressed data, stored in little-endian format.\n\n## Version Changes\n- 0.1.0: initial version\n"
  },
  {
    "path": "contrib/seekable_format/zstdseek_compress.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n */\n\n#include <stdlib.h>     /* malloc, free */\n#include <limits.h>     /* UINT_MAX */\n#include <assert.h>\n\n#define XXH_STATIC_LINKING_ONLY\n#include \"xxhash.h\"\n\n#define ZSTD_STATIC_LINKING_ONLY\n#include \"zstd.h\"\n#include \"zstd_errors.h\"\n#include \"mem.h\"\n\n#include \"zstd_seekable.h\"\n\n#define CHECK_Z(f) { size_t const ret = (f); if (ret != 0) return ret; }\n\n#undef ERROR\n#define ERROR(name) ((size_t)-ZSTD_error_##name)\n\n#undef MIN\n#undef MAX\n#define MIN(a, b) ((a) < (b) ? (a) : (b))\n#define MAX(a, b) ((a) > (b) ? (a) : (b))\n\ntypedef struct {\n    U32 cSize;\n    U32 dSize;\n    U32 checksum;\n} framelogEntry_t;\n\nstruct ZSTD_frameLog_s {\n    framelogEntry_t* entries;\n    U32 size;\n    U32 capacity;\n\n    int checksumFlag;\n\n    /* for use when streaming out the seek table */\n    U32 seekTablePos;\n    U32 seekTableIndex;\n} framelog_t;\n\nstruct ZSTD_seekable_CStream_s {\n    ZSTD_CStream* cstream;\n    ZSTD_frameLog framelog;\n\n    U32 frameCSize;\n    U32 frameDSize;\n\n    XXH64_state_t xxhState;\n\n    U32 maxFrameSize;\n\n    int writingSeekTable;\n};\n\nstatic size_t ZSTD_seekable_frameLog_allocVec(ZSTD_frameLog* fl)\n{\n    /* allocate some initial space */\n    size_t const FRAMELOG_STARTING_CAPACITY = 16;\n    fl->entries = (framelogEntry_t*)malloc(\n            sizeof(framelogEntry_t) * FRAMELOG_STARTING_CAPACITY);\n    if (fl->entries == NULL) return ERROR(memory_allocation);\n    fl->capacity = (U32)FRAMELOG_STARTING_CAPACITY;\n    return 0;\n}\n\nstatic size_t ZSTD_seekable_frameLog_freeVec(ZSTD_frameLog* fl)\n{\n    if (fl != NULL) free(fl->entries);\n    return 0;\n}\n\nZSTD_frameLog* ZSTD_seekable_createFrameLog(int checksumFlag)\n{\n    ZSTD_frameLog* const fl = (ZSTD_frameLog*)malloc(sizeof(ZSTD_frameLog));\n    if (fl == NULL) return NULL;\n\n    if (ZSTD_isError(ZSTD_seekable_frameLog_allocVec(fl))) {\n        free(fl);\n        return NULL;\n    }\n\n    fl->checksumFlag = checksumFlag;\n    fl->seekTablePos = 0;\n    fl->seekTableIndex = 0;\n    fl->size = 0;\n\n    return fl;\n}\n\nsize_t ZSTD_seekable_freeFrameLog(ZSTD_frameLog* fl)\n{\n    ZSTD_seekable_frameLog_freeVec(fl);\n    free(fl);\n    return 0;\n}\n\nZSTD_seekable_CStream* ZSTD_seekable_createCStream(void)\n{\n    ZSTD_seekable_CStream* const zcs = (ZSTD_seekable_CStream*)malloc(sizeof(ZSTD_seekable_CStream));\n    if (zcs == NULL) return NULL;\n\n    memset(zcs, 0, sizeof(*zcs));\n\n    zcs->cstream = ZSTD_createCStream();\n    if (zcs->cstream == NULL) goto failed1;\n\n    if (ZSTD_isError(ZSTD_seekable_frameLog_allocVec(&zcs->framelog))) goto failed2;\n\n    return zcs;\n\nfailed2:\n    ZSTD_freeCStream(zcs->cstream);\nfailed1:\n    free(zcs);\n    return NULL;\n}\n\nsize_t ZSTD_seekable_freeCStream(ZSTD_seekable_CStream* zcs)\n{\n    if (zcs == NULL) return 0; /* support free on null */\n    ZSTD_freeCStream(zcs->cstream);\n    ZSTD_seekable_frameLog_freeVec(&zcs->framelog);\n    free(zcs);\n    return 0;\n}\n\nsize_t ZSTD_seekable_initCStream(ZSTD_seekable_CStream* zcs,\n                                 int compressionLevel,\n                                 int checksumFlag,\n                                 unsigned maxFrameSize)\n{\n    zcs->framelog.size = 0;\n    zcs->frameCSize = 0;\n    zcs->frameDSize = 0;\n\n    /* make sure maxFrameSize has a reasonable value */\n    if (maxFrameSize > ZSTD_SEEKABLE_MAX_FRAME_DECOMPRESSED_SIZE) {\n        return ERROR(frameParameter_unsupported);\n    }\n\n    zcs->maxFrameSize = maxFrameSize ?\n                        maxFrameSize : ZSTD_SEEKABLE_MAX_FRAME_DECOMPRESSED_SIZE;\n\n    zcs->framelog.checksumFlag = checksumFlag;\n    if (zcs->framelog.checksumFlag) {\n        XXH64_reset(&zcs->xxhState, 0);\n    }\n\n    zcs->framelog.seekTablePos = 0;\n    zcs->framelog.seekTableIndex = 0;\n    zcs->writingSeekTable = 0;\n\n    return ZSTD_initCStream(zcs->cstream, compressionLevel);\n}\n\nsize_t ZSTD_seekable_logFrame(ZSTD_frameLog* fl,\n                              unsigned compressedSize,\n                              unsigned decompressedSize,\n                              unsigned checksum)\n{\n    if (fl->size == ZSTD_SEEKABLE_MAXFRAMES)\n        return ERROR(frameIndex_tooLarge);\n\n    /* grow the buffer if required */\n    if (fl->size == fl->capacity) {\n        /* exponential size increase for constant amortized runtime */\n        size_t const newCapacity = fl->capacity * 2;\n        framelogEntry_t* const newEntries = (framelogEntry_t*)realloc(fl->entries,\n                sizeof(framelogEntry_t) * newCapacity);\n\n        if (newEntries == NULL) return ERROR(memory_allocation);\n\n        fl->entries = newEntries;\n        assert(newCapacity <= UINT_MAX);\n        fl->capacity = (U32)newCapacity;\n    }\n\n    fl->entries[fl->size] = (framelogEntry_t){\n            compressedSize, decompressedSize, checksum\n    };\n    fl->size++;\n\n    return 0;\n}\n\nsize_t ZSTD_seekable_endFrame(ZSTD_seekable_CStream* zcs, ZSTD_outBuffer* output)\n{\n    size_t const prevOutPos = output->pos;\n    /* end the frame */\n    size_t ret = ZSTD_endStream(zcs->cstream, output);\n\n    zcs->frameCSize += (U32)(output->pos - prevOutPos);\n\n    /* need to flush before doing the rest */\n    if (ret) return ret;\n\n    /* frame done */\n\n    /* store the frame data for later */\n    ret = ZSTD_seekable_logFrame(\n            &zcs->framelog, zcs->frameCSize, zcs->frameDSize,\n            zcs->framelog.checksumFlag\n                    ? XXH64_digest(&zcs->xxhState) & 0xFFFFFFFFU\n                    : 0);\n    if (ret) return ret;\n\n    /* reset for the next frame */\n    zcs->frameCSize = 0;\n    zcs->frameDSize = 0;\n\n    ZSTD_CCtx_reset(zcs->cstream, ZSTD_reset_session_only);\n    if (zcs->framelog.checksumFlag) XXH64_reset(&zcs->xxhState, 0);\n\n    return 0;\n}\n\nsize_t ZSTD_seekable_compressStream(ZSTD_seekable_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input)\n{\n    const BYTE* const inBase = (const BYTE*) input->src + input->pos;\n    size_t inLen = input->size - input->pos;\n\n    assert(zcs->maxFrameSize < INT_MAX);\n    ZSTD_CCtx_setParameter(zcs->cstream, ZSTD_c_srcSizeHint, (int)zcs->maxFrameSize);\n    inLen = MIN(inLen, (size_t)(zcs->maxFrameSize - zcs->frameDSize));\n\n    /* if we haven't finished flushing the last frame, don't start writing a new one */\n    if (inLen > 0) {\n        ZSTD_inBuffer inTmp = { inBase, inLen, 0 };\n        size_t const prevOutPos = output->pos;\n\n        size_t const ret = ZSTD_compressStream(zcs->cstream, output, &inTmp);\n\n        if (zcs->framelog.checksumFlag) {\n            XXH64_update(&zcs->xxhState, inBase, inTmp.pos);\n        }\n\n        zcs->frameCSize += (U32)(output->pos - prevOutPos);\n        zcs->frameDSize += (U32)inTmp.pos;\n\n        input->pos += inTmp.pos;\n\n        if (ZSTD_isError(ret)) return ret;\n    }\n\n    if (zcs->maxFrameSize == zcs->frameDSize) {\n        /* log the frame and start over */\n        size_t const ret = ZSTD_seekable_endFrame(zcs, output);\n        if (ZSTD_isError(ret)) return ret;\n\n        /* get the client ready for the next frame */\n        return (size_t)zcs->maxFrameSize;\n    }\n\n    return (size_t)(zcs->maxFrameSize - zcs->frameDSize);\n}\n\nstatic inline size_t ZSTD_seekable_seekTableSize(const ZSTD_frameLog* fl)\n{\n    size_t const sizePerFrame = 8 + (fl->checksumFlag?4:0);\n    size_t const seekTableLen = ZSTD_SKIPPABLEHEADERSIZE +\n                                sizePerFrame * fl->size +\n                                ZSTD_seekTableFooterSize;\n\n    return seekTableLen;\n}\n\nstatic inline size_t ZSTD_stwrite32(ZSTD_frameLog* fl,\n                                    ZSTD_outBuffer* output, U32 const value,\n                                    U32 const offset)\n{\n    if (fl->seekTablePos < offset + 4) {\n        BYTE tmp[4]; /* so that we can work with buffers too small to write a whole word to */\n        size_t const lenWrite =\n                MIN(output->size - output->pos, offset + 4 - fl->seekTablePos);\n        MEM_writeLE32(tmp, value);\n        memcpy((BYTE*)output->dst + output->pos,\n               tmp + (fl->seekTablePos - offset), lenWrite);\n        output->pos += lenWrite;\n        fl->seekTablePos += (U32)lenWrite;\n\n        if (lenWrite < 4) return ZSTD_seekable_seekTableSize(fl) - fl->seekTablePos;\n    }\n    return 0;\n}\n\nsize_t ZSTD_seekable_writeSeekTable(ZSTD_frameLog* fl, ZSTD_outBuffer* output)\n{\n    /* seekTableIndex: the current index in the table and\n     * seekTableSize: the amount of the table written so far\n     *\n     * This function is written this way so that if it has to return early\n     * because of a small buffer, it can keep going where it left off.\n     */\n\n    size_t const sizePerFrame = 8 + (fl->checksumFlag?4:0);\n    size_t const seekTableLen = ZSTD_seekable_seekTableSize(fl);\n\n    CHECK_Z(ZSTD_stwrite32(fl, output, ZSTD_MAGIC_SKIPPABLE_START | 0xE, 0));\n    assert(seekTableLen <= (size_t)UINT_MAX);\n    CHECK_Z(ZSTD_stwrite32(fl, output, (U32)seekTableLen - ZSTD_SKIPPABLEHEADERSIZE, 4));\n\n    while (fl->seekTableIndex < fl->size) {\n        unsigned long long const start = ZSTD_SKIPPABLEHEADERSIZE + sizePerFrame * fl->seekTableIndex;\n        assert(start + 8 <= UINT_MAX);\n        CHECK_Z(ZSTD_stwrite32(fl, output,\n                               fl->entries[fl->seekTableIndex].cSize,\n                               (U32)start + 0));\n\n        CHECK_Z(ZSTD_stwrite32(fl, output,\n                               fl->entries[fl->seekTableIndex].dSize,\n                               (U32)start + 4));\n\n        if (fl->checksumFlag) {\n            CHECK_Z(ZSTD_stwrite32(\n                    fl, output, fl->entries[fl->seekTableIndex].checksum,\n                    (U32)start + 8));\n        }\n\n        fl->seekTableIndex++;\n    }\n\n    assert(seekTableLen <= UINT_MAX);\n    CHECK_Z(ZSTD_stwrite32(fl, output, fl->size,\n                           (U32)seekTableLen - ZSTD_seekTableFooterSize));\n\n    if (output->size - output->pos < 1) return seekTableLen - fl->seekTablePos;\n    if (fl->seekTablePos < seekTableLen - 4) {\n        BYTE const sfd = (BYTE)((fl->checksumFlag) << 7);\n\n        ((BYTE*)output->dst)[output->pos] = sfd;\n        output->pos++;\n        fl->seekTablePos++;\n    }\n\n    CHECK_Z(ZSTD_stwrite32(fl, output, ZSTD_SEEKABLE_MAGICNUMBER,\n                           (U32)seekTableLen - 4));\n\n    if (fl->seekTablePos != seekTableLen) return ERROR(GENERIC);\n    return 0;\n}\n\nsize_t ZSTD_seekable_endStream(ZSTD_seekable_CStream* zcs, ZSTD_outBuffer* output)\n{\n    if (!zcs->writingSeekTable) {\n        const size_t endFrame = ZSTD_seekable_endFrame(zcs, output);\n        if (ZSTD_isError(endFrame)) return endFrame;\n        /* return an accurate size hint */\n        if (endFrame) return endFrame + ZSTD_seekable_seekTableSize(&zcs->framelog);\n    }\n\n    zcs->writingSeekTable = 1;\n\n    return ZSTD_seekable_writeSeekTable(&zcs->framelog, output);\n}\n"
  },
  {
    "path": "contrib/seekable_format/zstdseek_decompress.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* *********************************************************\n*  Turn on Large Files support (>4GB) for 32-bit Linux/Unix\n***********************************************************/\n#if !defined(__64BIT__) || defined(__MINGW32__)       /* No point defining Large file for 64 bit but MinGW-w64 requires it */\n#  if !defined(_FILE_OFFSET_BITS)\n#    define _FILE_OFFSET_BITS 64                      /* turn off_t into a 64-bit type for ftello, fseeko */\n#  endif\n#  if !defined(_LARGEFILE_SOURCE)                     /* obsolete macro, replaced with _FILE_OFFSET_BITS */\n#    define _LARGEFILE_SOURCE 1                       /* Large File Support extension (LFS) - fseeko, ftello */\n#  endif\n#  if defined(_AIX) || defined(__hpux)\n#    define _LARGE_FILES                              /* Large file support on 32-bits AIX and HP-UX */\n#  endif\n#endif\n\n/* ************************************************************\n*  Detect POSIX version\n*  PLATFORM_POSIX_VERSION = 0 for non-Unix e.g. Windows\n*  PLATFORM_POSIX_VERSION = 1 for Unix-like but non-POSIX\n*  PLATFORM_POSIX_VERSION > 1 is equal to found _POSIX_VERSION\n*  Value of PLATFORM_POSIX_VERSION can be forced on command line\n***************************************************************/\n#ifndef PLATFORM_POSIX_VERSION\n\n#  if (defined(__APPLE__) && defined(__MACH__)) || defined(__SVR4) || defined(_AIX) || defined(__hpux) /* POSIX.1-2001 (SUSv3) conformant */ \\\n     || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)  /* BSD distros */\n     /* exception rule : force posix version to 200112L,\n      * note: it's better to use unistd.h's _POSIX_VERSION whenever possible */\n#    define PLATFORM_POSIX_VERSION 200112L\n\n/* try to determine posix version through official unistd.h's _POSIX_VERSION (https://pubs.opengroup.org/onlinepubs/7908799/xsh/unistd.h.html).\n * note : there is no simple way to know in advance if <unistd.h> is present or not on target system,\n * Posix specification mandates its presence and its content, but target system must respect this spec.\n * It's necessary to _not_ #include <unistd.h> whenever target OS is not unix-like\n * otherwise it will block preprocessing stage.\n * The following list of build macros tries to \"guess\" if target OS is likely unix-like, and therefore can #include <unistd.h>\n */\n#  elif !defined(_WIN32) \\\n     && ( defined(__unix__) || defined(__unix) \\\n       || defined(__midipix__) || defined(__VMS) || defined(__HAIKU__) )\n\n#    if defined(__linux__) || defined(__linux) || defined(__CYGWIN__)\n#      ifndef _POSIX_C_SOURCE\n#        define _POSIX_C_SOURCE 200809L  /* feature test macro : https://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html */\n#      endif\n#    endif\n#    include <unistd.h>  /* declares _POSIX_VERSION */\n#    if defined(_POSIX_VERSION)  /* POSIX compliant */\n#      define PLATFORM_POSIX_VERSION _POSIX_VERSION\n#    else\n#      define PLATFORM_POSIX_VERSION 1\n#    endif\n\n#    ifdef __UCLIBC__\n#     ifndef __USE_MISC\n#      define __USE_MISC /* enable st_mtim on uclibc */\n#     endif\n#    endif\n\n#  else  /* non-unix target platform (like Windows) */\n#    define PLATFORM_POSIX_VERSION 0\n#  endif\n\n#endif   /* PLATFORM_POSIX_VERSION */\n\n\n/* ************************************************************\n* Avoid fseek()'s 2GiB barrier with MSVC, macOS, *BSD, MinGW\n***************************************************************/\n#if defined(LIBC_NO_FSEEKO)\n/* Some older libc implementations don't include these functions (e.g. Bionic < 24) */\n#   define LONG_SEEK fseek\n#elif defined(_MSC_VER) && _MSC_VER >= 1400\n#   define LONG_SEEK _fseeki64\n#elif !defined(__64BIT__) && (PLATFORM_POSIX_VERSION >= 200112L) /* No point defining Large file for 64 bit */\n#   define LONG_SEEK fseeko\n#elif defined(__MINGW32__) && !defined(__STRICT_ANSI__) && !defined(__NO_MINGW_LFS) && defined(__MSVCRT__)\n#   define LONG_SEEK fseeko64\n#elif defined(_WIN32) && !defined(__DJGPP__)\n#   include <windows.h>\n    static int LONG_SEEK(FILE* file, __int64 offset, int origin) {\n        LARGE_INTEGER off;\n        DWORD method;\n        off.QuadPart = offset;\n        if (origin == SEEK_END)\n            method = FILE_END;\n        else if (origin == SEEK_CUR)\n            method = FILE_CURRENT;\n        else\n            method = FILE_BEGIN;\n\n        if (SetFilePointerEx((HANDLE) _get_osfhandle(_fileno(file)), off, NULL, method))\n            return 0;\n        else\n            return -1;\n    }\n#else\n#   define LONG_SEEK fseek\n#endif\n\n#include <stdlib.h>  /* malloc, free */\n#include <stdio.h>   /* FILE* */\n#include <limits.h>  /* UNIT_MAX */\n#include <assert.h>\n\n#define XXH_STATIC_LINKING_ONLY\n#include \"xxhash.h\"\n\n#define ZSTD_STATIC_LINKING_ONLY\n#include \"zstd.h\"\n#include \"zstd_errors.h\"\n#include \"mem.h\"\n#include \"zstd_seekable.h\"\n\n#undef ERROR\n#define ERROR(name) ((size_t)-ZSTD_error_##name)\n\n#define CHECK_IO(f) { int const errcod = (f); if (errcod < 0) return ERROR(seekableIO); }\n\n#undef MIN\n#undef MAX\n#define MIN(a, b) ((a) < (b) ? (a) : (b))\n#define MAX(a, b) ((a) > (b) ? (a) : (b))\n\n#define ZSTD_SEEKABLE_NO_OUTPUT_PROGRESS_MAX 16\n\n/* Special-case callbacks for FILE* and in-memory modes, so that we can treat\n * them the same way as the advanced API */\nstatic int ZSTD_seekable_read_FILE(void* opaque, void* buffer, size_t n)\n{\n    size_t const result = fread(buffer, 1, n, (FILE*)opaque);\n    if (result != n) {\n        return -1;\n    }\n    return 0;\n}\n\nstatic int ZSTD_seekable_seek_FILE(void* opaque, long long offset, int origin)\n{\n    int const ret = LONG_SEEK((FILE*)opaque, offset, origin);\n    if (ret) return ret;\n    return fflush((FILE*)opaque);\n}\n\ntypedef struct {\n    const void *ptr;\n    size_t size;\n    size_t pos;\n} buffWrapper_t;\n\nstatic int ZSTD_seekable_read_buff(void* opaque, void* buffer, size_t n)\n{\n    buffWrapper_t* const buff = (buffWrapper_t*)opaque;\n    assert(buff != NULL);\n    if (buff->pos + n > buff->size) return -1;\n    memcpy(buffer, (const BYTE*)buff->ptr + buff->pos, n);\n    buff->pos += n;\n    return 0;\n}\n\nstatic int ZSTD_seekable_seek_buff(void* opaque, long long offset, int origin)\n{\n    buffWrapper_t* const buff = (buffWrapper_t*) opaque;\n    unsigned long long newOffset;\n    assert(buff != NULL);\n    switch (origin) {\n    case SEEK_SET:\n        assert(offset >= 0);\n        newOffset = (unsigned long long)offset;\n        break;\n    case SEEK_CUR:\n        newOffset = (unsigned long long)((long long)buff->pos + offset);\n        break;\n    case SEEK_END:\n        newOffset = (unsigned long long)((long long)buff->size + offset);\n        break;\n    default:\n        assert(0);  /* not possible */\n    }\n    if (newOffset > buff->size) {\n        return -1;\n    }\n    buff->pos = newOffset;\n    return 0;\n}\n\ntypedef struct {\n    U64 cOffset;\n    U64 dOffset;\n    U32 checksum;\n} seekEntry_t;\n\nstruct ZSTD_seekTable_s {\n    seekEntry_t* entries;\n    size_t tableLen;\n\n    int checksumFlag;\n};\n\n#define SEEKABLE_BUFF_SIZE ZSTD_BLOCKSIZE_MAX\n\nstruct ZSTD_seekable_s {\n    ZSTD_DStream* dstream;\n    ZSTD_seekTable seekTable;\n    ZSTD_seekable_customFile src;\n\n    U64 decompressedOffset;\n    U32 curFrame;\n\n    BYTE inBuff[SEEKABLE_BUFF_SIZE]; /* need to do our own input buffering */\n    BYTE outBuff[SEEKABLE_BUFF_SIZE]; /* so we can efficiently decompress the\n                                         starts of chunks before we get to the\n                                         desired section */\n    ZSTD_inBuffer in; /* maintain continuity across ZSTD_seekable_decompress operations */\n    buffWrapper_t buffWrapper; /* for `src.opaque` in in-memory mode */\n\n    XXH64_state_t xxhState;\n};\n\nZSTD_seekable* ZSTD_seekable_create(void)\n{\n    ZSTD_seekable* const zs = (ZSTD_seekable*)malloc(sizeof(ZSTD_seekable));\n    if (zs == NULL) return NULL;\n\n    /* also initializes stage to zsds_init */\n    memset(zs, 0, sizeof(*zs));\n\n    zs->dstream = ZSTD_createDStream();\n    if (zs->dstream == NULL) {\n        free(zs);\n        return NULL;\n    }\n\n    return zs;\n}\n\nsize_t ZSTD_seekable_free(ZSTD_seekable* zs)\n{\n    if (zs == NULL) return 0; /* support free on null */\n    ZSTD_freeDStream(zs->dstream);\n    free(zs->seekTable.entries);\n    free(zs);\n    return 0;\n}\n\nZSTD_seekTable* ZSTD_seekTable_create_fromSeekable(const ZSTD_seekable* zs)\n{\n    assert(zs != NULL);\n    if (zs->seekTable.entries == NULL) return NULL;\n    ZSTD_seekTable* const st = (ZSTD_seekTable*)malloc(sizeof(ZSTD_seekTable));\n    if (st==NULL) return NULL;\n\n    st->checksumFlag = zs->seekTable.checksumFlag;\n    st->tableLen = zs->seekTable.tableLen;\n\n    /* Allocate an extra entry at the end to match logic of initial allocation */\n    size_t const entriesSize = sizeof(seekEntry_t) * (zs->seekTable.tableLen + 1);\n    seekEntry_t* const entries = (seekEntry_t*)malloc(entriesSize);\n    if (entries==NULL) {\n        free(st);\n        return NULL;\n    }\n\n    memcpy(entries, zs->seekTable.entries, entriesSize);\n    st->entries = entries;\n    return st;\n}\n\nsize_t ZSTD_seekTable_free(ZSTD_seekTable* st)\n{\n    if (st == NULL) return 0; /* support free on null */\n    free(st->entries);\n    free(st);\n    return 0;\n}\n\n/** ZSTD_seekable_offsetToFrameIndex() :\n *  Performs a binary search to find the last frame with a decompressed offset\n *  <= pos\n *  @return : the frame's index */\nunsigned ZSTD_seekable_offsetToFrameIndex(const ZSTD_seekable* zs, unsigned long long pos)\n{\n    return ZSTD_seekTable_offsetToFrameIndex(&zs->seekTable, pos);\n}\n\nunsigned ZSTD_seekTable_offsetToFrameIndex(const ZSTD_seekTable* st, unsigned long long pos)\n{\n    U32 lo = 0;\n    U32 hi = (U32)st->tableLen;\n    assert(st->tableLen <= UINT_MAX);\n\n    if (pos >= st->entries[st->tableLen].dOffset) {\n        return (unsigned)st->tableLen;\n    }\n\n    while (lo + 1 < hi) {\n        U32 const mid = lo + ((hi - lo) >> 1);\n        if (st->entries[mid].dOffset <= pos) {\n            lo = mid;\n        } else {\n            hi = mid;\n        }\n    }\n    return lo;\n}\n\nunsigned ZSTD_seekable_getNumFrames(const ZSTD_seekable* zs)\n{\n    return ZSTD_seekTable_getNumFrames(&zs->seekTable);\n}\n\nunsigned ZSTD_seekTable_getNumFrames(const ZSTD_seekTable* st)\n{\n    assert(st->tableLen <= UINT_MAX);\n    return (unsigned)st->tableLen;\n}\n\nunsigned long long ZSTD_seekable_getFrameCompressedOffset(const ZSTD_seekable* zs, unsigned frameIndex)\n{\n    return ZSTD_seekTable_getFrameCompressedOffset(&zs->seekTable, frameIndex);\n}\n\nunsigned long long ZSTD_seekTable_getFrameCompressedOffset(const ZSTD_seekTable* st, unsigned frameIndex)\n{\n    if (frameIndex >= st->tableLen) return ZSTD_SEEKABLE_FRAMEINDEX_TOOLARGE;\n    return st->entries[frameIndex].cOffset;\n}\n\nunsigned long long ZSTD_seekable_getFrameDecompressedOffset(const ZSTD_seekable* zs, unsigned frameIndex)\n{\n    return ZSTD_seekTable_getFrameDecompressedOffset(&zs->seekTable, frameIndex);\n}\n\nunsigned long long ZSTD_seekTable_getFrameDecompressedOffset(const ZSTD_seekTable* st, unsigned frameIndex)\n{\n    if (frameIndex >= st->tableLen) return ZSTD_SEEKABLE_FRAMEINDEX_TOOLARGE;\n    return st->entries[frameIndex].dOffset;\n}\n\nsize_t ZSTD_seekable_getFrameCompressedSize(const ZSTD_seekable* zs, unsigned frameIndex)\n{\n    return ZSTD_seekTable_getFrameCompressedSize(&zs->seekTable, frameIndex);\n}\n\nsize_t ZSTD_seekTable_getFrameCompressedSize(const ZSTD_seekTable* st, unsigned frameIndex)\n{\n    if (frameIndex >= st->tableLen) return ERROR(frameIndex_tooLarge);\n    return st->entries[frameIndex + 1].cOffset -\n           st->entries[frameIndex].cOffset;\n}\n\nsize_t ZSTD_seekable_getFrameDecompressedSize(const ZSTD_seekable* zs, unsigned frameIndex)\n{\n    return ZSTD_seekTable_getFrameDecompressedSize(&zs->seekTable, frameIndex);\n}\n\nsize_t ZSTD_seekTable_getFrameDecompressedSize(const ZSTD_seekTable* st, unsigned frameIndex)\n{\n    if (frameIndex > st->tableLen) return ERROR(frameIndex_tooLarge);\n    return st->entries[frameIndex + 1].dOffset -\n           st->entries[frameIndex].dOffset;\n}\n\nstatic size_t ZSTD_seekable_loadSeekTable(ZSTD_seekable* zs)\n{\n    int checksumFlag;\n    ZSTD_seekable_customFile src = zs->src;\n    /* read the footer, fixed size */\n    CHECK_IO(src.seek(src.opaque, -(int)ZSTD_seekTableFooterSize, SEEK_END));\n    CHECK_IO(src.read(src.opaque, zs->inBuff, ZSTD_seekTableFooterSize));\n\n    if (MEM_readLE32(zs->inBuff + 5) != ZSTD_SEEKABLE_MAGICNUMBER) {\n        return ERROR(prefix_unknown);\n    }\n\n    {   BYTE const sfd = zs->inBuff[4];\n        checksumFlag = sfd >> 7;\n\n        /* check reserved bits */\n        if ((sfd >> 2) & 0x1f) {\n            return ERROR(corruption_detected);\n    }   }\n\n    {   U32 const numFrames = MEM_readLE32(zs->inBuff);\n        U32 const sizePerEntry = 8 + (checksumFlag?4:0);\n        U32 const tableSize = sizePerEntry * numFrames;\n        U32 const frameSize = tableSize + ZSTD_seekTableFooterSize + ZSTD_SKIPPABLEHEADERSIZE;\n\n        U32 remaining = frameSize - ZSTD_seekTableFooterSize; /* don't need to re-read footer */\n        {   U32 const toRead = MIN(remaining, SEEKABLE_BUFF_SIZE);\n            CHECK_IO(src.seek(src.opaque, -(S64)frameSize, SEEK_END));\n            CHECK_IO(src.read(src.opaque, zs->inBuff, toRead));\n            remaining -= toRead;\n        }\n\n        if (MEM_readLE32(zs->inBuff) != (ZSTD_MAGIC_SKIPPABLE_START | 0xE)) {\n            return ERROR(prefix_unknown);\n        }\n        if (MEM_readLE32(zs->inBuff+4) + ZSTD_SKIPPABLEHEADERSIZE != frameSize) {\n            return ERROR(prefix_unknown);\n        }\n\n        {   /* Allocate an extra entry at the end so that we can do size\n             * computations on the last element without special case */\n            seekEntry_t* const entries = (seekEntry_t*)malloc(sizeof(seekEntry_t) * (numFrames + 1));\n\n            U32 idx = 0;\n            U32 pos = 8;\n\n            U64 cOffset = 0;\n            U64 dOffset = 0;\n\n            if (entries == NULL) return ERROR(memory_allocation);\n\n            /* compute cumulative positions */\n            for (; idx < numFrames; idx++) {\n                if (pos + sizePerEntry > SEEKABLE_BUFF_SIZE) {\n                    U32 const offset = SEEKABLE_BUFF_SIZE - pos;\n                    U32 const toRead = MIN(remaining, SEEKABLE_BUFF_SIZE - offset);\n                    memmove(zs->inBuff, zs->inBuff + pos, offset); /* move any data we haven't read yet */\n                    CHECK_IO(src.read(src.opaque, zs->inBuff+offset, toRead));\n                    remaining -= toRead;\n                    pos = 0;\n                }\n                entries[idx].cOffset = cOffset;\n                entries[idx].dOffset = dOffset;\n\n                cOffset += MEM_readLE32(zs->inBuff + pos);\n                pos += 4;\n                dOffset += MEM_readLE32(zs->inBuff + pos);\n                pos += 4;\n                if (checksumFlag) {\n                    entries[idx].checksum = MEM_readLE32(zs->inBuff + pos);\n                    pos += 4;\n                }\n            }\n            entries[numFrames].cOffset = cOffset;\n            entries[numFrames].dOffset = dOffset;\n\n            zs->seekTable.entries = entries;\n            zs->seekTable.tableLen = numFrames;\n            zs->seekTable.checksumFlag = checksumFlag;\n            return 0;\n        }\n    }\n}\n\nsize_t ZSTD_seekable_initBuff(ZSTD_seekable* zs, const void* src, size_t srcSize)\n{\n    zs->buffWrapper = (buffWrapper_t){src, srcSize, 0};\n    {   ZSTD_seekable_customFile srcFile = {&zs->buffWrapper,\n                                            &ZSTD_seekable_read_buff,\n                                            &ZSTD_seekable_seek_buff};\n        return ZSTD_seekable_initAdvanced(zs, srcFile); }\n}\n\nsize_t ZSTD_seekable_initFile(ZSTD_seekable* zs, FILE* src)\n{\n    ZSTD_seekable_customFile srcFile = {src, &ZSTD_seekable_read_FILE,\n                                        &ZSTD_seekable_seek_FILE};\n    return ZSTD_seekable_initAdvanced(zs, srcFile);\n}\n\nsize_t ZSTD_seekable_initAdvanced(ZSTD_seekable* zs, ZSTD_seekable_customFile src)\n{\n    zs->src = src;\n\n    {   const size_t seekTableInit = ZSTD_seekable_loadSeekTable(zs);\n        if (ZSTD_isError(seekTableInit)) return seekTableInit; }\n\n    zs->decompressedOffset = (U64)-1;\n    zs->curFrame = (U32)-1;\n\n    {   const size_t dstreamInit = ZSTD_initDStream(zs->dstream);\n        if (ZSTD_isError(dstreamInit)) return dstreamInit; }\n    return 0;\n}\n\nsize_t ZSTD_seekable_decompress(ZSTD_seekable* zs, void* dst, size_t len, unsigned long long offset)\n{\n    unsigned long long const eos = zs->seekTable.entries[zs->seekTable.tableLen].dOffset;\n    if (offset + len > eos) {\n        len = eos - offset;\n    }\n\n    U32 targetFrame = ZSTD_seekable_offsetToFrameIndex(zs, offset);\n    U32 noOutputProgressCount = 0;\n    size_t srcBytesRead = 0;\n    do {\n        /* check if we can continue from a previous decompress job */\n        if (targetFrame != zs->curFrame || offset < zs->decompressedOffset) {\n            zs->decompressedOffset = zs->seekTable.entries[targetFrame].dOffset;\n            zs->curFrame = targetFrame;\n\n            assert(zs->seekTable.entries[targetFrame].cOffset < LLONG_MAX);\n            CHECK_IO(zs->src.seek(zs->src.opaque,\n                                  (long long)zs->seekTable.entries[targetFrame].cOffset,\n                                  SEEK_SET));\n            zs->in = (ZSTD_inBuffer){zs->inBuff, 0, 0};\n            XXH64_reset(&zs->xxhState, 0);\n            ZSTD_DCtx_reset(zs->dstream, ZSTD_reset_session_only);\n            if (zs->buffWrapper.size && srcBytesRead > zs->buffWrapper.size) {\n                return ERROR(seekableIO);\n            }\n        }\n\n        while (zs->decompressedOffset < offset + len) {\n            size_t toRead;\n            ZSTD_outBuffer outTmp;\n            size_t prevOutPos;\n            size_t prevInPos;\n            size_t forwardProgress;\n            if (zs->decompressedOffset < offset) {\n                /* dummy decompressions until we get to the target offset */\n                outTmp = (ZSTD_outBuffer){zs->outBuff, (size_t) (MIN(SEEKABLE_BUFF_SIZE, offset - zs->decompressedOffset)), 0};\n            } else {\n                outTmp = (ZSTD_outBuffer){dst, len, (size_t) (zs->decompressedOffset - offset)};\n            }\n\n            prevOutPos = outTmp.pos;\n            prevInPos = zs->in.pos;\n            toRead = ZSTD_decompressStream(zs->dstream, &outTmp, &zs->in);\n            if (ZSTD_isError(toRead)) {\n                return toRead;\n            }\n\n            if (zs->seekTable.checksumFlag) {\n                XXH64_update(&zs->xxhState, (BYTE*)outTmp.dst + prevOutPos,\n                             outTmp.pos - prevOutPos);\n            }\n            forwardProgress = outTmp.pos - prevOutPos;\n            if (forwardProgress == 0) {\n                if (noOutputProgressCount++ > ZSTD_SEEKABLE_NO_OUTPUT_PROGRESS_MAX) {\n                    return ERROR(seekableIO);\n                }\n            } else {\n                noOutputProgressCount = 0;\n            }\n            zs->decompressedOffset += forwardProgress;\n            srcBytesRead += zs->in.pos - prevInPos;\n\n            if (toRead == 0) {\n                /* frame complete */\n\n                /* verify checksum */\n                if (zs->seekTable.checksumFlag &&\n                    (XXH64_digest(&zs->xxhState) & 0xFFFFFFFFU) !=\n                            zs->seekTable.entries[targetFrame].checksum) {\n                    return ERROR(corruption_detected);\n                }\n\n                if (zs->decompressedOffset < offset + len) {\n                    /* go back to the start and force a reset of the stream */\n                    targetFrame = ZSTD_seekable_offsetToFrameIndex(zs, zs->decompressedOffset);\n                    /* in this case it will fail later with corruption_detected, since last block does not have checksum */\n                    assert(targetFrame != zs->seekTable.tableLen);\n                }\n                break;\n            }\n\n            /* read in more data if we're done with this buffer */\n            if (zs->in.pos == zs->in.size) {\n                toRead = MIN(toRead, SEEKABLE_BUFF_SIZE);\n                CHECK_IO(zs->src.read(zs->src.opaque, zs->inBuff, toRead));\n                zs->in.size = toRead;\n                zs->in.pos = 0;\n            }\n        }  /* while (zs->decompressedOffset < offset + len) */\n    } while (zs->decompressedOffset != offset + len);\n\n    return len;\n}\n\nsize_t ZSTD_seekable_decompressFrame(ZSTD_seekable* zs, void* dst, size_t dstSize, unsigned frameIndex)\n{\n    if (frameIndex >= zs->seekTable.tableLen) {\n        return ERROR(frameIndex_tooLarge);\n    }\n\n    {   size_t const decompressedSize =\n                zs->seekTable.entries[frameIndex + 1].dOffset -\n                zs->seekTable.entries[frameIndex].dOffset;\n        if (dstSize < decompressedSize) {\n            return ERROR(dstSize_tooSmall);\n        }\n        return ZSTD_seekable_decompress(\n                zs, dst, decompressedSize,\n                zs->seekTable.entries[frameIndex].dOffset);\n    }\n}\n"
  },
  {
    "path": "contrib/seqBench/Makefile",
    "content": "# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# ################################################################\n\nPROGDIR = ../../programs\nLIBDIR  = ../../lib\n\nLIBZSTD = $(LIBDIR)/libzstd.a\n\nCPPFLAGS+= -I$(LIBDIR) -I$(LIBDIR)/common -I$(LIBDIR)/dictBuilder -I$(PROGDIR)\n\nCFLAGS  ?= -O3 -g\nCFLAGS  += -std=gnu99\nDEBUGFLAGS= -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \\\n            -Wstrict-aliasing=1 -Wswitch-enum \\\n            -Wstrict-prototypes -Wundef -Wpointer-arith \\\n            -Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \\\n            -Wredundant-decls\nCFLAGS  += $(DEBUGFLAGS) $(MOREFLAGS)\n\n\ndefault: seqBench\n\nall : seqBench\n\nseqBench: util.o timefn.o benchfn.o datagen.o xxhash.o seqBench.c $(LIBZSTD)\n\t$(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@\n\n.PHONY: $(LIBZSTD)\n$(LIBZSTD):\n\t$(MAKE) -C $(LIBDIR) libzstd.a CFLAGS=\"$(CFLAGS)\"\n\nbenchfn.o: $(PROGDIR)/benchfn.c\n\t$(CC) $(CPPFLAGS) $(CFLAGS) $^ -c\n\ntimefn.o: $(PROGDIR)/timefn.c\n\t$(CC) $(CPPFLAGS) $(CFLAGS) $^ -c\n\ndatagen.o: $(PROGDIR)/datagen.c\n\t$(CC) $(CPPFLAGS) $(CFLAGS) $^ -c\n\nutil.o: $(PROGDIR)/util.c\n\t$(CC) $(CPPFLAGS) $(CFLAGS) $^ -c\n\n\nxxhash.o : $(LIBDIR)/common/xxhash.c\n\t$(CC) $(CPPFLAGS) $(CFLAGS) $^ -c\n\n\nclean:\n\t$(RM) *.o\n\t$(MAKE) -C $(LIBDIR) clean > /dev/null\n\t$(RM) seqBench\n"
  },
  {
    "path": "contrib/seqBench/seqBench.c",
    "content": "#define ZSTD_STATIC_LINKING_ONLY\n#include <zstd.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <assert.h>\n#include <string.h>\n\nint main(int argc, char *argv[]) {\n    ZSTD_CCtx* zc = ZSTD_createCCtx();\n\n    if (argc != 2) {\n        printf(\"Usage: seqBench <file>\\n\"); // TODO provide the block delim option here\n        return 1;\n    }\n\n    FILE *f = fopen(argv[1], \"rb\");\n    fseek(f, 0, SEEK_END);\n    long inBufSize = ftell(f);\n    fseek(f, 0, SEEK_SET);\n\n    char *inBuf = malloc(inBufSize + 1);\n    fread(inBuf, inBufSize, 1, f);\n    fclose(f);\n\n    size_t seqsSize = ZSTD_sequenceBound(inBufSize);\n    ZSTD_Sequence *seqs = (ZSTD_Sequence*)malloc(seqsSize * sizeof(ZSTD_Sequence));\n    char *outBuf = malloc(ZSTD_compressBound(inBufSize));\n\n    ZSTD_generateSequences(zc, seqs, seqsSize, inBuf, inBufSize);\n    ZSTD_CCtx_setParameter(zc, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters);\n    size_t outBufSize = ZSTD_compressSequences(zc, outBuf, inBufSize, seqs, seqsSize, inBuf, inBufSize);\n    if (ZSTD_isError(outBufSize)) {\n        printf(\"ERROR: %lu\\n\", outBufSize);\n        return 1;\n    }\n\n    char *validationBuf = malloc(inBufSize);\n    ZSTD_decompress(validationBuf, inBufSize, outBuf, outBufSize);\n\n    if (memcmp(inBuf, validationBuf, inBufSize) == 0) {\n        printf(\"Compression and decompression were successful!\\n\");\n    } else {\n        printf(\"ERROR: input and validation buffers don't match!\\n\");\n        for (int i = 0; i < inBufSize; i++) {\n            if (inBuf[i] != validationBuf[i]) {\n                printf(\"First bad index: %d\\n\", i);\n                break;\n            }\n        }\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "contrib/snap/snapcraft.yaml",
    "content": "name: zstd\nversion: git\nsummary: Zstandard - Fast real-time compression algorithm\ndescription: |\n  Zstandard, or zstd as short version, is a fast lossless compression\n  algorithm, targeting real-time compression scenarios at zlib-level and better\n  compression ratios. It's backed by a very fast entropy stage, provided by\n  Huff0 and FSE library\n\ngrade: devel # must be 'stable' to release into candidate/stable channels\nconfinement: devmode # use 'strict' once you have the right plugs and slots\n\napps:\n  zstd:\n    command: usr/local/bin/zstd\n    plugs: [home, removable-media]\n  zstdgrep:\n    command: usr/local/bin/zstdgrep\n    plugs: [home, removable-media]\n  zstdless:\n    command: usr/local/bin/zstdless\n    plugs: [home, removable-media]\n\nparts:\n  zstd:\n    source: .\n    plugin: make\n    build-packages: [g++]\n"
  },
  {
    "path": "doc/README.md",
    "content": "Zstandard Documentation\n=======================\n\nThis directory contains material defining the Zstandard format,\nas well as detailed instructions to use `zstd` library.\n\n__`zstd_manual.html`__ : Documentation of `zstd.h` API, in html format.\nUnfortunately, Github doesn't display `html` files in parsed format, just as source code.\nFor a readable display of html API documentation of latest release,\nuse this link: [https://raw.githack.com/facebook/zstd/release/doc/zstd_manual.html](https://raw.githack.com/facebook/zstd/release/doc/zstd_manual.html) .\n\n__`zstd_compression_format.md`__ : This document defines the Zstandard compression format.\nCompliant decoders must adhere to this document,\nand compliant encoders must generate data that follows it.\n\nShould you look for resources to develop your own port of Zstandard algorithm,\nyou may find the following resources useful :\n\n__`educational_decoder`__ : This directory contains an implementation of a Zstandard decoder,\ncompliant with the Zstandard compression format.\nIt can be used, for example, to better understand the format,\nor as the basis for a separate implementation of Zstandard decoder.\n\n[__`decode_corpus`__](https://github.com/facebook/zstd/tree/dev/tests#decodecorpus---tool-to-generate-zstandard-frames-for-decoder-testing) :\nThis tool, stored in `/tests` directory, is able to generate random valid frames,\nwhich is useful if you wish to test your decoder and verify it fully supports the specification.\n"
  },
  {
    "path": "doc/decompressor_errata.md",
    "content": "Decompressor Errata\n===================\n\nThis document captures known decompressor bugs, where the decompressor rejects a valid zstd frame.\nEach entry will contain:\n1. The last affected decompressor versions.\n2. The decompressor components affected.\n2. Whether the compressed frame could ever be produced by the reference compressor.\n3. An example frame (hexadecimal string when it can be short enough, link to golden file otherwise)\n4. A description of the bug.\n\nThe document is in reverse chronological order, with the bugs that affect the most recent zstd decompressor versions listed first.\n\n\nNo sequence using the 2-bytes format\n------------------------------------------------\n\n**Last affected version**: v1.5.5\n\n**Affected decompressor component(s)**: Library & CLI\n\n**Produced by the reference compressor**: No\n\n**Example Frame**: see zstd/tests/golden-decompression/zeroSeq_2B.zst\n\nThe zstd decoder incorrectly expects FSE tables when there are 0 sequences present in the block\nif the value 0 is encoded using the 2-bytes format.\nInstead, it should immediately end the sequence section, and move on to next block.\n\nThis situation was never generated by the reference compressor,\nbecause representing 0 sequences with the 2-bytes format is inefficient\n(the 1-byte format is always used in this case).\n\n\nCompressed block with a size of exactly 128 KB\n------------------------------------------------\n\n**Last affected version**: v1.5.2\n\n**Affected decompressor component(s)**: Library & CLI\n\n**Produced by the reference compressor**: No\n\n**Example Frame**: see zstd/tests/golden-decompression/block-128k.zst\n\nThe zstd decoder incorrectly rejected blocks of type `Compressed_Block` when their size was exactly 128 KB.\nNote that `128 KB - 1` was accepted, and `128 KB + 1` is forbidden by the spec.\n\nThis type of block was never generated by the reference compressor.\n\nThese blocks used to be disallowed by the spec up until spec version 0.3.2 when the restriction was lifted by [PR#1689](https://github.com/facebook/zstd/pull/1689).\n\n> A Compressed_Block has the extra restriction that Block_Size is always strictly less than the decompressed size. If this condition cannot be respected, the block must be sent uncompressed instead (Raw_Block).\n\n\nCompressed block with 0 literals and 0 sequences\n------------------------------------------------\n\n**Last affected version**: v1.5.2\n\n**Affected decompressor component(s)**: Library & CLI\n\n**Produced by the reference compressor**: No\n\n**Example Frame**: `28b5 2ffd 2000 1500 0000 00`\n\nThe zstd decoder incorrectly rejected blocks of type `Compressed_Block` that encodes literals as `Raw_Literals_Block` with no literals, and has no sequences.\n\nThis type of block was never generated by the reference compressor.\n\nAdditionally, these blocks were disallowed by the spec up until spec version 0.3.2 when the restriction was lifted by [PR#1689](https://github.com/facebook/zstd/pull/1689).\n\n> A Compressed_Block has the extra restriction that Block_Size is always strictly less than the decompressed size. If this condition cannot be respected, the block must be sent uncompressed instead (Raw_Block).\n\n\nFirst block is RLE block\n------------------------\n\n**Last affected version**: v1.4.3\n\n**Affected decompressor component(s)**: CLI only\n\n**Produced by the reference compressor**: No\n\n**Example Frame**: `28b5 2ffd a001 0002 0002 0010 000b 0000 00`\n\nThe zstd CLI decompressor rejected cases where the first block was an RLE block whose `Block_Size` is 131072, and the frame contains more than one block.\nThis only affected the zstd CLI, and not the library.\n\nThe example is an RLE block with 131072 bytes, followed by a second RLE block with 1 byte.\n\nThe compressor currently works around this limitation by explicitly avoiding producing RLE blocks as the first\nblock.\n\nhttps://github.com/facebook/zstd/blob/8814aa5bfa74f05a86e55e9d508da177a893ceeb/lib/compress/zstd_compress.c#L3527-L3535\n\n\nTiny FSE Table & Block\n----------------------\n\n**Last affected version**: v1.3.4\n\n**Affected decompressor component(s)**: Library & CLI\n\n**Produced by the reference compressor**: Possibly until version v1.3.4, but probably never\n\n**Example Frame**: `28b5 2ffd 2027 c500 0080 f3f1 f0ec ebc6 c5c7 f09d 4300 0000 e0e0 0658 0100 603e 52`\n\nThe zstd library rejected blocks of type `Compressed_Block` whose offset of the last table with type `FSE_Compressed_Mode` was less than 4 bytes from the end of the block.\n\nIn more depth, let `Last_Table_Offset` be the offset in the compressed block (excluding the header) that\nthe last table with type `FSE_Compressed_Mode` started. If `Block_Content - Last_Table_Offset < 4` then\nthe buggy zstd decompressor would reject the block. This occurs when the last serialized table is 2 bytes\nand the bitstream size is 1 byte.\n\nFor example:\n* There is 1 sequence in the block\n* `Literals_Lengths_Mode` is `FSE_Compressed_Mode` & the serialized table size is 2 bytes\n* `Offsets_Mode` is `Predefined_Mode`\n* `Match_Lengths_Mode` is `Predefined_Mode`\n* The bitstream is 1 byte. E.g. there is only one sequence and it fits in 1 byte.\n\nThe total `Block_Content` is `5` bytes, and `Last_Table_Offset` is `2`.\n\nSee the compressor workaround code:\n\nhttps://github.com/facebook/zstd/blob/8814aa5bfa74f05a86e55e9d508da177a893ceeb/lib/compress/zstd_compress.c#L2667-L2682\n\nMagicless format\n----------------------\n\n**Last affected version**: v1.5.5\n\n**Affected decompressor component(s)**: Library\n\n**Produced by the reference compressor**: Yes (example: https://gist.github.com/embg/9940726094f4cf2cef162cffe9319232)\n\n**Example Frame**: `27 b5 2f fd 00 03 19 00 00 66 6f 6f 3f ba c4 59`\n\nv1.5.6 fixes several bugs in which the magicless-format decoder rejects valid frames.\nThese include but are not limited to:\n* Valid frames that happen to begin with a legacy magic number (little-endian)\n* Valid frames that happen to begin with a skippable magic number (little-endian)\n\nIf you are affected by this issue and cannot update to v1.5.6 or later, there is a\nworkaround to recover affected data. Simply prepend the ZSTD magic number\n`0xFD2FB528` (little-endian) to your data and decompress using the standard-format\ndecoder.\n"
  },
  {
    "path": "doc/decompressor_permissive.md",
    "content": "Decompressor Permissiveness to Invalid Data\n===========================================\n\nThis document describes the behavior of the reference decompressor in cases\nwhere it accepts formally invalid data instead of reporting an error.\n\nWhile the reference decompressor *must* decode any compliant frame following\nthe specification, its ability to detect erroneous data is on a best effort\nbasis: the decoder may accept input data that would be formally invalid,\nwhen it causes no risk to the decoder, and which detection would cost too much\ncomplexity or speed regression.\n\nIn practice, the vast majority of invalid data are detected, if only because\nmany corruption events are dangerous for the decoder process (such as\nrequesting an out-of-bound memory access) and many more are easy to check.\n\nThis document lists a few known cases where invalid data was formerly accepted\nby the decoder, and what has changed since.\n\n\nTruncated Huffman states\n------------------------\n\n**Last affected version**: v1.5.6\n\n**Produced by the reference compressor**: No\n\n**Example Frame**: `28b5 2ffd 0000 5500 0072 8001 0420 7e1f 02aa 00`\n\nWhen using FSE-compressed Huffman weights, the compressed weight bitstream\ncould contain fewer bits than necessary to decode the initial states.\n\nThe reference decompressor up to v1.5.6 will decode truncated or missing\ninitial states as zero, which can result in a valid Huffman tree if only\nthe second state is truncated.\n\nIn newer versions, truncated initial states are reported as a corruption\nerror by the decoder.\n\n\nOffset == 0\n-----------\n\n**Last affected version**: v1.5.5\n\n**Produced by the reference compressor**: No\n\n**Example Frame**: `28b5 2ffd 0000 4500 0008 0002 002f 430b ae`\n\nIf a sequence is decoded with `literals_length = 0` and `offset_value = 3`\nwhile `Repeated_Offset_1 = 1`, the computed offset will be `0`, which is\ninvalid.\n\nThe reference decompressor up to v1.5.5 processes this case as if the computed\noffset was `1`, including inserting `1` into the repeated offset list.\nThis prevents the output buffer from remaining uninitialized, thus denying a\npotential attack vector from an untrusted source.\nHowever, in the rare case where this scenario would be the outcome of a\ntransmission or storage error, the decoder relies on the checksum to detect\nthe error.\n\nIn newer versions, this case is always detected and reported as a corruption error.\n\n\nNon-zeroes reserved bits\n------------------------\n\n**Last affected version**: v1.5.5\n\n**Produced by the reference compressor**: No\n\nThe Sequences section of each block has a header, and one of its elements is a\nbyte, which describes the compression mode of each symbol.\nThis byte contains 2 reserved bits which must be set to zero.\n\nThe reference decompressor up to v1.5.5 just ignores these 2 bits.\nThis behavior has no consequence for the rest of the frame decoding process.\n\nIn newer versions, the 2 reserved bits are actively checked for value zero,\nand the decoder reports a corruption error if they are not.\n"
  },
  {
    "path": "doc/educational_decoder/.gitignore",
    "content": "# Build artifacts\nharness\n"
  },
  {
    "path": "doc/educational_decoder/Makefile",
    "content": "# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ################################################################\n\nZSTD ?= zstd   # note: requires zstd installation on local system\n\nUNAME?= $(shell sh -c 'MSYSTEM=\"MSYS\" uname') \nifeq ($(UNAME), SunOS)\nDIFF ?= gdiff\nelse\nDIFF ?= diff\nendif\n\nHARNESS_FILES=*.c\n\nMULTITHREAD_LDFLAGS = -pthread\nDEBUGFLAGS= -g -DZSTD_DEBUG=1\nCPPFLAGS += -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(ZSTDDIR)/compress \\\n            -I$(ZSTDDIR)/dictBuilder -I$(ZSTDDIR)/deprecated -I$(PRGDIR)\nCFLAGS   ?= -O2\nCFLAGS   += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow                 \\\n            -Wstrict-aliasing=1 -Wswitch-enum                               \\\n            -Wredundant-decls -Wstrict-prototypes -Wundef                   \\\n            -Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings      \\\n            -std=c99\nCFLAGS   += $(DEBUGFLAGS)\nCFLAGS   += $(MOREFLAGS)\nFLAGS     = $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(MULTITHREAD_LDFLAGS)\n\nharness: $(HARNESS_FILES)\n\t$(CC) $(FLAGS) $^ -o $@\n\nclean:\n\t@$(RM) harness *.o\n\t@$(RM) -rf harness.dSYM  # MacOS specific\n\ntest: harness\n\t#\n\t# Testing single-file decompression with educational decoder\n\t#\n\t@$(ZSTD) -f README.md -o tmp.zst\n\t@./harness tmp.zst tmp\n\t@$(DIFF) -s tmp README.md\n\t@$(RM) tmp*\n\t#\n\t# Testing dictionary decompression with education decoder\n\t#\n\t# note : files are presented multiple for training, to reach minimum threshold\n\t@$(ZSTD) --train harness.c zstd_decompress.c zstd_decompress.h README.md \\\n                  harness.c zstd_decompress.c zstd_decompress.h README.md \\\n                  harness.c zstd_decompress.c zstd_decompress.h README.md \\\n                  -o dictionary\n\t@$(ZSTD) -f README.md -D dictionary -o tmp.zst\n\t@./harness tmp.zst tmp dictionary\n\t@$(DIFF) -s tmp README.md\n\t@$(RM) tmp* dictionary\n"
  },
  {
    "path": "doc/educational_decoder/README.md",
    "content": "Educational Decoder\n===================\n\n`zstd_decompress.c` is a self-contained implementation in C99 of a decoder,\naccording to the [Zstandard format specification].\nWhile it does not implement as many features as the reference decoder,\nsuch as the streaming API or content checksums, it is written to be easy to\nfollow and understand, to help understand how the Zstandard format works.\nIt's laid out to match the [format specification],\nso it can be used to understand how complex segments could be implemented.\nIt also contains implementations of Huffman and FSE table decoding.\n\n[Zstandard format specification]: https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md\n[format specification]: https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md\n\nWhile the library's primary objective is code clarity,\nit also happens to compile into a small object file.\nThe object file can be made even smaller by removing error messages,\nusing the macro directive `ZDEC_NO_MESSAGE` at compilation time.\nThis can be reduced even further by foregoing dictionary support,\nby defining `ZDEC_NO_DICTIONARY`.\n\n`harness.c` provides a simple test harness around the decoder:\n\n    harness <input-file> <output-file> [dictionary]\n\nAs an additional resource to be used with this decoder,\nsee the `decodecorpus` tool in the [tests] directory.\nIt generates valid Zstandard frames that can be used to verify\na Zstandard decoder implementation.\nNote that to use the tool to verify this decoder implementation,\nthe --content-size flag should be set,\nas this decoder does not handle streaming decoding,\nand so it must know the decompressed size in advance.\n\n[tests]: https://github.com/facebook/zstd/blob/dev/tests/\n"
  },
  {
    "path": "doc/educational_decoder/harness.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n\n#include \"zstd_decompress.h\"\n\ntypedef unsigned char u8;\n\n// If the data doesn't have decompressed size with it, fallback on assuming the\n// compression ratio is at most 16\n#define MAX_COMPRESSION_RATIO (16)\n\n// Protect against allocating too much memory for output\n#define MAX_OUTPUT_SIZE ((size_t)1024 * 1024 * 1024)\n\n// Error message then exit\n#define ERR_OUT(...) { fprintf(stderr, __VA_ARGS__); exit(1); }\n\n\ntypedef struct {\n    u8* address;\n    size_t size;\n} buffer_s;\n\nstatic void freeBuffer(buffer_s b) { free(b.address); }\n\nstatic buffer_s read_file(const char *path)\n{\n    FILE* const f = fopen(path, \"rb\");\n    if (!f) ERR_OUT(\"failed to open file %s \\n\", path);\n\n    fseek(f, 0L, SEEK_END);\n    size_t const size = (size_t)ftell(f);\n    rewind(f);\n\n    void* const ptr = malloc(size);\n    if (!ptr) ERR_OUT(\"failed to allocate memory to hold %s \\n\", path);\n\n    size_t const read = fread(ptr, 1, size, f);\n    if (read != size) ERR_OUT(\"error while reading file %s \\n\", path);\n\n    fclose(f);\n    buffer_s const b = { ptr, size };\n    return b;\n}\n\nstatic void write_file(const char* path, const u8* ptr, size_t size)\n{\n    FILE* const f = fopen(path, \"wb\");\n    if (!f) ERR_OUT(\"failed to open file %s \\n\", path);\n\n    size_t written = 0;\n    while (written < size) {\n        written += fwrite(ptr+written, 1, size, f);\n        if (ferror(f)) ERR_OUT(\"error while writing file %s\\n\", path);\n    }\n\n    fclose(f);\n}\n\nint main(int argc, char **argv)\n{\n    if (argc < 3)\n        ERR_OUT(\"usage: %s <file.zst> <out_path> [dictionary] \\n\", argv[0]);\n\n    buffer_s const input = read_file(argv[1]);\n\n    buffer_s dict = { NULL, 0 };\n    if (argc >= 4) {\n        dict = read_file(argv[3]);\n    }\n\n    size_t out_capacity = ZSTD_get_decompressed_size(input.address, input.size);\n    if (out_capacity == (size_t)-1) {\n        out_capacity = MAX_COMPRESSION_RATIO * input.size;\n        fprintf(stderr, \"WARNING: Compressed data does not contain \"\n                        \"decompressed size, going to assume the compression \"\n                        \"ratio is at most %d (decompressed size of at most \"\n                        \"%u) \\n\",\n                MAX_COMPRESSION_RATIO, (unsigned)out_capacity);\n    }\n    if (out_capacity > MAX_OUTPUT_SIZE)\n        ERR_OUT(\"Required output size too large for this implementation \\n\");\n\n    u8* const output = malloc(out_capacity);\n    if (!output) ERR_OUT(\"failed to allocate memory \\n\");\n\n    dictionary_t* const parsed_dict = create_dictionary();\n    if (dict.size) {\n#if defined (ZDEC_NO_DICTIONARY)\n        printf(\"dict.size = %zu \\n\", dict.size);\n        ERR_OUT(\"no dictionary support \\n\");\n#else\n        parse_dictionary(parsed_dict, dict.address, dict.size);\n#endif\n    }\n    size_t const decompressed_size =\n        ZSTD_decompress_with_dict(output, out_capacity,\n                                  input.address, input.size,\n                                  parsed_dict);\n\n    free_dictionary(parsed_dict);\n\n    write_file(argv[2], output, decompressed_size);\n\n    freeBuffer(input);\n    freeBuffer(dict);\n    free(output);\n    return 0;\n}\n"
  },
  {
    "path": "doc/educational_decoder/zstd_decompress.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/// Zstandard educational decoder implementation\n/// See https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md\n\n#include <stdint.h>   // uint8_t, etc.\n#include <stdlib.h>   // malloc, free, exit\n#include <stdio.h>    // fprintf\n#include <string.h>   // memset, memcpy\n#include \"zstd_decompress.h\"\n\n\n/******* IMPORTANT CONSTANTS *********************************************/\n\n// Zstandard frame\n// \"Magic_Number\n// 4 Bytes, little-endian format. Value : 0xFD2FB528\"\n#define ZSTD_MAGIC_NUMBER 0xFD2FB528U\n\n// The size of `Block_Content` is limited by `Block_Maximum_Size`,\n#define ZSTD_BLOCK_SIZE_MAX ((size_t)128 * 1024)\n\n// literal blocks can't be larger than their block\n#define MAX_LITERALS_SIZE ZSTD_BLOCK_SIZE_MAX\n\n\n/******* UTILITY MACROS AND TYPES *********************************************/\n#define MAX(a, b) ((a) > (b) ? (a) : (b))\n#define MIN(a, b) ((a) < (b) ? (a) : (b))\n\n#if defined(ZDEC_NO_MESSAGE)\n#define MESSAGE(...)\n#else\n#define MESSAGE(...)  fprintf(stderr, \"\" __VA_ARGS__)\n#endif\n\n/// This decoder calls exit(1) when it encounters an error, however a production\n/// library should propagate error codes\n#define ERROR(s)                                                               \\\n    do {                                                                       \\\n        MESSAGE(\"Error: %s\\n\", s);                                     \\\n        exit(1);                                                               \\\n    } while (0)\n#define INP_SIZE()                                                             \\\n    ERROR(\"Input buffer smaller than it should be or input is \"                \\\n          \"corrupted\")\n#define OUT_SIZE() ERROR(\"Output buffer too small for output\")\n#define CORRUPTION() ERROR(\"Corruption detected while decompressing\")\n#define BAD_ALLOC() ERROR(\"Memory allocation error\")\n#define IMPOSSIBLE() ERROR(\"An impossibility has occurred\")\n\ntypedef uint8_t  u8;\ntypedef uint16_t u16;\ntypedef uint32_t u32;\ntypedef uint64_t u64;\n\ntypedef int8_t  i8;\ntypedef int16_t i16;\ntypedef int32_t i32;\ntypedef int64_t i64;\n/******* END UTILITY MACROS AND TYPES *****************************************/\n\n/******* IMPLEMENTATION PRIMITIVE PROTOTYPES **********************************/\n/// The implementations for these functions can be found at the bottom of this\n/// file.  They implement low-level functionality needed for the higher level\n/// decompression functions.\n\n/*** IO STREAM OPERATIONS *************/\n\n/// ostream_t/istream_t are used to wrap the pointers/length data passed into\n/// ZSTD_decompress, so that all IO operations are safely bounds checked\n/// They are written/read forward, and reads are treated as little-endian\n/// They should be used opaquely to ensure safety\ntypedef struct {\n    u8 *ptr;\n    size_t len;\n} ostream_t;\n\ntypedef struct {\n    const u8 *ptr;\n    size_t len;\n\n    // Input often reads a few bits at a time, so maintain an internal offset\n    int bit_offset;\n} istream_t;\n\n/// The following two functions are the only ones that allow the istream to be\n/// non-byte aligned\n\n/// Reads `num` bits from a bitstream, and updates the internal offset\nstatic inline u64 IO_read_bits(istream_t *const in, const int num_bits);\n/// Backs-up the stream by `num` bits so they can be read again\nstatic inline void IO_rewind_bits(istream_t *const in, const int num_bits);\n/// If the remaining bits in a byte will be unused, advance to the end of the\n/// byte\nstatic inline void IO_align_stream(istream_t *const in);\n\n/// Write the given byte into the output stream\nstatic inline void IO_write_byte(ostream_t *const out, u8 symb);\n\n/// Returns the number of bytes left to be read in this stream.  The stream must\n/// be byte aligned.\nstatic inline size_t IO_istream_len(const istream_t *const in);\n\n/// Advances the stream by `len` bytes, and returns a pointer to the chunk that\n/// was skipped.  The stream must be byte aligned.\nstatic inline const u8 *IO_get_read_ptr(istream_t *const in, size_t len);\n/// Advances the stream by `len` bytes, and returns a pointer to the chunk that\n/// was skipped so it can be written to.\nstatic inline u8 *IO_get_write_ptr(ostream_t *const out, size_t len);\n\n/// Advance the inner state by `len` bytes.  The stream must be byte aligned.\nstatic inline void IO_advance_input(istream_t *const in, size_t len);\n\n/// Returns an `ostream_t` constructed from the given pointer and length.\nstatic inline ostream_t IO_make_ostream(u8 *out, size_t len);\n/// Returns an `istream_t` constructed from the given pointer and length.\nstatic inline istream_t IO_make_istream(const u8 *in, size_t len);\n\n/// Returns an `istream_t` with the same base as `in`, and length `len`.\n/// Then, advance `in` to account for the consumed bytes.\n/// `in` must be byte aligned.\nstatic inline istream_t IO_make_sub_istream(istream_t *const in, size_t len);\n/*** END IO STREAM OPERATIONS *********/\n\n/*** BITSTREAM OPERATIONS *************/\n/// Read `num` bits (up to 64) from `src + offset`, where `offset` is in bits,\n/// and return them interpreted as a little-endian unsigned integer.\nstatic inline u64 read_bits_LE(const u8 *src, const int num_bits,\n                               const size_t offset);\n\n/// Read bits from the end of a HUF or FSE bitstream.  `offset` is in bits, so\n/// it updates `offset` to `offset - bits`, and then reads `bits` bits from\n/// `src + offset`.  If the offset becomes negative, the extra bits at the\n/// bottom are filled in with `0` bits instead of reading from before `src`.\nstatic inline u64 STREAM_read_bits(const u8 *src, const int bits,\n                                   i64 *const offset);\n/*** END BITSTREAM OPERATIONS *********/\n\n/*** BIT COUNTING OPERATIONS **********/\n/// Returns the index of the highest set bit in `num`, or `-1` if `num == 0`\nstatic inline int highest_set_bit(const u64 num);\n/*** END BIT COUNTING OPERATIONS ******/\n\n/*** HUFFMAN PRIMITIVES ***************/\n// Table decode method uses exponential memory, so we need to limit depth\n#define HUF_MAX_BITS (16)\n\n// Limit the maximum number of symbols to 256 so we can store a symbol in a byte\n#define HUF_MAX_SYMBS (256)\n\n/// Structure containing all tables necessary for efficient Huffman decoding\ntypedef struct {\n    u8 *symbols;\n    u8 *num_bits;\n    int max_bits;\n} HUF_dtable;\n\n/// Decode a single symbol and read in enough bits to refresh the state\nstatic inline u8 HUF_decode_symbol(const HUF_dtable *const dtable,\n                                   u16 *const state, const u8 *const src,\n                                   i64 *const offset);\n/// Read in a full state's worth of bits to initialize it\nstatic inline void HUF_init_state(const HUF_dtable *const dtable,\n                                  u16 *const state, const u8 *const src,\n                                  i64 *const offset);\n\n/// Decompresses a single Huffman stream, returns the number of bytes decoded.\n/// `src_len` must be the exact length of the Huffman-coded block.\nstatic size_t HUF_decompress_1stream(const HUF_dtable *const dtable,\n                                     ostream_t *const out, istream_t *const in);\n/// Same as previous but decodes 4 streams, formatted as in the Zstandard\n/// specification.\n/// `src_len` must be the exact length of the Huffman-coded block.\nstatic size_t HUF_decompress_4stream(const HUF_dtable *const dtable,\n                                     ostream_t *const out, istream_t *const in);\n\n/// Initialize a Huffman decoding table using the table of bit counts provided\nstatic void HUF_init_dtable(HUF_dtable *const table, const u8 *const bits,\n                            const int num_symbs);\n/// Initialize a Huffman decoding table using the table of weights provided\n/// Weights follow the definition provided in the Zstandard specification\nstatic void HUF_init_dtable_usingweights(HUF_dtable *const table,\n                                         const u8 *const weights,\n                                         const int num_symbs);\n\n/// Free the malloc'ed parts of a decoding table\nstatic void HUF_free_dtable(HUF_dtable *const dtable);\n/*** END HUFFMAN PRIMITIVES ***********/\n\n/*** FSE PRIMITIVES *******************/\n/// For more description of FSE see\n/// https://github.com/Cyan4973/FiniteStateEntropy/\n\n// FSE table decoding uses exponential memory, so limit the maximum accuracy\n#define FSE_MAX_ACCURACY_LOG (15)\n// Limit the maximum number of symbols so they can be stored in a single byte\n#define FSE_MAX_SYMBS (256)\n\n/// The tables needed to decode FSE encoded streams\ntypedef struct {\n    u8 *symbols;\n    u8 *num_bits;\n    u16 *new_state_base;\n    int accuracy_log;\n} FSE_dtable;\n\n/// Return the symbol for the current state\nstatic inline u8 FSE_peek_symbol(const FSE_dtable *const dtable,\n                                 const u16 state);\n/// Read the number of bits necessary to update state, update, and shift offset\n/// back to reflect the bits read\nstatic inline void FSE_update_state(const FSE_dtable *const dtable,\n                                    u16 *const state, const u8 *const src,\n                                    i64 *const offset);\n\n/// Combine peek and update: decode a symbol and update the state\nstatic inline u8 FSE_decode_symbol(const FSE_dtable *const dtable,\n                                   u16 *const state, const u8 *const src,\n                                   i64 *const offset);\n\n/// Read bits from the stream to initialize the state and shift offset back\nstatic inline void FSE_init_state(const FSE_dtable *const dtable,\n                                  u16 *const state, const u8 *const src,\n                                  i64 *const offset);\n\n/// Decompress two interleaved bitstreams (e.g. compressed Huffman weights)\n/// using an FSE decoding table.  `src_len` must be the exact length of the\n/// block.\nstatic size_t FSE_decompress_interleaved2(const FSE_dtable *const dtable,\n                                          ostream_t *const out,\n                                          istream_t *const in);\n\n/// Initialize a decoding table using normalized frequencies.\nstatic void FSE_init_dtable(FSE_dtable *const dtable,\n                            const i16 *const norm_freqs, const int num_symbs,\n                            const int accuracy_log);\n\n/// Decode an FSE header as defined in the Zstandard format specification and\n/// use the decoded frequencies to initialize a decoding table.\nstatic void FSE_decode_header(FSE_dtable *const dtable, istream_t *const in,\n                                const int max_accuracy_log);\n\n/// Initialize an FSE table that will always return the same symbol and consume\n/// 0 bits per symbol, to be used for RLE mode in sequence commands\nstatic void FSE_init_dtable_rle(FSE_dtable *const dtable, const u8 symb);\n\n/// Free the malloc'ed parts of a decoding table\nstatic void FSE_free_dtable(FSE_dtable *const dtable);\n/*** END FSE PRIMITIVES ***************/\n\n/******* END IMPLEMENTATION PRIMITIVE PROTOTYPES ******************************/\n\n/******* ZSTD HELPER STRUCTS AND PROTOTYPES ***********************************/\n\n/// A small structure that can be reused in various places that need to access\n/// frame header information\ntypedef struct {\n    // The size of window that we need to be able to contiguously store for\n    // references\n    size_t window_size;\n    // The total output size of this compressed frame\n    size_t frame_content_size;\n\n    // The dictionary id if this frame uses one\n    u32 dictionary_id;\n\n    // Whether or not the content of this frame has a checksum\n    int content_checksum_flag;\n    // Whether or not the output for this frame is in a single segment\n    int single_segment_flag;\n} frame_header_t;\n\n/// The context needed to decode blocks in a frame\ntypedef struct {\n    frame_header_t header;\n\n    // The total amount of data available for backreferences, to determine if an\n    // offset too large to be correct\n    size_t current_total_output;\n\n    const u8 *dict_content;\n    size_t dict_content_len;\n\n    // Entropy encoding tables so they can be repeated by future blocks instead\n    // of retransmitting\n    HUF_dtable literals_dtable;\n    FSE_dtable ll_dtable;\n    FSE_dtable ml_dtable;\n    FSE_dtable of_dtable;\n\n    // The last 3 offsets for the special \"repeat offsets\".\n    u64 previous_offsets[3];\n} frame_context_t;\n\n/// The decoded contents of a dictionary so that it doesn't have to be repeated\n/// for each frame that uses it\nstruct dictionary_s {\n    // Entropy tables\n    HUF_dtable literals_dtable;\n    FSE_dtable ll_dtable;\n    FSE_dtable ml_dtable;\n    FSE_dtable of_dtable;\n\n    // Raw content for backreferences\n    u8 *content;\n    size_t content_size;\n\n    // Offset history to prepopulate the frame's history\n    u64 previous_offsets[3];\n\n    u32 dictionary_id;\n};\n\n/// A tuple containing the parts necessary to decode and execute a ZSTD sequence\n/// command\ntypedef struct {\n    u32 literal_length;\n    u32 match_length;\n    u32 offset;\n} sequence_command_t;\n\n/// The decoder works top-down, starting at the high level like Zstd frames, and\n/// working down to lower more technical levels such as blocks, literals, and\n/// sequences.  The high-level functions roughly follow the outline of the\n/// format specification:\n/// https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md\n\n/// Before the implementation of each high-level function declared here, the\n/// prototypes for their helper functions are defined and explained\n\n/// Decode a single Zstd frame, or error if the input is not a valid frame.\n/// Accepts a dict argument, which may be NULL indicating no dictionary.\n/// See\n/// https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#frame-concatenation\nstatic void decode_frame(ostream_t *const out, istream_t *const in,\n                         const dictionary_t *const dict);\n\n// Decode data in a compressed block\nstatic void decompress_block(frame_context_t *const ctx, ostream_t *const out,\n                             istream_t *const in);\n\n// Decode the literals section of a block\nstatic size_t decode_literals(frame_context_t *const ctx, istream_t *const in,\n                              u8 **const literals);\n\n// Decode the sequences part of a block\nstatic size_t decode_sequences(frame_context_t *const ctx, istream_t *const in,\n                               sequence_command_t **const sequences);\n\n// Execute the decoded sequences on the literals block\nstatic void execute_sequences(frame_context_t *const ctx, ostream_t *const out,\n                              const u8 *const literals,\n                              const size_t literals_len,\n                              const sequence_command_t *const sequences,\n                              const size_t num_sequences);\n\n// Copies literals and returns the total literal length that was copied\nstatic u32 copy_literals(const size_t seq, istream_t *litstream,\n                         ostream_t *const out);\n\n// Given an offset code from a sequence command (either an actual offset value\n// or an index for previous offset), computes the correct offset and updates\n// the offset history\nstatic size_t compute_offset(sequence_command_t seq, u64 *const offset_hist);\n\n// Given an offset, match length, and total output, as well as the frame\n// context for the dictionary, determines if the dictionary is used and\n// executes the copy operation\nstatic void execute_match_copy(frame_context_t *const ctx, size_t offset,\n                              size_t match_length, size_t total_output,\n                              ostream_t *const out);\n\n/******* END ZSTD HELPER STRUCTS AND PROTOTYPES *******************************/\n\nsize_t ZSTD_decompress(void *const dst, const size_t dst_len,\n                       const void *const src, const size_t src_len) {\n    dictionary_t* const uninit_dict = create_dictionary();\n    size_t const decomp_size = ZSTD_decompress_with_dict(dst, dst_len, src,\n                                                         src_len, uninit_dict);\n    free_dictionary(uninit_dict);\n    return decomp_size;\n}\n\nsize_t ZSTD_decompress_with_dict(void *const dst, const size_t dst_len,\n                                 const void *const src, const size_t src_len,\n                                 dictionary_t* parsed_dict) {\n\n    istream_t in = IO_make_istream(src, src_len);\n    ostream_t out = IO_make_ostream(dst, dst_len);\n\n    // \"A content compressed by Zstandard is transformed into a Zstandard frame.\n    // Multiple frames can be appended into a single file or stream. A frame is\n    // totally independent, has a defined beginning and end, and a set of\n    // parameters which tells the decoder how to decompress it.\"\n\n    /* this decoder assumes decompression of a single frame */\n    decode_frame(&out, &in, parsed_dict);\n\n    return (size_t)(out.ptr - (u8 *)dst);\n}\n\n/******* FRAME DECODING ******************************************************/\n\nstatic void decode_data_frame(ostream_t *const out, istream_t *const in,\n                              const dictionary_t *const dict);\nstatic void init_frame_context(frame_context_t *const context,\n                               istream_t *const in,\n                               const dictionary_t *const dict);\nstatic void free_frame_context(frame_context_t *const context);\nstatic void parse_frame_header(frame_header_t *const header,\n                               istream_t *const in);\nstatic void frame_context_apply_dict(frame_context_t *const ctx,\n                                     const dictionary_t *const dict);\n\nstatic void decompress_data(frame_context_t *const ctx, ostream_t *const out,\n                            istream_t *const in);\n\nstatic void decode_frame(ostream_t *const out, istream_t *const in,\n                         const dictionary_t *const dict) {\n    const u32 magic_number = (u32)IO_read_bits(in, 32);\n    if (magic_number == ZSTD_MAGIC_NUMBER) {\n        // ZSTD frame\n        decode_data_frame(out, in, dict);\n\n        return;\n    }\n\n    // not a real frame or a skippable frame\n    ERROR(\"Tried to decode non-ZSTD frame\");\n}\n\n/// Decode a frame that contains compressed data.  Not all frames do as there\n/// are skippable frames.\n/// See\n/// https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#general-structure-of-zstandard-frame-format\nstatic void decode_data_frame(ostream_t *const out, istream_t *const in,\n                              const dictionary_t *const dict) {\n    frame_context_t ctx;\n\n    // Initialize the context that needs to be carried from block to block\n    init_frame_context(&ctx, in, dict);\n\n    if (ctx.header.frame_content_size != 0 &&\n        ctx.header.frame_content_size > out->len) {\n        OUT_SIZE();\n    }\n\n    decompress_data(&ctx, out, in);\n\n    free_frame_context(&ctx);\n}\n\n/// Takes the information provided in the header and dictionary, and initializes\n/// the context for this frame\nstatic void init_frame_context(frame_context_t *const context,\n                               istream_t *const in,\n                               const dictionary_t *const dict) {\n    // Most fields in context are correct when initialized to 0\n    memset(context, 0, sizeof(frame_context_t));\n\n    // Parse data from the frame header\n    parse_frame_header(&context->header, in);\n\n    // Set up the offset history for the repeat offset commands\n    context->previous_offsets[0] = 1;\n    context->previous_offsets[1] = 4;\n    context->previous_offsets[2] = 8;\n\n    // Apply details from the dict if it exists\n    frame_context_apply_dict(context, dict);\n}\n\nstatic void free_frame_context(frame_context_t *const context) {\n    HUF_free_dtable(&context->literals_dtable);\n\n    FSE_free_dtable(&context->ll_dtable);\n    FSE_free_dtable(&context->ml_dtable);\n    FSE_free_dtable(&context->of_dtable);\n\n    memset(context, 0, sizeof(frame_context_t));\n}\n\nstatic void parse_frame_header(frame_header_t *const header,\n                               istream_t *const in) {\n    // \"The first header's byte is called the Frame_Header_Descriptor. It tells\n    // which other fields are present. Decoding this byte is enough to tell the\n    // size of Frame_Header.\n    //\n    // Bit number   Field name\n    // 7-6  Frame_Content_Size_flag\n    // 5    Single_Segment_flag\n    // 4    Unused_bit\n    // 3    Reserved_bit\n    // 2    Content_Checksum_flag\n    // 1-0  Dictionary_ID_flag\"\n    const u8 descriptor = (u8)IO_read_bits(in, 8);\n\n    // decode frame header descriptor into flags\n    const u8 frame_content_size_flag = descriptor >> 6;\n    const u8 single_segment_flag = (descriptor >> 5) & 1;\n    const u8 reserved_bit = (descriptor >> 3) & 1;\n    const u8 content_checksum_flag = (descriptor >> 2) & 1;\n    const u8 dictionary_id_flag = descriptor & 3;\n\n    if (reserved_bit != 0) {\n        CORRUPTION();\n    }\n\n    header->single_segment_flag = single_segment_flag;\n    header->content_checksum_flag = content_checksum_flag;\n\n    // decode window size\n    if (!single_segment_flag) {\n        // \"Provides guarantees on maximum back-reference distance that will be\n        // used within compressed data. This information is important for\n        // decoders to allocate enough memory.\n        //\n        // Bit numbers  7-3         2-0\n        // Field name   Exponent    Mantissa\"\n        u8 window_descriptor = (u8)IO_read_bits(in, 8);\n        u8 exponent = window_descriptor >> 3;\n        u8 mantissa = window_descriptor & 7;\n\n        // Use the algorithm from the specification to compute window size\n        // https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#window_descriptor\n        size_t window_base = (size_t)1 << (10 + exponent);\n        size_t window_add = (window_base / 8) * mantissa;\n        header->window_size = window_base + window_add;\n    }\n\n    // decode dictionary id if it exists\n    if (dictionary_id_flag) {\n        // \"This is a variable size field, which contains the ID of the\n        // dictionary required to properly decode the frame. Note that this\n        // field is optional. When it's not present, it's up to the caller to\n        // make sure it uses the correct dictionary. Format is little-endian.\"\n        const int bytes_array[] = {0, 1, 2, 4};\n        const int bytes = bytes_array[dictionary_id_flag];\n\n        header->dictionary_id = (u32)IO_read_bits(in, bytes * 8);\n    } else {\n        header->dictionary_id = 0;\n    }\n\n    // decode frame content size if it exists\n    if (single_segment_flag || frame_content_size_flag) {\n        // \"This is the original (uncompressed) size. This information is\n        // optional. The Field_Size is provided according to value of\n        // Frame_Content_Size_flag. The Field_Size can be equal to 0 (not\n        // present), 1, 2, 4 or 8 bytes. Format is little-endian.\"\n        //\n        // if frame_content_size_flag == 0 but single_segment_flag is set, we\n        // still have a 1 byte field\n        const int bytes_array[] = {1, 2, 4, 8};\n        const int bytes = bytes_array[frame_content_size_flag];\n\n        header->frame_content_size = IO_read_bits(in, bytes * 8);\n        if (bytes == 2) {\n            // \"When Field_Size is 2, the offset of 256 is added.\"\n            header->frame_content_size += 256;\n        }\n    } else {\n        header->frame_content_size = 0;\n    }\n\n    if (single_segment_flag) {\n        // \"The Window_Descriptor byte is optional. It is absent when\n        // Single_Segment_flag is set. In this case, the maximum back-reference\n        // distance is the content size itself, which can be any value from 1 to\n        // 2^64-1 bytes (16 EB).\"\n        header->window_size = header->frame_content_size;\n    }\n}\n\n/// Decompress the data from a frame block by block\nstatic void decompress_data(frame_context_t *const ctx, ostream_t *const out,\n                            istream_t *const in) {\n    // \"A frame encapsulates one or multiple blocks. Each block can be\n    // compressed or not, and has a guaranteed maximum content size, which\n    // depends on frame parameters. Unlike frames, each block depends on\n    // previous blocks for proper decoding. However, each block can be\n    // decompressed without waiting for its successor, allowing streaming\n    // operations.\"\n    int last_block = 0;\n    do {\n        // \"Last_Block\n        //\n        // The lowest bit signals if this block is the last one. Frame ends\n        // right after this block.\n        //\n        // Block_Type and Block_Size\n        //\n        // The next 2 bits represent the Block_Type, while the remaining 21 bits\n        // represent the Block_Size. Format is little-endian.\"\n        last_block = (int)IO_read_bits(in, 1);\n        const int block_type = (int)IO_read_bits(in, 2);\n        const size_t block_len = IO_read_bits(in, 21);\n\n        switch (block_type) {\n        case 0: {\n            // \"Raw_Block - this is an uncompressed block. Block_Size is the\n            // number of bytes to read and copy.\"\n            const u8 *const read_ptr = IO_get_read_ptr(in, block_len);\n            u8 *const write_ptr = IO_get_write_ptr(out, block_len);\n\n            // Copy the raw data into the output\n            memcpy(write_ptr, read_ptr, block_len);\n\n            ctx->current_total_output += block_len;\n            break;\n        }\n        case 1: {\n            // \"RLE_Block - this is a single byte, repeated N times. In which\n            // case, Block_Size is the size to regenerate, while the\n            // \"compressed\" block is just 1 byte (the byte to repeat).\"\n            const u8 *const read_ptr = IO_get_read_ptr(in, 1);\n            u8 *const write_ptr = IO_get_write_ptr(out, block_len);\n\n            // Copy `block_len` copies of `read_ptr[0]` to the output\n            memset(write_ptr, read_ptr[0], block_len);\n\n            ctx->current_total_output += block_len;\n            break;\n        }\n        case 2: {\n            // \"Compressed_Block - this is a Zstandard compressed block,\n            // detailed in another section of this specification. Block_Size is\n            // the compressed size.\n\n            // Create a sub-stream for the block\n            istream_t block_stream = IO_make_sub_istream(in, block_len);\n            decompress_block(ctx, out, &block_stream);\n            break;\n        }\n        case 3:\n            // \"Reserved - this is not a block. This value cannot be used with\n            // current version of this specification.\"\n            CORRUPTION();\n            break;\n        default:\n            IMPOSSIBLE();\n        }\n    } while (!last_block);\n\n    if (ctx->header.content_checksum_flag) {\n        // This program does not support checking the checksum, so skip over it\n        // if it's present\n        IO_advance_input(in, 4);\n    }\n}\n/******* END FRAME DECODING ***************************************************/\n\n/******* BLOCK DECOMPRESSION **************************************************/\nstatic void decompress_block(frame_context_t *const ctx, ostream_t *const out,\n                             istream_t *const in) {\n    // \"A compressed block consists of 2 sections :\n    //\n    // Literals_Section\n    // Sequences_Section\"\n\n\n    // Part 1: decode the literals block\n    u8 *literals = NULL;\n    const size_t literals_size = decode_literals(ctx, in, &literals);\n\n    // Part 2: decode the sequences block\n    sequence_command_t *sequences = NULL;\n    const size_t num_sequences =\n        decode_sequences(ctx, in, &sequences);\n\n    // Part 3: combine literals and sequence commands to generate output\n    execute_sequences(ctx, out, literals, literals_size, sequences,\n                      num_sequences);\n    free(literals);\n    free(sequences);\n}\n/******* END BLOCK DECOMPRESSION **********************************************/\n\n/******* LITERALS DECODING ****************************************************/\nstatic size_t decode_literals_simple(istream_t *const in, u8 **const literals,\n                                     const int block_type,\n                                     const int size_format);\nstatic size_t decode_literals_compressed(frame_context_t *const ctx,\n                                         istream_t *const in,\n                                         u8 **const literals,\n                                         const int block_type,\n                                         const int size_format);\nstatic void decode_huf_table(HUF_dtable *const dtable, istream_t *const in);\nstatic void fse_decode_hufweights(ostream_t *weights, istream_t *const in,\n                                    int *const num_symbs);\n\nstatic size_t decode_literals(frame_context_t *const ctx, istream_t *const in,\n                              u8 **const literals) {\n    // \"Literals can be stored uncompressed or compressed using Huffman prefix\n    // codes. When compressed, an optional tree description can be present,\n    // followed by 1 or 4 streams.\"\n    //\n    // \"Literals_Section_Header\n    //\n    // Header is in charge of describing how literals are packed. It's a\n    // byte-aligned variable-size bitfield, ranging from 1 to 5 bytes, using\n    // little-endian convention.\"\n    //\n    // \"Literals_Block_Type\n    //\n    // This field uses 2 lowest bits of first byte, describing 4 different block\n    // types\"\n    //\n    // size_format takes between 1 and 2 bits\n    int block_type = (int)IO_read_bits(in, 2);\n    int size_format = (int)IO_read_bits(in, 2);\n\n    if (block_type <= 1) {\n        // Raw or RLE literals block\n        return decode_literals_simple(in, literals, block_type,\n                                      size_format);\n    } else {\n        // Huffman compressed literals\n        return decode_literals_compressed(ctx, in, literals, block_type,\n                                          size_format);\n    }\n}\n\n/// Decodes literals blocks in raw or RLE form\nstatic size_t decode_literals_simple(istream_t *const in, u8 **const literals,\n                                     const int block_type,\n                                     const int size_format) {\n    size_t size;\n    switch (size_format) {\n    // These cases are in the form ?0\n    // In this case, the ? bit is actually part of the size field\n    case 0:\n    case 2:\n        // \"Size_Format uses 1 bit. Regenerated_Size uses 5 bits (0-31).\"\n        IO_rewind_bits(in, 1);\n        size = IO_read_bits(in, 5);\n        break;\n    case 1:\n        // \"Size_Format uses 2 bits. Regenerated_Size uses 12 bits (0-4095).\"\n        size = IO_read_bits(in, 12);\n        break;\n    case 3:\n        // \"Size_Format uses 2 bits. Regenerated_Size uses 20 bits (0-1048575).\"\n        size = IO_read_bits(in, 20);\n        break;\n    default:\n        // Size format is in range 0-3\n        IMPOSSIBLE();\n    }\n\n    if (size > MAX_LITERALS_SIZE) {\n        CORRUPTION();\n    }\n\n    *literals = malloc(size);\n    if (!*literals) {\n        BAD_ALLOC();\n    }\n\n    switch (block_type) {\n    case 0: {\n        // \"Raw_Literals_Block - Literals are stored uncompressed.\"\n        const u8 *const read_ptr = IO_get_read_ptr(in, size);\n        memcpy(*literals, read_ptr, size);\n        break;\n    }\n    case 1: {\n        // \"RLE_Literals_Block - Literals consist of a single byte value repeated N times.\"\n        const u8 *const read_ptr = IO_get_read_ptr(in, 1);\n        memset(*literals, read_ptr[0], size);\n        break;\n    }\n    default:\n        IMPOSSIBLE();\n    }\n\n    return size;\n}\n\n/// Decodes Huffman compressed literals\nstatic size_t decode_literals_compressed(frame_context_t *const ctx,\n                                         istream_t *const in,\n                                         u8 **const literals,\n                                         const int block_type,\n                                         const int size_format) {\n    size_t regenerated_size, compressed_size;\n    // Only size_format=0 has 1 stream, so default to 4\n    int num_streams = 4;\n    switch (size_format) {\n    case 0:\n        // \"A single stream. Both Compressed_Size and Regenerated_Size use 10\n        // bits (0-1023).\"\n        num_streams = 1;\n    // Fall through as it has the same size format\n        /* fallthrough */\n    case 1:\n        // \"4 streams. Both Compressed_Size and Regenerated_Size use 10 bits\n        // (0-1023).\"\n        regenerated_size = IO_read_bits(in, 10);\n        compressed_size = IO_read_bits(in, 10);\n        break;\n    case 2:\n        // \"4 streams. Both Compressed_Size and Regenerated_Size use 14 bits\n        // (0-16383).\"\n        regenerated_size = IO_read_bits(in, 14);\n        compressed_size = IO_read_bits(in, 14);\n        break;\n    case 3:\n        // \"4 streams. Both Compressed_Size and Regenerated_Size use 18 bits\n        // (0-262143).\"\n        regenerated_size = IO_read_bits(in, 18);\n        compressed_size = IO_read_bits(in, 18);\n        break;\n    default:\n        // Impossible\n        IMPOSSIBLE();\n    }\n    if (regenerated_size > MAX_LITERALS_SIZE) {\n        CORRUPTION();\n    }\n\n    *literals = malloc(regenerated_size);\n    if (!*literals) {\n        BAD_ALLOC();\n    }\n\n    ostream_t lit_stream = IO_make_ostream(*literals, regenerated_size);\n    istream_t huf_stream = IO_make_sub_istream(in, compressed_size);\n\n    if (block_type == 2) {\n        // Decode the provided Huffman table\n        // \"This section is only present when Literals_Block_Type type is\n        // Compressed_Literals_Block (2).\"\n\n        HUF_free_dtable(&ctx->literals_dtable);\n        decode_huf_table(&ctx->literals_dtable, &huf_stream);\n    } else {\n        // If the previous Huffman table is being repeated, ensure it exists\n        if (!ctx->literals_dtable.symbols) {\n            CORRUPTION();\n        }\n    }\n\n    size_t symbols_decoded;\n    if (num_streams == 1) {\n        symbols_decoded = HUF_decompress_1stream(&ctx->literals_dtable, &lit_stream, &huf_stream);\n    } else {\n        symbols_decoded = HUF_decompress_4stream(&ctx->literals_dtable, &lit_stream, &huf_stream);\n    }\n\n    if (symbols_decoded != regenerated_size) {\n        CORRUPTION();\n    }\n\n    return regenerated_size;\n}\n\n// Decode the Huffman table description\nstatic void decode_huf_table(HUF_dtable *const dtable, istream_t *const in) {\n    // \"All literal values from zero (included) to last present one (excluded)\n    // are represented by Weight with values from 0 to Max_Number_of_Bits.\"\n\n    // \"This is a single byte value (0-255), which describes how to decode the list of weights.\"\n    const u8 header = IO_read_bits(in, 8);\n\n    u8 weights[HUF_MAX_SYMBS];\n    memset(weights, 0, sizeof(weights));\n\n    int num_symbs;\n\n    if (header >= 128) {\n        // \"This is a direct representation, where each Weight is written\n        // directly as a 4 bits field (0-15). The full representation occupies\n        // ((Number_of_Symbols+1)/2) bytes, meaning it uses a last full byte\n        // even if Number_of_Symbols is odd. Number_of_Symbols = headerByte -\n        // 127\"\n        num_symbs = header - 127;\n        const size_t bytes = (num_symbs + 1) / 2;\n\n        const u8 *const weight_src = IO_get_read_ptr(in, bytes);\n\n        for (int i = 0; i < num_symbs; i++) {\n            // \"They are encoded forward, 2\n            // weights to a byte with the first weight taking the top four bits\n            // and the second taking the bottom four (e.g. the following\n            // operations could be used to read the weights: Weight[0] =\n            // (Byte[0] >> 4), Weight[1] = (Byte[0] & 0xf), etc.).\"\n            if (i % 2 == 0) {\n                weights[i] = weight_src[i / 2] >> 4;\n            } else {\n                weights[i] = weight_src[i / 2] & 0xf;\n            }\n        }\n    } else {\n        // The weights are FSE encoded, decode them before we can construct the\n        // table\n        istream_t fse_stream = IO_make_sub_istream(in, header);\n        ostream_t weight_stream = IO_make_ostream(weights, HUF_MAX_SYMBS);\n        fse_decode_hufweights(&weight_stream, &fse_stream, &num_symbs);\n    }\n\n    // Construct the table using the decoded weights\n    HUF_init_dtable_usingweights(dtable, weights, num_symbs);\n}\n\nstatic void fse_decode_hufweights(ostream_t *weights, istream_t *const in,\n                                    int *const num_symbs) {\n    const int MAX_ACCURACY_LOG = 7;\n\n    FSE_dtable dtable;\n\n    // \"An FSE bitstream starts by a header, describing probabilities\n    // distribution. It will create a Decoding Table. For a list of Huffman\n    // weights, maximum accuracy is 7 bits.\"\n    FSE_decode_header(&dtable, in, MAX_ACCURACY_LOG);\n\n    // Decode the weights\n    *num_symbs = FSE_decompress_interleaved2(&dtable, weights, in);\n\n    FSE_free_dtable(&dtable);\n}\n/******* END LITERALS DECODING ************************************************/\n\n/******* SEQUENCE DECODING ****************************************************/\n/// The combination of FSE states needed to decode sequences\ntypedef struct {\n    FSE_dtable ll_table;\n    FSE_dtable of_table;\n    FSE_dtable ml_table;\n\n    u16 ll_state;\n    u16 of_state;\n    u16 ml_state;\n} sequence_states_t;\n\n/// Different modes to signal to decode_seq_tables what to do\ntypedef enum {\n    seq_literal_length = 0,\n    seq_offset = 1,\n    seq_match_length = 2,\n} seq_part_t;\n\ntypedef enum {\n    seq_predefined = 0,\n    seq_rle = 1,\n    seq_fse = 2,\n    seq_repeat = 3,\n} seq_mode_t;\n\n/// The predefined FSE distribution tables for `seq_predefined` mode\nstatic const i16 SEQ_LITERAL_LENGTH_DEFAULT_DIST[36] = {\n    4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,  1,  2,  2,\n    2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1, -1, -1, -1, -1};\nstatic const i16 SEQ_OFFSET_DEFAULT_DIST[29] = {\n    1, 1, 1, 1, 1, 1, 2, 2, 2, 1,  1,  1,  1,  1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1};\nstatic const i16 SEQ_MATCH_LENGTH_DEFAULT_DIST[53] = {\n    1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1,  1,  1,  1,  1,  1,  1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  1,  1,  1,  1,  1,  1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1};\n\n/// The sequence decoding baseline and number of additional bits to read/add\n/// https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#the-codes-for-literals-lengths-match-lengths-and-offsets\nstatic const u32 SEQ_LITERAL_LENGTH_BASELINES[36] = {\n    0,  1,  2,   3,   4,   5,    6,    7,    8,    9,     10,    11,\n    12, 13, 14,  15,  16,  18,   20,   22,   24,   28,    32,    40,\n    48, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536};\nstatic const u8 SEQ_LITERAL_LENGTH_EXTRA_BITS[36] = {\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  1,  1,\n    1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};\n\nstatic const u32 SEQ_MATCH_LENGTH_BASELINES[53] = {\n    3,  4,   5,   6,   7,    8,    9,    10,   11,    12,    13,   14, 15, 16,\n    17, 18,  19,  20,  21,   22,   23,   24,   25,    26,    27,   28, 29, 30,\n    31, 32,  33,  34,  35,   37,   39,   41,   43,    47,    51,   59, 67, 83,\n    99, 131, 259, 515, 1027, 2051, 4099, 8195, 16387, 32771, 65539};\nstatic const u8 SEQ_MATCH_LENGTH_EXTRA_BITS[53] = {\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  1,  1,  1, 1,\n    2, 2, 3, 3, 4, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};\n\n/// Offset decoding is simpler so we just need a maximum code value\nstatic const u8 SEQ_MAX_CODES[3] = {35, (u8)-1, 52};\n\nstatic void decompress_sequences(frame_context_t *const ctx,\n                                 istream_t *const in,\n                                 sequence_command_t *const sequences,\n                                 const size_t num_sequences);\nstatic sequence_command_t decode_sequence(sequence_states_t *const state,\n                                          const u8 *const src,\n                                          i64 *const offset,\n                                          int lastSequence);\nstatic void decode_seq_table(FSE_dtable *const table, istream_t *const in,\n                               const seq_part_t type, const seq_mode_t mode);\n\nstatic size_t decode_sequences(frame_context_t *const ctx, istream_t *in,\n                               sequence_command_t **const sequences) {\n    // \"A compressed block is a succession of sequences . A sequence is a\n    // literal copy command, followed by a match copy command. A literal copy\n    // command specifies a length. It is the number of bytes to be copied (or\n    // extracted) from the literal section. A match copy command specifies an\n    // offset and a length. The offset gives the position to copy from, which\n    // can be within a previous block.\"\n\n    size_t num_sequences;\n\n    // \"Number_of_Sequences\n    //\n    // This is a variable size field using between 1 and 3 bytes. Let's call its\n    // first byte byte0.\"\n    u8 header = IO_read_bits(in, 8);\n    if (header < 128) {\n        // \"Number_of_Sequences = byte0 . Uses 1 byte.\"\n        num_sequences = header;\n    } else if (header < 255) {\n        // \"Number_of_Sequences = ((byte0-128) << 8) + byte1 . Uses 2 bytes.\"\n        num_sequences = ((header - 128) << 8) + IO_read_bits(in, 8);\n    } else {\n        // \"Number_of_Sequences = byte1 + (byte2<<8) + 0x7F00 . Uses 3 bytes.\"\n        num_sequences = IO_read_bits(in, 16) + 0x7F00;\n    }\n\n    if (num_sequences == 0) {\n        // \"There are no sequences. The sequence section stops there.\"\n        *sequences = NULL;\n        return 0;\n    }\n\n    *sequences = malloc(num_sequences * sizeof(sequence_command_t));\n    if (!*sequences) {\n        BAD_ALLOC();\n    }\n\n    decompress_sequences(ctx, in, *sequences, num_sequences);\n    return num_sequences;\n}\n\n/// Decompress the FSE encoded sequence commands\nstatic void decompress_sequences(frame_context_t *const ctx, istream_t *in,\n                                 sequence_command_t *const sequences,\n                                 const size_t num_sequences) {\n    // \"The Sequences_Section regroup all symbols required to decode commands.\n    // There are 3 symbol types : literals lengths, offsets and match lengths.\n    // They are encoded together, interleaved, in a single bitstream.\"\n\n    // \"Symbol compression modes\n    //\n    // This is a single byte, defining the compression mode of each symbol\n    // type.\"\n    //\n    // Bit number : Field name\n    // 7-6        : Literals_Lengths_Mode\n    // 5-4        : Offsets_Mode\n    // 3-2        : Match_Lengths_Mode\n    // 1-0        : Reserved\n    u8 compression_modes = IO_read_bits(in, 8);\n\n    if ((compression_modes & 3) != 0) {\n        // Reserved bits set\n        CORRUPTION();\n    }\n\n    // \"Following the header, up to 3 distribution tables can be described. When\n    // present, they are in this order :\n    //\n    // Literals lengths\n    // Offsets\n    // Match Lengths\"\n    // Update the tables we have stored in the context\n    decode_seq_table(&ctx->ll_dtable, in, seq_literal_length,\n                     (compression_modes >> 6) & 3);\n\n    decode_seq_table(&ctx->of_dtable, in, seq_offset,\n                     (compression_modes >> 4) & 3);\n\n    decode_seq_table(&ctx->ml_dtable, in, seq_match_length,\n                     (compression_modes >> 2) & 3);\n\n\n    sequence_states_t states;\n\n    // Initialize the decoding tables\n    {\n        states.ll_table = ctx->ll_dtable;\n        states.of_table = ctx->of_dtable;\n        states.ml_table = ctx->ml_dtable;\n    }\n\n    const size_t len = IO_istream_len(in);\n    const u8 *const src = IO_get_read_ptr(in, len);\n\n    // \"After writing the last bit containing information, the compressor writes\n    // a single 1-bit and then fills the byte with 0-7 0 bits of padding.\"\n    const int padding = 8 - highest_set_bit(src[len - 1]);\n    // The offset starts at the end because FSE streams are read backwards\n    i64 bit_offset = (i64)(len * 8 - (size_t)padding);\n\n    // \"The bitstream starts with initial state values, each using the required\n    // number of bits in their respective accuracy, decoded previously from\n    // their normalized distribution.\n    //\n    // It starts by Literals_Length_State, followed by Offset_State, and finally\n    // Match_Length_State.\"\n    FSE_init_state(&states.ll_table, &states.ll_state, src, &bit_offset);\n    FSE_init_state(&states.of_table, &states.of_state, src, &bit_offset);\n    FSE_init_state(&states.ml_table, &states.ml_state, src, &bit_offset);\n\n    for (size_t i = 0; i < num_sequences; i++) {\n        // Decode sequences one by one\n        sequences[i] = decode_sequence(&states, src, &bit_offset, i==num_sequences-1);\n    }\n\n    if (bit_offset != 0) {\n        CORRUPTION();\n    }\n}\n\n// Decode a single sequence and update the state\nstatic sequence_command_t decode_sequence(sequence_states_t *const states,\n                                          const u8 *const src,\n                                          i64 *const offset,\n                                          int lastSequence) {\n    // \"Each symbol is a code in its own context, which specifies Baseline and\n    // Number_of_Bits to add. Codes are FSE compressed, and interleaved with raw\n    // additional bits in the same bitstream.\"\n\n    // Decode symbols, but don't update states\n    const u8 of_code = FSE_peek_symbol(&states->of_table, states->of_state);\n    const u8 ll_code = FSE_peek_symbol(&states->ll_table, states->ll_state);\n    const u8 ml_code = FSE_peek_symbol(&states->ml_table, states->ml_state);\n\n    // Offset doesn't need a max value as it's not decoded using a table\n    if (ll_code > SEQ_MAX_CODES[seq_literal_length] ||\n        ml_code > SEQ_MAX_CODES[seq_match_length]) {\n        CORRUPTION();\n    }\n\n    // Read the interleaved bits\n    sequence_command_t seq;\n    // \"Decoding starts by reading the Number_of_Bits required to decode Offset.\n    // It then does the same for Match_Length, and then for Literals_Length.\"\n    seq.offset = ((u32)1 << of_code) + STREAM_read_bits(src, of_code, offset);\n\n    seq.match_length =\n        SEQ_MATCH_LENGTH_BASELINES[ml_code] +\n        STREAM_read_bits(src, SEQ_MATCH_LENGTH_EXTRA_BITS[ml_code], offset);\n\n    seq.literal_length =\n        SEQ_LITERAL_LENGTH_BASELINES[ll_code] +\n        STREAM_read_bits(src, SEQ_LITERAL_LENGTH_EXTRA_BITS[ll_code], offset);\n\n    // \"If it is not the last sequence in the block, the next operation is to\n    // update states. Using the rules pre-calculated in the decoding tables,\n    // Literals_Length_State is updated, followed by Match_Length_State, and\n    // then Offset_State.\"\n    // If the stream is complete don't read bits to update state\n    if (!lastSequence) {\n        FSE_update_state(&states->ll_table, &states->ll_state, src, offset);\n        FSE_update_state(&states->ml_table, &states->ml_state, src, offset);\n        FSE_update_state(&states->of_table, &states->of_state, src, offset);\n    }\n\n    return seq;\n}\n\n/// Given a sequence part and table mode, decode the FSE distribution\n/// Errors if the mode is `seq_repeat` without a pre-existing table in `table`\nstatic void decode_seq_table(FSE_dtable *const table, istream_t *const in,\n                             const seq_part_t type, const seq_mode_t mode) {\n    // Constant arrays indexed by seq_part_t\n    const i16 *const default_distributions[] = {SEQ_LITERAL_LENGTH_DEFAULT_DIST,\n                                                SEQ_OFFSET_DEFAULT_DIST,\n                                                SEQ_MATCH_LENGTH_DEFAULT_DIST};\n    const size_t default_distribution_lengths[] = {36, 29, 53};\n    const size_t default_distribution_accuracies[] = {6, 5, 6};\n\n    const size_t max_accuracies[] = {9, 8, 9};\n\n    if (mode != seq_repeat) {\n        // Free old one before overwriting\n        FSE_free_dtable(table);\n    }\n\n    switch (mode) {\n    case seq_predefined: {\n        // \"Predefined_Mode : uses a predefined distribution table.\"\n        const i16 *distribution = default_distributions[type];\n        const size_t symbs = default_distribution_lengths[type];\n        const size_t accuracy_log = default_distribution_accuracies[type];\n\n        FSE_init_dtable(table, distribution, symbs, accuracy_log);\n        break;\n    }\n    case seq_rle: {\n        // \"RLE_Mode : it's a single code, repeated Number_of_Sequences times.\"\n        const u8 symb = IO_get_read_ptr(in, 1)[0];\n        FSE_init_dtable_rle(table, symb);\n        break;\n    }\n    case seq_fse: {\n        // \"FSE_Compressed_Mode : standard FSE compression. A distribution table\n        // will be present \"\n        FSE_decode_header(table, in, max_accuracies[type]);\n        break;\n    }\n    case seq_repeat:\n        // \"Repeat_Mode : reuse distribution table from previous compressed\n        // block.\"\n        // Nothing to do here, table will be unchanged\n        if (!table->symbols) {\n            // This mode is invalid if we don't already have a table\n            CORRUPTION();\n        }\n        break;\n    default:\n        // Impossible, as mode is from 0-3\n        IMPOSSIBLE();\n        break;\n    }\n\n}\n/******* END SEQUENCE DECODING ************************************************/\n\n/******* SEQUENCE EXECUTION ***************************************************/\nstatic void execute_sequences(frame_context_t *const ctx, ostream_t *const out,\n                              const u8 *const literals,\n                              const size_t literals_len,\n                              const sequence_command_t *const sequences,\n                              const size_t num_sequences) {\n    istream_t litstream = IO_make_istream(literals, literals_len);\n\n    u64 *const offset_hist = ctx->previous_offsets;\n    size_t total_output = ctx->current_total_output;\n\n    for (size_t i = 0; i < num_sequences; i++) {\n        const sequence_command_t seq = sequences[i];\n        {\n            const u32 literals_size = copy_literals(seq.literal_length, &litstream, out);\n            total_output += literals_size;\n        }\n\n        size_t const offset = compute_offset(seq, offset_hist);\n\n        size_t const match_length = seq.match_length;\n\n        execute_match_copy(ctx, offset, match_length, total_output, out);\n\n        total_output += match_length;\n    }\n\n    // Copy any leftover literals\n    {\n        size_t len = IO_istream_len(&litstream);\n        copy_literals(len, &litstream, out);\n        total_output += len;\n    }\n\n    ctx->current_total_output = total_output;\n}\n\nstatic u32 copy_literals(const size_t literal_length, istream_t *litstream,\n                         ostream_t *const out) {\n    // If the sequence asks for more literals than are left, the\n    // sequence must be corrupted\n    if (literal_length > IO_istream_len(litstream)) {\n        CORRUPTION();\n    }\n\n    u8 *const write_ptr = IO_get_write_ptr(out, literal_length);\n    const u8 *const read_ptr =\n         IO_get_read_ptr(litstream, literal_length);\n    // Copy literals to output\n    memcpy(write_ptr, read_ptr, literal_length);\n\n    return literal_length;\n}\n\nstatic size_t compute_offset(sequence_command_t seq, u64 *const offset_hist) {\n    size_t offset;\n    // Offsets are special, we need to handle the repeat offsets\n    if (seq.offset <= 3) {\n        // \"The first 3 values define a repeated offset and we will call\n        // them Repeated_Offset1, Repeated_Offset2, and Repeated_Offset3.\n        // They are sorted in recency order, with Repeated_Offset1 meaning\n        // 'most recent one'\".\n\n        // Use 0 indexing for the array\n        u32 idx = seq.offset - 1;\n        if (seq.literal_length == 0) {\n            // \"There is an exception though, when current sequence's\n            // literals length is 0. In this case, repeated offsets are\n            // shifted by one, so Repeated_Offset1 becomes Repeated_Offset2,\n            // Repeated_Offset2 becomes Repeated_Offset3, and\n            // Repeated_Offset3 becomes Repeated_Offset1 - 1_byte.\"\n            idx++;\n        }\n\n        if (idx == 0) {\n            offset = offset_hist[0];\n        } else {\n            // If idx == 3 then literal length was 0 and the offset was 3,\n            // as per the exception listed above\n            offset = idx < 3 ? offset_hist[idx] : offset_hist[0] - 1;\n\n            // If idx == 1 we don't need to modify offset_hist[2], since\n            // we're using the second-most recent code\n            if (idx > 1) {\n                offset_hist[2] = offset_hist[1];\n            }\n            offset_hist[1] = offset_hist[0];\n            offset_hist[0] = offset;\n        }\n    } else {\n        // When it's not a repeat offset:\n        // \"if (Offset_Value > 3) offset = Offset_Value - 3;\"\n        offset = seq.offset - 3;\n\n        // Shift back history\n        offset_hist[2] = offset_hist[1];\n        offset_hist[1] = offset_hist[0];\n        offset_hist[0] = offset;\n    }\n    return offset;\n}\n\nstatic void execute_match_copy(frame_context_t *const ctx, size_t offset,\n                              size_t match_length, size_t total_output,\n                              ostream_t *const out) {\n    u8 *write_ptr = IO_get_write_ptr(out, match_length);\n    if (total_output <= ctx->header.window_size) {\n        // In this case offset might go back into the dictionary\n        if (offset > total_output + ctx->dict_content_len) {\n            // The offset goes beyond even the dictionary\n            CORRUPTION();\n        }\n\n        if (offset > total_output) {\n            // \"The rest of the dictionary is its content. The content act\n            // as a \"past\" in front of data to compress or decompress, so it\n            // can be referenced in sequence commands.\"\n            const size_t dict_copy =\n                MIN(offset - total_output, match_length);\n            const size_t dict_offset =\n                ctx->dict_content_len - (offset - total_output);\n\n            memcpy(write_ptr, ctx->dict_content + dict_offset, dict_copy);\n            write_ptr += dict_copy;\n            match_length -= dict_copy;\n        }\n    } else if (offset > ctx->header.window_size) {\n        CORRUPTION();\n    }\n\n    // We must copy byte by byte because the match length might be larger\n    // than the offset\n    // ex: if the output so far was \"abc\", a command with offset=3 and\n    // match_length=6 would produce \"abcabcabc\" as the new output\n    for (size_t j = 0; j < match_length; j++) {\n        *write_ptr = *(write_ptr - offset);\n        write_ptr++;\n    }\n}\n/******* END SEQUENCE EXECUTION ***********************************************/\n\n/******* OUTPUT SIZE COUNTING *************************************************/\n/// Get the decompressed size of an input stream so memory can be allocated in\n/// advance.\n/// This implementation assumes `src` points to a single ZSTD-compressed frame\nsize_t ZSTD_get_decompressed_size(const void *src, const size_t src_len) {\n    istream_t in = IO_make_istream(src, src_len);\n\n    // get decompressed size from ZSTD frame header\n    {\n        const u32 magic_number = (u32)IO_read_bits(&in, 32);\n\n        if (magic_number == ZSTD_MAGIC_NUMBER) {\n            // ZSTD frame\n            frame_header_t header;\n            parse_frame_header(&header, &in);\n\n            if (header.frame_content_size == 0 && !header.single_segment_flag) {\n                // Content size not provided, we can't tell\n                return (size_t)-1;\n            }\n\n            return header.frame_content_size;\n        } else {\n            // not a real frame or skippable frame\n            ERROR(\"ZSTD frame magic number did not match\");\n        }\n    }\n}\n/******* END OUTPUT SIZE COUNTING *********************************************/\n\n/******* DICTIONARY PARSING ***************************************************/\ndictionary_t* create_dictionary(void) {\n    dictionary_t* const dict = calloc(1, sizeof(dictionary_t));\n    if (!dict) {\n        BAD_ALLOC();\n    }\n    return dict;\n}\n\n/// Free an allocated dictionary\nvoid free_dictionary(dictionary_t *const dict) {\n    HUF_free_dtable(&dict->literals_dtable);\n    FSE_free_dtable(&dict->ll_dtable);\n    FSE_free_dtable(&dict->of_dtable);\n    FSE_free_dtable(&dict->ml_dtable);\n\n    free(dict->content);\n\n    memset(dict, 0, sizeof(dictionary_t));\n\n    free(dict);\n}\n\n\n#if !defined(ZDEC_NO_DICTIONARY)\n#define DICT_SIZE_ERROR() ERROR(\"Dictionary size cannot be less than 8 bytes\")\n#define NULL_SRC() ERROR(\"Tried to create dictionary with pointer to null src\");\n\nstatic void init_dictionary_content(dictionary_t *const dict,\n                                    istream_t *const in);\n\nvoid parse_dictionary(dictionary_t *const dict, const void *src,\n                             size_t src_len) {\n    const u8 *byte_src = (const u8 *)src;\n    memset(dict, 0, sizeof(dictionary_t));\n    if (src == NULL) { /* cannot initialize dictionary with null src */\n        NULL_SRC();\n    }\n    if (src_len < 8) {\n        DICT_SIZE_ERROR();\n    }\n\n    istream_t in = IO_make_istream(byte_src, src_len);\n\n    const u32 magic_number = IO_read_bits(&in, 32);\n    if (magic_number != 0xEC30A437) {\n        // raw content dict\n        IO_rewind_bits(&in, 32);\n        init_dictionary_content(dict, &in);\n        return;\n    }\n\n    dict->dictionary_id = IO_read_bits(&in, 32);\n\n    // \"Entropy_Tables : following the same format as the tables in compressed\n    // blocks. They are stored in following order : Huffman tables for literals,\n    // FSE table for offsets, FSE table for match lengths, and FSE table for\n    // literals lengths. It's finally followed by 3 offset values, populating\n    // recent offsets (instead of using {1,4,8}), stored in order, 4-bytes\n    // little-endian each, for a total of 12 bytes. Each recent offset must have\n    // a value < dictionary size.\"\n    decode_huf_table(&dict->literals_dtable, &in);\n    decode_seq_table(&dict->of_dtable, &in, seq_offset, seq_fse);\n    decode_seq_table(&dict->ml_dtable, &in, seq_match_length, seq_fse);\n    decode_seq_table(&dict->ll_dtable, &in, seq_literal_length, seq_fse);\n\n    // Read in the previous offset history\n    dict->previous_offsets[0] = IO_read_bits(&in, 32);\n    dict->previous_offsets[1] = IO_read_bits(&in, 32);\n    dict->previous_offsets[2] = IO_read_bits(&in, 32);\n\n    // Ensure the provided offsets aren't too large\n    // \"Each recent offset must have a value < dictionary size.\"\n    for (int i = 0; i < 3; i++) {\n        if (dict->previous_offsets[i] > src_len) {\n            ERROR(\"Dictionary corrupted\");\n        }\n    }\n\n    // \"Content : The rest of the dictionary is its content. The content act as\n    // a \"past\" in front of data to compress or decompress, so it can be\n    // referenced in sequence commands.\"\n    init_dictionary_content(dict, &in);\n}\n\nstatic void init_dictionary_content(dictionary_t *const dict,\n                                    istream_t *const in) {\n    // Copy in the content\n    dict->content_size = IO_istream_len(in);\n    dict->content = malloc(dict->content_size);\n    if (!dict->content) {\n        BAD_ALLOC();\n    }\n\n    const u8 *const content = IO_get_read_ptr(in, dict->content_size);\n\n    memcpy(dict->content, content, dict->content_size);\n}\n\nstatic void HUF_copy_dtable(HUF_dtable *const dst,\n                            const HUF_dtable *const src) {\n    if (src->max_bits == 0) {\n        memset(dst, 0, sizeof(HUF_dtable));\n        return;\n    }\n\n    const size_t size = (size_t)1 << src->max_bits;\n    dst->max_bits = src->max_bits;\n\n    dst->symbols = malloc(size);\n    dst->num_bits = malloc(size);\n    if (!dst->symbols || !dst->num_bits) {\n        BAD_ALLOC();\n    }\n\n    memcpy(dst->symbols, src->symbols, size);\n    memcpy(dst->num_bits, src->num_bits, size);\n}\n\nstatic void FSE_copy_dtable(FSE_dtable *const dst, const FSE_dtable *const src) {\n    if (src->accuracy_log == 0) {\n        memset(dst, 0, sizeof(FSE_dtable));\n        return;\n    }\n\n    size_t size = (size_t)1 << src->accuracy_log;\n    dst->accuracy_log = src->accuracy_log;\n\n    dst->symbols = malloc(size);\n    dst->num_bits = malloc(size);\n    dst->new_state_base = malloc(size * sizeof(u16));\n    if (!dst->symbols || !dst->num_bits || !dst->new_state_base) {\n        BAD_ALLOC();\n    }\n\n    memcpy(dst->symbols, src->symbols, size);\n    memcpy(dst->num_bits, src->num_bits, size);\n    memcpy(dst->new_state_base, src->new_state_base, size * sizeof(u16));\n}\n\n/// A dictionary acts as initializing values for the frame context before\n/// decompression, so we implement it by applying it's predetermined\n/// tables and content to the context before beginning decompression\nstatic void frame_context_apply_dict(frame_context_t *const ctx,\n                                     const dictionary_t *const dict) {\n    // If the content pointer is NULL then it must be an empty dict\n    if (!dict || !dict->content)\n        return;\n\n    // If the requested dictionary_id is non-zero, the correct dictionary must\n    // be present\n    if (ctx->header.dictionary_id != 0 &&\n        ctx->header.dictionary_id != dict->dictionary_id) {\n        ERROR(\"Wrong dictionary provided\");\n    }\n\n    // Copy the dict content to the context for references during sequence\n    // execution\n    ctx->dict_content = dict->content;\n    ctx->dict_content_len = dict->content_size;\n\n    // If it's a formatted dict copy the precomputed tables in so they can\n    // be used in the table repeat modes\n    if (dict->dictionary_id != 0) {\n        // Deep copy the entropy tables so they can be freed independently of\n        // the dictionary struct\n        HUF_copy_dtable(&ctx->literals_dtable, &dict->literals_dtable);\n        FSE_copy_dtable(&ctx->ll_dtable, &dict->ll_dtable);\n        FSE_copy_dtable(&ctx->of_dtable, &dict->of_dtable);\n        FSE_copy_dtable(&ctx->ml_dtable, &dict->ml_dtable);\n\n        // Copy the repeated offsets\n        memcpy(ctx->previous_offsets, dict->previous_offsets,\n               sizeof(ctx->previous_offsets));\n    }\n}\n\n#else  // ZDEC_NO_DICTIONARY is defined\n\nstatic void frame_context_apply_dict(frame_context_t *const ctx,\n                                     const dictionary_t *const dict) {\n    (void)ctx;\n    if (dict && dict->content) ERROR(\"dictionary not supported\");\n}\n\n#endif\n/******* END DICTIONARY PARSING ***********************************************/\n\n/******* IO STREAM OPERATIONS *************************************************/\n\n/// Reads `num` bits from a bitstream, and updates the internal offset\nstatic inline u64 IO_read_bits(istream_t *const in, const int num_bits) {\n    if (num_bits > 64 || num_bits <= 0) {\n        ERROR(\"Attempt to read an invalid number of bits\");\n    }\n\n    const size_t bytes = (num_bits + in->bit_offset + 7) / 8;\n    const size_t full_bytes = (num_bits + in->bit_offset) / 8;\n    if (bytes > in->len) {\n        INP_SIZE();\n    }\n\n    const u64 result = read_bits_LE(in->ptr, num_bits, in->bit_offset);\n\n    in->bit_offset = (num_bits + in->bit_offset) % 8;\n    in->ptr += full_bytes;\n    in->len -= full_bytes;\n\n    return result;\n}\n\n/// If a non-zero number of bits have been read from the current byte, advance\n/// the offset to the next byte\nstatic inline void IO_rewind_bits(istream_t *const in, int num_bits) {\n    if (num_bits < 0) {\n        ERROR(\"Attempting to rewind stream by a negative number of bits\");\n    }\n\n    // move the offset back by `num_bits` bits\n    const int new_offset = in->bit_offset - num_bits;\n    // determine the number of whole bytes we have to rewind, rounding up to an\n    // integer number (e.g. if `new_offset == -5`, `bytes == 1`)\n    const i64 bytes = -(new_offset - 7) / 8;\n\n    in->ptr -= bytes;\n    in->len += bytes;\n    // make sure the resulting `bit_offset` is positive, as mod in C does not\n    // convert numbers from negative to positive (e.g. -22 % 8 == -6)\n    in->bit_offset = ((new_offset % 8) + 8) % 8;\n}\n\n/// If the remaining bits in a byte will be unused, advance to the end of the\n/// byte\nstatic inline void IO_align_stream(istream_t *const in) {\n    if (in->bit_offset != 0) {\n        if (in->len == 0) {\n            INP_SIZE();\n        }\n        in->ptr++;\n        in->len--;\n        in->bit_offset = 0;\n    }\n}\n\n/// Write the given byte into the output stream\nstatic inline void IO_write_byte(ostream_t *const out, u8 symb) {\n    if (out->len == 0) {\n        OUT_SIZE();\n    }\n\n    out->ptr[0] = symb;\n    out->ptr++;\n    out->len--;\n}\n\n/// Returns the number of bytes left to be read in this stream.  The stream must\n/// be byte aligned.\nstatic inline size_t IO_istream_len(const istream_t *const in) {\n    return in->len;\n}\n\n/// Returns a pointer where `len` bytes can be read, and advances the internal\n/// state.  The stream must be byte aligned.\nstatic inline const u8 *IO_get_read_ptr(istream_t *const in, size_t len) {\n    if (len > in->len) {\n        INP_SIZE();\n    }\n    if (in->bit_offset != 0) {\n        ERROR(\"Attempting to operate on a non-byte aligned stream\");\n    }\n    const u8 *const ptr = in->ptr;\n    in->ptr += len;\n    in->len -= len;\n\n    return ptr;\n}\n/// Returns a pointer to write `len` bytes to, and advances the internal state\nstatic inline u8 *IO_get_write_ptr(ostream_t *const out, size_t len) {\n    if (len > out->len) {\n        OUT_SIZE();\n    }\n    u8 *const ptr = out->ptr;\n    out->ptr += len;\n    out->len -= len;\n\n    return ptr;\n}\n\n/// Advance the inner state by `len` bytes\nstatic inline void IO_advance_input(istream_t *const in, size_t len) {\n    if (len > in->len) {\n         INP_SIZE();\n    }\n    if (in->bit_offset != 0) {\n        ERROR(\"Attempting to operate on a non-byte aligned stream\");\n    }\n\n    in->ptr += len;\n    in->len -= len;\n}\n\n/// Returns an `ostream_t` constructed from the given pointer and length\nstatic inline ostream_t IO_make_ostream(u8 *out, size_t len) {\n    return (ostream_t) { out, len };\n}\n\n/// Returns an `istream_t` constructed from the given pointer and length\nstatic inline istream_t IO_make_istream(const u8 *in, size_t len) {\n    return (istream_t) { in, len, 0 };\n}\n\n/// Returns an `istream_t` with the same base as `in`, and length `len`\n/// Then, advance `in` to account for the consumed bytes\n/// `in` must be byte aligned\nstatic inline istream_t IO_make_sub_istream(istream_t *const in, size_t len) {\n    // Consume `len` bytes of the parent stream\n    const u8 *const ptr = IO_get_read_ptr(in, len);\n\n    // Make a substream using the pointer to those `len` bytes\n    return IO_make_istream(ptr, len);\n}\n/******* END IO STREAM OPERATIONS *********************************************/\n\n/******* BITSTREAM OPERATIONS *************************************************/\n/// Read `num` bits (up to 64) from `src + offset`, where `offset` is in bits\nstatic inline u64 read_bits_LE(const u8 *src, const int num_bits,\n                               const size_t offset) {\n    if (num_bits > 64) {\n        ERROR(\"Attempt to read an invalid number of bits\");\n    }\n\n    // Skip over bytes that aren't in range\n    src += offset / 8;\n    size_t bit_offset = offset % 8;\n    u64 res = 0;\n\n    int shift = 0;\n    int left = num_bits;\n    while (left > 0) {\n        u64 mask = left >= 8 ? 0xff : (((u64)1 << left) - 1);\n        // Read the next byte, shift it to account for the offset, and then mask\n        // out the top part if we don't need all the bits\n        res += (((u64)*src++ >> bit_offset) & mask) << shift;\n        shift += 8 - bit_offset;\n        left -= 8 - bit_offset;\n        bit_offset = 0;\n    }\n\n    return res;\n}\n\n/// Read bits from the end of a HUF or FSE bitstream.  `offset` is in bits, so\n/// it updates `offset` to `offset - bits`, and then reads `bits` bits from\n/// `src + offset`.  If the offset becomes negative, the extra bits at the\n/// bottom are filled in with `0` bits instead of reading from before `src`.\nstatic inline u64 STREAM_read_bits(const u8 *const src, const int bits,\n                                   i64 *const offset) {\n    *offset = *offset - bits;\n    size_t actual_off = *offset;\n    size_t actual_bits = bits;\n    // Don't actually read bits from before the start of src, so if `*offset <\n    // 0` fix actual_off and actual_bits to reflect the quantity to read\n    if (*offset < 0) {\n        actual_bits += *offset;\n        actual_off = 0;\n    }\n    u64 res = read_bits_LE(src, actual_bits, actual_off);\n\n    if (*offset < 0) {\n        // Fill in the bottom \"overflowed\" bits with 0's\n        res = -*offset >= 64 ? 0 : (res << -*offset);\n    }\n    return res;\n}\n/******* END BITSTREAM OPERATIONS *********************************************/\n\n/******* BIT COUNTING OPERATIONS **********************************************/\n/// Returns `x`, where `2^x` is the largest power of 2 less than or equal to\n/// `num`, or `-1` if `num == 0`.\nstatic inline int highest_set_bit(const u64 num) {\n    for (int i = 63; i >= 0; i--) {\n        if (((u64)1 << i) <= num) {\n            return i;\n        }\n    }\n    return -1;\n}\n/******* END BIT COUNTING OPERATIONS ******************************************/\n\n/******* HUFFMAN PRIMITIVES ***************************************************/\nstatic inline u8 HUF_decode_symbol(const HUF_dtable *const dtable,\n                                   u16 *const state, const u8 *const src,\n                                   i64 *const offset) {\n    // Look up the symbol and number of bits to read\n    const u8 symb = dtable->symbols[*state];\n    const u8 bits = dtable->num_bits[*state];\n    const u16 rest = STREAM_read_bits(src, bits, offset);\n    // Shift `bits` bits out of the state, keeping the low order bits that\n    // weren't necessary to determine this symbol.  Then add in the new bits\n    // read from the stream.\n    *state = ((*state << bits) + rest) & (((u16)1 << dtable->max_bits) - 1);\n\n    return symb;\n}\n\nstatic inline void HUF_init_state(const HUF_dtable *const dtable,\n                                  u16 *const state, const u8 *const src,\n                                  i64 *const offset) {\n    // Read in a full `dtable->max_bits` bits to initialize the state\n    const u8 bits = dtable->max_bits;\n    *state = STREAM_read_bits(src, bits, offset);\n}\n\nstatic size_t HUF_decompress_1stream(const HUF_dtable *const dtable,\n                                     ostream_t *const out,\n                                     istream_t *const in) {\n    const size_t len = IO_istream_len(in);\n    if (len == 0) {\n        INP_SIZE();\n    }\n    const u8 *const src = IO_get_read_ptr(in, len);\n\n    // \"Each bitstream must be read backward, that is starting from the end down\n    // to the beginning. Therefore it's necessary to know the size of each\n    // bitstream.\n    //\n    // It's also necessary to know exactly which bit is the latest. This is\n    // detected by a final bit flag : the highest bit of latest byte is a\n    // final-bit-flag. Consequently, a last byte of 0 is not possible. And the\n    // final-bit-flag itself is not part of the useful bitstream. Hence, the\n    // last byte contains between 0 and 7 useful bits.\"\n    const int padding = 8 - highest_set_bit(src[len - 1]);\n\n    // Offset starts at the end because HUF streams are read backwards\n    i64 bit_offset = len * 8 - padding;\n    u16 state;\n\n    HUF_init_state(dtable, &state, src, &bit_offset);\n\n    size_t symbols_written = 0;\n    while (bit_offset > -dtable->max_bits) {\n        // Iterate over the stream, decoding one symbol at a time\n        IO_write_byte(out, HUF_decode_symbol(dtable, &state, src, &bit_offset));\n        symbols_written++;\n    }\n    // \"The process continues up to reading the required number of symbols per\n    // stream. If a bitstream is not entirely and exactly consumed, hence\n    // reaching exactly its beginning position with all bits consumed, the\n    // decoding process is considered faulty.\"\n\n    // When all symbols have been decoded, the final state value shouldn't have\n    // any data from the stream, so it should have \"read\" dtable->max_bits from\n    // before the start of `src`\n    // Therefore `offset`, the edge to start reading new bits at, should be\n    // dtable->max_bits before the start of the stream\n    if (bit_offset != -dtable->max_bits) {\n        CORRUPTION();\n    }\n\n    return symbols_written;\n}\n\nstatic size_t HUF_decompress_4stream(const HUF_dtable *const dtable,\n                                     ostream_t *const out, istream_t *const in) {\n    // \"Compressed size is provided explicitly : in the 4-streams variant,\n    // bitstreams are preceded by 3 unsigned little-endian 16-bits values. Each\n    // value represents the compressed size of one stream, in order. The last\n    // stream size is deducted from total compressed size and from previously\n    // decoded stream sizes\"\n    const size_t csize1 = IO_read_bits(in, 16);\n    const size_t csize2 = IO_read_bits(in, 16);\n    const size_t csize3 = IO_read_bits(in, 16);\n\n    istream_t in1 = IO_make_sub_istream(in, csize1);\n    istream_t in2 = IO_make_sub_istream(in, csize2);\n    istream_t in3 = IO_make_sub_istream(in, csize3);\n    istream_t in4 = IO_make_sub_istream(in, IO_istream_len(in));\n\n    size_t total_output = 0;\n    // Decode each stream independently for simplicity\n    // If we wanted to we could decode all 4 at the same time for speed,\n    // utilizing more execution units\n    total_output += HUF_decompress_1stream(dtable, out, &in1);\n    total_output += HUF_decompress_1stream(dtable, out, &in2);\n    total_output += HUF_decompress_1stream(dtable, out, &in3);\n    total_output += HUF_decompress_1stream(dtable, out, &in4);\n\n    return total_output;\n}\n\n/// Initializes a Huffman table using canonical Huffman codes\n/// For more explanation on canonical Huffman codes see\n/// https://www.cs.scranton.edu/~mccloske/courses/cmps340/huff_canonical_dec2015.html\n/// Codes within a level are allocated in symbol order (i.e. smaller symbols get\n/// earlier codes)\nstatic void HUF_init_dtable(HUF_dtable *const table, const u8 *const bits,\n                            const int num_symbs) {\n    memset(table, 0, sizeof(HUF_dtable));\n    if (num_symbs > HUF_MAX_SYMBS) {\n        ERROR(\"Too many symbols for Huffman\");\n    }\n\n    u8 max_bits = 0;\n    u16 rank_count[HUF_MAX_BITS + 1];\n    memset(rank_count, 0, sizeof(rank_count));\n\n    // Count the number of symbols for each number of bits, and determine the\n    // depth of the tree\n    for (int i = 0; i < num_symbs; i++) {\n        if (bits[i] > HUF_MAX_BITS) {\n            ERROR(\"Huffman table depth too large\");\n        }\n        max_bits = MAX(max_bits, bits[i]);\n        rank_count[bits[i]]++;\n    }\n\n    const size_t table_size = 1 << max_bits;\n    table->max_bits = max_bits;\n    table->symbols = malloc(table_size);\n    table->num_bits = malloc(table_size);\n\n    if (!table->symbols || !table->num_bits) {\n        free(table->symbols);\n        free(table->num_bits);\n        BAD_ALLOC();\n    }\n\n    // \"Symbols are sorted by Weight. Within same Weight, symbols keep natural\n    // order. Symbols with a Weight of zero are removed. Then, starting from\n    // lowest weight, prefix codes are distributed in order.\"\n\n    u32 rank_idx[HUF_MAX_BITS + 1];\n    // Initialize the starting codes for each rank (number of bits)\n    rank_idx[max_bits] = 0;\n    for (int i = max_bits; i >= 1; i--) {\n        rank_idx[i - 1] = rank_idx[i] + rank_count[i] * (1 << (max_bits - i));\n        // The entire range takes the same number of bits so we can memset it\n        memset(&table->num_bits[rank_idx[i]], i, rank_idx[i - 1] - rank_idx[i]);\n    }\n\n    if (rank_idx[0] != table_size) {\n        CORRUPTION();\n    }\n\n    // Allocate codes and fill in the table\n    for (int i = 0; i < num_symbs; i++) {\n        if (bits[i] != 0) {\n            // Allocate a code for this symbol and set its range in the table\n            const u16 code = rank_idx[bits[i]];\n            // Since the code doesn't care about the bottom `max_bits - bits[i]`\n            // bits of state, it gets a range that spans all possible values of\n            // the lower bits\n            const u16 len = 1 << (max_bits - bits[i]);\n            memset(&table->symbols[code], i, len);\n            rank_idx[bits[i]] += len;\n        }\n    }\n}\n\nstatic void HUF_init_dtable_usingweights(HUF_dtable *const table,\n                                         const u8 *const weights,\n                                         const int num_symbs) {\n    // +1 because the last weight is not transmitted in the header\n    if (num_symbs + 1 > HUF_MAX_SYMBS) {\n        ERROR(\"Too many symbols for Huffman\");\n    }\n\n    u8 bits[HUF_MAX_SYMBS];\n\n    u64 weight_sum = 0;\n    for (int i = 0; i < num_symbs; i++) {\n        // Weights are in the same range as bit count\n        if (weights[i] > HUF_MAX_BITS) {\n            CORRUPTION();\n        }\n        weight_sum += weights[i] > 0 ? (u64)1 << (weights[i] - 1) : 0;\n    }\n\n    // Find the first power of 2 larger than the sum\n    const int max_bits = highest_set_bit(weight_sum) + 1;\n    const u64 left_over = ((u64)1 << max_bits) - weight_sum;\n    // If the left over isn't a power of 2, the weights are invalid\n    if (left_over & (left_over - 1)) {\n        CORRUPTION();\n    }\n\n    // left_over is used to find the last weight as it's not transmitted\n    // by inverting 2^(weight - 1) we can determine the value of last_weight\n    const int last_weight = highest_set_bit(left_over) + 1;\n\n    for (int i = 0; i < num_symbs; i++) {\n        // \"Number_of_Bits = Number_of_Bits ? Max_Number_of_Bits + 1 - Weight : 0\"\n        bits[i] = weights[i] > 0 ? (max_bits + 1 - weights[i]) : 0;\n    }\n    bits[num_symbs] =\n        max_bits + 1 - last_weight; // Last weight is always non-zero\n\n    HUF_init_dtable(table, bits, num_symbs + 1);\n}\n\nstatic void HUF_free_dtable(HUF_dtable *const dtable) {\n    free(dtable->symbols);\n    free(dtable->num_bits);\n    memset(dtable, 0, sizeof(HUF_dtable));\n}\n/******* END HUFFMAN PRIMITIVES ***********************************************/\n\n/******* FSE PRIMITIVES *******************************************************/\n/// For more description of FSE see\n/// https://github.com/Cyan4973/FiniteStateEntropy/\n\n/// Allow a symbol to be decoded without updating state\nstatic inline u8 FSE_peek_symbol(const FSE_dtable *const dtable,\n                                 const u16 state) {\n    return dtable->symbols[state];\n}\n\n/// Consumes bits from the input and uses the current state to determine the\n/// next state\nstatic inline void FSE_update_state(const FSE_dtable *const dtable,\n                                    u16 *const state, const u8 *const src,\n                                    i64 *const offset) {\n    const u8 bits = dtable->num_bits[*state];\n    const u16 rest = STREAM_read_bits(src, bits, offset);\n    *state = dtable->new_state_base[*state] + rest;\n}\n\n/// Decodes a single FSE symbol and updates the offset\nstatic inline u8 FSE_decode_symbol(const FSE_dtable *const dtable,\n                                   u16 *const state, const u8 *const src,\n                                   i64 *const offset) {\n    const u8 symb = FSE_peek_symbol(dtable, *state);\n    FSE_update_state(dtable, state, src, offset);\n    return symb;\n}\n\nstatic inline void FSE_init_state(const FSE_dtable *const dtable,\n                                  u16 *const state, const u8 *const src,\n                                  i64 *const offset) {\n    // Read in a full `accuracy_log` bits to initialize the state\n    const u8 bits = dtable->accuracy_log;\n    *state = STREAM_read_bits(src, bits, offset);\n}\n\nstatic size_t FSE_decompress_interleaved2(const FSE_dtable *const dtable,\n                                          ostream_t *const out,\n                                          istream_t *const in) {\n    const size_t len = IO_istream_len(in);\n    if (len == 0) {\n        INP_SIZE();\n    }\n    const u8 *const src = IO_get_read_ptr(in, len);\n\n    // \"Each bitstream must be read backward, that is starting from the end down\n    // to the beginning. Therefore it's necessary to know the size of each\n    // bitstream.\n    //\n    // It's also necessary to know exactly which bit is the latest. This is\n    // detected by a final bit flag : the highest bit of latest byte is a\n    // final-bit-flag. Consequently, a last byte of 0 is not possible. And the\n    // final-bit-flag itself is not part of the useful bitstream. Hence, the\n    // last byte contains between 0 and 7 useful bits.\"\n    const int padding = 8 - highest_set_bit(src[len - 1]);\n    i64 offset = len * 8 - padding;\n\n    u16 state1, state2;\n    // \"The first state (State1) encodes the even indexed symbols, and the\n    // second (State2) encodes the odd indexes. State1 is initialized first, and\n    // then State2, and they take turns decoding a single symbol and updating\n    // their state.\"\n    FSE_init_state(dtable, &state1, src, &offset);\n    FSE_init_state(dtable, &state2, src, &offset);\n\n    // Decode until we overflow the stream\n    // Since we decode in reverse order, overflowing the stream is offset going\n    // negative\n    size_t symbols_written = 0;\n    while (1) {\n        // \"The number of symbols to decode is determined by tracking bitStream\n        // overflow condition: If updating state after decoding a symbol would\n        // require more bits than remain in the stream, it is assumed the extra\n        // bits are 0. Then, the symbols for each of the final states are\n        // decoded and the process is complete.\"\n        IO_write_byte(out, FSE_decode_symbol(dtable, &state1, src, &offset));\n        symbols_written++;\n        if (offset < 0) {\n            // There's still a symbol to decode in state2\n            IO_write_byte(out, FSE_peek_symbol(dtable, state2));\n            symbols_written++;\n            break;\n        }\n\n        IO_write_byte(out, FSE_decode_symbol(dtable, &state2, src, &offset));\n        symbols_written++;\n        if (offset < 0) {\n            // There's still a symbol to decode in state1\n            IO_write_byte(out, FSE_peek_symbol(dtable, state1));\n            symbols_written++;\n            break;\n        }\n    }\n\n    return symbols_written;\n}\n\nstatic void FSE_init_dtable(FSE_dtable *const dtable,\n                            const i16 *const norm_freqs, const int num_symbs,\n                            const int accuracy_log) {\n    if (accuracy_log > FSE_MAX_ACCURACY_LOG) {\n        ERROR(\"FSE accuracy too large\");\n    }\n    if (num_symbs > FSE_MAX_SYMBS) {\n        ERROR(\"Too many symbols for FSE\");\n    }\n\n    dtable->accuracy_log = accuracy_log;\n\n    const size_t size = (size_t)1 << accuracy_log;\n    dtable->symbols = malloc(size * sizeof(u8));\n    dtable->num_bits = malloc(size * sizeof(u8));\n    dtable->new_state_base = malloc(size * sizeof(u16));\n\n    if (!dtable->symbols || !dtable->num_bits || !dtable->new_state_base) {\n        BAD_ALLOC();\n    }\n\n    // Used to determine how many bits need to be read for each state,\n    // and where the destination range should start\n    // Needs to be u16 because max value is 2 * max number of symbols,\n    // which can be larger than a byte can store\n    u16 state_desc[FSE_MAX_SYMBS];\n\n    // \"Symbols are scanned in their natural order for \"less than 1\"\n    // probabilities. Symbols with this probability are being attributed a\n    // single cell, starting from the end of the table. These symbols define a\n    // full state reset, reading Accuracy_Log bits.\"\n    int high_threshold = size;\n    for (int s = 0; s < num_symbs; s++) {\n        // Scan for low probability symbols to put at the top\n        if (norm_freqs[s] == -1) {\n            dtable->symbols[--high_threshold] = s;\n            state_desc[s] = 1;\n        }\n    }\n\n    // \"All remaining symbols are sorted in their natural order. Starting from\n    // symbol 0 and table position 0, each symbol gets attributed as many cells\n    // as its probability. Cell allocation is spread, not linear.\"\n    // Place the rest in the table\n    const u16 step = (size >> 1) + (size >> 3) + 3;\n    const u16 mask = size - 1;\n    u16 pos = 0;\n    for (int s = 0; s < num_symbs; s++) {\n        if (norm_freqs[s] <= 0) {\n            continue;\n        }\n\n        state_desc[s] = norm_freqs[s];\n\n        for (int i = 0; i < norm_freqs[s]; i++) {\n            // Give `norm_freqs[s]` states to symbol s\n            dtable->symbols[pos] = s;\n            // \"A position is skipped if already occupied, typically by a \"less\n            // than 1\" probability symbol.\"\n            do {\n                pos = (pos + step) & mask;\n            } while (pos >=\n                     high_threshold);\n            // Note: no other collision checking is necessary as `step` is\n            // coprime to `size`, so the cycle will visit each position exactly\n            // once\n        }\n    }\n    if (pos != 0) {\n        CORRUPTION();\n    }\n\n    // Now we can fill baseline and num bits\n    for (size_t i = 0; i < size; i++) {\n        u8 symbol = dtable->symbols[i];\n        u16 next_state_desc = state_desc[symbol]++;\n        // Fills in the table appropriately, next_state_desc increases by symbol\n        // over time, decreasing number of bits\n        dtable->num_bits[i] = (u8)(accuracy_log - highest_set_bit(next_state_desc));\n        // Baseline increases until the bit threshold is passed, at which point\n        // it resets to 0\n        dtable->new_state_base[i] =\n            ((u16)next_state_desc << dtable->num_bits[i]) - size;\n    }\n}\n\n/// Decode an FSE header as defined in the Zstandard format specification and\n/// use the decoded frequencies to initialize a decoding table.\nstatic void FSE_decode_header(FSE_dtable *const dtable, istream_t *const in,\n                                const int max_accuracy_log) {\n    // \"An FSE distribution table describes the probabilities of all symbols\n    // from 0 to the last present one (included) on a normalized scale of 1 <<\n    // Accuracy_Log .\n    //\n    // It's a bitstream which is read forward, in little-endian fashion. It's\n    // not necessary to know its exact size, since it will be discovered and\n    // reported by the decoding process.\n    if (max_accuracy_log > FSE_MAX_ACCURACY_LOG) {\n        ERROR(\"FSE accuracy too large\");\n    }\n\n    // The bitstream starts by reporting on which scale it operates.\n    // Accuracy_Log = low4bits + 5. Note that maximum Accuracy_Log for literal\n    // and match lengths is 9, and for offsets is 8. Higher values are\n    // considered errors.\"\n    const int accuracy_log = 5 + IO_read_bits(in, 4);\n    if (accuracy_log > max_accuracy_log) {\n        ERROR(\"FSE accuracy too large\");\n    }\n\n    // \"Then follows each symbol value, from 0 to last present one. The number\n    // of bits used by each field is variable. It depends on :\n    //\n    // Remaining probabilities + 1 : example : Presuming an Accuracy_Log of 8,\n    // and presuming 100 probabilities points have already been distributed, the\n    // decoder may read any value from 0 to 255 - 100 + 1 == 156 (inclusive).\n    // Therefore, it must read log2sup(156) == 8 bits.\n    //\n    // Value decoded : small values use 1 less bit : example : Presuming values\n    // from 0 to 156 (inclusive) are possible, 255-156 = 99 values are remaining\n    // in an 8-bits field. They are used this way : first 99 values (hence from\n    // 0 to 98) use only 7 bits, values from 99 to 156 use 8 bits. \"\n\n    i32 remaining = 1 << accuracy_log;\n    i16 frequencies[FSE_MAX_SYMBS];\n\n    int symb = 0;\n    while (remaining > 0 && symb < FSE_MAX_SYMBS) {\n        // Log of the number of possible values we could read\n        int bits = highest_set_bit(remaining + 1) + 1;\n\n        u16 val = IO_read_bits(in, bits);\n\n        // Try to mask out the lower bits to see if it qualifies for the \"small\n        // value\" threshold\n        const u16 lower_mask = ((u16)1 << (bits - 1)) - 1;\n        const u16 threshold = ((u16)1 << bits) - 1 - (remaining + 1);\n\n        if ((val & lower_mask) < threshold) {\n            IO_rewind_bits(in, 1);\n            val = val & lower_mask;\n        } else if (val > lower_mask) {\n            val = val - threshold;\n        }\n\n        // \"Probability is obtained from Value decoded by following formula :\n        // Proba = value - 1\"\n        const i16 proba = (i16)val - 1;\n\n        // \"It means value 0 becomes negative probability -1. -1 is a special\n        // probability, which means \"less than 1\". Its effect on distribution\n        // table is described in next paragraph. For the purpose of calculating\n        // cumulated distribution, it counts as one.\"\n        remaining -= proba < 0 ? -proba : proba;\n\n        frequencies[symb] = proba;\n        symb++;\n\n        // \"When a symbol has a probability of zero, it is followed by a 2-bits\n        // repeat flag. This repeat flag tells how many probabilities of zeroes\n        // follow the current one. It provides a number ranging from 0 to 3. If\n        // it is a 3, another 2-bits repeat flag follows, and so on.\"\n        if (proba == 0) {\n            // Read the next two bits to see how many more 0s\n            int repeat = IO_read_bits(in, 2);\n\n            while (1) {\n                for (int i = 0; i < repeat && symb < FSE_MAX_SYMBS; i++) {\n                    frequencies[symb++] = 0;\n                }\n                if (repeat == 3) {\n                    repeat = IO_read_bits(in, 2);\n                } else {\n                    break;\n                }\n            }\n        }\n    }\n    IO_align_stream(in);\n\n    // \"When last symbol reaches cumulated total of 1 << Accuracy_Log, decoding\n    // is complete. If the last symbol makes cumulated total go above 1 <<\n    // Accuracy_Log, distribution is considered corrupted.\"\n    if (remaining != 0 || symb >= FSE_MAX_SYMBS) {\n        CORRUPTION();\n    }\n\n    // Initialize the decoding table using the determined weights\n    FSE_init_dtable(dtable, frequencies, symb, accuracy_log);\n}\n\nstatic void FSE_init_dtable_rle(FSE_dtable *const dtable, const u8 symb) {\n    dtable->symbols = malloc(sizeof(u8));\n    dtable->num_bits = malloc(sizeof(u8));\n    dtable->new_state_base = malloc(sizeof(u16));\n\n    if (!dtable->symbols || !dtable->num_bits || !dtable->new_state_base) {\n        BAD_ALLOC();\n    }\n\n    // This setup will always have a state of 0, always return symbol `symb`,\n    // and never consume any bits\n    dtable->symbols[0] = symb;\n    dtable->num_bits[0] = 0;\n    dtable->new_state_base[0] = 0;\n    dtable->accuracy_log = 0;\n}\n\nstatic void FSE_free_dtable(FSE_dtable *const dtable) {\n    free(dtable->symbols);\n    free(dtable->num_bits);\n    free(dtable->new_state_base);\n    memset(dtable, 0, sizeof(FSE_dtable));\n}\n/******* END FSE PRIMITIVES ***************************************************/\n"
  },
  {
    "path": "doc/educational_decoder/zstd_decompress.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include <stddef.h>   /* size_t */\n\n/******* EXPOSED TYPES ********************************************************/\n/*\n* Contains the parsed contents of a dictionary\n* This includes Huffman and FSE tables used for decoding and data on offsets\n*/\ntypedef struct dictionary_s dictionary_t;\n/******* END EXPOSED TYPES ****************************************************/\n\n/******* DECOMPRESSION FUNCTIONS **********************************************/\n/// Zstandard decompression functions.\n/// `dst` must point to a space at least as large as the reconstructed output.\nsize_t ZSTD_decompress(void *const dst, const size_t dst_len,\n                    const void *const src, const size_t src_len);\n\n/// If `dict != NULL` and `dict_len >= 8`, does the same thing as\n/// `ZSTD_decompress` but uses the provided dict\nsize_t ZSTD_decompress_with_dict(void *const dst, const size_t dst_len,\n                              const void *const src, const size_t src_len,\n                              dictionary_t* parsed_dict);\n\n/// Get the decompressed size of an input stream so memory can be allocated in\n/// advance\n/// Returns -1 if the size can't be determined\n/// Assumes decompression of a single frame\nsize_t ZSTD_get_decompressed_size(const void *const src, const size_t src_len);\n/******* END DECOMPRESSION FUNCTIONS ******************************************/\n\n/******* DICTIONARY MANAGEMENT ***********************************************/\n/*\n * Return a valid dictionary_t pointer for use with dictionary initialization\n * or decompression\n */\ndictionary_t* create_dictionary(void);\n\n/*\n * Parse a provided dictionary blob for use in decompression\n * `src` -- must point to memory space representing the dictionary\n * `src_len` -- must provide the dictionary size\n * `dict` -- will contain the parsed contents of the dictionary and\n *        can be used for decompression\n */\nvoid parse_dictionary(dictionary_t *const dict, const void *src,\n                             size_t src_len);\n\n/*\n * Free internal Huffman tables, FSE tables, and dictionary content\n */\nvoid free_dictionary(dictionary_t *const dict);\n/******* END DICTIONARY MANAGEMENT *******************************************/\n"
  },
  {
    "path": "doc/zstd_compression_format.md",
    "content": "Zstandard Compression Format\n============================\n\n### Notices\n\nCopyright (c) Meta Platforms, Inc. and affiliates.\n\nPermission is granted to copy and distribute this document\nfor any purpose and without charge,\nincluding translations into other languages\nand incorporation into compilations,\nprovided that the copyright notice and this notice are preserved,\nand that any substantive changes or deletions from the original\nare clearly marked.\nDistribution of this document is unlimited.\n\n### Version\n\n0.4.4 (2025-03-22)\n\n\nIntroduction\n------------\n\nThe purpose of this document is to define a lossless compressed data format,\nthat is independent of CPU type, operating system,\nfile system and character set, suitable for\nfile compression, pipe and streaming compression,\nusing the [Zstandard algorithm](https://facebook.github.io/zstd/).\nThe text of the specification assumes a basic background in programming\nat the level of bits and other primitive data representations.\n\nThe data can be produced or consumed,\neven for an arbitrarily long sequentially presented input data stream,\nusing only an a priori bounded amount of intermediate storage,\nand hence can be used in data communications.\nThe format uses the Zstandard compression method,\nand optional [xxHash-64 checksum method](https://cyan4973.github.io/xxHash/),\nfor detection of data corruption.\n\nThe data format defined by this specification\ndoes not attempt to allow random access to compressed data.\n\nUnless otherwise indicated below,\na compliant compressor must produce data sets\nthat conform to the specifications presented here.\nIt doesn’t need to support all options though.\n\nA compliant decompressor must be able to decompress\nat least one working set of parameters\nthat conforms to the specifications presented here.\nIt may also ignore informative fields, such as checksum.\nWhenever it does not support a parameter defined in the compressed stream,\nit must produce a non-ambiguous error code and associated error message\nexplaining which parameter is unsupported.\n\nThis specification is intended for use by implementers of software\nto compress data into Zstandard format and/or decompress data from Zstandard format.\nThe Zstandard format is supported by an open source reference implementation,\nwritten in portable C, and available at : https://github.com/facebook/zstd .\n\n\n### Overall conventions\nIn this document:\n- square brackets i.e. `[` and `]` are used to indicate optional fields or parameters.\n- the naming convention for identifiers is `Mixed_Case_With_Underscores`\n\n### Definitions\nContent compressed by Zstandard is transformed into a Zstandard __frame__.\nMultiple frames can be appended into a single file or stream.\nA frame is completely independent, has a defined beginning and end,\nand a set of parameters which tells the decoder how to decompress it.\n\nA frame encapsulates one or multiple __blocks__.\nEach block contains arbitrary content, which is described by its header,\nand has a guaranteed maximum content size, which depends on frame parameters.\nUnlike frames, each block depends on previous blocks for proper decoding.\nHowever, each block can be decompressed without waiting for its successor,\nallowing streaming operations.\n\nOverview\n---------\n- [Frames](#frames)\n  - [Zstandard frames](#zstandard-frames)\n    - [Blocks](#blocks)\n      - [Literals Section](#literals-section)\n      - [Sequences Section](#sequences-section)\n      - [Sequence Execution](#sequence-execution)\n  - [Skippable frames](#skippable-frames)\n- [Entropy Encoding](#entropy-encoding)\n  - [FSE](#fse)\n  - [Huffman Coding](#huffman-coding)\n- [Dictionary Format](#dictionary-format)\n\nFrames\n------\nZstandard compressed data is made of one or more __frames__.\nEach frame is independent and can be decompressed independently of other frames.\nThe decompressed content of multiple concatenated frames is the concatenation of\neach frame decompressed content.\n\nThere are two frame formats defined by Zstandard:\n  Zstandard frames and Skippable frames.\nZstandard frames contain compressed data, while\nskippable frames contain custom user metadata.\n\n## Zstandard frames\nThe structure of a single Zstandard frame is following:\n\n| `Magic_Number` | `Frame_Header` |`Data_Block`| [More data blocks] | [`Content_Checksum`] |\n|:--------------:|:--------------:|:----------:| ------------------ |:--------------------:|\n|  4 bytes       |  2-14 bytes    |  n bytes   |                    |     0-4 bytes        |\n\n__`Magic_Number`__\n\n4 Bytes, __little-endian__ format.\nValue : 0xFD2FB528\nNote: This value was selected to be less probable to find at the beginning of some random file.\nIt avoids trivial patterns (0x00, 0xFF, repeated bytes, increasing bytes, etc.),\ncontains byte values outside of ASCII range,\nand doesn't map into UTF8 space.\nIt reduces the chances that a text file represent this value by accident.\n\n__`Frame_Header`__\n\n2 to 14 Bytes, detailed in [`Frame_Header`](#frame_header).\n\n__`Data_Block`__\n\nDetailed in [`Blocks`](#blocks).\nThat’s where compressed data is stored.\n\n__`Content_Checksum`__\n\nAn optional 32-bit checksum, only present if `Content_Checksum_flag` is set.\nThe content checksum is the result\nof [xxh64() hash function](https://cyan4973.github.io/xxHash/)\ndigesting the original (decoded) data as input, and a seed of zero.\nThe low 4 bytes of the checksum are stored in __little-endian__ format.\n\n### `Frame_Header`\n\nThe `Frame_Header` has a variable size, with a minimum of 2 bytes,\nand up to 14 bytes depending on optional parameters.\nThe structure of `Frame_Header` is following:\n\n| `Frame_Header_Descriptor` | [`Window_Descriptor`] | [`Dictionary_ID`] | [`Frame_Content_Size`] |\n| ------------------------- | --------------------- | ----------------- | ---------------------- |\n| 1 byte                    | 0-1 byte              | 0-4 bytes         | 0-8 bytes              |\n\n#### `Frame_Header_Descriptor`\n\nThe first header's byte is called the `Frame_Header_Descriptor`.\nIt describes which other fields are present.\nDecoding this byte is enough to tell the size of `Frame_Header`.\n\n| Bit number | Field name                |\n| ---------- | ----------                |\n| 7-6        | `Frame_Content_Size_flag` |\n| 5          | `Single_Segment_flag`     |\n| 4          | `Unused_bit`              |\n| 3          | `Reserved_bit`            |\n| 2          | `Content_Checksum_flag`   |\n| 1-0        | `Dictionary_ID_flag`      |\n\nIn this table, bit 7 is the highest bit, while bit 0 is the lowest one.\n\n__`Frame_Content_Size_flag`__\n\nThis is a 2-bits flag (`= Frame_Header_Descriptor >> 6`),\nspecifying if `Frame_Content_Size` (the decompressed data size)\nis provided within the header.\n`Flag_Value` provides `FCS_Field_Size`,\nwhich is the number of bytes used by `Frame_Content_Size`\naccording to the following table:\n\n|  `Flag_Value`  |    0   |  1  |  2  |  3  |\n| -------------- | ------ | --- | --- | --- |\n|`FCS_Field_Size`| 0 or 1 |  2  |  4  |  8  |\n\nWhen `Flag_Value` is `0`, `FCS_Field_Size` depends on `Single_Segment_flag` :\nif `Single_Segment_flag` is set, `FCS_Field_Size` is 1.\nOtherwise, `FCS_Field_Size` is 0 : `Frame_Content_Size` is not provided.\n\n__`Single_Segment_flag`__\n\nIf this flag is set,\ndata must be regenerated within a single continuous memory segment.\n\nIn this case, `Window_Descriptor` byte is skipped,\nbut `Frame_Content_Size` is necessarily present.\nAs a consequence, the decoder must allocate a memory segment\nof size equal or larger than `Frame_Content_Size`.\n\nIn order to preserve the decoder from unreasonable memory requirements,\na decoder is allowed to reject a compressed frame\nwhich requests a memory size beyond decoder's authorized range.\n\nFor broader compatibility, decoders are recommended to support\nmemory sizes of at least 8 MB.\nThis is only a recommendation,\neach decoder is free to support higher or lower limits,\ndepending on local limitations.\n\n__`Unused_bit`__\n\nA decoder compliant with this specification version shall not interpret this bit.\nIt might be used in any future version,\nto signal a property which is transparent to properly decode the frame.\nAn encoder compliant with this specification version must set this bit to zero.\n\n__`Reserved_bit`__\n\nThis bit is reserved for some future feature.\nIts value _must be zero_.\nA decoder compliant with this specification version must ensure it is not set.\nThis bit may be used in a future revision,\nto signal a feature that must be interpreted to decode the frame correctly.\n\n__`Content_Checksum_flag`__\n\nIf this flag is set, a 32-bits `Content_Checksum` will be present at frame's end.\nSee `Content_Checksum` paragraph.\n\n__`Dictionary_ID_flag`__\n\nThis is a 2-bits flag (`= FHD & 3`),\ntelling if a dictionary ID is provided within the header.\nIt also specifies the size of this field as `DID_Field_Size`.\n\n|`Flag_Value`    |  0  |  1  |  2  |  3  |\n| -------------- | --- | --- | --- | --- |\n|`DID_Field_Size`|  0  |  1  |  2  |  4  |\n\n#### `Window_Descriptor`\n\nProvides guarantees on minimum memory buffer required to decompress a frame.\nThis information is important for decoders to allocate enough memory.\n\nThe `Window_Descriptor` byte is optional.\nWhen `Single_Segment_flag` is set, `Window_Descriptor` is not present.\nIn this case, `Window_Size` is `Frame_Content_Size`,\nwhich can be any value from 0 to 2^64-1 bytes (16 ExaBytes).\n\n| Bit numbers |     7-3    |     2-0    |\n| ----------- | ---------- | ---------- |\n| Field name  | `Exponent` | `Mantissa` |\n\nThe minimum memory buffer size is called `Window_Size`.\nIt is described by the following formulas :\n```\nwindowLog = 10 + Exponent;\nwindowBase = 1 << windowLog;\nwindowAdd = (windowBase / 8) * Mantissa;\nWindow_Size = windowBase + windowAdd;\n```\nThe minimum `Window_Size` is 1 KB.\nThe maximum `Window_Size` is `(1<<41) + 7*(1<<38)` bytes, which is 3.75 TB.\n\nIn general, larger `Window_Size` tend to improve compression ratio,\nbut at the cost of memory usage.\n\nTo properly decode compressed data,\na decoder will need to allocate a buffer of at least `Window_Size` bytes.\n\nIn order to preserve decoder from unreasonable memory requirements,\na decoder is allowed to reject a compressed frame\nwhich requests a memory size beyond decoder's authorized range.\n\nFor improved interoperability,\nit's recommended for decoders to support `Window_Size` of up to 8 MB,\nand it's recommended for encoders to not generate frame requiring `Window_Size` larger than 8 MB.\nIt's merely a recommendation though,\ndecoders are free to support larger or lower limits,\ndepending on local limitations.\n\n#### `Dictionary_ID`\n\nThis is a variable size field, which contains\nthe ID of the dictionary required to properly decode the frame.\n`Dictionary_ID` field is optional. When it's not present,\nit's up to the decoder to know which dictionary to use.\n\n`Dictionary_ID` field size is provided by `DID_Field_Size`.\n`DID_Field_Size` is directly derived from value of `Dictionary_ID_flag`.\n1 byte can represent an ID 0-255.\n2 bytes can represent an ID 0-65535.\n4 bytes can represent an ID 0-4294967295.\nFormat is __little-endian__.\n\nIt's allowed to represent a small ID (for example `13`)\nwith a large 4-bytes dictionary ID, even if it is less efficient.\n\nA value of `0` has same meaning as no `Dictionary_ID`,\nin which case the frame may or may not need a dictionary to be decoded,\nand the ID of such a dictionary is not specified.\nThe decoder must know this information by other means.\n\n#### `Frame_Content_Size`\n\nThis is the original (uncompressed) size. This information is optional.\n`Frame_Content_Size` uses a variable number of bytes, provided by `FCS_Field_Size`.\n`FCS_Field_Size` is provided by the value of `Frame_Content_Size_flag`.\n`FCS_Field_Size` can be equal to 0 (not present), 1, 2, 4 or 8 bytes.\n\n| `FCS_Field_Size` |    Range   |\n| ---------------- | ---------- |\n|        0         |   unknown  |\n|        1         |   0 - 255  |\n|        2         | 256 - 65791|\n|        4         | 0 - 2^32-1 |\n|        8         | 0 - 2^64-1 |\n\n`Frame_Content_Size` format is __little-endian__.\nWhen `FCS_Field_Size` is 1, 4 or 8 bytes, the value is read directly.\nWhen `FCS_Field_Size` is 2, _the offset of 256 is added_.\nIt's allowed to represent a small size (for example `18`) using any compatible variant.\n\n\nBlocks\n-------\n\nAfter `Magic_Number` and `Frame_Header`, there are some number of blocks.\nEach frame must have at least one block,\nbut there is no upper limit on the number of blocks per frame.\n\nThe structure of a block is as follows:\n\n| `Block_Header` | `Block_Content` |\n|:--------------:|:---------------:|\n|    3 bytes     |     n bytes     |\n\n__`Block_Header`__\n\n`Block_Header` uses 3 bytes, written using __little-endian__ convention.\nIt contains 3 fields :\n\n| `Last_Block` | `Block_Type` | `Block_Size` |\n|:------------:|:------------:|:------------:|\n|    bit 0     |  bits 1-2    |  bits 3-23   |\n\n__`Last_Block`__\n\nThe lowest bit signals if this block is the last one.\nThe frame will end after this last block.\nIt may be followed by an optional `Content_Checksum`\n(see [Zstandard Frames](#zstandard-frames)).\n\n__`Block_Type`__\n\nThe next 2 bits represent the `Block_Type`.\n`Block_Type` influences the meaning of `Block_Size`.\nThere are 4 block types :\n\n|    Value     |      0      |      1      |         2          |     3     |\n| ------------ | ----------- | ----------- | ------------------ | --------- |\n| `Block_Type` | `Raw_Block` | `RLE_Block` | `Compressed_Block` | `Reserved`|\n\n- `Raw_Block` - this is an uncompressed block.\n  `Block_Content` contains `Block_Size` bytes.\n\n- `RLE_Block` - this is a single byte, repeated `Block_Size` times.\n  `Block_Content` consists of a single byte.\n  On the decompression side, this byte must be repeated `Block_Size` times.\n\n- `Compressed_Block` - this is a [Zstandard compressed block](#compressed-blocks),\n  explained later on.\n  `Block_Size` is the length of `Block_Content`, the compressed data.\n  The decompressed size is not known,\n  but its maximum possible value is guaranteed (see below)\n\n- `Reserved` - this is not a block.\n  This value cannot be used with current version of this specification.\n  If such a value is present, it is considered corrupted data.\n\n__`Block_Size`__\n\nThe upper 21 bits of `Block_Header` represent the `Block_Size`.\n\nWhen `Block_Type` is `Compressed_Block` or `Raw_Block`,\n`Block_Size` is the size of `Block_Content` (hence excluding `Block_Header`).\n\nWhen `Block_Type` is `RLE_Block`, since `Block_Content`’s size is always 1,\n`Block_Size` represents the number of times this byte must be repeated.\n\n`Block_Size` is limited by `Block_Maximum_Size` (see below).\n\n__`Block_Content`__ and __`Block_Maximum_Size`__\n\nThe size of `Block_Content` is limited by `Block_Maximum_Size`,\nwhich is the smallest of:\n-  `Window_Size`\n-  128 KiB (131.072 bytes)\n\n`Block_Maximum_Size` is constant for a given frame.\nThis maximum is applicable to both the decompressed size\nand the compressed size of any block in the frame.\n\nThe reasoning for this limit is that a decoder can read this information\nat the beginning of a frame and use it to allocate buffers.\nThe guarantees on the size of blocks ensure that\nthe buffers will be large enough for any following block of the valid frame.\n\n\nCompressed Blocks\n-----------------\nTo decompress a compressed block, the compressed size must be provided\nfrom `Block_Size` field within `Block_Header`.\n\nA compressed block consists of 2 sections :\n- [Literals Section](#literals-section)\n- [Sequences Section](#sequences-section)\n\nThe results of the two sections are then combined to produce the decompressed\ndata in [Sequence Execution](#sequence-execution)\n\n#### Prerequisites\nTo decode a compressed block, the following elements are necessary :\n- Previous decoded data, up to a distance of `Window_Size`,\n  or beginning of the Frame, whichever is smaller.\n- List of \"recent offsets\" from previous `Compressed_Block`.\n- The previous Huffman tree, required by `Treeless_Literals_Block` type\n- Previous FSE decoding tables, required by `Repeat_Mode`\n  for each symbol type (literals lengths, match lengths, offsets)\n\nNote that decoding tables aren't always from the previous `Compressed_Block`.\n\n- Every decoding table can come from a dictionary.\n- The Huffman tree comes from the previous `Compressed_Literals_Block`.\n\nLiterals Section\n----------------\nAll literals are regrouped in the first part of the block.\nThey can be decoded first, and then copied during [Sequence Execution],\nor they can be decoded on the flow during [Sequence Execution].\n\nLiterals can be stored uncompressed or compressed using Huffman prefix codes.\nWhen compressed, a tree description may optionally be present,\nfollowed by 1 or 4 streams.\n\n| `Literals_Section_Header` | [`Huffman_Tree_Description`] | [jumpTable] | Stream1 | [Stream2] | [Stream3] | [Stream4] |\n| ------------------------- | ---------------------------- | ----------- | ------- | --------- | --------- | --------- |\n\n\n### `Literals_Section_Header`\n\nHeader is in charge of describing how literals are packed.\nIt's a byte-aligned variable-size bitfield, ranging from 1 to 5 bytes,\nusing __little-endian__ convention.\n\n| `Literals_Block_Type` | `Size_Format` | `Regenerated_Size` | [`Compressed_Size`] |\n| --------------------- | ------------- | ------------------ | ------------------- |\n|       2 bits          |  1 - 2 bits   |    5 - 20 bits     |     0 - 18 bits     |\n\nIn this representation, bits on the left are the lowest bits.\n\n__`Literals_Block_Type`__\n\nThis field uses 2 lowest bits of first byte, describing 4 different block types :\n\n| `Literals_Block_Type`       | Value |\n| --------------------------- | ----- |\n| `Raw_Literals_Block`        |   0   |\n| `RLE_Literals_Block`        |   1   |\n| `Compressed_Literals_Block` |   2   |\n| `Treeless_Literals_Block`   |   3   |\n\n- `Raw_Literals_Block` - Literals are stored uncompressed.\n- `RLE_Literals_Block` - Literals consist of a single byte value\n        repeated `Regenerated_Size` times.\n- `Compressed_Literals_Block` - This is a standard Huffman-compressed block,\n        starting with a Huffman tree description.\n        In this mode, there are at least 2 different literals represented in the Huffman tree description.\n        See details below.\n- `Treeless_Literals_Block` - This is a Huffman-compressed block,\n        using Huffman tree _from previous Huffman-compressed literals block_.\n        `Huffman_Tree_Description` will be skipped.\n        Note: If this mode is triggered without any previous Huffman-table in the frame\n        (or [dictionary](#dictionary-format)), this should be treated as data corruption.\n\n__`Size_Format`__\n\n`Size_Format` is divided into 2 families :\n\n- For `Raw_Literals_Block` and `RLE_Literals_Block`,\n  it's only necessary to decode `Regenerated_Size`.\n  There is no `Compressed_Size` field.\n- For `Compressed_Block` and `Treeless_Literals_Block`,\n  it's required to decode both `Compressed_Size`\n  and `Regenerated_Size` (the decompressed size).\n  It's also necessary to decode the number of streams (1 or 4).\n\nFor values spanning several bytes, convention is __little-endian__.\n\n__`Size_Format` for `Raw_Literals_Block` and `RLE_Literals_Block`__ :\n\n`Size_Format` uses 1 _or_ 2 bits.\nIts value is : `Size_Format = (Literals_Section_Header[0]>>2) & 3`\n\n- `Size_Format` == 00 or 10 : `Size_Format` uses 1 bit.\n               `Regenerated_Size` uses 5 bits (0-31).\n               `Literals_Section_Header` uses 1 byte.\n               `Regenerated_Size = Literals_Section_Header[0]>>3`\n- `Size_Format` == 01 : `Size_Format` uses 2 bits.\n               `Regenerated_Size` uses 12 bits (0-4095).\n               `Literals_Section_Header` uses 2 bytes.\n               `Regenerated_Size = (Literals_Section_Header[0]>>4) + (Literals_Section_Header[1]<<4)`\n- `Size_Format` == 11 : `Size_Format` uses 2 bits.\n               `Regenerated_Size` uses 20 bits (0-1048575).\n               `Literals_Section_Header` uses 3 bytes.\n               `Regenerated_Size = (Literals_Section_Header[0]>>4) + (Literals_Section_Header[1]<<4) + (Literals_Section_Header[2]<<12)`\n\nOnly Stream1 is present for these cases.\nNote : it's allowed to represent a short value (for example `27`)\nusing a long format, even if it's less efficient.\n\n__`Size_Format` for `Compressed_Literals_Block` and `Treeless_Literals_Block`__ :\n\n`Size_Format` always uses 2 bits.\n\n- `Size_Format` == 00 : _A single stream_.\n               Both `Regenerated_Size` and `Compressed_Size` use 10 bits (0-1023).\n               `Literals_Section_Header` uses 3 bytes.\n- `Size_Format` == 01 : 4 streams.\n               Both `Regenerated_Size` and `Compressed_Size` use 10 bits (6-1023).\n               `Literals_Section_Header` uses 3 bytes.\n- `Size_Format` == 10 : 4 streams.\n               Both `Regenerated_Size` and `Compressed_Size` use 14 bits (6-16383).\n               `Literals_Section_Header` uses 4 bytes.\n- `Size_Format` == 11 : 4 streams.\n               Both `Regenerated_Size` and `Compressed_Size` use 18 bits (6-262143).\n               `Literals_Section_Header` uses 5 bytes.\n\nBoth `Compressed_Size` and `Regenerated_Size` fields follow __little-endian__ convention.\nNote: `Compressed_Size` __includes__ the size of the Huffman Tree description\n_when_ it is present.\nNote 2: `Compressed_Size` can never be `==0`.\nEven in single-stream scenario, assuming an empty content, it must be `>=1`,\nsince it contains at least the final end bit flag.\nIn 4-streams scenario, a valid `Compressed_Size` is necessarily `>= 10`\n(6 bytes for the jump table, + 4x1 bytes for the 4 streams).\n\n4 streams is faster than 1 stream in decompression speed,\nby exploiting instruction level parallelism.\nBut it's also more expensive,\ncosting on average ~7.3 bytes more than the 1 stream mode, mostly from the jump table.\n\nIn general, use the 4 streams mode when there are more literals to decode,\nto favor higher decompression speeds.\nNote that beyond >1KB of literals, the 4 streams mode is compulsory.\n\nNote that a minimum of 6 bytes is required for the 4 streams mode.\nThat's a technical minimum, but it's not recommended to employ the 4 streams mode\nfor such a small quantity, that would be wasteful.\nA more practical lower bound would be around ~256 bytes.\n\n#### Raw Literals Block\nThe data in Stream1 is `Regenerated_Size` bytes long,\nit contains the raw literals data to be used during [Sequence Execution].\n\n#### RLE Literals Block\nStream1 consists of a single byte which should be repeated `Regenerated_Size` times\nto generate the decoded literals.\n\n#### Compressed Literals Block and Treeless Literals Block\nBoth of these modes contain Huffman encoded data.\n\nFor `Treeless_Literals_Block`,\nthe Huffman table comes from previously compressed literals block,\nor from a dictionary.\n\n\n### `Huffman_Tree_Description`\nThis section is only present when `Literals_Block_Type` type is `Compressed_Literals_Block` (`2`).\nThe tree describes the weights of all literals symbols that can be present in the literals block, at least 2 and up to 256.\nThe format of the Huffman tree description can be found at [Huffman Tree description](#huffman-tree-description).\nThe size of `Huffman_Tree_Description` is determined during decoding process,\nit must be used to determine where streams begin.\n`Total_Streams_Size = Compressed_Size - Huffman_Tree_Description_Size`.\n\n\n### Jump Table\nThe Jump Table is only present when there are 4 Huffman-coded streams.\n\nReminder : Huffman compressed data consists of either 1 or 4 streams.\n\nIf only one stream is present, it is a single bitstream occupying the entire\nremaining portion of the literals block, encoded as described in\n[Huffman-Coded Streams](#huffman-coded-streams).\n\nIf there are four streams, `Literals_Section_Header` only provided\nenough information to know the decompressed and compressed sizes\nof all four streams _combined_.\nThe decompressed size of _each_ stream is equal to `(Regenerated_Size+3)/4`,\nexcept for the last stream which may be up to 3 bytes smaller,\nto reach a total decompressed size as specified in `Regenerated_Size`.\n\nThe compressed size of each stream is provided explicitly in the Jump Table.\nJump Table is 6 bytes long, and consists of three 2-byte __little-endian__ fields,\ndescribing the compressed sizes of the first three streams.\n`Stream4_Size` is computed from `Total_Streams_Size` minus sizes of other streams:\n\n`Stream4_Size = Total_Streams_Size - 6 - Stream1_Size - Stream2_Size - Stream3_Size`.\n\n`Stream4_Size` is necessarily `>= 1`. Therefore,\nif `Total_Streams_Size < Stream1_Size + Stream2_Size + Stream3_Size + 6 + 1`,\ndata is considered corrupted.\n\nEach of these 4 bitstreams is then decoded independently as a Huffman-Coded stream,\nas described in [Huffman-Coded Streams](#huffman-coded-streams)\n\n\nSequences Section\n-----------------\nA compressed block is a succession of _sequences_ .\nA sequence is a literal copy command, followed by a match copy command.\nA literal copy command specifies a length.\nIt is the number of bytes to be copied (or extracted) from the Literals Section.\nA match copy command specifies an offset and a length.\n\nWhen all _sequences_ are decoded,\nif there are literals left in the _literals section_,\nthese bytes are added at the end of the block.\n\nThis is described in more detail in [Sequence Execution](#sequence-execution).\n\nThe `Sequences_Section` regroup all symbols required to decode commands.\nThere are 3 symbol types : literals lengths, offsets and match lengths.\nThey are encoded together, interleaved, in a single _bitstream_.\n\nThe `Sequences_Section` starts by a header,\nfollowed by optional probability tables for each symbol type,\nfollowed by the bitstream.\n\n| `Sequences_Section_Header` | [`Literals_Length_Table`] | [`Offset_Table`] | [`Match_Length_Table`] | bitStream |\n| -------------------------- | ------------------------- | ---------------- | ---------------------- | --------- |\n\nTo decode the `Sequences_Section`, it's required to know its size.\nIts size is deduced from the size of `Literals_Section`:\n`Sequences_Section_Size = Block_Size - Literals_Section_Size`.\n\n\n#### `Sequences_Section_Header`\n\nConsists of 2 items:\n- `Number_of_Sequences`\n- Symbol compression modes\n\n__`Number_of_Sequences`__\n\nThis is a variable size field using between 1 and 3 bytes.\nLet's call its first byte `byte0`.\n- `if (byte0 < 128)` : `Number_of_Sequences = byte0` . Uses 1 byte.\n- `if (byte0 < 255)` : `Number_of_Sequences = ((byte0 - 0x80) << 8) + byte1`. Uses 2 bytes.\n            Note that the 2 bytes format fully overlaps the 1 byte format.\n- `if (byte0 == 255)`: `Number_of_Sequences = byte1 + (byte2<<8) + 0x7F00`. Uses 3 bytes.\n\n`if (Number_of_Sequences == 0)` : there are no sequences.\n            The sequence section stops immediately,\n            FSE tables used in `Repeat_Mode` aren't updated.\n            Block's decompressed content is defined solely by the Literals Section content.\n\n__Symbol compression modes__\n\nThis is a single byte, defining the compression mode of each symbol type.\n\n|Bit number|          7-6            |      5-4       |        3-2           |     1-0    |\n| -------- | ----------------------- | -------------- | -------------------- | ---------- |\n|Field name| `Literals_Lengths_Mode` | `Offsets_Mode` | `Match_Lengths_Mode` | `Reserved` |\n\nThe last field, `Reserved`, must be all-zeroes.\n\n`Literals_Lengths_Mode`, `Offsets_Mode` and `Match_Lengths_Mode` define the `Compression_Mode` of\nliterals lengths, offsets, and match lengths symbols respectively.\n\nThey follow the same enumeration :\n\n|        Value       |         0         |      1     |           2           |       3       |\n| ------------------ | ----------------- | ---------- | --------------------- | ------------- |\n| `Compression_Mode` | `Predefined_Mode` | `RLE_Mode` | `FSE_Compressed_Mode` | `Repeat_Mode` |\n\n- `Predefined_Mode` : A predefined FSE distribution table is used, defined in\n          [default distributions](#default-distributions).\n          No distribution table will be present.\n- `RLE_Mode` : The table description consists of a single byte, which contains the symbol's value.\n          This symbol will be used for all sequences.\n- `FSE_Compressed_Mode` : standard FSE compression.\n          A distribution table will be present.\n          The format of this distribution table is described in [FSE Table Description](#fse-table-description).\n          Note that the maximum allowed accuracy log for literals length and match length tables is 9,\n          and the maximum accuracy log for the offsets table is 8.\n          `FSE_Compressed_Mode` must not be used when only one symbol is present,\n          `RLE_Mode` should be used instead (although any other mode will work).\n- `Repeat_Mode` : The table used in the previous `Compressed_Block` with `Number_of_Sequences > 0` will be used again,\n          or if this is the first block, table in the dictionary will be used.\n          Note that this includes `RLE_mode`, so if `Repeat_Mode` follows `RLE_Mode`, the same symbol will be repeated.\n          It also includes `Predefined_Mode`, in which case `Repeat_Mode` will have same outcome as `Predefined_Mode`.\n          No distribution table will be present.\n          If this mode is used without any previous sequence table in the frame\n          (nor [dictionary](#dictionary-format)) to repeat, this should be treated as corruption.\n\n#### The codes for literals lengths, match lengths, and offsets.\n\nEach symbol is a _code_ in its own context,\nwhich specifies `Baseline` and `Number_of_Bits` to add.\n_Codes_ are FSE compressed,\nand interleaved with raw additional bits in the same bitstream.\n\n##### Literals length codes\n\nLiterals length codes are values ranging from `0` to `35` included.\nThey define lengths from 0 to 131071 bytes.\nThe literals length is equal to the decoded `Baseline` plus\nthe result of reading `Number_of_Bits` bits from the bitstream,\nas a __little-endian__ value.\n\n| `Literals_Length_Code` |         0-15           |\n| ---------------------- | ---------------------- |\n| length                 | `Literals_Length_Code` |\n| `Number_of_Bits`       |          0             |\n\n| `Literals_Length_Code` |  16  |  17  |  18  |  19  |  20  |  21  |  22  |  23  |\n| ---------------------- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |\n| `Baseline`             |  16  |  18  |  20  |  22  |  24  |  28  |  32  |  40  |\n| `Number_of_Bits`       |   1  |   1  |   1  |   1  |   2  |   2  |   3  |   3  |\n\n| `Literals_Length_Code` |  24  |  25  |  26  |  27  |  28  |  29  |  30  |  31  |\n| ---------------------- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |\n| `Baseline`             |  48  |  64  |  128 |  256 |  512 | 1024 | 2048 | 4096 |\n| `Number_of_Bits`       |   4  |   6  |   7  |   8  |   9  |  10  |  11  |  12  |\n\n| `Literals_Length_Code` |  32  |  33  |  34  |  35  |\n| ---------------------- | ---- | ---- | ---- | ---- |\n| `Baseline`             | 8192 |16384 |32768 |65536 |\n| `Number_of_Bits`       |  13  |  14  |  15  |  16  |\n\n\n##### Match length codes\n\nMatch length codes are values ranging from `0` to `52` included.\nThey define lengths from 3 to 131074 bytes.\nThe match length is equal to the decoded `Baseline` plus\nthe result of reading `Number_of_Bits` bits from the bitstream,\nas a __little-endian__ value.\n\n| `Match_Length_Code` |         0-31            |\n| ------------------- | ----------------------- |\n| value               | `Match_Length_Code` + 3 |\n| `Number_of_Bits`    |          0              |\n\n| `Match_Length_Code` |  32  |  33  |  34  |  35  |  36  |  37  |  38  |  39  |\n| ------------------- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |\n| `Baseline`          |  35  |  37  |  39  |  41  |  43  |  47  |  51  |  59  |\n| `Number_of_Bits`    |   1  |   1  |   1  |   1  |   2  |   2  |   3  |   3  |\n\n| `Match_Length_Code` |  40  |  41  |  42  |  43  |  44  |  45  |  46  |  47  |\n| ------------------- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |\n| `Baseline`          |  67  |  83  |  99  |  131 |  259 |  515 | 1027 | 2051 |\n| `Number_of_Bits`    |   4  |   4  |   5  |   7  |   8  |   9  |  10  |  11  |\n\n| `Match_Length_Code` |  48  |  49  |  50  |  51  |  52  |\n| ------------------- | ---- | ---- | ---- | ---- | ---- |\n| `Baseline`          | 4099 | 8195 |16387 |32771 |65539 |\n| `Number_of_Bits`    |  12  |  13  |  14  |  15  |  16  |\n\n##### Offset codes\n\nOffset codes are values ranging from `0` to `N`.\n\nA decoder is free to limit its maximum `N` supported.\nRecommendation is to support at least up to `22`.\nFor information, at the time of this writing.\nthe reference decoder supports a maximum `N` value of `31`.\n\nAn offset code is also the number of additional bits to read in __little-endian__ fashion,\nand can be translated into an `Offset_Value` using the following formulas :\n\n```\nOffset_Value = (1 << offsetCode) + readNBits(offsetCode);\nif (Offset_Value > 3) offset = Offset_Value - 3;\n```\nIt means that maximum `Offset_Value` is `(2^(N+1))-1`\nsupporting back-reference distances up to `(2^(N+1))-4`,\nbut is limited by [maximum back-reference distance](#window_descriptor).\n\n`Offset_Value` from 1 to 3 are special : they define \"repeat codes\".\nThis is described in more detail in [Repeat Offsets](#repeat-offsets).\n\n#### Decoding Sequences\nFSE bitstreams are read in reverse direction than written. In zstd,\nthe compressor writes bits forward into a block and the decompressor\nmust read the bitstream _backwards_.\n\nTo find the start of the bitstream it is therefore necessary to\nknow the offset of the last byte of the block which can be found\nby counting `Block_Size` bytes after the block header.\n\nAfter writing the last bit containing information, the compressor\nwrites a single `1`-bit and then fills the byte with 0-7 `0` bits of\npadding. The last byte of the compressed bitstream cannot be `0` for\nthat reason.\n\nWhen decompressing, the last byte containing the padding is the first\nbyte to read. The decompressor needs to skip 0-7 initial `0`-bits and\nthe first `1`-bit it occurs. Afterwards, the useful part of the bitstream\nbegins.\n\nFSE decoding requires a 'state' to be carried from symbol to symbol.\nFor more explanation on FSE decoding, see the [FSE section](#fse).\n\nFor sequence decoding, a separate state keeps track of each\nliteral lengths, offsets, and match lengths symbols.\nSome FSE primitives are also used.\nFor more details on the operation of these primitives, see the [FSE section](#fse).\n\n##### Starting states\nThe bitstream starts with initial FSE state values,\neach using the required number of bits in their respective _accuracy_,\ndecoded previously from their normalized distribution.\n\nIt starts by `Literals_Length_State`,\nfollowed by `Offset_State`,\nand finally `Match_Length_State`.\n\nReminder : always keep in mind that all values are read _backward_,\nso the 'start' of the bitstream is at the highest position in memory,\nimmediately before the last `1`-bit for padding.\n\nAfter decoding the starting states, a single sequence is decoded\n`Number_Of_Sequences` times.\nThese sequences are decoded in order from first to last.\nSince the compressor writes the bitstream in the forward direction,\nthis means the compressor must encode the sequences starting with the last\none and ending with the first.\n\n##### Decoding a sequence\nFor each of the symbol types, the FSE state can be used to determine the appropriate code.\nThe code then defines the `Baseline` and `Number_of_Bits` to read for each type.\nSee the [description of the codes] for how to determine these values.\n\n[description of the codes]: #the-codes-for-literals-lengths-match-lengths-and-offsets\n\nDecoding starts by reading the `Number_of_Bits` required to decode `Offset`.\nIt then does the same for `Match_Length`, and then for `Literals_Length`.\nThis sequence is then used for [sequence execution](#sequence-execution).\n\nIf it is not the last sequence in the block,\nthe next operation is to update states.\nUsing the rules pre-calculated in the decoding tables,\n`Literals_Length_State` is updated,\nfollowed by `Match_Length_State`,\nand then `Offset_State`.\nSee the [FSE section](#fse) for details on how to update states from the bitstream.\n\nThis operation will be repeated `Number_of_Sequences` times.\nAt the end, the bitstream shall be entirely consumed,\notherwise the bitstream is considered corrupted.\n\n#### Default Distributions\nIf `Predefined_Mode` is selected for a symbol type,\nits FSE decoding table is generated from a predefined distribution table defined here.\nFor details on how to convert this distribution into a decoding table, see the [FSE section].\n\n[FSE section]: #from-normalized-distribution-to-decoding-tables\n\n##### Literals Length\nThe decoding table uses an accuracy log of 6 bits (64 states).\n```\nshort literalsLength_defaultDistribution[36] =\n        { 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,\n          2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1,\n         -1,-1,-1,-1 };\n```\n\n##### Match Length\nThe decoding table uses an accuracy log of 6 bits (64 states).\n```\nshort matchLengths_defaultDistribution[53] =\n        { 1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,\n          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,\n         -1,-1,-1,-1,-1 };\n```\n\n##### Offset Codes\nThe decoding table uses an accuracy log of 5 bits (32 states),\nand supports a maximum `N` value of 28, allowing offset values up to 536,870,908 .\n\nIf any sequence in the compressed block requires a larger offset than this,\nit's not possible to use the default distribution to represent it.\n```\nshort offsetCodes_defaultDistribution[29] =\n        { 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,\n          1, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1 };\n```\n\n\nSequence Execution\n------------------\nOnce literals and sequences have been decoded,\nthey are combined to produce the decoded content of a block.\n\nEach sequence consists of a tuple of (`literals_length`, `offset_value`, `match_length`),\ndecoded as described in the [Sequences Section](#sequences-section).\nTo execute a sequence, first copy `literals_length` bytes\nfrom the decoded literals to the output.\n\nThen `match_length` bytes are copied from previous decoded data.\nThe offset to copy from is determined by `offset_value`:\nif `offset_value > 3`, then the offset is `offset_value - 3`.\nIf `offset_value` is from 1-3, the offset is a special repeat offset value.\nSee the [repeat offset](#repeat-offsets) section for how the offset is determined\nin this case.\n\nThe offset is defined as from the current position, so an offset of 6\nand a match length of 3 means that 3 bytes should be copied from 6 bytes back.\nNote that all offsets leading to previously decoded data\nmust be smaller than `Window_Size` defined in `Frame_Header_Descriptor`.\n\n#### Repeat offsets\nAs seen in [Sequence Execution](#sequence-execution),\nthe first 3 values define a repeated offset and we will call them\n`Repeated_Offset1`, `Repeated_Offset2`, and `Repeated_Offset3`.\nThey are sorted in recency order, with `Repeated_Offset1` meaning \"most recent one\".\n\nIf `offset_value == 1`, then the offset used is `Repeated_Offset1`, etc.\n\nThere is an exception though, when current sequence's `literals_length = 0`.\nIn this case, repeated offsets are shifted by one,\nso an `offset_value` of 1 means `Repeated_Offset2`,\nan `offset_value` of 2 means `Repeated_Offset3`,\nand an `offset_value` of 3 means `Repeated_Offset1 - 1`.\n\nIn the final case, if `Repeated_Offset1 - 1` evaluates to 0, then the\ndata is considered corrupted.\n\nFor the first block, the starting offset history is populated with following values :\n`Repeated_Offset1`=1, `Repeated_Offset2`=4, `Repeated_Offset3`=8,\nunless a dictionary is used, in which case they come from the dictionary.\n\nThen each block gets its starting offset history from the ending values of the most recent `Compressed_Block`.\nNote that blocks which are not `Compressed_Block` are skipped, they do not contribute to offset history.\n\n[Offset Codes]: #offset-codes\n\n###### Offset updates rules\n\nDuring the execution of the sequences of a `Compressed_Block`, the\n`Repeated_Offsets`' values are kept up to date, so that they always represent\nthe three most-recently used offsets. In order to achieve that, they are\nupdated after executing each sequence in the following way:\n\nWhen the sequence's `offset_value` does not refer to one of the\n`Repeated_Offsets`--when it has value greater than 3, or when it has value 3\nand the sequence's `literals_length` is zero--the `Repeated_Offsets`' values\nare shifted back one, and `Repeated_Offset1` takes on the value of the\njust-used offset.\n\nOtherwise, when the sequence's `offset_value` refers to one of the\n`Repeated_Offsets`--when it has value 1 or 2, or when it has value 3 and the\nsequence's `literals_length` is non-zero--the `Repeated_Offsets` are re-ordered\nso that `Repeated_Offset1` takes on the value of the used Repeated_Offset, and\nthe existing values are pushed back from the first `Repeated_Offset` through to\nthe `Repeated_Offset` selected by the `offset_value`. This effectively performs\na single-stepped wrapping rotation of the values of these offsets, so that\ntheir order again reflects the recency of their use.\n\nThe following table shows the values of the `Repeated_Offsets` as a series of\nsequences are applied to them:\n\n| `offset_value` | `literals_length` | `Repeated_Offset1` | `Repeated_Offset2` | `Repeated_Offset3` | Comment                 |\n|:--------------:|:-----------------:|:------------------:|:------------------:|:------------------:|:-----------------------:|\n|                |                   |                  1 |                  4 |                  8 | starting values         |\n|           1114 |                11 |               1111 |                  1 |                  4 | non-repeat              |\n|              1 |                22 |               1111 |                  1 |                  4 | repeat 1: no change     |\n|           2225 |                22 |               2222 |               1111 |                  1 | non-repeat              |\n|           1114 |               111 |               1111 |               2222 |               1111 | non-repeat              |\n|           3336 |                33 |               3333 |               1111 |               2222 | non-repeat              |\n|              2 |                22 |               1111 |               3333 |               2222 | repeat 2: swap 1 & 2    |\n|              3 |                33 |               2222 |               1111 |               3333 | repeat 3: rotate 3 to 1 |\n|              3 |                 0 |               2221 |               2222 |               1111 | special case : insert `repeat1 - 1` |\n|              1 |                 0 |               2222 |               2221 |               1111 | == repeat 2             |\n\n\nSkippable Frames\n----------------\n\n| `Magic_Number` | `Frame_Size` | `User_Data` |\n|:--------------:|:------------:|:-----------:|\n|   4 bytes      |  4 bytes     |   n bytes   |\n\nSkippable frames allow the insertion of user-defined metadata\ninto a flow of concatenated frames.\n\nSkippable frames defined in this specification are compatible with [LZ4] ones.\n\n[LZ4]:https://lz4.github.io/lz4/\n\nFrom a compliant decoder perspective, skippable frames need just be skipped,\nand their content ignored, resuming decoding after the skippable frame.\n\nIt can be noted that a skippable frame\ncan be used to watermark a stream of concatenated frames\nembedding any kind of tracking information (even just a UUID).\nUsers wary of such possibility should scan the stream of concatenated frames\nin an attempt to detect such frame for analysis or removal.\n\n__`Magic_Number`__\n\n4 Bytes, __little-endian__ format.\nValue : 0x184D2A5?, which means any value from 0x184D2A50 to 0x184D2A5F.\nAll 16 values are valid to identify a skippable frame.\nThis specification doesn't detail any specific tagging for skippable frames.\n\n__`Frame_Size`__\n\nThis is the size, in bytes, of the following `User_Data`\n(without including the magic number nor the size field itself).\nThis field is represented using 4 Bytes, __little-endian__ format, unsigned 32-bits.\nThis means `User_Data` can’t be bigger than (2^32-1) bytes.\n\n__`User_Data`__\n\nThe `User_Data` can be anything. Data will just be skipped by the decoder.\n\n\n\nEntropy Encoding\n----------------\nTwo types of entropy encoding are used by the Zstandard format:\nFSE, and Huffman coding.\nHuffman is used to compress literals,\nwhile FSE is used for all other symbols\n(`Literals_Length_Code`, `Match_Length_Code`, offset codes)\nand to compress Huffman headers.\n\n\nFSE\n---\nFSE, short for Finite State Entropy, is an entropy codec based on [ANS].\nFSE encoding/decoding involves a state that is carried over between symbols.\nDecoding must be done in the opposite direction as encoding.\nTherefore, all FSE bitstreams are read from end to beginning.\nNote that the order of the bits in the stream is not reversed,\nwe just read each multi-bits element in the reverse order they are encoded.\n\nFor additional details on FSE, see [Finite State Entropy].\n\n[Finite State Entropy]:https://github.com/Cyan4973/FiniteStateEntropy/\n\nFSE decoding is directed by a decoding table with a power of 2 size, each row containing three elements:\n`Symbol`, `Num_Bits`, and `Baseline`.\nThe `log2` of the table size is its `Accuracy_Log`.\nAn FSE state value represents an index in this table.\n\nTo obtain the initial state value, consume `Accuracy_Log` bits from the stream as a __little-endian__ value.\nThe first symbol in the stream is the `Symbol` indicated in the table for that state.\nTo obtain the next state value,\nthe decoder should consume `Num_Bits` bits from the stream as a __little-endian__ value and add it to `Baseline`.\n\n[ANS]: https://en.wikipedia.org/wiki/Asymmetric_Numeral_Systems\n\n### FSE Table Description\nTo decode an FSE bitstream, it is necessary to build its FSE decoding table.\nThe decoding table is derived from a distribution of Probabilities.\nThe Zstandard format encodes distributions of Probabilities as follows:\n\nThe distribution of probabilities is described in a bitstream which is read forward,\nin __little-endian__ fashion.\nThe amount of bytes consumed from the bitstream to describe the distribution\nis discovered at the end of the decoding process.\n\nThe bitstream starts by reporting on which scale the distribution operates.\nLet's `low4Bits` designate the lowest 4 bits of the first byte :\n`Accuracy_Log = low4bits + 5`.\n\nAn FSE distribution table describes the probabilities of all symbols\nfrom `0` to the last present one (included) in natural order.\nThe sum of probabilities is normalized to reach a power of 2 total of `1 << Accuracy_Log` .\nThere must be two or more symbols with non-zero probabilities.\n\nThe number of bits used to decode each probability is variable.\nIt depends on :\n\n- Remaining probabilities + 1 :\n  __example__ :\n  Presuming an `Accuracy_Log` of 8,\n  and presuming 100 probability points have already been distributed,\n  the decoder may read any value from `0` to `256 - 100 + 1 == 157` (inclusive).\n  Therefore, it may read up to `log2sup(157) == 8` bits, where `log2sup(N)`\n  is the smallest integer `T` that satisfies `(1 << T) > N`.\n\n- Value decoded : small values use 1 less bit :\n  __example__ :\n  Presuming values from 0 to 157 (inclusive) are possible,\n  255-157 = 98 values are remaining in an 8-bits field.\n  They are used this way :\n  first 98 values (hence from 0 to 97) use only 7 bits,\n  values from 98 to 157 use 8 bits.\n  This is achieved through this scheme :\n\n  | 8-bit field read | Value decoded | Nb of bits consumed |\n  | ---------------- | ------------- | ------------------- |\n  |         0 -  97  |   0 -  97     |  7                  |\n  |        98 - 127  |  98 - 127     |  8                  |\n  |       128 - 225  |   0 -  97     |  7                  |\n  |       226 - 255  | 128 - 157     |  8                  |\n\nProbability is derived from Value decoded using the following formula:\n`Probality = Value - 1`\n\nConsequently, a Probability of `0` is described by a Value `1`.\n\nA Value `0` is used to signal a special case, named \"Probability `-1`\".\nIt describes a probability which should have been \"less than 1\".\nIts effect on the decoding table building process is described in the [next section].\nFor the purpose of counting total allocated probability points, it counts as one.\n\n[next section]:#from-normalized-distribution-to-decoding-tables\n\nSymbols probabilities are read one by one, in order.\nAfter each probability is decoded, the total nb of probability points is updated.\nThis is used to determine how many bits must be read to decode the probability of next symbol.\n\nWhen a symbol has a __probability__ of `zero` (decoded from reading a Value `1`),\nit is followed by a 2-bits repeat flag.\nThis repeat flag tells how many probabilities of zeroes follow the current one.\nIt provides a number ranging from 0 to 3.\nIf it is a 3, another 2-bits repeat flag follows, and so on.\n\nWhen the Probability for a symbol makes cumulated total reach `1 << Accuracy_Log`,\nthen it's the last symbol, and decoding is complete.\n\nThen the decoder can tell how many bytes were used in this process,\nand how many symbols are present.\nThe bitstream consumes a round number of bytes.\nAny remaining bit within the last byte is just unused.\n\nIf this process results in a non-zero probability for a symbol outside of the\nvalid range of symbols that the FSE table is defined for, even if that symbol is\nnot used, then the data is considered corrupted.\nFor the specific case of offset codes,\na decoder implementation may reject a frame containing a non-zero probability\nfor an offset code larger than the largest offset code supported by the decoder\nimplementation.\n\n#### From normalized distribution to decoding tables\n\nThe normalized distribution of probabilities is enough\nto create a unique decoding table.\nIt is generated using the following build rule :\n\nThe table has a size of `Table_Size = 1 << Accuracy_Log`.\nEach row specifies the decoded symbol,\nand instructions to reach the next state (`Number_of_Bits` and `Baseline`).\n\nSymbols are first scanned in their natural order for \"less than 1\" probabilities\n(previously decoded from a Value of `0`).\nSymbols with this special probability are being attributed a single row,\nstarting from the end of the table and retreating.\nThese symbols define a full state reset, reading `Accuracy_Log` bits.\n\nThen, all remaining symbols, sorted in natural order, are allocated rows.\nStarting from smallest present symbol, and table position `0`,\neach symbol gets allocated as many rows as its probability.\n\nRow allocation is not linear, it follows this order, in modular arithmetic:\n```\nposition += (tableSize>>1) + (tableSize>>3) + 3;\nposition &= tableSize-1;\n```\n\nUsing above ordering rule, each symbol gets allocated as many rows as its probability.\nIf a position is already occupied by a \"less than 1\" probability symbol,\nit is simply skipped, and the next position is allocated instead.\nOnce enough rows have been allocated for the current symbol,\nthe allocation process continues, using the next symbol, in natural order.\nThis process guarantees that the table is entirely and exactly filled.\n\nEach row specifies a decoded symbol, and is accessed by current state value.\nIt also specifies `Number_of_Bits` and `Baseline`, which are required to determine next state value.\n\nTo correctly set these fields, it's necessary to sort all occurrences of each symbol in state value order,\nand then attribute N+1 bits to lower rows, and N bits to higher rows,\nfollowing the process described below (using an example):\n\n__Example__ :\nPresuming an `Accuracy_Log` of 7,\nlet's imagine a symbol with a Probability of 5:\nit receives 5 rows, corresponding to 5 state values between `0` and `127`.\n\nIn this example, the first state value happens to be `1` (after unspecified previous symbols).\nThe next 4 states are then determined using above modular arithmetic rule,\nwhich specifies to add `64+16+3 = 83` modulo `128` to jump to next position,\nproducing the following series: `1`, `84`, `39`, `122`, `77` (modular arithmetic).\n(note: the next symbol will then start at `32`).\n\nThese state values are then sorted in natural order,\nresulting in the following series: `1`, `39`, `77`, `84`, `122`.\n\nThe next power of 2 after 5 is 8.\nTherefore, the probability space will be divided into 8 equal parts.\nSince the probability space is `1<<7 = 128` large, each share is `128/8 = 16` large.\n\nIn order to reach 8 shares, the `8-5 = 3` lowest states will count \"double\",\ndoubling their shares (32 in width), hence requiring one more bit.\n\nBaseline is assigned starting from the lowest state using fewer bits,\ncontinuing in natural state order, looping back at the beginning.\nEach state takes its allocated range from Baseline, sized by its `Number_of_Bits`.\n\n| state order      |   0   |   1   |    2   |   3  |    4   |\n| ---------------- | ----- | ----- | ------ | ---- | ------ |\n| state value      |   1   |  39   |   77   |  84  |  122   |\n| width            |  32   |  32   |   32   |  16  |   16   |\n| `Number_of_Bits` |   5   |   5   |    5   |   4  |    4   |\n| allocation order |   3   |   4   |    5   |   1  |    2   |\n| `Baseline`       |  32   |  64   |   96   |   0  |   16   |\n| range            | 32-63 | 64-95 | 96-127 | 0-15 | 16-31  |\n\nDuring decoding, the next state value is determined by using current state value as row number,\nthen reading the required `Number_of_Bits` from the bitstream, and adding the specified `Baseline`.\n\nNote:\nas a trivial example, it follows that, for a symbol with a Probability of `1`,\n`Baseline` is necessarily `0`, and `Number_of_Bits` is necessarily `Accuracy_Log`.\n\nSee [Appendix A] to see the outcome of this process applied to the default distributions.\n\n[Appendix A]: #appendix-a---decoding-tables-for-predefined-codes\n\n\nHuffman Coding\n--------------\nZstandard Huffman-coded streams are read backwards,\nsimilar to the FSE bitstreams.\nTherefore, to find the start of the bitstream, it is required to\nknow the offset of the last byte of the Huffman-coded stream.\n\nAfter writing the last bit containing information, the compressor\nwrites a single `1`-bit and then fills the byte with 0-7 `0` bits of\npadding. The last byte of the compressed bitstream cannot be `0` for\nthat reason.\n\nWhen decompressing, the last byte containing the padding is the first\nbyte to read. The decompressor needs to skip 0-7 initial `0`-bits and\nthe first `1`-bit it occurs. Afterwards, the useful part of the bitstream\nbegins.\n\nThe bitstream contains Huffman-coded symbols in __little-endian__ order,\nwith the codes defined by the method below.\n\n### Huffman Tree Description\n\nPrefix coding represents symbols from an a priori known alphabet\nby bit sequences (codewords), one codeword for each symbol,\nin a manner such that different symbols may be represented\nby bit sequences of different lengths,\nbut a parser can always parse an encoded string\nunambiguously symbol-by-symbol.\n\nGiven an alphabet with known symbol frequencies,\nthe Huffman algorithm allows the construction of an optimal prefix code\nusing the fewest bits of any possible prefix codes for that alphabet.\n\nPrefix code must not exceed a maximum code length.\nMore bits improve accuracy but cost more header size,\nand require more memory or more complex decoding operations.\nThis specification limits maximum code length to 11 bits.\n\n#### Representation\n\nAll literal symbols from zero (included) to last present one (excluded)\nare represented by `Weight` with values from `0` to `Max_Number_of_Bits`.\nTransformation from `Weight` to `Number_of_Bits` follows this formula :\n```\nNumber_of_Bits = Weight ? (Max_Number_of_Bits + 1 - Weight) : 0\n```\nWhen a literal symbol is not present, it receives a `Weight` of 0.\nThe least frequent symbol receives a `Weight` of 1.\nIf no literal has a `Weight` of 1, then the data is considered corrupted.\nIf there are not at least two literals with non-zero `Weight`, then the data\nis considered corrupted.\nThe most frequent symbol receives a `Weight` anywhere between 1 and 11 (max).\nThe last symbol's `Weight` is deduced from previously retrieved Weights,\nby completing to the nearest power of 2. It's necessarily non 0.\nIf it's not possible to reach a clean power of 2 with a single `Weight` value,\nthe Huffman Tree Description is considered invalid.\nThis final power of 2 gives `Max_Number_of_Bits`, the depth of the current tree.\n`Max_Number_of_Bits` must be <= 11,\notherwise the representation is considered corrupted.\n\n__Example__ :\nLet's presume the following Huffman tree must be described :\n\n|  literal symbol  |  A  |  B  |  C  |  D  |  E  |  F  |\n| ---------------- | --- | --- | --- | --- | --- | --- |\n| `Number_of_Bits` |  1  |  2  |  3  |  0  |  4  |  4  |\n\nThe tree depth is 4, since its longest elements uses 4 bits\n(longest elements are the ones with smallest frequency).\n\nAll symbols will now receive a `Weight` instead of `Number_of_Bits`.\nWeight formula is :\n```\nWeight = Number_of_Bits ? (Max_Number_of_Bits + 1 - Number_of_Bits) : 0\n```\nIt gives the following series of Weights :\n\n| literal symbol |  A  |  B  |  C  |  D  |  E  |  F  |\n| -------------- | --- | --- | --- | --- | --- | --- |\n|   `Weight`     |  4  |  3  |  2  |  0  |  1  |  1  |\n\nThis list will be sent to the decoder, with the following modifications:\n\n- `F` will not be listed, because it can be determined from previous symbols\n- nor will symbols above `F` as they are all 0\n- on the other hand, all symbols before `A`, starting with `\\0`, will be listed, with a Weight of 0.\n\nThe decoder will do the inverse operation :\nhaving collected weights of literal symbols from `A` to `E`,\nit knows the last literal, `F`, is present with a non-zero `Weight`.\nThe `Weight` of `F` can be determined by advancing to the next power of 2.\nThe sum of `2^(Weight-1)` (excluding 0's) is :\n`8 + 4 + 2 + 0 + 1 = 15`.\nNearest larger power of 2 value is 16.\nTherefore, `Max_Number_of_Bits = log2(16) = 4` and `Weight[F] = log_2(16 - 15) + 1 = 1`.\n\n#### Huffman Tree header\n\nThis is a single byte value (0-255),\nwhich describes how the series of weights is encoded.\n\n- if `headerByte` < 128 :\n  the series of weights is compressed using FSE (see below).\n  The length of the FSE-compressed series is equal to `headerByte` (0-127).\n\n- if `headerByte` >= 128 :\n  + the series of weights uses a direct representation,\n    where each `Weight` is encoded directly as a 4 bits field (0-15).\n  + They are encoded forward, 2 weights to a byte,\n    first weight taking the top four bits and second one taking the bottom four.\n    * e.g. the following operations could be used to read the weights:\n      `Weight[0] = (Byte[0] >> 4), Weight[1] = (Byte[0] & 0xf)`, etc.\n  + The full representation occupies `Ceiling(Number_of_Weights/2)` bytes,\n    meaning it uses only full bytes even if `Number_of_Weights` is odd.\n  + `Number_of_Weights = headerByte - 127`.\n    * Note that maximum `Number_of_Weights` is 255-127 = 128,\n      therefore, only up to 128 `Weight` can be encoded using direct representation.\n    * Since the last non-zero `Weight` is _not_ encoded,\n      this scheme is compatible with alphabet sizes of up to 129 symbols,\n      hence including literal symbol 128.\n    * If any literal symbol > 128 has a non-zero `Weight`,\n      direct representation is not possible.\n      In such case, it's necessary to use FSE compression.\n\n\n#### Finite State Entropy (FSE) compression of Huffman weights\n\nIn this case, the series of Huffman weights is compressed using FSE compression.\nIt's a single bitstream with 2 interleaved states,\nsharing a single distribution table.\n\nTo decode an FSE bitstream, it is necessary to know its compressed size.\nCompressed size is provided by `headerByte`.\nIt's also necessary to know its _maximum possible_ decompressed size,\nwhich is `255`, since literal symbols span from `0` to `255`,\nand last symbol's `Weight` is not represented.\n\nAn FSE bitstream starts by a header, describing probabilities distribution.\nIt will create a Decoding Table.\nFor a list of Huffman weights, the maximum accuracy log is 6 bits.\nFor more description see the [FSE header description](#fse-table-description)\n\nThe Huffman header compression uses 2 states,\nwhich share the same FSE distribution table.\nThe first state (`State1`) encodes the even indexed symbols,\nand the second (`State2`) encodes the odd indexed symbols.\n`State1` is initialized first, and then `State2`, and they take turns\ndecoding a single symbol and updating their state.\nFor more details on these FSE operations, see the [FSE section](#fse).\n\nThe number of symbols to decode is determined\nby tracking bitStream overflow condition:\nIf updating state after decoding a symbol would require more bits than\nremain in the stream, it is assumed that extra bits are 0.  Then,\nsymbols for each of the final states are decoded and the process is complete.\n\nIf this process would produce more weights than the maximum number of decoded\nweights (255), then the data is considered corrupted.\n\nIf either of the 2 initial states are absent or truncated, then the data is\nconsidered corrupted.  Consequently, it is not possible to encode fewer than\n2 weights using this mode.\n\n#### Conversion from weights to Huffman prefix codes\n\nAll present symbols shall now have a `Weight` value.\nIt is possible to transform weights into `Number_of_Bits`, using this formula:\n```\nNumber_of_Bits = (Weight>0) ? Max_Number_of_Bits + 1 - Weight : 0\n```\nIn order to determine which prefix code is assigned to each Symbol,\nSymbols are first sorted by `Weight`, then by natural sequential order.\nSymbols with a `Weight` of zero are removed.\nThen, starting from lowest `Weight` (hence highest `Number_of_Bits`),\nprefix codes are assigned in ascending order.\n\n__Example__ :\nLet's assume the following list of weights has been decoded:\n\n| Literal  |  A  |  B  |  C  |  D  |  E  |  F  |\n| -------- | --- | --- | --- | --- | --- | --- |\n| `Weight` |  4  |  3  |  2  |  0  |  1  |  1  |\n\nSorted by weight and then natural sequential order,\nit gives the following prefix codes distribution:\n\n| Literal          |  D  |   E  |   F  |   C  |   B  |   A  |\n| ---------------- | --- | ---- | ---- | ---- | ---- | ---- |\n| `Weight`         |  0  |   1  |   1  |   2  |   3  |   4  |\n| `Number_of_Bits` |  0  |   4  |   4  |   3  |   2  |   1  |\n| prefix code      | N/A | 0000 | 0001 | 001  | 01   | 1    |\n| ascending order  | N/A | 0000 | 0001 | 001x | 01xx | 1xxx |\n\n### Huffman-coded Streams\n\nGiven a Huffman decoding table,\nit's possible to decode a Huffman-coded stream.\n\nEach bitstream must be read _backward_,\nthat is starting from the end down to the beginning.\nTherefore it's necessary to know the size of each bitstream.\n\nIt's also necessary to know exactly which _bit_ is the last one.\nThis is detected by a final bit flag :\nthe highest bit of latest byte is a final-bit-flag.\nConsequently, a last byte of `0` is not possible.\nAnd the final-bit-flag itself is not part of the useful bitstream.\nHence, the last byte contains between 0 and 7 useful bits.\n\nStarting from the end,\nit's possible to read the bitstream in a __little-endian__ fashion,\nkeeping track of already used bits. Since the bitstream is encoded in reverse\norder, starting from the end read symbols in forward order.\n\nFor example, if the literal sequence `ABEF` was encoded using above prefix code,\nit would be encoded (in reverse order) as:\n\n|Symbol  |   F  |   E  |  B | A | Padding |\n|--------|------|------|----|---|---------|\n|Encoding|`0000`|`0001`|`01`|`1`| `00001` |\n\nResulting in following 2-bytes bitstream :\n```\n00010000 00001101\n```\n\nHere is an alternative representation with the symbol codes separated by underscore:\n```\n0001_0000 00001_1_01\n```\n\nReading highest `Max_Number_of_Bits` bits,\nit's possible to compare extracted value to decoding table,\ndetermining the symbol to decode and number of bits to discard.\n\nThe process continues up to reading the required number of symbols per stream.\nIf a bitstream is not entirely and exactly consumed,\nhence reaching exactly its beginning position with _all_ bits consumed,\nthe decoding process is considered faulty.\n\n\nDictionary Format\n-----------------\n\nZstandard is compatible with \"raw content\" dictionaries,\nfree of any format restriction, except that they must be at least 8 bytes.\nThese dictionaries function as if they were just the `Content` part\nof a formatted dictionary.\n\nBut dictionaries created by `zstd --train` follow a format, described here.\n\n__Pre-requisites__ : a dictionary has a size,\n                     defined either by a buffer limit, or a file size.\n\n| `Magic_Number` | `Dictionary_ID` | `Entropy_Tables` | `Content` |\n| -------------- | --------------- | ---------------- | --------- |\n\n__`Magic_Number`__ : 4 bytes ID, value 0xEC30A437, __little-endian__ format\n\n__`Dictionary_ID`__ : 4 bytes, stored in __little-endian__ format.\n              `Dictionary_ID` can be any value, except 0 (which means no `Dictionary_ID`).\n              It's used by decoders to check if they use the correct dictionary.\n\n_Reserved ranges :_\nIf the dictionary is going to be distributed in a public environment,\nthe following ranges of `Dictionary_ID` are reserved for some future registrar\nand shall not be used :\n\n    - low range  : <= 32767\n    - high range : >= (2^31)\n\nOutside of these ranges, any value of `Dictionary_ID`\nwhich is both `>= 32768` and `< (1<<31)` can be used freely,\neven in public environment.\n\n\n__`Entropy_Tables`__ : follow the same format as tables in [compressed blocks].\n              See the relevant [FSE](#fse-table-description)\n              and [Huffman](#huffman-tree-description) sections for how to decode these tables.\n              They are stored in following order :\n              Huffman tables for literals, FSE table for offsets,\n              FSE table for match lengths, and FSE table for literals lengths.\n              These tables populate the Repeat Stats literals mode and\n              Repeat distribution mode for sequence decoding.\n              It's finally followed by 3 offset values, populating recent offsets (instead of using `{1,4,8}`),\n              stored in order, 4-bytes __little-endian__ each, for a total of 12 bytes.\n              Each recent offset must have a value <= dictionary content size, and cannot equal 0.\n\n__`Content`__ : The rest of the dictionary is its content.\n              The content act as a \"past\" in front of data to compress or decompress,\n              so it can be referenced in sequence commands.\n              As long as the amount of data decoded from this frame is less than or\n              equal to `Window_Size`, sequence commands may specify offsets longer\n              than the total length of decoded output so far to reference back to the\n              dictionary, even parts of the dictionary with offsets larger than `Window_Size`.\n              After the total output has surpassed `Window_Size` however,\n              this is no longer allowed and the dictionary is no longer accessible.\n\n[compressed blocks]: #the-format-of-compressed_block\n\nIf a dictionary is provided by an external source,\nit should be loaded with great care, its content considered untrusted.\n\n\n\nAppendix A - Decoding tables for predefined codes\n-------------------------------------------------\n\nThis appendix contains FSE decoding tables\nfor the predefined literal length, match length, and offset codes.\nThe tables have been constructed using the algorithm as given above in chapter\n\"from normalized distribution to decoding tables\".\nThe tables here can be used as examples\nto crosscheck that an implementation build its decoding tables correctly.\n\n#### Literal Length Code:\n\n| State | Symbol | Number_Of_Bits | Base |\n| ----- | ------ | -------------- | ---- |\n|     0 |      0 |              4 |    0 |\n|     1 |      0 |              4 |   16 |\n|     2 |      1 |              5 |   32 |\n|     3 |      3 |              5 |    0 |\n|     4 |      4 |              5 |    0 |\n|     5 |      6 |              5 |    0 |\n|     6 |      7 |              5 |    0 |\n|     7 |      9 |              5 |    0 |\n|     8 |     10 |              5 |    0 |\n|     9 |     12 |              5 |    0 |\n|    10 |     14 |              6 |    0 |\n|    11 |     16 |              5 |    0 |\n|    12 |     18 |              5 |    0 |\n|    13 |     19 |              5 |    0 |\n|    14 |     21 |              5 |    0 |\n|    15 |     22 |              5 |    0 |\n|    16 |     24 |              5 |    0 |\n|    17 |     25 |              5 |   32 |\n|    18 |     26 |              5 |    0 |\n|    19 |     27 |              6 |    0 |\n|    20 |     29 |              6 |    0 |\n|    21 |     31 |              6 |    0 |\n|    22 |      0 |              4 |   32 |\n|    23 |      1 |              4 |    0 |\n|    24 |      2 |              5 |    0 |\n|    25 |      4 |              5 |   32 |\n|    26 |      5 |              5 |    0 |\n|    27 |      7 |              5 |   32 |\n|    28 |      8 |              5 |    0 |\n|    29 |     10 |              5 |   32 |\n|    30 |     11 |              5 |    0 |\n|    31 |     13 |              6 |    0 |\n|    32 |     16 |              5 |   32 |\n|    33 |     17 |              5 |    0 |\n|    34 |     19 |              5 |   32 |\n|    35 |     20 |              5 |    0 |\n|    36 |     22 |              5 |   32 |\n|    37 |     23 |              5 |    0 |\n|    38 |     25 |              4 |    0 |\n|    39 |     25 |              4 |   16 |\n|    40 |     26 |              5 |   32 |\n|    41 |     28 |              6 |    0 |\n|    42 |     30 |              6 |    0 |\n|    43 |      0 |              4 |   48 |\n|    44 |      1 |              4 |   16 |\n|    45 |      2 |              5 |   32 |\n|    46 |      3 |              5 |   32 |\n|    47 |      5 |              5 |   32 |\n|    48 |      6 |              5 |   32 |\n|    49 |      8 |              5 |   32 |\n|    50 |      9 |              5 |   32 |\n|    51 |     11 |              5 |   32 |\n|    52 |     12 |              5 |   32 |\n|    53 |     15 |              6 |    0 |\n|    54 |     17 |              5 |   32 |\n|    55 |     18 |              5 |   32 |\n|    56 |     20 |              5 |   32 |\n|    57 |     21 |              5 |   32 |\n|    58 |     23 |              5 |   32 |\n|    59 |     24 |              5 |   32 |\n|    60 |     35 |              6 |    0 |\n|    61 |     34 |              6 |    0 |\n|    62 |     33 |              6 |    0 |\n|    63 |     32 |              6 |    0 |\n\n#### Match Length Code:\n\n| State | Symbol | Number_Of_Bits | Base |\n| ----- | ------ | -------------- | ---- |\n|     0 |      0 |              6 |    0 |\n|     1 |      1 |              4 |    0 |\n|     2 |      2 |              5 |   32 |\n|     3 |      3 |              5 |    0 |\n|     4 |      5 |              5 |    0 |\n|     5 |      6 |              5 |    0 |\n|     6 |      8 |              5 |    0 |\n|     7 |     10 |              6 |    0 |\n|     8 |     13 |              6 |    0 |\n|     9 |     16 |              6 |    0 |\n|    10 |     19 |              6 |    0 |\n|    11 |     22 |              6 |    0 |\n|    12 |     25 |              6 |    0 |\n|    13 |     28 |              6 |    0 |\n|    14 |     31 |              6 |    0 |\n|    15 |     33 |              6 |    0 |\n|    16 |     35 |              6 |    0 |\n|    17 |     37 |              6 |    0 |\n|    18 |     39 |              6 |    0 |\n|    19 |     41 |              6 |    0 |\n|    20 |     43 |              6 |    0 |\n|    21 |     45 |              6 |    0 |\n|    22 |      1 |              4 |   16 |\n|    23 |      2 |              4 |    0 |\n|    24 |      3 |              5 |   32 |\n|    25 |      4 |              5 |    0 |\n|    26 |      6 |              5 |   32 |\n|    27 |      7 |              5 |    0 |\n|    28 |      9 |              6 |    0 |\n|    29 |     12 |              6 |    0 |\n|    30 |     15 |              6 |    0 |\n|    31 |     18 |              6 |    0 |\n|    32 |     21 |              6 |    0 |\n|    33 |     24 |              6 |    0 |\n|    34 |     27 |              6 |    0 |\n|    35 |     30 |              6 |    0 |\n|    36 |     32 |              6 |    0 |\n|    37 |     34 |              6 |    0 |\n|    38 |     36 |              6 |    0 |\n|    39 |     38 |              6 |    0 |\n|    40 |     40 |              6 |    0 |\n|    41 |     42 |              6 |    0 |\n|    42 |     44 |              6 |    0 |\n|    43 |      1 |              4 |   32 |\n|    44 |      1 |              4 |   48 |\n|    45 |      2 |              4 |   16 |\n|    46 |      4 |              5 |   32 |\n|    47 |      5 |              5 |   32 |\n|    48 |      7 |              5 |   32 |\n|    49 |      8 |              5 |   32 |\n|    50 |     11 |              6 |    0 |\n|    51 |     14 |              6 |    0 |\n|    52 |     17 |              6 |    0 |\n|    53 |     20 |              6 |    0 |\n|    54 |     23 |              6 |    0 |\n|    55 |     26 |              6 |    0 |\n|    56 |     29 |              6 |    0 |\n|    57 |     52 |              6 |    0 |\n|    58 |     51 |              6 |    0 |\n|    59 |     50 |              6 |    0 |\n|    60 |     49 |              6 |    0 |\n|    61 |     48 |              6 |    0 |\n|    62 |     47 |              6 |    0 |\n|    63 |     46 |              6 |    0 |\n\n#### Offset Code:\n\n| State | Symbol | Number_Of_Bits | Base |\n| ----- | ------ | -------------- | ---- |\n|     0 |      0 |              5 |    0 |\n|     1 |      6 |              4 |    0 |\n|     2 |      9 |              5 |    0 |\n|     3 |     15 |              5 |    0 |\n|     4 |     21 |              5 |    0 |\n|     5 |      3 |              5 |    0 |\n|     6 |      7 |              4 |    0 |\n|     7 |     12 |              5 |    0 |\n|     8 |     18 |              5 |    0 |\n|     9 |     23 |              5 |    0 |\n|    10 |      5 |              5 |    0 |\n|    11 |      8 |              4 |    0 |\n|    12 |     14 |              5 |    0 |\n|    13 |     20 |              5 |    0 |\n|    14 |      2 |              5 |    0 |\n|    15 |      7 |              4 |   16 |\n|    16 |     11 |              5 |    0 |\n|    17 |     17 |              5 |    0 |\n|    18 |     22 |              5 |    0 |\n|    19 |      4 |              5 |    0 |\n|    20 |      8 |              4 |   16 |\n|    21 |     13 |              5 |    0 |\n|    22 |     19 |              5 |    0 |\n|    23 |      1 |              5 |    0 |\n|    24 |      6 |              4 |   16 |\n|    25 |     10 |              5 |    0 |\n|    26 |     16 |              5 |    0 |\n|    27 |     28 |              5 |    0 |\n|    28 |     27 |              5 |    0 |\n|    29 |     26 |              5 |    0 |\n|    30 |     25 |              5 |    0 |\n|    31 |     24 |              5 |    0 |\n\n\n\nAppendix B - Resources for implementers\n-------------------------------------------------\n\nAn open source reference implementation is available on :\nhttps://github.com/facebook/zstd\n\nThe project contains a frame generator, called [decodeCorpus],\nwhich can be used by any 3rd-party implementation\nto verify that a tested decoder is compliant with the specification.\n\n[decodeCorpus]: https://github.com/facebook/zstd/tree/v1.3.4/tests#decodecorpus---tool-to-generate-zstandard-frames-for-decoder-testing\n\n`decodeCorpus` generates random valid frames.\nA compliant decoder should be able to decode them all,\nor at least provide a meaningful error code explaining for which reason it cannot\n(memory limit restrictions for example).\n\n\nVersion changes\n---------------\n- 0.4.4 : minor clarification for block size\n- 0.4.3 : clarifications for Huffman prefix code assignment example\n- 0.4.2 : refactor FSE table construction process, inspired by Donald Pian\n- 0.4.1 : clarifications on a few error scenarios, by Eric Lasota\n- 0.4.0 : fixed imprecise behavior for nbSeq==0, detected by Igor Pavlov\n- 0.3.9 : clarifications for Huffman-compressed literal sizes.\n- 0.3.8 : clarifications for Huffman Blocks and Huffman Tree descriptions.\n- 0.3.7 : clarifications for Repeat_Offsets, matching RFC8878\n- 0.3.6 : clarifications for Dictionary_ID\n- 0.3.5 : clarifications for Block_Maximum_Size\n- 0.3.4 : clarifications for FSE decoding table\n- 0.3.3 : clarifications for field Block_Size\n- 0.3.2 : remove additional block size restriction on compressed blocks\n- 0.3.1 : minor clarification regarding offset history update rules\n- 0.3.0 : minor edits to match RFC8478\n- 0.2.9 : clarifications for huffman weights direct representation, by Ulrich Kunitz\n- 0.2.8 : clarifications for IETF RFC discuss\n- 0.2.7 : clarifications from IETF RFC review, by Vijay Gurbani and Nick Terrell\n- 0.2.6 : fixed an error in huffman example, by Ulrich Kunitz\n- 0.2.5 : minor typos and clarifications\n- 0.2.4 : section restructuring, by Sean Purcell\n- 0.2.3 : clarified several details, by Sean Purcell\n- 0.2.2 : added predefined codes, by Johannes Rudolph\n- 0.2.1 : clarify field names, by Przemyslaw Skibinski\n- 0.2.0 : numerous format adjustments for zstd v0.8+\n- 0.1.2 : limit Huffman tree depth to 11 bits\n- 0.1.1 : reserved dictID ranges\n- 0.1.0 : initial release\n"
  },
  {
    "path": "doc/zstd_manual.html",
    "content": "<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">\n<title>zstd 1.5.7 Manual</title>\n</head>\n<body>\n<h1>zstd 1.5.7 Manual</h1>\nNote: the content of this file has been automatically generated by parsing \"zstd.h\" \n<hr>\n<a name=\"Contents\"></a><h2>Contents</h2>\n<ol>\n<li><a href=\"#Chapter1\">Introduction</a></li>\n<li><a href=\"#Chapter2\">Version</a></li>\n<li><a href=\"#Chapter3\">Simple Core API</a></li>\n<li><a href=\"#Chapter4\">Explicit context</a></li>\n<li><a href=\"#Chapter5\">Advanced compression API (Requires v1.4.0+)</a></li>\n<li><a href=\"#Chapter6\">Advanced decompression API (Requires v1.4.0+)</a></li>\n<li><a href=\"#Chapter7\">Streaming</a></li>\n<li><a href=\"#Chapter8\">Streaming compression - HowTo</a></li>\n<li><a href=\"#Chapter9\">Streaming decompression - HowTo</a></li>\n<li><a href=\"#Chapter10\">Simple dictionary API</a></li>\n<li><a href=\"#Chapter11\">Bulk processing dictionary API</a></li>\n<li><a href=\"#Chapter12\">Dictionary helper functions</a></li>\n<li><a href=\"#Chapter13\">Advanced dictionary and prefix API (Requires v1.4.0+)</a></li>\n<li><a href=\"#Chapter14\">experimental API (static linking only)</a></li>\n<li><a href=\"#Chapter15\">Frame header and size functions</a></li>\n<li><a href=\"#Chapter16\">Memory management</a></li>\n<li><a href=\"#Chapter17\">Advanced compression functions</a></li>\n<li><a href=\"#Chapter18\">Advanced decompression functions</a></li>\n<li><a href=\"#Chapter19\">Advanced streaming functions</a></li>\n<li><a href=\"#Chapter20\">Buffer-less and synchronous inner streaming functions (DEPRECATED)</a></li>\n<li><a href=\"#Chapter21\">Buffer-less streaming compression (synchronous mode)</a></li>\n<li><a href=\"#Chapter22\">Buffer-less streaming decompression (synchronous mode)</a></li>\n<li><a href=\"#Chapter23\">Block level API (DEPRECATED)</a></li>\n</ol>\n<hr>\n<a name=\"Chapter1\"></a><h2>Introduction</h2><pre>\n  zstd, short for Zstandard, is a fast lossless compression algorithm, targeting\n  real-time compression scenarios at zlib-level and better compression ratios.\n  The zstd compression library provides in-memory compression and decompression\n  functions.\n\n  The library supports regular compression levels from 1 up to ZSTD_maxCLevel(),\n  which is currently 22. Levels >= 20, labeled `--ultra`, should be used with\n  caution, as they require more memory. The library also offers negative\n  compression levels, which extend the range of speed vs. ratio preferences.\n  The lower the level, the faster the speed (at the cost of compression).\n\n  Compression can be done in:\n    - a single step (described as Simple API)\n    - a single step, reusing a context (described as Explicit context)\n    - unbounded multiple steps (described as Streaming compression)\n\n  The compression ratio achievable on small data can be highly improved using\n  a dictionary. Dictionary compression can be performed in:\n    - a single step (described as Simple dictionary API)\n    - a single step, reusing a dictionary (described as Bulk-processing\n      dictionary API)\n\n  Advanced experimental functions can be accessed using\n  `#define ZSTD_STATIC_LINKING_ONLY` before including zstd.h.\n\n  Advanced experimental APIs should never be used with a dynamically-linked\n  library. They are not \"stable\"; their definitions or signatures may change in\n  the future. Only static linking is allowed.\n<BR></pre>\n\n<a name=\"Chapter2\"></a><h2>Version</h2><pre></pre>\n\n<pre><b>unsigned ZSTD_versionNumber(void);\n</b><p>  Return runtime library version, the value is (MAJOR*100*100 + MINOR*100 + RELEASE). \n</p></pre><BR>\n\n<pre><b>const char* ZSTD_versionString(void);\n</b><p>  Return runtime library version, like \"1.4.5\". Requires v1.3.0+. \n</p></pre><BR>\n\n<a name=\"Chapter3\"></a><h2>Simple Core API</h2><pre></pre>\n\n<pre><b>size_t ZSTD_compress( void* dst, size_t dstCapacity,\n                const void* src, size_t srcSize,\n                      int compressionLevel);\n</b><p>  Compresses `src` content as a single zstd compressed frame into already allocated `dst`.\n  NOTE: Providing `dstCapacity >= ZSTD_compressBound(srcSize)` guarantees that zstd will have\n        enough space to successfully compress the data.\n  @return : compressed size written into `dst` (<= `dstCapacity),\n            or an error code if it fails (which can be tested using ZSTD_isError()). \n</p></pre><BR>\n\n<pre><b>size_t ZSTD_decompress( void* dst, size_t dstCapacity,\n                  const void* src, size_t compressedSize);\n</b><p> `compressedSize` : must be the _exact_ size of some number of compressed and/or skippable frames.\n  Multiple compressed frames can be decompressed at once with this method.\n  The result will be the concatenation of all decompressed frames, back to back.\n `dstCapacity` is an upper bound of originalSize to regenerate.\n  First frame's decompressed size can be extracted using ZSTD_getFrameContentSize().\n  If maximum upper bound isn't known, prefer using streaming mode to decompress data.\n @return : the number of bytes decompressed into `dst` (<= `dstCapacity`),\n           or an errorCode if it fails (which can be tested using ZSTD_isError()). \n</p></pre><BR>\n\n<h3>Decompression helper functions</h3><pre></pre><b><pre></pre></b><BR>\n<pre><b>#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1)\n#define ZSTD_CONTENTSIZE_ERROR   (0ULL - 2)\nunsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize);\n</b><p> `src` should point to the start of a ZSTD encoded frame.\n `srcSize` must be at least as large as the frame header.\n           hint : any size >= `ZSTD_frameHeaderSize_max` is large enough.\n @return : - decompressed size of `src` frame content, if known\n           - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined\n           - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small)\n  note 1 : a 0 return value means the frame is valid but \"empty\".\n           When invoking this method on a skippable frame, it will return 0.\n  note 2 : decompressed size is an optional field, it may not be present (typically in streaming mode).\n           When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size.\n           In which case, it's necessary to use streaming mode to decompress data.\n           Optionally, application can rely on some implicit limit,\n           as ZSTD_decompress() only needs an upper bound of decompressed size.\n           (For example, data could be necessarily cut into blocks <= 16 KB).\n  note 3 : decompressed size is always present when compression is completed using single-pass functions,\n           such as ZSTD_compress(), ZSTD_compressCCtx() ZSTD_compress_usingDict() or ZSTD_compress_usingCDict().\n  note 4 : decompressed size can be very large (64-bits value),\n           potentially larger than what local system can handle as a single memory segment.\n           In which case, it's necessary to use streaming mode to decompress data.\n  note 5 : If source is untrusted, decompressed size could be wrong or intentionally modified.\n           Always ensure return value fits within application's authorized limits.\n           Each application can set its own limits.\n  note 6 : This function replaces ZSTD_getDecompressedSize() \n</p></pre><BR>\n\n<pre><b>ZSTD_DEPRECATED(\"Replaced by ZSTD_getFrameContentSize\")\nunsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize);\n</b><p>  This function is now obsolete, in favor of ZSTD_getFrameContentSize().\n  Both functions work the same way, but ZSTD_getDecompressedSize() blends\n  \"empty\", \"unknown\" and \"error\" results to the same return value (0),\n  while ZSTD_getFrameContentSize() gives them separate return values.\n @return : decompressed size of `src` frame content _if known and not empty_, 0 otherwise. \n</p></pre><BR>\n\n<pre><b>size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize);\n</b><p> `src` should point to the start of a ZSTD frame or skippable frame.\n `srcSize` must be >= first frame size\n @return : the compressed size of the first frame starting at `src`,\n           suitable to pass as `srcSize` to `ZSTD_decompress` or similar,\n           or an error code if input is invalid\n  Note 1: this method is called _find*() because it's not enough to read the header,\n          it may have to scan through the frame's content, to reach its end.\n  Note 2: this method also works with Skippable Frames. In which case,\n          it returns the size of the complete skippable frame,\n          which is always equal to its content size + 8 bytes for headers. \n</p></pre><BR>\n\n<h3>Compression helper functions</h3><pre></pre><b><pre></pre></b><BR>\n<pre><b>#define ZSTD_MAX_INPUT_SIZE ((sizeof(size_t)==8) ? 0xFF00FF00FF00FF00ULL : 0xFF00FF00U)\n#define ZSTD_COMPRESSBOUND(srcSize)   (((size_t)(srcSize) >= ZSTD_MAX_INPUT_SIZE) ? 0 : (srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) </b>/* margin, from 64 to 0 */ : 0))  /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */<b>\nsize_t ZSTD_compressBound(size_t srcSize); </b>/*!< maximum compressed size in worst case single-pass scenario */<b>\n</b><p> maximum compressed size in worst case single-pass scenario.\n When invoking `ZSTD_compress()`, or any other one-pass compression function,\n it's recommended to provide @dstCapacity >= ZSTD_compressBound(srcSize)\n as it eliminates one potential failure scenario,\n aka not enough room in dst buffer to write the compressed frame.\n Note : ZSTD_compressBound() itself can fail, if @srcSize >= ZSTD_MAX_INPUT_SIZE .\n        In which case, ZSTD_compressBound() will return an error code\n        which can be tested using ZSTD_isError().\n\n ZSTD_COMPRESSBOUND() :\n same as ZSTD_compressBound(), but as a macro.\n It can be used to produce constants, which can be useful for static allocation,\n for example to size a static array on stack.\n Will produce constant value 0 if srcSize is too large.\n \n</p></pre><BR>\n\n<h3>Error helper functions</h3><pre></pre><b><pre></b>/* ZSTD_isError() :<b>\n * Most ZSTD_* functions returning a size_t value can be tested for error,\n * using ZSTD_isError().\n * @return 1 if error, 0 otherwise\n */\nunsigned     ZSTD_isError(size_t result);      </b>/*!< tells if a `size_t` function result is an error code */<b>\nZSTD_ErrorCode ZSTD_getErrorCode(size_t functionResult); </b>/* convert a result into an error code, which can be compared to error enum list */<b>\nconst char*  ZSTD_getErrorName(size_t result); </b>/*!< provides readable string from a function result */<b>\nint          ZSTD_minCLevel(void);             </b>/*!< minimum negative compression level allowed, requires v1.4.0+ */<b>\nint          ZSTD_maxCLevel(void);             </b>/*!< maximum compression level available */<b>\nint          ZSTD_defaultCLevel(void);         </b>/*!< default compression level, specified by ZSTD_CLEVEL_DEFAULT, requires v1.5.0+ */<b>\n</pre></b><BR>\n<a name=\"Chapter4\"></a><h2>Explicit context</h2><pre></pre>\n\n<h3>Compression context</h3><pre>  When compressing many times,\n  it is recommended to allocate a compression context just once,\n  and reuse it for each successive compression operation.\n  This will make the workload easier for system's memory.\n  Note : re-using context is just a speed / resource optimization.\n         It doesn't change the compression ratio, which remains identical.\n  Note 2: For parallel execution in multi-threaded environments,\n         use one different context per thread .\n \n</pre><b><pre>typedef struct ZSTD_CCtx_s ZSTD_CCtx;\nZSTD_CCtx* ZSTD_createCCtx(void);\nsize_t     ZSTD_freeCCtx(ZSTD_CCtx* cctx);  </b>/* compatible with NULL pointer */<b>\n</pre></b><BR>\n<pre><b>size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx,\n                         void* dst, size_t dstCapacity,\n                   const void* src, size_t srcSize,\n                         int compressionLevel);\n</b><p>  Same as ZSTD_compress(), using an explicit ZSTD_CCtx.\n  Important : in order to mirror `ZSTD_compress()` behavior,\n  this function compresses at the requested compression level,\n  __ignoring any other advanced parameter__ .\n  If any advanced parameter was set using the advanced API,\n  they will all be reset. Only @compressionLevel remains.\n \n</p></pre><BR>\n\n<h3>Decompression context</h3><pre>  When decompressing many times,\n  it is recommended to allocate a context only once,\n  and reuse it for each successive compression operation.\n  This will make workload friendlier for system's memory.\n  Use one context per thread for parallel execution. \n</pre><b><pre>typedef struct ZSTD_DCtx_s ZSTD_DCtx;\nZSTD_DCtx* ZSTD_createDCtx(void);\nsize_t     ZSTD_freeDCtx(ZSTD_DCtx* dctx);  </b>/* accept NULL pointer */<b>\n</pre></b><BR>\n<pre><b>size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx,\n                           void* dst, size_t dstCapacity,\n                     const void* src, size_t srcSize);\n</b><p>  Same as ZSTD_decompress(),\n  requires an allocated ZSTD_DCtx.\n  Compatible with sticky parameters (see below).\n \n</p></pre><BR>\n\n<a name=\"Chapter5\"></a><h2>Advanced compression API (Requires v1.4.0+)</h2><pre></pre>\n\n<pre><b>typedef enum { ZSTD_fast=1,\n               ZSTD_dfast=2,\n               ZSTD_greedy=3,\n               ZSTD_lazy=4,\n               ZSTD_lazy2=5,\n               ZSTD_btlazy2=6,\n               ZSTD_btopt=7,\n               ZSTD_btultra=8,\n               ZSTD_btultra2=9\n               </b>/* note : new strategies _might_ be added in the future.<b>\n                         Only the order (from fast to strong) is guaranteed */\n} ZSTD_strategy;\n</b></pre><BR>\n<pre><b>typedef enum {\n\n    </b>/* compression parameters<b>\n     * Note: When compressing with a ZSTD_CDict these parameters are superseded\n     * by the parameters used to construct the ZSTD_CDict.\n     * See ZSTD_CCtx_refCDict() for more info (superseded-by-cdict). */\n    ZSTD_c_compressionLevel=100, </b>/* Set compression parameters according to pre-defined cLevel table.<b>\n                              * Note that exact compression parameters are dynamically determined,\n                              * depending on both compression level and srcSize (when known).\n                              * Default level is ZSTD_CLEVEL_DEFAULT==3.\n                              * Special: value 0 means default, which is controlled by ZSTD_CLEVEL_DEFAULT.\n                              * Note 1 : it's possible to pass a negative compression level.\n                              * Note 2 : setting a level does not automatically set all other compression parameters\n                              *   to default. Setting this will however eventually dynamically impact the compression\n                              *   parameters which have not been manually set. The manually set\n                              *   ones will 'stick'. */\n    </b>/* Advanced compression parameters :<b>\n     * It's possible to pin down compression parameters to some specific values.\n     * In which case, these values are no longer dynamically selected by the compressor */\n    ZSTD_c_windowLog=101,    </b>/* Maximum allowed back-reference distance, expressed as power of 2.<b>\n                              * This will set a memory budget for streaming decompression,\n                              * with larger values requiring more memory\n                              * and typically compressing more.\n                              * Must be clamped between ZSTD_WINDOWLOG_MIN and ZSTD_WINDOWLOG_MAX.\n                              * Special: value 0 means \"use default windowLog\".\n                              * Note: Using a windowLog greater than ZSTD_WINDOWLOG_LIMIT_DEFAULT\n                              *       requires explicitly allowing such size at streaming decompression stage. */\n    ZSTD_c_hashLog=102,      </b>/* Size of the initial probe table, as a power of 2.<b>\n                              * Resulting memory usage is (1 << (hashLog+2)).\n                              * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX.\n                              * Larger tables improve compression ratio of strategies <= dFast,\n                              * and improve speed of strategies > dFast.\n                              * Special: value 0 means \"use default hashLog\". */\n    ZSTD_c_chainLog=103,     </b>/* Size of the multi-probe search table, as a power of 2.<b>\n                              * Resulting memory usage is (1 << (chainLog+2)).\n                              * Must be clamped between ZSTD_CHAINLOG_MIN and ZSTD_CHAINLOG_MAX.\n                              * Larger tables result in better and slower compression.\n                              * This parameter is useless for \"fast\" strategy.\n                              * It's still useful when using \"dfast\" strategy,\n                              * in which case it defines a secondary probe table.\n                              * Special: value 0 means \"use default chainLog\". */\n    ZSTD_c_searchLog=104,    </b>/* Number of search attempts, as a power of 2.<b>\n                              * More attempts result in better and slower compression.\n                              * This parameter is useless for \"fast\" and \"dFast\" strategies.\n                              * Special: value 0 means \"use default searchLog\". */\n    ZSTD_c_minMatch=105,     </b>/* Minimum size of searched matches.<b>\n                              * Note that Zstandard can still find matches of smaller size,\n                              * it just tweaks its search algorithm to look for this size and larger.\n                              * Larger values increase compression and decompression speed, but decrease ratio.\n                              * Must be clamped between ZSTD_MINMATCH_MIN and ZSTD_MINMATCH_MAX.\n                              * Note that currently, for all strategies < btopt, effective minimum is 4.\n                              *                    , for all strategies > fast, effective maximum is 6.\n                              * Special: value 0 means \"use default minMatchLength\". */\n    ZSTD_c_targetLength=106, </b>/* Impact of this field depends on strategy.<b>\n                              * For strategies btopt, btultra & btultra2:\n                              *     Length of Match considered \"good enough\" to stop search.\n                              *     Larger values make compression stronger, and slower.\n                              * For strategy fast:\n                              *     Distance between match sampling.\n                              *     Larger values make compression faster, and weaker.\n                              * Special: value 0 means \"use default targetLength\". */\n    ZSTD_c_strategy=107,     </b>/* See ZSTD_strategy enum definition.<b>\n                              * The higher the value of selected strategy, the more complex it is,\n                              * resulting in stronger and slower compression.\n                              * Special: value 0 means \"use default strategy\". */\n\n    ZSTD_c_targetCBlockSize=130, </b>/* v1.5.6+<b>\n                                  * Attempts to fit compressed block size into approximately targetCBlockSize.\n                                  * Bound by ZSTD_TARGETCBLOCKSIZE_MIN and ZSTD_TARGETCBLOCKSIZE_MAX.\n                                  * Note that it's not a guarantee, just a convergence target (default:0).\n                                  * No target when targetCBlockSize == 0.\n                                  * This is helpful in low bandwidth streaming environments to improve end-to-end latency,\n                                  * when a client can make use of partial documents (a prominent example being Chrome).\n                                  * Note: this parameter is stable since v1.5.6.\n                                  * It was present as an experimental parameter in earlier versions,\n                                  * but it's not recommended using it with earlier library versions\n                                  * due to massive performance regressions.\n                                  */\n    </b>/* LDM mode parameters */<b>\n    ZSTD_c_enableLongDistanceMatching=160, </b>/* Enable long distance matching.<b>\n                                     * This parameter is designed to improve compression ratio\n                                     * for large inputs, by finding large matches at long distance.\n                                     * It increases memory usage and window size.\n                                     * Note: enabling this parameter increases default ZSTD_c_windowLog to 128 MB\n                                     * except when expressly set to a different value.\n                                     * Note: will be enabled by default if ZSTD_c_windowLog >= 128 MB and\n                                     * compression strategy >= ZSTD_btopt (== compression level 16+) */\n    ZSTD_c_ldmHashLog=161,   </b>/* Size of the table for long distance matching, as a power of 2.<b>\n                              * Larger values increase memory usage and compression ratio,\n                              * but decrease compression speed.\n                              * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX\n                              * default: windowlog - 7.\n                              * Special: value 0 means \"automatically determine hashlog\". */\n    ZSTD_c_ldmMinMatch=162,  </b>/* Minimum match size for long distance matcher.<b>\n                              * Larger/too small values usually decrease compression ratio.\n                              * Must be clamped between ZSTD_LDM_MINMATCH_MIN and ZSTD_LDM_MINMATCH_MAX.\n                              * Special: value 0 means \"use default value\" (default: 64). */\n    ZSTD_c_ldmBucketSizeLog=163, </b>/* Log size of each bucket in the LDM hash table for collision resolution.<b>\n                              * Larger values improve collision resolution but decrease compression speed.\n                              * The maximum value is ZSTD_LDM_BUCKETSIZELOG_MAX.\n                              * Special: value 0 means \"use default value\" (default: 3). */\n    ZSTD_c_ldmHashRateLog=164, </b>/* Frequency of inserting/looking up entries into the LDM hash table.<b>\n                              * Must be clamped between 0 and (ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN).\n                              * Default is MAX(0, (windowLog - ldmHashLog)), optimizing hash table usage.\n                              * Larger values improve compression speed.\n                              * Deviating far from default value will likely result in a compression ratio decrease.\n                              * Special: value 0 means \"automatically determine hashRateLog\". */\n\n    </b>/* frame parameters */<b>\n    ZSTD_c_contentSizeFlag=200, </b>/* Content size will be written into frame header _whenever known_ (default:1)<b>\n                              * Content size must be known at the beginning of compression.\n                              * This is automatically the case when using ZSTD_compress2(),\n                              * For streaming scenarios, content size must be provided with ZSTD_CCtx_setPledgedSrcSize() */\n    ZSTD_c_checksumFlag=201, </b>/* A 32-bits checksum of content is written at end of frame (default:0) */<b>\n    ZSTD_c_dictIDFlag=202,   </b>/* When applicable, dictionary's ID is written into frame header (default:1) */<b>\n\n    </b>/* multi-threading parameters */<b>\n    </b>/* These parameters are only active if multi-threading is enabled (compiled with build macro ZSTD_MULTITHREAD).<b>\n     * Otherwise, trying to set any other value than default (0) will be a no-op and return an error.\n     * In a situation where it's unknown if the linked library supports multi-threading or not,\n     * setting ZSTD_c_nbWorkers to any value >= 1 and consulting the return value provides a quick way to check this property.\n     */\n    ZSTD_c_nbWorkers=400,    </b>/* Select how many threads will be spawned to compress in parallel.<b>\n                              * When nbWorkers >= 1, triggers asynchronous mode when invoking ZSTD_compressStream*() :\n                              * ZSTD_compressStream*() consumes input and flush output if possible, but immediately gives back control to caller,\n                              * while compression is performed in parallel, within worker thread(s).\n                              * (note : a strong exception to this rule is when first invocation of ZSTD_compressStream2() sets ZSTD_e_end :\n                              *  in which case, ZSTD_compressStream2() delegates to ZSTD_compress2(), which is always a blocking call).\n                              * More workers improve speed, but also increase memory usage.\n                              * Default value is `0`, aka \"single-threaded mode\" : no worker is spawned,\n                              * compression is performed inside Caller's thread, and all invocations are blocking */\n    ZSTD_c_jobSize=401,      </b>/* Size of a compression job. This value is enforced only when nbWorkers >= 1.<b>\n                              * Each compression job is completed in parallel, so this value can indirectly impact the nb of active threads.\n                              * 0 means default, which is dynamically determined based on compression parameters.\n                              * Job size must be a minimum of overlap size, or ZSTDMT_JOBSIZE_MIN (= 512 KB), whichever is largest.\n                              * The minimum size is automatically and transparently enforced. */\n    ZSTD_c_overlapLog=402,   </b>/* Control the overlap size, as a fraction of window size.<b>\n                              * The overlap size is an amount of data reloaded from previous job at the beginning of a new job.\n                              * It helps preserve compression ratio, while each job is compressed in parallel.\n                              * This value is enforced only when nbWorkers >= 1.\n                              * Larger values increase compression ratio, but decrease speed.\n                              * Possible values range from 0 to 9 :\n                              * - 0 means \"default\" : value will be determined by the library, depending on strategy\n                              * - 1 means \"no overlap\"\n                              * - 9 means \"full overlap\", using a full window size.\n                              * Each intermediate rank increases/decreases load size by a factor 2 :\n                              * 9: full window;  8: w/2;  7: w/4;  6: w/8;  5:w/16;  4: w/32;  3:w/64;  2:w/128;  1:no overlap;  0:default\n                              * default value varies between 6 and 9, depending on strategy */\n\n    </b>/* note : additional experimental parameters are also available<b>\n     * within the experimental section of the API.\n     * At the time of this writing, they include :\n     * ZSTD_c_rsyncable\n     * ZSTD_c_format\n     * ZSTD_c_forceMaxWindow\n     * ZSTD_c_forceAttachDict\n     * ZSTD_c_literalCompressionMode\n     * ZSTD_c_srcSizeHint\n     * ZSTD_c_enableDedicatedDictSearch\n     * ZSTD_c_stableInBuffer\n     * ZSTD_c_stableOutBuffer\n     * ZSTD_c_blockDelimiters\n     * ZSTD_c_validateSequences\n     * ZSTD_c_blockSplitterLevel\n     * ZSTD_c_splitAfterSequences\n     * ZSTD_c_useRowMatchFinder\n     * ZSTD_c_prefetchCDictTables\n     * ZSTD_c_enableSeqProducerFallback\n     * ZSTD_c_maxBlockSize\n     * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.\n     * note : never ever use experimentalParam? names directly;\n     *        also, the enums values themselves are unstable and can still change.\n     */\n     ZSTD_c_experimentalParam1=500,\n     ZSTD_c_experimentalParam2=10,\n     ZSTD_c_experimentalParam3=1000,\n     ZSTD_c_experimentalParam4=1001,\n     ZSTD_c_experimentalParam5=1002,\n     </b>/* was ZSTD_c_experimentalParam6=1003; is now ZSTD_c_targetCBlockSize */<b>\n     ZSTD_c_experimentalParam7=1004,\n     ZSTD_c_experimentalParam8=1005,\n     ZSTD_c_experimentalParam9=1006,\n     ZSTD_c_experimentalParam10=1007,\n     ZSTD_c_experimentalParam11=1008,\n     ZSTD_c_experimentalParam12=1009,\n     ZSTD_c_experimentalParam13=1010,\n     ZSTD_c_experimentalParam14=1011,\n     ZSTD_c_experimentalParam15=1012,\n     ZSTD_c_experimentalParam16=1013,\n     ZSTD_c_experimentalParam17=1014,\n     ZSTD_c_experimentalParam18=1015,\n     ZSTD_c_experimentalParam19=1016,\n     ZSTD_c_experimentalParam20=1017\n} ZSTD_cParameter;\n</b></pre><BR>\n<pre><b>typedef struct {\n    size_t error;\n    int lowerBound;\n    int upperBound;\n} ZSTD_bounds;\n</b></pre><BR>\n<pre><b>ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter cParam);\n</b><p>  All parameters must belong to an interval with lower and upper bounds,\n  otherwise they will either trigger an error or be automatically clamped.\n @return : a structure, ZSTD_bounds, which contains\n         - an error status field, which must be tested using ZSTD_isError()\n         - lower and upper bounds, both inclusive\n \n</p></pre><BR>\n\n<pre><b>size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value);\n</b><p>  Set one compression parameter, selected by enum ZSTD_cParameter.\n  All parameters have valid bounds. Bounds can be queried using ZSTD_cParam_getBounds().\n  Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter).\n  Setting a parameter is generally only possible during frame initialization (before starting compression).\n  Exception : when using multi-threading mode (nbWorkers >= 1),\n              the following parameters can be updated _during_ compression (within same frame):\n              => compressionLevel, hashLog, chainLog, searchLog, minMatch, targetLength and strategy.\n              new parameters will be active for next job only (after a flush()).\n @return : an error code (which can be tested using ZSTD_isError()).\n \n</p></pre><BR>\n\n<pre><b>size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize);\n</b><p>  Total input data size to be compressed as a single frame.\n  Value will be written in frame header, unless if explicitly forbidden using ZSTD_c_contentSizeFlag.\n  This value will also be controlled at end of frame, and trigger an error if not respected.\n @result : 0, or an error code (which can be tested with ZSTD_isError()).\n  Note 1 : pledgedSrcSize==0 actually means zero, aka an empty frame.\n           In order to mean \"unknown content size\", pass constant ZSTD_CONTENTSIZE_UNKNOWN.\n           ZSTD_CONTENTSIZE_UNKNOWN is default value for any new frame.\n  Note 2 : pledgedSrcSize is only valid once, for the next frame.\n           It's discarded at the end of the frame, and replaced by ZSTD_CONTENTSIZE_UNKNOWN.\n  Note 3 : Whenever all input data is provided and consumed in a single round,\n           for example with ZSTD_compress2(),\n           or invoking immediately ZSTD_compressStream2(,,,ZSTD_e_end),\n           this value is automatically overridden by srcSize instead.\n \n</p></pre><BR>\n\n<pre><b>typedef enum {\n    ZSTD_reset_session_only = 1,\n    ZSTD_reset_parameters = 2,\n    ZSTD_reset_session_and_parameters = 3\n} ZSTD_ResetDirective;\n</b></pre><BR>\n<pre><b>size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset);\n</b><p>  There are 2 different things that can be reset, independently or jointly :\n  - The session : will stop compressing current frame, and make CCtx ready to start a new one.\n                  Useful after an error, or to interrupt any ongoing compression.\n                  Any internal data not yet flushed is cancelled.\n                  Compression parameters and dictionary remain unchanged.\n                  They will be used to compress next frame.\n                  Resetting session never fails.\n  - The parameters : changes all parameters back to \"default\".\n                  This also removes any reference to any dictionary or external sequence producer.\n                  Parameters can only be changed between 2 sessions (i.e. no compression is currently ongoing)\n                  otherwise the reset fails, and function returns an error value (which can be tested using ZSTD_isError())\n  - Both : similar to resetting the session, followed by resetting parameters.\n \n</p></pre><BR>\n\n<pre><b>size_t ZSTD_compress2( ZSTD_CCtx* cctx,\n                       void* dst, size_t dstCapacity,\n                 const void* src, size_t srcSize);\n</b><p>  Behave the same as ZSTD_compressCCtx(), but compression parameters are set using the advanced API.\n  (note that this entry point doesn't even expose a compression level parameter).\n  ZSTD_compress2() always starts a new frame.\n  Should cctx hold data from a previously unfinished frame, everything about it is forgotten.\n  - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()\n  - The function is always blocking, returns when compression is completed.\n  NOTE: Providing `dstCapacity >= ZSTD_compressBound(srcSize)` guarantees that zstd will have\n        enough space to successfully compress the data, though it is possible it fails for other reasons.\n @return : compressed size written into `dst` (<= `dstCapacity),\n           or an error code if it fails (which can be tested using ZSTD_isError()).\n \n</p></pre><BR>\n\n<a name=\"Chapter6\"></a><h2>Advanced decompression API (Requires v1.4.0+)</h2><pre></pre>\n\n<pre><b>typedef enum {\n\n    ZSTD_d_windowLogMax=100, </b>/* Select a size limit (in power of 2) beyond which<b>\n                              * the streaming API will refuse to allocate memory buffer\n                              * in order to protect the host from unreasonable memory requirements.\n                              * This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode.\n                              * By default, a decompression context accepts window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT).\n                              * Special: value 0 means \"use default maximum windowLog\". */\n\n    </b>/* note : additional experimental parameters are also available<b>\n     * within the experimental section of the API.\n     * At the time of this writing, they include :\n     * ZSTD_d_format\n     * ZSTD_d_stableOutBuffer\n     * ZSTD_d_forceIgnoreChecksum\n     * ZSTD_d_refMultipleDDicts\n     * ZSTD_d_disableHuffmanAssembly\n     * ZSTD_d_maxBlockSize\n     * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.\n     * note : never ever use experimentalParam? names directly\n     */\n     ZSTD_d_experimentalParam1=1000,\n     ZSTD_d_experimentalParam2=1001,\n     ZSTD_d_experimentalParam3=1002,\n     ZSTD_d_experimentalParam4=1003,\n     ZSTD_d_experimentalParam5=1004,\n     ZSTD_d_experimentalParam6=1005\n\n} ZSTD_dParameter;\n</b></pre><BR>\n<pre><b>ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam);\n</b><p>  All parameters must belong to an interval with lower and upper bounds,\n  otherwise they will either trigger an error or be automatically clamped.\n @return : a structure, ZSTD_bounds, which contains\n         - an error status field, which must be tested using ZSTD_isError()\n         - both lower and upper bounds, inclusive\n \n</p></pre><BR>\n\n<pre><b>size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int value);\n</b><p>  Set one compression parameter, selected by enum ZSTD_dParameter.\n  All parameters have valid bounds. Bounds can be queried using ZSTD_dParam_getBounds().\n  Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter).\n  Setting a parameter is only possible during frame initialization (before starting decompression).\n @return : 0, or an error code (which can be tested using ZSTD_isError()).\n \n</p></pre><BR>\n\n<pre><b>size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset);\n</b><p>  Return a DCtx to clean state.\n  Session and parameters can be reset jointly or separately.\n  Parameters can only be reset when no active frame is being decompressed.\n @return : 0, or an error code, which can be tested with ZSTD_isError()\n \n</p></pre><BR>\n\n<a name=\"Chapter7\"></a><h2>Streaming</h2><pre></pre>\n\n<pre><b>typedef struct ZSTD_inBuffer_s {\n  const void* src;    </b>/**< start of input buffer */<b>\n  size_t size;        </b>/**< size of input buffer */<b>\n  size_t pos;         </b>/**< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */<b>\n} ZSTD_inBuffer;\n</b></pre><BR>\n<pre><b>typedef struct ZSTD_outBuffer_s {\n  void*  dst;         </b>/**< start of output buffer */<b>\n  size_t size;        </b>/**< size of output buffer */<b>\n  size_t pos;         </b>/**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */<b>\n} ZSTD_outBuffer;\n</b></pre><BR>\n<a name=\"Chapter8\"></a><h2>Streaming compression - HowTo</h2><pre>\n  A ZSTD_CStream object is required to track streaming operation.\n  Use ZSTD_createCStream() and ZSTD_freeCStream() to create/release resources.\n  ZSTD_CStream objects can be reused multiple times on consecutive compression operations.\n  It is recommended to reuse ZSTD_CStream since it will play nicer with system's memory, by re-using already allocated memory.\n\n  For parallel execution, use one separate ZSTD_CStream per thread.\n\n  note : since v1.3.0, ZSTD_CStream and ZSTD_CCtx are the same thing.\n\n  Parameters are sticky : when starting a new compression on the same context,\n  it will reuse the same sticky parameters as previous compression session.\n  When in doubt, it's recommended to fully initialize the context before usage.\n  Use ZSTD_CCtx_reset() to reset the context and ZSTD_CCtx_setParameter(),\n  ZSTD_CCtx_setPledgedSrcSize(), or ZSTD_CCtx_loadDictionary() and friends to\n  set more specific parameters, the pledged source size, or load a dictionary.\n\n  Use ZSTD_compressStream2() with ZSTD_e_continue as many times as necessary to\n  consume input stream. The function will automatically update both `pos`\n  fields within `input` and `output`.\n  Note that the function may not consume the entire input, for example, because\n  the output buffer is already full, in which case `input.pos < input.size`.\n  The caller must check if input has been entirely consumed.\n  If not, the caller must make some room to receive more compressed data,\n  and then present again remaining input data.\n  note: ZSTD_e_continue is guaranteed to make some forward progress when called,\n        but doesn't guarantee maximal forward progress. This is especially relevant\n        when compressing with multiple threads. The call won't block if it can\n        consume some input, but if it can't it will wait for some, but not all,\n        output to be flushed.\n @return : provides a minimum amount of data remaining to be flushed from internal buffers\n           or an error code, which can be tested using ZSTD_isError().\n\n  At any moment, it's possible to flush whatever data might remain stuck within internal buffer,\n  using ZSTD_compressStream2() with ZSTD_e_flush. `output->pos` will be updated.\n  Note that, if `output->size` is too small, a single invocation with ZSTD_e_flush might not be enough (return code > 0).\n  In which case, make some room to receive more compressed data, and call again ZSTD_compressStream2() with ZSTD_e_flush.\n  You must continue calling ZSTD_compressStream2() with ZSTD_e_flush until it returns 0, at which point you can change the\n  operation.\n  note: ZSTD_e_flush will flush as much output as possible, meaning when compressing with multiple threads, it will\n        block until the flush is complete or the output buffer is full.\n  @return : 0 if internal buffers are entirely flushed,\n            >0 if some data still present within internal buffer (the value is minimal estimation of remaining size),\n            or an error code, which can be tested using ZSTD_isError().\n\n  Calling ZSTD_compressStream2() with ZSTD_e_end instructs to finish a frame.\n  It will perform a flush and write frame epilogue.\n  The epilogue is required for decoders to consider a frame completed.\n  flush operation is the same, and follows same rules as calling ZSTD_compressStream2() with ZSTD_e_flush.\n  You must continue calling ZSTD_compressStream2() with ZSTD_e_end until it returns 0, at which point you are free to\n  start a new frame.\n  note: ZSTD_e_end will flush as much output as possible, meaning when compressing with multiple threads, it will\n        block until the flush is complete or the output buffer is full.\n  @return : 0 if frame fully completed and fully flushed,\n            >0 if some data still present within internal buffer (the value is minimal estimation of remaining size),\n            or an error code, which can be tested using ZSTD_isError().\n\n \n<BR></pre>\n\n<pre><b>typedef ZSTD_CCtx ZSTD_CStream;  </b>/**< CCtx and CStream are now effectively same object (>= v1.3.0) */<b>\n</b></pre><BR>\n<h3>ZSTD_CStream management functions</h3><pre></pre><b><pre>ZSTD_CStream* ZSTD_createCStream(void);\nsize_t ZSTD_freeCStream(ZSTD_CStream* zcs);  </b>/* accept NULL pointer */<b>\n</pre></b><BR>\n<h3>Streaming compression functions</h3><pre></pre><b><pre>typedef enum {\n    ZSTD_e_continue=0, </b>/* collect more data, encoder decides when to output compressed result, for optimal compression ratio */<b>\n    ZSTD_e_flush=1,    </b>/* flush any data provided so far,<b>\n                        * it creates (at least) one new block, that can be decoded immediately on reception;\n                        * frame will continue: any future data can still reference previously compressed data, improving compression.\n                        * note : multithreaded compression will block to flush as much output as possible. */\n    ZSTD_e_end=2       </b>/* flush any remaining data _and_ close current frame.<b>\n                        * note that frame is only closed after compressed data is fully flushed (return value == 0).\n                        * After that point, any additional data starts a new frame.\n                        * note : each frame is independent (does not reference any content from previous frame).\n                        : note : multithreaded compression will block to flush as much output as possible. */\n} ZSTD_EndDirective;\n</pre></b><BR>\n<pre><b>size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,\n                             ZSTD_outBuffer* output,\n                             ZSTD_inBuffer* input,\n                             ZSTD_EndDirective endOp);\n</b><p>  Behaves about the same as ZSTD_compressStream, with additional control on end directive.\n  - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()\n  - Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode)\n  - output->pos must be <= dstCapacity, input->pos must be <= srcSize\n  - output->pos and input->pos will be updated. They are guaranteed to remain below their respective limit.\n  - endOp must be a valid directive\n  - When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller.\n  - When nbWorkers>=1, function is non-blocking : it copies a portion of input, distributes jobs to internal worker threads, flush to output whatever is available,\n                                                  and then immediately returns, just indicating that there is some data remaining to be flushed.\n                                                  The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte.\n  - Exception : if the first call requests a ZSTD_e_end directive and provides enough dstCapacity, the function delegates to ZSTD_compress2() which is always blocking.\n  - @return provides a minimum amount of data remaining to be flushed from internal buffers\n            or an error code, which can be tested using ZSTD_isError().\n            if @return != 0, flush is not fully completed, there is still some data left within internal buffers.\n            This is useful for ZSTD_e_flush, since in this case more flushes are necessary to empty all buffers.\n            For ZSTD_e_end, @return == 0 when internal buffers are fully flushed and frame is completed.\n  - after a ZSTD_e_end directive, if internal buffer is not fully flushed (@return != 0),\n            only ZSTD_e_end or ZSTD_e_flush operations are allowed.\n            Before starting a new compression job, or changing compression parameters,\n            it is required to fully flush internal buffers.\n  - note: if an operation ends with an error, it may leave @cctx in an undefined state.\n          Therefore, it's UB to invoke ZSTD_compressStream2() of ZSTD_compressStream() on such a state.\n          In order to be re-employed after an error, a state must be reset,\n          which can be done explicitly (ZSTD_CCtx_reset()),\n          or is sometimes implied by methods starting a new compression job (ZSTD_initCStream(), ZSTD_compressCCtx())\n \n</p></pre><BR>\n\n<pre><b>size_t ZSTD_CStreamInSize(void);    </b>/**< recommended size for input buffer */<b>\n</b></pre><BR>\n<pre><b>size_t ZSTD_CStreamOutSize(void);   </b>/**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block. */<b>\n</b></pre><BR>\n<pre><b>size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel);\n</b>/*!<b>\n * Alternative for ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue).\n * NOTE: The return value is different. ZSTD_compressStream() returns a hint for\n * the next read size (if non-zero and not an error). ZSTD_compressStream2()\n * returns the minimum nb of bytes left to flush (if non-zero and not an error).\n */\nsize_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input);\n</b>/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_flush). */<b>\nsize_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);\n</b>/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_end). */<b>\nsize_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);\n</b><p>\n     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n     ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)\n     ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);\n\n Note that ZSTD_initCStream() clears any previously set dictionary. Use the new API\n to compress with a dictionary.\n \n</p></pre><BR>\n\n<a name=\"Chapter9\"></a><h2>Streaming decompression - HowTo</h2><pre>\n  A ZSTD_DStream object is required to track streaming operations.\n  Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources.\n  ZSTD_DStream objects can be re-employed multiple times.\n\n  Use ZSTD_initDStream() to start a new decompression operation.\n @return : recommended first input size\n  Alternatively, use advanced API to set specific properties.\n\n  Use ZSTD_decompressStream() repetitively to consume your input.\n  The function will update both `pos` fields.\n  If `input.pos < input.size`, some input has not been consumed.\n  It's up to the caller to present again remaining data.\n\n  The function tries to flush all data decoded immediately, respecting output buffer size.\n  If `output.pos < output.size`, decoder has flushed everything it could.\n\n  However, when `output.pos == output.size`, it's more difficult to know.\n  If @return > 0, the frame is not complete, meaning\n  either there is still some data left to flush within internal buffers,\n  or there is more input to read to complete the frame (or both).\n  In which case, call ZSTD_decompressStream() again to flush whatever remains in the buffer.\n  Note : with no additional input provided, amount of data flushed is necessarily <= ZSTD_BLOCKSIZE_MAX.\n @return : 0 when a frame is completely decoded and fully flushed,\n        or an error code, which can be tested using ZSTD_isError(),\n        or any other value > 0, which means there is still some decoding or flushing to do to complete current frame :\n                                the return value is a suggested next input size (just a hint for better latency)\n                                that will never request more than the remaining content of the compressed frame.\n \n<BR></pre>\n\n<pre><b>typedef ZSTD_DCtx ZSTD_DStream;  </b>/**< DCtx and DStream are now effectively same object (>= v1.3.0) */<b>\n</b></pre><BR>\n<h3>ZSTD_DStream management functions</h3><pre></pre><b><pre>ZSTD_DStream* ZSTD_createDStream(void);\nsize_t ZSTD_freeDStream(ZSTD_DStream* zds);  </b>/* accept NULL pointer */<b>\n</pre></b><BR>\n<h3>Streaming decompression functions</h3><pre></pre><b><pre></pre></b><BR>\n<pre><b>size_t ZSTD_initDStream(ZSTD_DStream* zds);\n</b><p> Initialize/reset DStream state for new decompression operation.\n Call before new decompression operation using same DStream.\n\n Note : This function is redundant with the advanced API and equivalent to:\n     ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);\n     ZSTD_DCtx_refDDict(zds, NULL);\n \n</p></pre><BR>\n\n<pre><b>size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input);\n</b><p> Streaming decompression function.\n Call repetitively to consume full input updating it as necessary.\n Function will update both input and output `pos` fields exposing current state via these fields:\n - `input.pos < input.size`, some input remaining and caller should provide remaining input\n   on the next call.\n - `output.pos < output.size`, decoder flushed internal output buffer.\n - `output.pos == output.size`, unflushed data potentially present in the internal buffers,\n   check ZSTD_decompressStream() @return value,\n   if > 0, invoke it again to flush remaining data to output.\n Note : with no additional input, amount of data flushed <= ZSTD_BLOCKSIZE_MAX.\n\n @return : 0 when a frame is completely decoded and fully flushed,\n           or an error code, which can be tested using ZSTD_isError(),\n           or any other value > 0, which means there is some decoding or flushing to do to complete current frame.\n\n Note: when an operation returns with an error code, the @zds state may be left in undefined state.\n       It's UB to invoke `ZSTD_decompressStream()` on such a state.\n       In order to re-use such a state, it must be first reset,\n       which can be done explicitly (`ZSTD_DCtx_reset()`),\n       or is implied for operations starting some new decompression job (`ZSTD_initDStream`, `ZSTD_decompressDCtx()`, `ZSTD_decompress_usingDict()`)\n \n</p></pre><BR>\n\n<pre><b>size_t ZSTD_DStreamInSize(void);    </b>/*!< recommended size for input buffer */<b>\n</b></pre><BR>\n<pre><b>size_t ZSTD_DStreamOutSize(void);   </b>/*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */<b>\n</b></pre><BR>\n<a name=\"Chapter10\"></a><h2>Simple dictionary API</h2><pre></pre>\n\n<pre><b>size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx,\n                               void* dst, size_t dstCapacity,\n                         const void* src, size_t srcSize,\n                         const void* dict,size_t dictSize,\n                               int compressionLevel);\n</b><p>  Compression at an explicit compression level using a Dictionary.\n  A dictionary can be any arbitrary data segment (also called a prefix),\n  or a buffer with specified information (see zdict.h).\n  Note : This function loads the dictionary, resulting in significant startup delay.\n         It's intended for a dictionary used only once.\n  Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used. \n</p></pre><BR>\n\n<pre><b>size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,\n                                 void* dst, size_t dstCapacity,\n                           const void* src, size_t srcSize,\n                           const void* dict,size_t dictSize);\n</b><p>  Decompression using a known Dictionary.\n  Dictionary must be identical to the one used during compression.\n  Note : This function loads the dictionary, resulting in significant startup delay.\n         It's intended for a dictionary used only once.\n  Note : When `dict == NULL || dictSize < 8` no dictionary is used. \n</p></pre><BR>\n\n<a name=\"Chapter11\"></a><h2>Bulk processing dictionary API</h2><pre></pre>\n\n<pre><b>ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize,\n                             int compressionLevel);\n</b><p>  When compressing multiple messages or blocks using the same dictionary,\n  it's recommended to digest the dictionary only once, since it's a costly operation.\n  ZSTD_createCDict() will create a state from digesting a dictionary.\n  The resulting state can be used for future compression operations with very limited startup cost.\n  ZSTD_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only.\n @dictBuffer can be released after ZSTD_CDict creation, because its content is copied within CDict.\n  Note 1 : Consider experimental function `ZSTD_createCDict_byReference()` if you prefer to not duplicate @dictBuffer content.\n  Note 2 : A ZSTD_CDict can be created from an empty @dictBuffer,\n      in which case the only thing that it transports is the @compressionLevel.\n      This can be useful in a pipeline featuring ZSTD_compress_usingCDict() exclusively,\n      expecting a ZSTD_CDict parameter with any data, including those without a known dictionary. \n</p></pre><BR>\n\n<pre><b>size_t      ZSTD_freeCDict(ZSTD_CDict* CDict);\n</b><p>  Function frees memory allocated by ZSTD_createCDict().\n  If a NULL pointer is passed, no operation is performed. \n</p></pre><BR>\n\n<pre><b>size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,\n                                void* dst, size_t dstCapacity,\n                          const void* src, size_t srcSize,\n                          const ZSTD_CDict* cdict);\n</b><p>  Compression using a digested Dictionary.\n  Recommended when same dictionary is used multiple times.\n  Note : compression level is _decided at dictionary creation time_,\n     and frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no) \n</p></pre><BR>\n\n<pre><b>ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize);\n</b><p>  Create a digested dictionary, ready to start decompression operation without startup delay.\n  dictBuffer can be released after DDict creation, as its content is copied inside DDict. \n</p></pre><BR>\n\n<pre><b>size_t      ZSTD_freeDDict(ZSTD_DDict* ddict);\n</b><p>  Function frees memory allocated with ZSTD_createDDict()\n  If a NULL pointer is passed, no operation is performed. \n</p></pre><BR>\n\n<pre><b>size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,\n                                  void* dst, size_t dstCapacity,\n                            const void* src, size_t srcSize,\n                            const ZSTD_DDict* ddict);\n</b><p>  Decompression using a digested Dictionary.\n  Recommended when same dictionary is used multiple times. \n</p></pre><BR>\n\n<a name=\"Chapter12\"></a><h2>Dictionary helper functions</h2><pre></pre>\n\n<pre><b>unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize);\n</b><p>  Provides the dictID stored within dictionary.\n  if @return == 0, the dictionary is not conformant with Zstandard specification.\n  It can still be loaded, but as a content-only dictionary. \n</p></pre><BR>\n\n<pre><b>unsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* cdict);\n</b><p>  Provides the dictID of the dictionary loaded into `cdict`.\n  If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.\n  Non-conformant dictionaries can still be loaded, but as content-only dictionaries. \n</p></pre><BR>\n\n<pre><b>unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);\n</b><p>  Provides the dictID of the dictionary loaded into `ddict`.\n  If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.\n  Non-conformant dictionaries can still be loaded, but as content-only dictionaries. \n</p></pre><BR>\n\n<pre><b>unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);\n</b><p>  Provides the dictID required to decompressed the frame stored within `src`.\n  If @return == 0, the dictID could not be decoded.\n  This could for one of the following reasons :\n  - The frame does not require a dictionary to be decoded (most common case).\n  - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden piece of information.\n    Note : this use case also happens when using a non-conformant dictionary.\n  - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).\n  - This is not a Zstandard frame.\n  When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code. \n</p></pre><BR>\n\n<a name=\"Chapter13\"></a><h2>Advanced dictionary and prefix API (Requires v1.4.0+)</h2><pre>\n This API allows dictionaries to be used with ZSTD_compress2(),\n ZSTD_compressStream2(), and ZSTD_decompressDCtx().\n Dictionaries are sticky, they remain valid when same context is reused,\n they only reset when the context is reset\n with ZSTD_reset_parameters or ZSTD_reset_session_and_parameters.\n In contrast, Prefixes are single-use.\n<BR></pre>\n\n<pre><b>size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);\n</b><p>  Create an internal CDict from `dict` buffer.\n  Decompression will have to use same dictionary.\n @result : 0, or an error code (which can be tested with ZSTD_isError()).\n  Special: Loading a NULL (or 0-size) dictionary invalidates previous dictionary,\n           meaning \"return to no-dictionary mode\".\n  Note 1 : Dictionary is sticky, it will be used for all future compressed frames,\n           until parameters are reset, a new dictionary is loaded, or the dictionary\n           is explicitly invalidated by loading a NULL dictionary.\n  Note 2 : Loading a dictionary involves building tables.\n           It's also a CPU consuming operation, with non-negligible impact on latency.\n           Tables are dependent on compression parameters, and for this reason,\n           compression parameters can no longer be changed after loading a dictionary.\n  Note 3 :`dict` content will be copied internally.\n           Use experimental ZSTD_CCtx_loadDictionary_byReference() to reference content instead.\n           In such a case, dictionary buffer must outlive its users.\n  Note 4 : Use ZSTD_CCtx_loadDictionary_advanced()\n           to precisely select how dictionary content must be interpreted.\n  Note 5 : This method does not benefit from LDM (long distance mode).\n           If you want to employ LDM on some large dictionary content,\n           prefer employing ZSTD_CCtx_refPrefix() described below.\n \n</p></pre><BR>\n\n<pre><b>size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);\n</b><p>  Reference a prepared dictionary, to be used for all future compressed frames.\n  Note that compression parameters are enforced from within CDict,\n  and supersede any compression parameter previously set within CCtx.\n  The parameters ignored are labelled as \"superseded-by-cdict\" in the ZSTD_cParameter enum docs.\n  The ignored parameters will be used again if the CCtx is returned to no-dictionary mode.\n  The dictionary will remain valid for future compressed frames using same CCtx.\n @result : 0, or an error code (which can be tested with ZSTD_isError()).\n  Special : Referencing a NULL CDict means \"return to no-dictionary mode\".\n  Note 1 : Currently, only one dictionary can be managed.\n           Referencing a new dictionary effectively \"discards\" any previous one.\n  Note 2 : CDict is just referenced, its lifetime must outlive its usage within CCtx. \n</p></pre><BR>\n\n<pre><b>size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx,\n                     const void* prefix, size_t prefixSize);\n</b><p>  Reference a prefix (single-usage dictionary) for next compressed frame.\n  A prefix is **only used once**. Tables are discarded at end of frame (ZSTD_e_end).\n  Decompression will need same prefix to properly regenerate data.\n  Compressing with a prefix is similar in outcome as performing a diff and compressing it,\n  but performs much faster, especially during decompression (compression speed is tunable with compression level).\n  This method is compatible with LDM (long distance mode).\n @result : 0, or an error code (which can be tested with ZSTD_isError()).\n  Special: Adding any prefix (including NULL) invalidates any previous prefix or dictionary\n  Note 1 : Prefix buffer is referenced. It **must** outlive compression.\n           Its content must remain unmodified during compression.\n  Note 2 : If the intention is to diff some large src data blob with some prior version of itself,\n           ensure that the window size is large enough to contain the entire source.\n           See ZSTD_c_windowLog.\n  Note 3 : Referencing a prefix involves building tables, which are dependent on compression parameters.\n           It's a CPU consuming operation, with non-negligible impact on latency.\n           If there is a need to use the same prefix multiple times, consider loadDictionary instead.\n  Note 4 : By default, the prefix is interpreted as raw content (ZSTD_dct_rawContent).\n           Use experimental ZSTD_CCtx_refPrefix_advanced() to alter dictionary interpretation. \n</p></pre><BR>\n\n<pre><b>size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);\n</b><p>  Create an internal DDict from dict buffer, to be used to decompress all future frames.\n  The dictionary remains valid for all future frames, until explicitly invalidated, or\n  a new dictionary is loaded.\n @result : 0, or an error code (which can be tested with ZSTD_isError()).\n  Special : Adding a NULL (or 0-size) dictionary invalidates any previous dictionary,\n            meaning \"return to no-dictionary mode\".\n  Note 1 : Loading a dictionary involves building tables,\n           which has a non-negligible impact on CPU usage and latency.\n           It's recommended to \"load once, use many times\", to amortize the cost\n  Note 2 :`dict` content will be copied internally, so `dict` can be released after loading.\n           Use ZSTD_DCtx_loadDictionary_byReference() to reference dictionary content instead.\n  Note 3 : Use ZSTD_DCtx_loadDictionary_advanced() to take control of\n           how dictionary content is loaded and interpreted.\n \n</p></pre><BR>\n\n<pre><b>size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);\n</b><p>  Reference a prepared dictionary, to be used to decompress next frames.\n  The dictionary remains active for decompression of future frames using same DCtx.\n\n  If called with ZSTD_d_refMultipleDDicts enabled, repeated calls of this function\n  will store the DDict references in a table, and the DDict used for decompression\n  will be determined at decompression time, as per the dict ID in the frame.\n  The memory for the table is allocated on the first call to refDDict, and can be\n  freed with ZSTD_freeDCtx().\n\n  If called with ZSTD_d_refMultipleDDicts disabled (the default), only one dictionary\n  will be managed, and referencing a dictionary effectively \"discards\" any previous one.\n\n @result : 0, or an error code (which can be tested with ZSTD_isError()).\n  Special: referencing a NULL DDict means \"return to no-dictionary mode\".\n  Note 2 : DDict is just referenced, its lifetime must outlive its usage from DCtx.\n \n</p></pre><BR>\n\n<pre><b>size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx,\n                     const void* prefix, size_t prefixSize);\n</b><p>  Reference a prefix (single-usage dictionary) to decompress next frame.\n  This is the reverse operation of ZSTD_CCtx_refPrefix(),\n  and must use the same prefix as the one used during compression.\n  Prefix is **only used once**. Reference is discarded at end of frame.\n  End of frame is reached when ZSTD_decompressStream() returns 0.\n @result : 0, or an error code (which can be tested with ZSTD_isError()).\n  Note 1 : Adding any prefix (including NULL) invalidates any previously set prefix or dictionary\n  Note 2 : Prefix buffer is referenced. It **must** outlive decompression.\n           Prefix buffer must remain unmodified up to the end of frame,\n           reached when ZSTD_decompressStream() returns 0.\n  Note 3 : By default, the prefix is treated as raw content (ZSTD_dct_rawContent).\n           Use ZSTD_CCtx_refPrefix_advanced() to alter dictMode (Experimental section)\n  Note 4 : Referencing a raw content prefix has almost no cpu nor memory cost.\n           A full dictionary is more costly, as it requires building tables.\n \n</p></pre><BR>\n\n<pre><b>size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);\nsize_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);\nsize_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);\nsize_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);\nsize_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict);\nsize_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);\n</b><p>  These functions give the _current_ memory usage of selected object.\n  Note that object memory usage can evolve (increase or decrease) over time. \n</p></pre><BR>\n\n<a name=\"Chapter14\"></a><h2>experimental API (static linking only)</h2><pre>\n The following symbols and constants\n are not planned to join \"stable API\" status in the near future.\n They can still change in future versions.\n Some of them are planned to remain in the static_only section indefinitely.\n Some of them might be removed in the future (especially when redundant with existing stable functions)\n \n<BR></pre>\n\n<pre><b>typedef struct {\n    unsigned int offset;      </b>/* The offset of the match. (NOT the same as the offset code)<b>\n                               * If offset == 0 and matchLength == 0, this sequence represents the last\n                               * literals in the block of litLength size.\n                               */\n\n    unsigned int litLength;   </b>/* Literal length of the sequence. */<b>\n    unsigned int matchLength; </b>/* Match length of the sequence. */<b>\n\n                              </b>/* Note: Users of this API may provide a sequence with matchLength == litLength == offset == 0.<b>\n                               * In this case, we will treat the sequence as a marker for a block boundary.\n                               */\n\n    unsigned int rep;         </b>/* Represents which repeat offset is represented by the field 'offset'.<b>\n                               * Ranges from [0, 3].\n                               *\n                               * Repeat offsets are essentially previous offsets from previous sequences sorted in\n                               * recency order. For more detail, see doc/zstd_compression_format.md\n                               *\n                               * If rep == 0, then 'offset' does not contain a repeat offset.\n                               * If rep > 0:\n                               *  If litLength != 0:\n                               *      rep == 1 --> offset == repeat_offset_1\n                               *      rep == 2 --> offset == repeat_offset_2\n                               *      rep == 3 --> offset == repeat_offset_3\n                               *  If litLength == 0:\n                               *      rep == 1 --> offset == repeat_offset_2\n                               *      rep == 2 --> offset == repeat_offset_3\n                               *      rep == 3 --> offset == repeat_offset_1 - 1\n                               *\n                               * Note: This field is optional. ZSTD_generateSequences() will calculate the value of\n                               * 'rep', but repeat offsets do not necessarily need to be calculated from an external\n                               * sequence provider perspective. For example, ZSTD_compressSequences() does not\n                               * use this 'rep' field at all (as of now).\n                               */\n} ZSTD_Sequence;\n</b></pre><BR>\n<pre><b>typedef struct {\n    unsigned windowLog;       </b>/**< largest match distance : larger == more compression, more memory needed during decompression */<b>\n    unsigned chainLog;        </b>/**< fully searched segment : larger == more compression, slower, more memory (useless for fast) */<b>\n    unsigned hashLog;         </b>/**< dispatch table : larger == faster, more memory */<b>\n    unsigned searchLog;       </b>/**< nb of searches : larger == more compression, slower */<b>\n    unsigned minMatch;        </b>/**< match length searched : larger == faster decompression, sometimes less compression */<b>\n    unsigned targetLength;    </b>/**< acceptable match size for optimal parser (only) : larger == more compression, slower */<b>\n    ZSTD_strategy strategy;   </b>/**< see ZSTD_strategy definition above */<b>\n} ZSTD_compressionParameters;\n</b></pre><BR>\n<pre><b>typedef struct {\n    int contentSizeFlag; </b>/**< 1: content size will be in frame header (when known) */<b>\n    int checksumFlag;    </b>/**< 1: generate a 32-bits checksum using XXH64 algorithm at end of frame, for error detection */<b>\n    int noDictIDFlag;    </b>/**< 1: no dictID will be saved into frame header (dictID is only useful for dictionary compression) */<b>\n} ZSTD_frameParameters;\n</b></pre><BR>\n<pre><b>typedef struct {\n    ZSTD_compressionParameters cParams;\n    ZSTD_frameParameters fParams;\n} ZSTD_parameters;\n</b></pre><BR>\n<pre><b>typedef enum {\n    ZSTD_dct_auto = 0,       </b>/* dictionary is \"full\" when starting with ZSTD_MAGIC_DICTIONARY, otherwise it is \"rawContent\" */<b>\n    ZSTD_dct_rawContent = 1, </b>/* ensures dictionary is always loaded as rawContent, even if it starts with ZSTD_MAGIC_DICTIONARY */<b>\n    ZSTD_dct_fullDict = 2    </b>/* refuses to load a dictionary if it does not respect Zstandard's specification, starting with ZSTD_MAGIC_DICTIONARY */<b>\n} ZSTD_dictContentType_e;\n</b></pre><BR>\n<pre><b>typedef enum {\n    ZSTD_dlm_byCopy = 0,  </b>/**< Copy dictionary content internally */<b>\n    ZSTD_dlm_byRef = 1    </b>/**< Reference dictionary content -- the dictionary buffer must outlive its users. */<b>\n} ZSTD_dictLoadMethod_e;\n</b></pre><BR>\n<pre><b>typedef enum {\n    ZSTD_f_zstd1 = 0,           </b>/* zstd frame format, specified in zstd_compression_format.md (default) */<b>\n    ZSTD_f_zstd1_magicless = 1  </b>/* Variant of zstd frame format, without initial 4-bytes magic number.<b>\n                                 * Useful to save 4 bytes per generated frame.\n                                 * Decoder cannot recognise automatically this format, requiring this instruction. */\n} ZSTD_format_e;\n</b></pre><BR>\n<pre><b>typedef enum {\n    </b>/* Note: this enum controls ZSTD_d_forceIgnoreChecksum */<b>\n    ZSTD_d_validateChecksum = 0,\n    ZSTD_d_ignoreChecksum = 1\n} ZSTD_forceIgnoreChecksum_e;\n</b></pre><BR>\n<pre><b>typedef enum {\n    </b>/* Note: this enum controls ZSTD_d_refMultipleDDicts */<b>\n    ZSTD_rmd_refSingleDDict = 0,\n    ZSTD_rmd_refMultipleDDicts = 1\n} ZSTD_refMultipleDDicts_e;\n</b></pre><BR>\n<pre><b>typedef enum {\n    </b>/* Note: this enum and the behavior it controls are effectively internal<b>\n     * implementation details of the compressor. They are expected to continue\n     * to evolve and should be considered only in the context of extremely\n     * advanced performance tuning.\n     *\n     * Zstd currently supports the use of a CDict in three ways:\n     *\n     * - The contents of the CDict can be copied into the working context. This\n     *   means that the compression can search both the dictionary and input\n     *   while operating on a single set of internal tables. This makes\n     *   the compression faster per-byte of input. However, the initial copy of\n     *   the CDict's tables incurs a fixed cost at the beginning of the\n     *   compression. For small compressions (< 8 KB), that copy can dominate\n     *   the cost of the compression.\n     *\n     * - The CDict's tables can be used in-place. In this model, compression is\n     *   slower per input byte, because the compressor has to search two sets of\n     *   tables. However, this model incurs no start-up cost (as long as the\n     *   working context's tables can be reused). For small inputs, this can be\n     *   faster than copying the CDict's tables.\n     *\n     * - The CDict's tables are not used at all, and instead we use the working\n     *   context alone to reload the dictionary and use params based on the source\n     *   size. See ZSTD_compress_insertDictionary() and ZSTD_compress_usingDict().\n     *   This method is effective when the dictionary sizes are very small relative\n     *   to the input size, and the input size is fairly large to begin with.\n     *\n     * Zstd has a simple internal heuristic that selects which strategy to use\n     * at the beginning of a compression. However, if experimentation shows that\n     * Zstd is making poor choices, it is possible to override that choice with\n     * this enum.\n     */\n    ZSTD_dictDefaultAttach = 0, </b>/* Use the default heuristic. */<b>\n    ZSTD_dictForceAttach   = 1, </b>/* Never copy the dictionary. */<b>\n    ZSTD_dictForceCopy     = 2, </b>/* Always copy the dictionary. */<b>\n    ZSTD_dictForceLoad     = 3  </b>/* Always reload the dictionary */<b>\n} ZSTD_dictAttachPref_e;\n</b></pre><BR>\n<pre><b>typedef enum {\n  ZSTD_lcm_auto = 0,          </b>/**< Automatically determine the compression mode based on the compression level.<b>\n                               *   Negative compression levels will be uncompressed, and positive compression\n                               *   levels will be compressed. */\n  ZSTD_lcm_huffman = 1,       </b>/**< Always attempt Huffman compression. Uncompressed literals will still be<b>\n                               *   emitted if Huffman compression is not profitable. */\n  ZSTD_lcm_uncompressed = 2   </b>/**< Always emit uncompressed literals. */<b>\n} ZSTD_literalCompressionMode_e;\n</b></pre><BR>\n<pre><b>typedef enum {\n  </b>/* Note: This enum controls features which are conditionally beneficial.<b>\n   * Zstd can take a decision on whether or not to enable the feature (ZSTD_ps_auto),\n   * but setting the switch to ZSTD_ps_enable or ZSTD_ps_disable force enable/disable the feature.\n   */\n  ZSTD_ps_auto = 0,         </b>/* Let the library automatically determine whether the feature shall be enabled */<b>\n  ZSTD_ps_enable = 1,       </b>/* Force-enable the feature */<b>\n  ZSTD_ps_disable = 2       </b>/* Do not use the feature */<b>\n} ZSTD_ParamSwitch_e;\n</b></pre><BR>\n<a name=\"Chapter15\"></a><h2>Frame header and size functions</h2><pre></pre>\n\n<pre><b>ZSTDLIB_STATIC_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize);\n</b><p>  `src` should point to the start of a series of ZSTD encoded and/or skippable frames\n  `srcSize` must be the _exact_ size of this series\n       (i.e. there should be a frame boundary at `src + srcSize`)\n  @return : - decompressed size of all data in all successive frames\n            - if the decompressed size cannot be determined: ZSTD_CONTENTSIZE_UNKNOWN\n            - if an error occurred: ZSTD_CONTENTSIZE_ERROR\n\n   note 1 : decompressed size is an optional field, that may not be present, especially in streaming mode.\n            When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size.\n            In which case, it's necessary to use streaming mode to decompress data.\n   note 2 : decompressed size is always present when compression is done with ZSTD_compress()\n   note 3 : decompressed size can be very large (64-bits value),\n            potentially larger than what local system can handle as a single memory segment.\n            In which case, it's necessary to use streaming mode to decompress data.\n   note 4 : If source is untrusted, decompressed size could be wrong or intentionally modified.\n            Always ensure result fits within application's authorized limits.\n            Each application can set its own limits.\n   note 5 : ZSTD_findDecompressedSize handles multiple frames, and so it must traverse the input to\n            read each contained frame header.  This is fast as most of the data is skipped,\n            however it does mean that all frame data must be present and valid. \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize);\n</b><p>  `src` should point to the start of a series of ZSTD encoded and/or skippable frames\n  `srcSize` must be the _exact_ size of this series\n       (i.e. there should be a frame boundary at `src + srcSize`)\n  @return : - upper-bound for the decompressed size of all data in all successive frames\n            - if an error occurred: ZSTD_CONTENTSIZE_ERROR\n\n  note 1  : an error can occur if `src` contains an invalid or incorrectly formatted frame.\n  note 2  : the upper-bound is exact when the decompressed size field is available in every ZSTD encoded frame of `src`.\n            in this case, `ZSTD_findDecompressedSize` and `ZSTD_decompressBound` return the same value.\n  note 3  : when the decompressed size field isn't available, the upper-bound for that frame is calculated by:\n              upper-bound = # blocks * min(128 KB, Window_Size)\n \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize);\n</b><p>  srcSize must be large enough, aka >= ZSTD_FRAMEHEADERSIZE_PREFIX.\n @return : size of the Frame Header,\n           or an error code (if srcSize is too small) \n</p></pre><BR>\n\n<pre><b>typedef enum { ZSTD_frame, ZSTD_skippableFrame } ZSTD_FrameType_e;\n</b></pre><BR>\n<pre><b>typedef struct {\n    unsigned long long frameContentSize; </b>/* if == ZSTD_CONTENTSIZE_UNKNOWN, it means this field is not available. 0 means \"empty\" */<b>\n    unsigned long long windowSize;       </b>/* can be very large, up to <= frameContentSize */<b>\n    unsigned blockSizeMax;\n    ZSTD_FrameType_e frameType;          </b>/* if == ZSTD_skippableFrame, frameContentSize is the size of skippable content */<b>\n    unsigned headerSize;\n    unsigned dictID;                     </b>/* for ZSTD_skippableFrame, contains the skippable magic variant [0-15] */<b>\n    unsigned checksumFlag;\n    unsigned _reserved1;\n    unsigned _reserved2;\n} ZSTD_FrameHeader;\n</b></pre><BR>\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader(ZSTD_FrameHeader* zfhPtr, const void* src, size_t srcSize);\n</b>/*! ZSTD_getFrameHeader_advanced() :<b>\n *  same as ZSTD_getFrameHeader(),\n *  with added capability to select a format (like ZSTD_f_zstd1_magicless) */\nZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader_advanced(ZSTD_FrameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format);\n</b><p>  decode Frame Header into `zfhPtr`, or requires larger `srcSize`.\n @return : 0 => header is complete, `zfhPtr` is correctly filled,\n          >0 => `srcSize` is too small, @return value is the wanted `srcSize` amount, `zfhPtr` is not filled,\n           or an error code, which can be tested using ZSTD_isError() \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_decompressionMargin(const void* src, size_t srcSize);\n</b><p> Zstd supports in-place decompression, where the input and output buffers overlap.\n In this case, the output buffer must be at least (Margin + Output_Size) bytes large,\n and the input buffer must be at the end of the output buffer.\n\n  _______________________ Output Buffer ________________________\n |                                                              |\n |                                        ____ Input Buffer ____|\n |                                       |                      |\n v                                       v                      v\n |---------------------------------------|-----------|----------|\n ^                                                   ^          ^\n |___________________ Output_Size ___________________|_ Margin _|\n\n NOTE: See also ZSTD_DECOMPRESSION_MARGIN().\n NOTE: This applies only to single-pass decompression through ZSTD_decompress() or\n ZSTD_decompressDCtx().\n NOTE: This function supports multi-frame input.\n\n @param src The compressed frame(s)\n @param srcSize The size of the compressed frame(s)\n @returns The decompression margin or an error that can be checked with ZSTD_isError().\n \n</p></pre><BR>\n\n<pre><b>#define ZSTD_DECOMPRESSION_MARGIN(originalSize, blockSize) ((size_t)(                                              \\\n        ZSTD_FRAMEHEADERSIZE_MAX                                                              </b>/* Frame header */ + \\<b>\n        4                                                                                         </b>/* checksum */ + \\<b>\n        ((originalSize) == 0 ? 0 : 3 * (((originalSize) + (blockSize) - 1) / blockSize)) </b>/* 3 bytes per block */ + \\<b>\n        (blockSize)                                                                    </b>/* One block of margin */   \\<b>\n    ))\n</b><p> Similar to ZSTD_decompressionMargin(), but instead of computing the margin from\n the compressed frame, compute it from the original size and the blockSizeLog.\n See ZSTD_decompressionMargin() for details.\n\n WARNING: This macro does not support multi-frame input, the input must be a single\n zstd frame. If you need that support use the function, or implement it yourself.\n\n @param originalSize The original uncompressed size of the data.\n @param blockSize    The block size == MIN(windowSize, ZSTD_BLOCKSIZE_MAX).\n                     Unless you explicitly set the windowLog smaller than\n                     ZSTD_BLOCKSIZELOG_MAX you can just use ZSTD_BLOCKSIZE_MAX.\n \n</p></pre><BR>\n\n<pre><b>typedef enum {\n  ZSTD_sf_noBlockDelimiters = 0,         </b>/* ZSTD_Sequence[] has no block delimiters, just sequences */<b>\n  ZSTD_sf_explicitBlockDelimiters = 1    </b>/* ZSTD_Sequence[] contains explicit block delimiters */<b>\n} ZSTD_SequenceFormat_e;\n</b></pre><BR>\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_sequenceBound(size_t srcSize);\n</b><p> `srcSize` : size of the input buffer\n  @return : upper-bound for the number of sequences that can be generated\n            from a buffer of srcSize bytes\n\n  note : returns number of sequences - to get bytes, multiply by sizeof(ZSTD_Sequence).\n \n</p></pre><BR>\n\n<pre><b>ZSTD_DEPRECATED(\"For debugging only, will be replaced by ZSTD_extractSequences()\")\nZSTDLIB_STATIC_API size_t\nZSTD_generateSequences(ZSTD_CCtx* zc,\n           ZSTD_Sequence* outSeqs, size_t outSeqsCapacity,\n           const void* src, size_t srcSize);\n</b><p> WARNING: This function is meant for debugging and informational purposes ONLY!\n Its implementation is flawed, and it will be deleted in a future version.\n It is not guaranteed to succeed, as there are several cases where it will give\n up and fail. You should NOT use this function in production code.\n\n This function is deprecated, and will be removed in a future version.\n\n Generate sequences using ZSTD_compress2(), given a source buffer.\n\n @param zc The compression context to be used for ZSTD_compress2(). Set any\n           compression parameters you need on this context.\n @param outSeqs The output sequences buffer of size @p outSeqsSize\n @param outSeqsCapacity The size of the output sequences buffer.\n                    ZSTD_sequenceBound(srcSize) is an upper bound on the number\n                    of sequences that can be generated.\n @param src The source buffer to generate sequences from of size @p srcSize.\n @param srcSize The size of the source buffer.\n\n Each block will end with a dummy sequence\n with offset == 0, matchLength == 0, and litLength == length of last literals.\n litLength may be == 0, and if so, then the sequence of (of: 0 ml: 0 ll: 0)\n simply acts as a block delimiter.\n\n @returns The number of sequences generated, necessarily less than\n          ZSTD_sequenceBound(srcSize), or an error code that can be checked\n          with ZSTD_isError().\n \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize);\n</b><p> Given an array of ZSTD_Sequence, remove all sequences that represent block delimiters/last literals\n by merging them into the literals of the next sequence.\n\n As such, the final generated result has no explicit representation of block boundaries,\n and the final last literals segment is not represented in the sequences.\n\n The output of this function can be fed into ZSTD_compressSequences() with CCtx\n setting of ZSTD_c_blockDelimiters as ZSTD_sf_noBlockDelimiters\n @return : number of sequences left after merging\n \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t\nZSTD_compressSequences(ZSTD_CCtx* cctx,\n           void* dst, size_t dstCapacity,\n     const ZSTD_Sequence* inSeqs, size_t inSeqsSize,\n     const void* src, size_t srcSize);\n</b><p> Compress an array of ZSTD_Sequence, associated with @src buffer, into dst.\n @src contains the entire input (not just the literals).\n If @srcSize > sum(sequence.length), the remaining bytes are considered all literals\n If a dictionary is included, then the cctx should reference the dict (see: ZSTD_CCtx_refCDict(), ZSTD_CCtx_loadDictionary(), etc.).\n The entire source is compressed into a single frame.\n\n The compression behavior changes based on cctx params. In particular:\n    If ZSTD_c_blockDelimiters == ZSTD_sf_noBlockDelimiters, the array of ZSTD_Sequence is expected to contain\n    no block delimiters (defined in ZSTD_Sequence). Block boundaries are roughly determined based on\n    the block size derived from the cctx, and sequences may be split. This is the default setting.\n\n    If ZSTD_c_blockDelimiters == ZSTD_sf_explicitBlockDelimiters, the array of ZSTD_Sequence is expected to contain\n    valid block delimiters (defined in ZSTD_Sequence). Behavior is undefined if no block delimiters are provided.\n\n    When ZSTD_c_blockDelimiters == ZSTD_sf_explicitBlockDelimiters, it's possible to decide generating repcodes\n    using the advanced parameter ZSTD_c_repcodeResolution. Repcodes will improve compression ratio, though the benefit\n    can vary greatly depending on Sequences. On the other hand, repcode resolution is an expensive operation.\n    By default, it's disabled at low (<10) compression levels, and enabled above the threshold (>=10).\n    ZSTD_c_repcodeResolution makes it possible to directly manage this processing in either direction.\n\n    If ZSTD_c_validateSequences == 0, this function blindly accepts the Sequences provided. Invalid Sequences cause undefined\n    behavior. If ZSTD_c_validateSequences == 1, then the function will detect invalid Sequences (see doc/zstd_compression_format.md for\n    specifics regarding offset/matchlength requirements) and then bail out and return an error.\n\n    In addition to the two adjustable experimental params, there are other important cctx params.\n    - ZSTD_c_minMatch MUST be set as less than or equal to the smallest match generated by the match finder. It has a minimum value of ZSTD_MINMATCH_MIN.\n    - ZSTD_c_compressionLevel accordingly adjusts the strength of the entropy coder, as it would in typical compression.\n    - ZSTD_c_windowLog affects offset validation: this function will return an error at higher debug levels if a provided offset\n      is larger than what the spec allows for a given window log and dictionary (if present). See: doc/zstd_compression_format.md\n\n Note: Repcodes are, as of now, always re-calculated within this function, ZSTD_Sequence.rep is effectively unused.\n Dev Note: Once ability to ingest repcodes become available, the explicit block delims mode must respect those repcodes exactly,\n         and cannot emit an RLE block that disagrees with the repcode history.\n @return : final compressed size, or a ZSTD error code.\n \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t\nZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx,\n                      void* dst, size_t dstCapacity,\n                const ZSTD_Sequence* inSeqs, size_t nbSequences,\n                const void* literals, size_t litSize, size_t litBufCapacity,\n                size_t decompressedSize);\n</b><p> This is a variant of ZSTD_compressSequences() which,\n instead of receiving (src,srcSize) as input parameter, receives (literals,litSize),\n aka all the literals, already extracted and laid out into a single continuous buffer.\n This can be useful if the process generating the sequences also happens to generate the buffer of literals,\n thus skipping an extraction + caching stage.\n It's a speed optimization, useful when the right conditions are met,\n but it also features the following limitations:\n - Only supports explicit delimiter mode\n - Currently does not support Sequences validation (so input Sequences are trusted)\n - Not compatible with frame checksum, which must be disabled\n - If any block is incompressible, will fail and return an error\n - @litSize must be == sum of all @.litLength fields in @inSeqs. Any discrepancy will generate an error.\n - @litBufCapacity is the size of the underlying buffer into which literals are written, starting at address @literals.\n   @litBufCapacity must be at least 8 bytes larger than @litSize.\n - @decompressedSize must be correct, and correspond to the sum of all Sequences. Any discrepancy will generate an error.\n @return : final compressed size, or a ZSTD error code.\n \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity,\n                                 const void* src, size_t srcSize,\n                                       unsigned magicVariant);\n</b><p> Generates a zstd skippable frame containing data given by src, and writes it to dst buffer.\n\n Skippable frames begin with a 4-byte magic number. There are 16 possible choices of magic number,\n ranging from ZSTD_MAGIC_SKIPPABLE_START to ZSTD_MAGIC_SKIPPABLE_START+15.\n As such, the parameter magicVariant controls the exact skippable frame magic number variant used,\n so the magic number used will be ZSTD_MAGIC_SKIPPABLE_START + magicVariant.\n\n Returns an error if destination buffer is not large enough, if the source size is not representable\n with a 4-byte unsigned int, or if the parameter magicVariant is greater than 15 (and therefore invalid).\n\n @return : number of bytes written or a ZSTD error.\n \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity,\n                                      unsigned* magicVariant,\n                                      const void* src, size_t srcSize);\n</b><p> Retrieves the content of a zstd skippable frame starting at @src, and writes it to @dst buffer.\n\n The parameter @magicVariant will receive the magicVariant that was supplied when the frame was written,\n i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START.\n This can be NULL if the caller is not interested in the magicVariant.\n\n Returns an error if destination buffer is not large enough, or if the frame is not skippable.\n\n @return : number of bytes written or a ZSTD error.\n \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size);\n</b><p>  Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame.\n \n</p></pre><BR>\n\n<a name=\"Chapter16\"></a><h2>Memory management</h2><pre></pre>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize(int maxCompressionLevel);\nZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams);\nZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params);\nZSTDLIB_STATIC_API size_t ZSTD_estimateDCtxSize(void);\n</b><p>  These functions make it possible to estimate memory usage\n  of a future {D,C}Ctx, before its creation.\n  This is useful in combination with ZSTD_initStatic(),\n  which makes it possible to employ a static buffer for ZSTD_CCtx* state.\n\n  ZSTD_estimateCCtxSize() will provide a memory budget large enough\n  to compress data of any size using one-shot compression ZSTD_compressCCtx() or ZSTD_compress2()\n  associated with any compression level up to max specified one.\n  The estimate will assume the input may be arbitrarily large,\n  which is the worst case.\n\n  Note that the size estimation is specific for one-shot compression,\n  it is not valid for streaming (see ZSTD_estimateCStreamSize*())\n  nor other potential ways of using a ZSTD_CCtx* state.\n\n  When srcSize can be bound by a known and rather \"small\" value,\n  this knowledge can be used to provide a tighter budget estimation\n  because the ZSTD_CCtx* state will need less memory for small inputs.\n  This tighter estimation can be provided by employing more advanced functions\n  ZSTD_estimateCCtxSize_usingCParams(), which can be used in tandem with ZSTD_getCParams(),\n  and ZSTD_estimateCCtxSize_usingCCtxParams(), which can be used in tandem with ZSTD_CCtxParams_setParameter().\n  Both can be used to estimate memory using custom compression parameters and arbitrary srcSize limits.\n\n  Note : only single-threaded compression is supported.\n  ZSTD_estimateCCtxSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1.\n \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize(int maxCompressionLevel);\nZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams);\nZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params);\nZSTDLIB_STATIC_API size_t ZSTD_estimateDStreamSize(size_t maxWindowSize);\nZSTDLIB_STATIC_API size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize);\n</b><p>  ZSTD_estimateCStreamSize() will provide a memory budget large enough for streaming compression\n  using any compression level up to the max specified one.\n  It will also consider src size to be arbitrarily \"large\", which is a worst case scenario.\n  If srcSize is known to always be small, ZSTD_estimateCStreamSize_usingCParams() can provide a tighter estimation.\n  ZSTD_estimateCStreamSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel.\n  ZSTD_estimateCStreamSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParams_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1.\n  Note : CStream size estimation is only correct for single-threaded compression.\n  ZSTD_estimateCStreamSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1.\n  Note 2 : ZSTD_estimateCStreamSize* functions are not compatible with the Block-Level Sequence Producer API at this time.\n  Size estimates assume that no external sequence producer is registered.\n\n  ZSTD_DStream memory budget depends on frame's window Size.\n  This information can be passed manually, using ZSTD_estimateDStreamSize,\n  or deducted from a valid frame Header, using ZSTD_estimateDStreamSize_fromFrame();\n  Any frame requesting a window size larger than max specified one will be rejected.\n  Note : if streaming is init with function ZSTD_init?Stream_usingDict(),\n         an internal ?Dict will be created, which additional size is not estimated here.\n         In this case, get total size by adding ZSTD_estimate?DictSize\n \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel);\nZSTDLIB_STATIC_API size_t ZSTD_estimateCDictSize_advanced(size_t dictSize, ZSTD_compressionParameters cParams, ZSTD_dictLoadMethod_e dictLoadMethod);\nZSTDLIB_STATIC_API size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod);\n</b><p>  ZSTD_estimateCDictSize() will bet that src size is relatively \"small\", and content is copied, like ZSTD_createCDict().\n  ZSTD_estimateCDictSize_advanced() makes it possible to control compression parameters precisely, like ZSTD_createCDict_advanced().\n  Note : dictionaries created by reference (`ZSTD_dlm_byRef`) are logically smaller.\n \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API ZSTD_CCtx*    ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize);\nZSTDLIB_STATIC_API ZSTD_CStream* ZSTD_initStaticCStream(void* workspace, size_t workspaceSize);    </b>/**< same as ZSTD_initStaticCCtx() */<b>\n</b><p>  Initialize an object using a pre-allocated fixed-size buffer.\n  workspace: The memory area to emplace the object into.\n             Provided pointer *must be 8-bytes aligned*.\n             Buffer must outlive object.\n  workspaceSize: Use ZSTD_estimate*Size() to determine\n                 how large workspace must be to support target scenario.\n @return : pointer to object (same address as workspace, just different type),\n           or NULL if error (size too small, incorrect alignment, etc.)\n  Note : zstd will never resize nor malloc() when using a static buffer.\n         If the object requires more memory than available,\n         zstd will just error out (typically ZSTD_error_memory_allocation).\n  Note 2 : there is no corresponding \"free\" function.\n           Since workspace is allocated externally, it must be freed externally too.\n  Note 3 : cParams : use ZSTD_getCParams() to convert a compression level\n           into its associated cParams.\n  Limitation 1 : currently not compatible with internal dictionary creation, triggered by\n                 ZSTD_CCtx_loadDictionary(), ZSTD_initCStream_usingDict() or ZSTD_initDStream_usingDict().\n  Limitation 2 : static cctx currently not compatible with multi-threading.\n  Limitation 3 : static dctx is incompatible with legacy support.\n \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API ZSTD_DStream* ZSTD_initStaticDStream(void* workspace, size_t workspaceSize);    </b>/**< same as ZSTD_initStaticDCtx() */<b>\n</b></pre><BR>\n<pre><b>typedef void* (*ZSTD_allocFunction) (void* opaque, size_t size);\ntypedef void  (*ZSTD_freeFunction) (void* opaque, void* address);\ntypedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem;\nstatic\n#ifdef __GNUC__\n__attribute__((__unused__))\n#endif\n</b><p>  These prototypes make it possible to pass your own allocation/free functions.\n  ZSTD_customMem is provided at creation time, using ZSTD_create*_advanced() variants listed below.\n  All allocation/free operations will be completed using these custom variants instead of regular <stdlib.h> ones.\n \n</p></pre><BR>\n\n<pre><b>ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL };  </b>/**< this constant defers to stdlib's functions */<b>\n</b></pre><BR>\n<pre><b>typedef struct POOL_ctx_s ZSTD_threadPool;\nZSTDLIB_STATIC_API ZSTD_threadPool* ZSTD_createThreadPool(size_t numThreads);\nZSTDLIB_STATIC_API void ZSTD_freeThreadPool (ZSTD_threadPool* pool);  </b>/* accept NULL pointer */<b>\nZSTDLIB_STATIC_API size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool);\n</b><p>  These prototypes make it possible to share a thread pool among multiple compression contexts.\n  This can limit resources for applications with multiple threads where each one uses\n  a threaded compression mode (via ZSTD_c_nbWorkers parameter).\n  ZSTD_createThreadPool creates a new thread pool with a given number of threads.\n  Note that the lifetime of such pool must exist while being used.\n  ZSTD_CCtx_refThreadPool assigns a thread pool to a context (use NULL argument value\n  to use an internal thread pool).\n  ZSTD_freeThreadPool frees a thread pool, accepts NULL pointer.\n \n</p></pre><BR>\n\n<a name=\"Chapter17\"></a><h2>Advanced compression functions</h2><pre></pre>\n\n<pre><b>ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);\n</b><p>  Create a digested dictionary for compression\n  Dictionary content is just referenced, not duplicated.\n  As a consequence, `dictBuffer` **must** outlive CDict,\n  and its content must remain unmodified throughout the lifetime of CDict.\n  note: equivalent to ZSTD_createCDict_advanced(), with dictLoadMethod==ZSTD_dlm_byRef \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);\n</b><p> @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize.\n `estimatedSrcSize` value is optional, select 0 if not known \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);\n</b><p>  same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`.\n  All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0 \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params);\n</b><p>  Ensure param values remain within authorized range.\n @return 0 on success, or an error code (can be checked with ZSTD_isError()) \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize);\n</b><p>  optimize params for a given `srcSize` and `dictSize`.\n `srcSize` can be unknown, in which case use ZSTD_CONTENTSIZE_UNKNOWN.\n `dictSize` must be `0` when there is no dictionary.\n  cPar can be invalid : all parameters will be clamped within valid range in the @return struct.\n  This function never fails (wide contract) \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_CCtx_setCParams(ZSTD_CCtx* cctx, ZSTD_compressionParameters cparams);\n</b><p>  Set all parameters provided within @p cparams into the working @p cctx.\n  Note : if modifying parameters during compression (MT mode only),\n         note that changes to the .windowLog parameter will be ignored.\n @return 0 on success, or an error code (can be checked with ZSTD_isError()).\n         On failure, no parameters are updated.\n \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_CCtx_setFParams(ZSTD_CCtx* cctx, ZSTD_frameParameters fparams);\n</b><p>  Set all parameters provided within @p fparams into the working @p cctx.\n @return 0 on success, or an error code (can be checked with ZSTD_isError()).\n \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_CCtx_setParams(ZSTD_CCtx* cctx, ZSTD_parameters params);\n</b><p>  Set all parameters provided within @p params into the working @p cctx.\n @return 0 on success, or an error code (can be checked with ZSTD_isError()).\n \n</p></pre><BR>\n\n<pre><b>ZSTD_DEPRECATED(\"use ZSTD_compress2\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_compress_advanced(ZSTD_CCtx* cctx,\n                  void* dst, size_t dstCapacity,\n            const void* src, size_t srcSize,\n            const void* dict,size_t dictSize,\n                  ZSTD_parameters params);\n</b><p>  Note : this function is now DEPRECATED.\n         It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_setParameter() and other parameter setters.\n  This prototype will generate compilation warnings. \n</p></pre><BR>\n\n<pre><b>ZSTD_DEPRECATED(\"use ZSTD_compress2 with ZSTD_CCtx_loadDictionary\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,\n                                  void* dst, size_t dstCapacity,\n                            const void* src, size_t srcSize,\n                            const ZSTD_CDict* cdict,\n                                  ZSTD_frameParameters fParams);\n</b><p>  Note : this function is now DEPRECATED.\n         It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_loadDictionary() and other parameter setters.\n  This prototype will generate compilation warnings. \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_CCtx_loadDictionary_byReference(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);\n</b><p>  Same as ZSTD_CCtx_loadDictionary(), but dictionary content is referenced, instead of being copied into CCtx.\n  It saves some memory, but also requires that `dict` outlives its usage within `cctx` \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);\n</b><p>  Same as ZSTD_CCtx_loadDictionary(), but gives finer control over\n  how to load the dictionary (by copy ? by reference ?)\n  and how to interpret it (automatic ? force raw mode ? full mode only ?) \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);\n</b><p>  Same as ZSTD_CCtx_refPrefix(), but gives finer control over\n  how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_CCtx_getParameter(const ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value);\n</b><p>  Get the requested compression parameter value, selected by enum ZSTD_cParameter,\n  and store it into int* value.\n @return : 0, or an error code (which can be tested with ZSTD_isError()).\n \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void);\nZSTDLIB_STATIC_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);  </b>/* accept NULL pointer */<b>\n</b><p>  Quick howto :\n  - ZSTD_createCCtxParams() : Create a ZSTD_CCtx_params structure\n  - ZSTD_CCtxParams_setParameter() : Push parameters one by one into\n                                     an existing ZSTD_CCtx_params structure.\n                                     This is similar to\n                                     ZSTD_CCtx_setParameter().\n  - ZSTD_CCtx_setParametersUsingCCtxParams() : Apply parameters to\n                                    an existing CCtx.\n                                    These parameters will be applied to\n                                    all subsequent frames.\n  - ZSTD_compressStream2() : Do compression using the CCtx.\n  - ZSTD_freeCCtxParams() : Free the memory, accept NULL pointer.\n\n  This can be used with ZSTD_estimateCCtxSize_advanced_usingCCtxParams()\n  for static allocation of CCtx for single-threaded compression.\n \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params);\n</b><p>  Reset params to default values.\n \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel);\n</b><p>  Initializes the compression parameters of cctxParams according to\n  compression level. All other parameters are reset to their default values.\n \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params);\n</b><p>  Initializes the compression and frame parameters of cctxParams according to\n  params. All other parameters are reset to their default values.\n \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value);\n</b><p>  Similar to ZSTD_CCtx_setParameter.\n  Set one compression parameter, selected by enum ZSTD_cParameter.\n  Parameters must be applied to a ZSTD_CCtx using\n  ZSTD_CCtx_setParametersUsingCCtxParams().\n @result : a code representing success or failure (which can be tested with\n           ZSTD_isError()).\n \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_getParameter(const ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value);\n</b><p> Similar to ZSTD_CCtx_getParameter.\n Get the requested value of one compression parameter, selected by enum ZSTD_cParameter.\n @result : 0, or an error code (which can be tested with ZSTD_isError()).\n \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_CCtx_setParametersUsingCCtxParams(\n        ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params);\n</b><p>  Apply a set of ZSTD_CCtx_params to the compression context.\n  This can be done even after compression is started,\n    if nbWorkers==0, this will have no impact until a new compression is started.\n    if nbWorkers>=1, new parameters will be picked up at next job,\n       with a few restrictions (windowLog, pledgedSrcSize, nbWorkers, jobSize, and overlapLog are not updated).\n \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_compressStream2_simpleArgs (\n                ZSTD_CCtx* cctx,\n                void* dst, size_t dstCapacity, size_t* dstPos,\n          const void* src, size_t srcSize, size_t* srcPos,\n                ZSTD_EndDirective endOp);\n</b><p>  Same as ZSTD_compressStream2(),\n  but using only integral types as arguments.\n  This variant might be helpful for binders from dynamic languages\n  which have troubles handling structures containing memory pointers.\n \n</p></pre><BR>\n\n<a name=\"Chapter18\"></a><h2>Advanced decompression functions</h2><pre></pre>\n\n<pre><b>ZSTDLIB_STATIC_API unsigned ZSTD_isFrame(const void* buffer, size_t size);\n</b><p>  Tells if the content of `buffer` starts with a valid Frame Identifier.\n  Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.\n  Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled.\n  Note 3 : Skippable Frame Identifiers are considered valid. \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize);\n</b><p>  Create a digested dictionary, ready to start decompression operation without startup delay.\n  Dictionary content is referenced, and therefore stays in dictBuffer.\n  It is important that dictBuffer outlives DDict,\n  it must remain read accessible throughout the lifetime of DDict \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);\n</b><p>  Same as ZSTD_DCtx_loadDictionary(),\n  but references `dict` content instead of copying it into `dctx`.\n  This saves memory if `dict` remains around.,\n  However, it's imperative that `dict` remains accessible (and unmodified) while being used, so it must outlive decompression. \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);\n</b><p>  Same as ZSTD_DCtx_loadDictionary(),\n  but gives direct control over\n  how to load the dictionary (by copy ? by reference ?)\n  and how to interpret it (automatic ? force raw mode ? full mode only ?). \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);\n</b><p>  Same as ZSTD_DCtx_refPrefix(), but gives finer control over\n  how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize);\n</b><p>  Refuses allocating internal buffers for frames requiring a window size larger than provided limit.\n  This protects a decoder context from reserving too much memory for itself (potential attack scenario).\n  This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode.\n  By default, a decompression context accepts all window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT)\n @return : 0, or an error code (which can be tested using ZSTD_isError()).\n \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value);\n</b><p>  Get the requested decompression parameter value, selected by enum ZSTD_dParameter,\n  and store it into int* value.\n @return : 0, or an error code (which can be tested with ZSTD_isError()).\n \n</p></pre><BR>\n\n<pre><b>ZSTD_DEPRECATED(\"use ZSTD_DCtx_setParameter() instead\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format);\n</b><p>  This function is REDUNDANT. Prefer ZSTD_DCtx_setParameter().\n  Instruct the decoder context about what kind of data to decode next.\n  This instruction is mandatory to decode data without a fully-formed header,\n  such ZSTD_f_zstd1_magicless for example.\n @return : 0, or an error code (which can be tested using ZSTD_isError()). \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_decompressStream_simpleArgs (\n                ZSTD_DCtx* dctx,\n                void* dst, size_t dstCapacity, size_t* dstPos,\n          const void* src, size_t srcSize, size_t* srcPos);\n</b><p>  Same as ZSTD_decompressStream(),\n  but using only integral types as arguments.\n  This can be helpful for binders from dynamic languages\n  which have troubles handling structures containing memory pointers.\n \n</p></pre><BR>\n\n<a name=\"Chapter19\"></a><h2>Advanced streaming functions</h2><pre>  Warning : most of these functions are now redundant with the Advanced API.\n  Once Advanced API reaches \"stable\" status,\n  redundant functions will be deprecated, and then at some point removed.\n<BR></pre>\n\n<h3>Advanced Streaming compression functions</h3><pre></pre><b><pre></pre></b><BR>\n<pre><b>ZSTD_DEPRECATED(\"use ZSTD_CCtx_reset, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs,\n             int compressionLevel,\n             unsigned long long pledgedSrcSize);\n</b><p> This function is DEPRECATED, and equivalent to:\n     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n     ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)\n     ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);\n     ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);\n\n pledgedSrcSize must be correct. If it is not known at init time, use\n ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs,\n \"0\" also disables frame content size field. It may be enabled in the future.\n This prototype will generate compilation warnings.\n \n</p></pre><BR>\n\n<pre><b>ZSTD_DEPRECATED(\"use ZSTD_CCtx_reset, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs,\n         const void* dict, size_t dictSize,\n               int compressionLevel);\n</b><p> This function is DEPRECATED, and is equivalent to:\n     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n     ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);\n     ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);\n\n Creates of an internal CDict (incompatible with static CCtx), except if\n dict == NULL or dictSize < 8, in which case no dict is used.\n Note: dict is loaded with ZSTD_dct_auto (treated as a full zstd dictionary if\n it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy.\n This prototype will generate compilation warnings.\n \n</p></pre><BR>\n\n<pre><b>ZSTD_DEPRECATED(\"use ZSTD_CCtx_reset, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,\n        const void* dict, size_t dictSize,\n              ZSTD_parameters params,\n              unsigned long long pledgedSrcSize);\n</b><p> This function is DEPRECATED, and is equivalent to:\n     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n     ZSTD_CCtx_setParams(zcs, params);\n     ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);\n     ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);\n\n dict is loaded with ZSTD_dct_auto and ZSTD_dlm_byCopy.\n pledgedSrcSize must be correct.\n If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN.\n This prototype will generate compilation warnings.\n \n</p></pre><BR>\n\n<pre><b>ZSTD_DEPRECATED(\"use ZSTD_CCtx_reset and ZSTD_CCtx_refCDict, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict);\n</b><p> This function is DEPRECATED, and equivalent to:\n     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n     ZSTD_CCtx_refCDict(zcs, cdict);\n\n note : cdict will just be referenced, and must outlive compression session\n This prototype will generate compilation warnings.\n \n</p></pre><BR>\n\n<pre><b>ZSTD_DEPRECATED(\"use ZSTD_CCtx_reset and ZSTD_CCtx_refCDict, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,\n                   const ZSTD_CDict* cdict,\n                         ZSTD_frameParameters fParams,\n                         unsigned long long pledgedSrcSize);\n</b><p>   This function is DEPRECATED, and is equivalent to:\n     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n     ZSTD_CCtx_setFParams(zcs, fParams);\n     ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);\n     ZSTD_CCtx_refCDict(zcs, cdict);\n\n same as ZSTD_initCStream_usingCDict(), with control over frame parameters.\n pledgedSrcSize must be correct. If srcSize is not known at init time, use\n value ZSTD_CONTENTSIZE_UNKNOWN.\n This prototype will generate compilation warnings.\n \n</p></pre><BR>\n\n<pre><b>ZSTD_DEPRECATED(\"use ZSTD_CCtx_reset, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);\n</b><p> This function is DEPRECATED, and is equivalent to:\n     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n     ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);\n Note: ZSTD_resetCStream() interprets pledgedSrcSize == 0 as ZSTD_CONTENTSIZE_UNKNOWN, but\n       ZSTD_CCtx_setPledgedSrcSize() does not do the same, so ZSTD_CONTENTSIZE_UNKNOWN must be\n       explicitly specified.\n\n  start a new frame, using same parameters from previous frame.\n  This is typically useful to skip dictionary loading stage, since it will reuse it in-place.\n  Note that zcs must be init at least once before using ZSTD_resetCStream().\n  If pledgedSrcSize is not known at reset time, use macro ZSTD_CONTENTSIZE_UNKNOWN.\n  If pledgedSrcSize > 0, its value must be correct, as it will be written in header, and controlled at the end.\n  For the time being, pledgedSrcSize==0 is interpreted as \"srcSize unknown\" for compatibility with older programs,\n  but it will change to mean \"empty\" in future version, so use macro ZSTD_CONTENTSIZE_UNKNOWN instead.\n @return : 0, or an error code (which can be tested using ZSTD_isError())\n  This prototype will generate compilation warnings.\n \n</p></pre><BR>\n\n<pre><b>typedef struct {\n    unsigned long long ingested;   </b>/* nb input bytes read and buffered */<b>\n    unsigned long long consumed;   </b>/* nb input bytes actually compressed */<b>\n    unsigned long long produced;   </b>/* nb of compressed bytes generated and buffered */<b>\n    unsigned long long flushed;    </b>/* nb of compressed bytes flushed : not provided; can be tracked from caller side */<b>\n    unsigned currentJobID;         </b>/* MT only : latest started job nb */<b>\n    unsigned nbActiveWorkers;      </b>/* MT only : nb of workers actively compressing at probe time */<b>\n} ZSTD_frameProgression;\n</b></pre><BR>\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx);\n</b><p>  Tell how many bytes are ready to be flushed immediately.\n  Useful for multithreading scenarios (nbWorkers >= 1).\n  Probe the oldest active job, defined as oldest job not yet entirely flushed,\n  and check its output buffer.\n @return : amount of data stored in oldest job and ready to be flushed immediately.\n  if @return == 0, it means either :\n  + there is no active job (could be checked with ZSTD_frameProgression()), or\n  + oldest job is still actively compressing data,\n    but everything it has produced has also been flushed so far,\n    therefore flush speed is limited by production speed of oldest job\n    irrespective of the speed of concurrent (and newer) jobs.\n \n</p></pre><BR>\n\n<h3>Advanced Streaming decompression functions</h3><pre></pre><b><pre></pre></b><BR>\n<pre><b>ZSTD_DEPRECATED(\"use ZSTD_DCtx_reset + ZSTD_DCtx_loadDictionary, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);\n</b><p>\n     ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);\n     ZSTD_DCtx_loadDictionary(zds, dict, dictSize);\n\n note: no dictionary will be used if dict == NULL or dictSize < 8\n \n</p></pre><BR>\n\n<pre><b>ZSTD_DEPRECATED(\"use ZSTD_DCtx_reset + ZSTD_DCtx_refDDict, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict);\n</b><p>\n     ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);\n     ZSTD_DCtx_refDDict(zds, ddict);\n\n note : ddict is referenced, it must outlive decompression session\n \n</p></pre><BR>\n\n<pre><b>ZSTD_DEPRECATED(\"use ZSTD_DCtx_reset, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);\n</b><p>\n     ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);\n\n reuse decompression parameters from previous init; saves dictionary loading\n \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API void\nZSTD_registerSequenceProducer(\n  ZSTD_CCtx* cctx,\n  void* sequenceProducerState,\n  ZSTD_sequenceProducer_F sequenceProducer\n);\n</b><p> Instruct zstd to use a block-level external sequence producer function.\n\n The sequenceProducerState must be initialized by the caller, and the caller is\n responsible for managing its lifetime. This parameter is sticky across\n compressions. It will remain set until the user explicitly resets compression\n parameters.\n\n Sequence producer registration is considered to be an \"advanced parameter\",\n part of the \"advanced API\". This means it will only have an effect on compression\n APIs which respect advanced parameters, such as compress2() and compressStream2().\n Older compression APIs such as compressCCtx(), which predate the introduction of\n \"advanced parameters\", will ignore any external sequence producer setting.\n\n The sequence producer can be \"cleared\" by registering a NULL function pointer. This\n removes all limitations described above in the \"LIMITATIONS\" section of the API docs.\n\n The user is strongly encouraged to read the full API documentation (above) before\n calling this function. \n</p></pre><BR>\n\n<pre><b>ZSTDLIB_STATIC_API void\nZSTD_CCtxParams_registerSequenceProducer(\n  ZSTD_CCtx_params* params,\n  void* sequenceProducerState,\n  ZSTD_sequenceProducer_F sequenceProducer\n);\n</b><p> Same as ZSTD_registerSequenceProducer(), but operates on ZSTD_CCtx_params.\n This is used for accurate size estimation with ZSTD_estimateCCtxSize_usingCCtxParams(),\n which is needed when creating a ZSTD_CCtx with ZSTD_initStaticCCtx().\n\n If you are using the external sequence producer API in a scenario where ZSTD_initStaticCCtx()\n is required, then this function is for you. Otherwise, you probably don't need it.\n\n See tests/zstreamtest.c for example usage. \n</p></pre><BR>\n\n<a name=\"Chapter20\"></a><h2>Buffer-less and synchronous inner streaming functions (DEPRECATED)</h2><pre>\n  This API is deprecated, and will be removed in a future version.\n  It allows streaming (de)compression with user allocated buffers.\n  However, it is hard to use, and not as well tested as the rest of\n  our API.\n\n  Please use the normal streaming API instead: ZSTD_compressStream2,\n  and ZSTD_decompressStream.\n  If there is functionality that you need, but it doesn't provide,\n  please open an issue on our GitHub.\n \n<BR></pre>\n\n<a name=\"Chapter21\"></a><h2>Buffer-less streaming compression (synchronous mode)</h2><pre>\n  A ZSTD_CCtx object is required to track streaming operations.\n  Use ZSTD_createCCtx() / ZSTD_freeCCtx() to manage resource.\n  ZSTD_CCtx object can be reused multiple times within successive compression operations.\n\n  Start by initializing a context.\n  Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary compression.\n\n  Then, consume your input using ZSTD_compressContinue().\n  There are some important considerations to keep in mind when using this advanced function :\n  - ZSTD_compressContinue() has no internal buffer. It uses externally provided buffers only.\n  - Interface is synchronous : input is consumed entirely and produces 1+ compressed blocks.\n  - Caller must ensure there is enough space in `dst` to store compressed data under worst case scenario.\n    Worst case evaluation is provided by ZSTD_compressBound().\n    ZSTD_compressContinue() doesn't guarantee recover after a failed compression.\n  - ZSTD_compressContinue() presumes prior input ***is still accessible and unmodified*** (up to maximum distance size, see WindowLog).\n    It remembers all previous contiguous blocks, plus one separated memory segment (which can itself consists of multiple contiguous blocks)\n  - ZSTD_compressContinue() detects that prior input has been overwritten when `src` buffer overlaps.\n    In which case, it will \"discard\" the relevant memory section from its history.\n\n  Finish a frame with ZSTD_compressEnd(), which will write the last block(s) and optional checksum.\n  It's possible to use srcSize==0, in which case, it will write a final empty block to end the frame.\n  Without last block mark, frames are considered unfinished (hence corrupted) by compliant decoders.\n\n  `ZSTD_CCtx` object can be reused (ZSTD_compressBegin()) to compress again.\n<BR></pre>\n\n<h3>Buffer-less streaming compression functions</h3><pre></pre><b><pre>ZSTD_DEPRECATED(\"The buffer-less API is deprecated in favor of the normal streaming API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel);\nZSTD_DEPRECATED(\"The buffer-less API is deprecated in favor of the normal streaming API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel);\nZSTD_DEPRECATED(\"The buffer-less API is deprecated in favor of the normal streaming API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); </b>/**< note: fails if cdict==NULL */<b>\n</pre></b><BR>\n<pre><b>size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); </b>/**<  note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */<b>\n</b></pre><BR>\n<pre><b>size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); </b>/**< pledgedSrcSize : If srcSize is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN */<b>\n</b></pre><BR>\n<a name=\"Chapter22\"></a><h2>Buffer-less streaming decompression (synchronous mode)</h2><pre>\n  A ZSTD_DCtx object is required to track streaming operations.\n  Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it.\n  A ZSTD_DCtx object can be reused multiple times.\n\n  First typical operation is to retrieve frame parameters, using ZSTD_getFrameHeader().\n  Frame header is extracted from the beginning of compressed frame, so providing only the frame's beginning is enough.\n  Data fragment must be large enough to ensure successful decoding.\n `ZSTD_frameHeaderSize_max` bytes is guaranteed to always be large enough.\n  result  : 0 : successful decoding, the `ZSTD_frameHeader` structure is correctly filled.\n           >0 : `srcSize` is too small, please provide at least result bytes on next attempt.\n           errorCode, which can be tested using ZSTD_isError().\n\n  It fills a ZSTD_FrameHeader structure with important information to correctly decode the frame,\n  such as the dictionary ID, content size, or maximum back-reference distance (`windowSize`).\n  Note that these values could be wrong, either because of data corruption, or because a 3rd party deliberately spoofs false information.\n  As a consequence, check that values remain within valid application range.\n  For example, do not allocate memory blindly, check that `windowSize` is within expectation.\n  Each application can set its own limits, depending on local restrictions.\n  For extended interoperability, it is recommended to support `windowSize` of at least 8 MB.\n\n  ZSTD_decompressContinue() needs previous data blocks during decompression, up to `windowSize` bytes.\n  ZSTD_decompressContinue() is very sensitive to contiguity,\n  if 2 blocks don't follow each other, make sure that either the compressor breaks contiguity at the same place,\n  or that previous contiguous segment is large enough to properly handle maximum back-reference distance.\n  There are multiple ways to guarantee this condition.\n\n  The most memory efficient way is to use a round buffer of sufficient size.\n  Sufficient size is determined by invoking ZSTD_decodingBufferSize_min(),\n  which can return an error code if required value is too large for current system (in 32-bits mode).\n  In a round buffer methodology, ZSTD_decompressContinue() decompresses each block next to previous one,\n  up to the moment there is not enough room left in the buffer to guarantee decoding another full block,\n  which maximum size is provided in `ZSTD_frameHeader` structure, field `blockSizeMax`.\n  At which point, decoding can resume from the beginning of the buffer.\n  Note that already decoded data stored in the buffer should be flushed before being overwritten.\n\n  There are alternatives possible, for example using two or more buffers of size `windowSize` each, though they consume more memory.\n\n  Finally, if you control the compression process, you can also ignore all buffer size rules,\n  as long as the encoder and decoder progress in \"lock-step\",\n  aka use exactly the same buffer sizes, break contiguity at the same place, etc.\n\n  Once buffers are setup, start decompression, with ZSTD_decompressBegin().\n  If decompression requires a dictionary, use ZSTD_decompressBegin_usingDict() or ZSTD_decompressBegin_usingDDict().\n\n  Then use ZSTD_nextSrcSizeToDecompress() and ZSTD_decompressContinue() alternatively.\n  ZSTD_nextSrcSizeToDecompress() tells how many bytes to provide as 'srcSize' to ZSTD_decompressContinue().\n  ZSTD_decompressContinue() requires this _exact_ amount of bytes, or it will fail.\n\n  result of ZSTD_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity).\n  It can be zero : it just means ZSTD_decompressContinue() has decoded some metadata item.\n  It can also be an error code, which can be tested with ZSTD_isError().\n\n  A frame is fully decoded when ZSTD_nextSrcSizeToDecompress() returns zero.\n  Context can then be reset to start a new decompression.\n\n  Note : it's possible to know if next input to present is a header or a block, using ZSTD_nextInputType().\n  This information is not required to properly decode a frame.\n\n  == Special case : skippable frames \n\n  Skippable frames allow integration of user-defined data into a flow of concatenated frames.\n  Skippable frames will be ignored (skipped) by decompressor.\n  The format of skippable frames is as follows :\n  a) Skippable frame ID - 4 Bytes, Little endian format, any value from 0x184D2A50 to 0x184D2A5F\n  b) Frame Size - 4 Bytes, Little endian format, unsigned 32-bits\n  c) Frame Content - any content (User Data) of length equal to Frame Size\n  For skippable frames ZSTD_getFrameHeader() returns zfhPtr->frameType==ZSTD_skippableFrame.\n  For skippable frames ZSTD_decompressContinue() always returns 0 : it only skips the content.\n<BR></pre>\n\n<h3>Buffer-less streaming decompression functions</h3><pre></pre><b><pre></pre></b><BR>\n<pre><b>ZSTDLIB_STATIC_API size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize);  </b>/**< when frame content size is not known, pass in frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN */<b>\n</b></pre><BR>\n<pre><b>typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e;\n</b></pre><BR>\n<a name=\"Chapter23\"></a><h2>Block level API (DEPRECATED)</h2><pre></pre>\n\n<pre><b></b><p>    You can get the frame header down to 2 bytes by setting:\n      - ZSTD_c_format = ZSTD_f_zstd1_magicless\n      - ZSTD_c_contentSizeFlag = 0\n      - ZSTD_c_checksumFlag = 0\n      - ZSTD_c_dictIDFlag = 0\n\n    This API is not as well tested as our normal API, so we recommend not using it.\n    We will be removing it in a future version. If the normal API doesn't provide\n    the functionality you need, please open a GitHub issue.\n\n    Block functions produce and decode raw zstd blocks, without frame metadata.\n    Frame metadata cost is typically ~12 bytes, which can be non-negligible for very small blocks (< 100 bytes).\n    But users will have to take in charge needed metadata to regenerate data, such as compressed and content sizes.\n\n    A few rules to respect :\n    - Compressing and decompressing require a context structure\n      + Use ZSTD_createCCtx() and ZSTD_createDCtx()\n    - It is necessary to init context before starting\n      + compression : any ZSTD_compressBegin*() variant, including with dictionary\n      + decompression : any ZSTD_decompressBegin*() variant, including with dictionary\n    - Block size is limited, it must be <= ZSTD_getBlockSize() <= ZSTD_BLOCKSIZE_MAX == 128 KB\n      + If input is larger than a block size, it's necessary to split input data into multiple blocks\n      + For inputs larger than a single block, consider using regular ZSTD_compress() instead.\n        Frame metadata is not that costly, and quickly becomes negligible as source size grows larger than a block.\n    - When a block is considered not compressible enough, ZSTD_compressBlock() result will be 0 (zero) !\n      ===> In which case, nothing is produced into `dst` !\n      + User __must__ test for such outcome and deal directly with uncompressed data\n      + A block cannot be declared incompressible if ZSTD_compressBlock() return value was != 0.\n        Doing so would mess up with statistics history, leading to potential data corruption.\n      + ZSTD_decompressBlock() _doesn't accept uncompressed data as input_ !!\n      + In case of multiple successive blocks, should some of them be uncompressed,\n        decoder must be informed of their existence in order to follow proper history.\n        Use ZSTD_insertBlock() for such a case.\n</p></pre><BR>\n\n<h3>Raw zstd block functions</h3><pre></pre><b><pre>ZSTD_DEPRECATED(\"The block API is deprecated in favor of the normal compression API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_getBlockSize   (const ZSTD_CCtx* cctx);\nZSTD_DEPRECATED(\"The block API is deprecated in favor of the normal compression API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_compressBlock  (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\nZSTD_DEPRECATED(\"The block API is deprecated in favor of the normal compression API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\nZSTD_DEPRECATED(\"The block API is deprecated in favor of the normal compression API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_insertBlock    (ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize);  </b>/**< insert uncompressed block into `dctx` history. Useful for multi-blocks decompression. */<b>\n</pre></b><BR>\n</html>\n</body>\n"
  },
  {
    "path": "examples/.gitignore",
    "content": "#build\nsimple_compression\nsimple_decompression\nmultiple_simple_compression\ndictionary_compression\ndictionary_decompression\nstreaming_compression\nstreaming_decompression\nmultiple_streaming_compression\nstreaming_memory_usage\n\n#test artefact\ntmp*\ntest*\n*.zst\n"
  },
  {
    "path": "examples/Makefile",
    "content": "# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ################################################################\n\nLIBDIR =../lib\nCPPFLAGS += -I$(LIBDIR)\nLIB = $(LIBDIR)/libzstd.a\n\n\n.PHONY: default\ndefault: all\n\n.PHONY: all\nall: simple_compression simple_decompression \\\n\tmultiple_simple_compression\\\n\tdictionary_compression dictionary_decompression \\\n\tstreaming_compression streaming_decompression \\\n\tmultiple_streaming_compression streaming_memory_usage\n\n$(LIB) :\n\t$(MAKE) -C $(LIBDIR) libzstd.a\n\nsimple_compression.o: common.h\nsimple_compression : $(LIB)\n\nsimple_decompression.o: common.h\nsimple_decompression : $(LIB)\n\nmultiple_simple_compression.o: common.h\nmultiple_simple_compression : $(LIB)\n\ndictionary_compression.o: common.h\ndictionary_compression : $(LIB)\n\ndictionary_decompression.o: common.h\ndictionary_decompression : $(LIB)\n\nstreaming_compression.o: common.h\nstreaming_compression : $(LIB)\n\nmultiple_streaming_compression.o: common.h\nmultiple_streaming_compression : $(LIB)\n\nstreaming_decompression.o: common.h\nstreaming_decompression : $(LIB)\n\nstreaming_memory_usage.o: common.h\nstreaming_memory_usage : $(LIB)\n\n\n.PHONY:clean\nclean:\n\t@$(RM) core *.o tmp* result* *.zst \\\n        simple_compression simple_decompression \\\n        multiple_simple_compression \\\n        dictionary_compression dictionary_decompression \\\n        streaming_compression streaming_decompression \\\n        multiple_streaming_compression streaming_memory_usage\n\t@echo Cleaning completed\n\n.PHONY:test\ntest: all\n\tcp README.md tmp\n\tcp Makefile tmp2\n\t@echo -- Simple compression tests\n\t./simple_compression tmp\n\t./simple_decompression tmp.zst\n\t./multiple_simple_compression *.c\n\t./streaming_decompression tmp.zst > /dev/null\n\t@echo -- Streaming memory usage\n\t./streaming_memory_usage\n\t@echo -- Streaming compression tests\n\t./streaming_compression tmp\n\t./streaming_decompression tmp.zst > /dev/null\n\t@echo -- Edge cases detection\n\t! ./streaming_decompression tmp    # invalid input, must fail\n\t! ./simple_decompression tmp       # invalid input, must fail\n\ttouch tmpNull                      # create 0-size file\n\t./simple_compression tmpNull\n\t./simple_decompression tmpNull.zst # 0-size frame : must work\n\t@echo -- Multiple streaming tests\n\t./multiple_streaming_compression *.c\n\t@echo -- Dictionary compression tests\n\t./dictionary_compression tmp2 tmp README.md\n\t./dictionary_decompression tmp2.zst tmp.zst README.md\n\t$(RM) tmp* *.zst\n\t@echo tests completed\n"
  },
  {
    "path": "examples/README.md",
    "content": "Zstandard library : usage examples\n==================================\n\n- [Simple compression](simple_compression.c) :\n  Compress a single file.\n  Introduces usage of : `ZSTD_compress()`\n\n- [Simple decompression](simple_decompression.c) :\n  Decompress a single file.\n  Only compatible with simple compression.\n  Result remains in memory.\n  Introduces usage of : `ZSTD_decompress()`\n\n- [Multiple simple compression](multiple_simple_compression.c) :\n  Compress multiple files (in simple mode) in a single command line.\n  Demonstrates memory preservation technique that\n  minimizes malloc()/free() calls by re-using existing resources.\n  Introduces usage of : `ZSTD_compressCCtx()`\n\n- [Streaming memory usage](streaming_memory_usage.c) :\n  Provides amount of memory used by streaming context.\n  Introduces usage of : `ZSTD_sizeof_CStream()`\n\n- [Streaming compression](streaming_compression.c) :\n  Compress a single file.\n  Introduces usage of : `ZSTD_compressStream()`\n\n- [Multiple Streaming compression](multiple_streaming_compression.c) :\n  Compress multiple files (in streaming mode) in a single command line.\n  Introduces memory usage preservation technique,\n  reducing impact of malloc()/free() and memset() by re-using existing resources.\n\n- [Streaming decompression](streaming_decompression.c) :\n  Decompress a single file compressed by zstd.\n  Compatible with both simple and streaming compression.\n  Result is sent to stdout.\n  Introduces usage of : `ZSTD_decompressStream()`\n\n- [Dictionary compression](dictionary_compression.c) :\n  Compress multiple files using the same dictionary.\n  Introduces usage of : `ZSTD_createCDict()` and `ZSTD_compress_usingCDict()`\n\n- [Dictionary decompression](dictionary_decompression.c) :\n  Decompress multiple files using the same dictionary.\n  Result remains in memory.\n  Introduces usage of : `ZSTD_createDDict()` and `ZSTD_decompress_usingDDict()`\n"
  },
  {
    "path": "examples/common.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/*\n * This header file has common utility functions used in examples.\n */\n#ifndef COMMON_H\n#define COMMON_H\n\n#include <stdlib.h>    // malloc, free, exit\n#include <stdio.h>     // fprintf, perror, fopen, etc.\n#include <string.h>    // strerror\n#include <errno.h>     // errno\n#include <sys/stat.h>  // stat\n#include <zstd.h>\n\n\n/* UNUSED_ATTR tells the compiler it is okay if the function is unused. */\n#if defined(__GNUC__)\n#  define UNUSED_ATTR __attribute__((unused))\n#else\n#  define UNUSED_ATTR\n#endif\n\n#define HEADER_FUNCTION static UNUSED_ATTR\n\n\n/*\n * Define the returned error code from utility functions.\n */\ntypedef enum {\n    ERROR_fsize = 1,\n    ERROR_fopen = 2,\n    ERROR_fclose = 3,\n    ERROR_fread = 4,\n    ERROR_fwrite = 5,\n    ERROR_loadFile = 6,\n    ERROR_saveFile = 7,\n    ERROR_malloc = 8,\n    ERROR_largeFile = 9,\n} COMMON_ErrorCode;\n\n/*! CHECK\n * Check that the condition holds. If it doesn't print a message and die.\n */\n#define CHECK(cond, ...)                        \\\n    do {                                        \\\n        if (!(cond)) {                          \\\n            fprintf(stderr,                     \\\n                    \"%s:%d CHECK(%s) failed: \", \\\n                    __FILE__,                   \\\n                    __LINE__,                   \\\n                    #cond);                     \\\n            fprintf(stderr, \"\" __VA_ARGS__);    \\\n            fprintf(stderr, \"\\n\");              \\\n            exit(1);                            \\\n        }                                       \\\n    } while (0)\n\n/*! CHECK_ZSTD\n * Check the zstd error code and die if an error occurred after printing a\n * message.\n */\n#define CHECK_ZSTD(fn)                                           \\\n    do {                                                         \\\n        size_t const err = (fn);                                 \\\n        CHECK(!ZSTD_isError(err), \"%s\", ZSTD_getErrorName(err)); \\\n    } while (0)\n\n/*! fsize_orDie() :\n * Get the size of a given file path.\n *\n * @return The size of a given file path.\n */\nHEADER_FUNCTION size_t fsize_orDie(const char *filename)\n{\n    struct stat st;\n    if (stat(filename, &st) != 0) {\n        /* error */\n        perror(filename);\n        exit(ERROR_fsize);\n    }\n\n    off_t const fileSize = st.st_size;\n    size_t const size = (size_t)fileSize;\n    /* 1. fileSize should be non-negative,\n     * 2. if off_t -> size_t type conversion results in discrepancy,\n     *    the file size is too large for type size_t.\n     */\n    if ((fileSize < 0) || (fileSize != (off_t)size)) {\n        fprintf(stderr, \"%s : filesize too large \\n\", filename);\n        exit(ERROR_largeFile);\n    }\n    return size;\n}\n\n/*! fopen_orDie() :\n * Open a file using given file path and open option.\n *\n * @return If successful this function will return a FILE pointer to an\n * opened file otherwise it sends an error to stderr and exits.\n */\nHEADER_FUNCTION FILE* fopen_orDie(const char *filename, const char *instruction)\n{\n    FILE* const inFile = fopen(filename, instruction);\n    if (inFile) return inFile;\n    /* error */\n    perror(filename);\n    exit(ERROR_fopen);\n}\n\n/*! fclose_orDie() :\n * Close an opened file using given FILE pointer.\n */\nHEADER_FUNCTION void fclose_orDie(FILE* file)\n{\n    if (!fclose(file)) { return; };\n    /* error */\n    perror(\"fclose\");\n    exit(ERROR_fclose);\n}\n\n/*! fread_orDie() :\n *\n * Read sizeToRead bytes from a given file, storing them at the\n * location given by buffer.\n *\n * @return The number of bytes read.\n */\nHEADER_FUNCTION size_t fread_orDie(void* buffer, size_t sizeToRead, FILE* file)\n{\n    size_t const readSize = fread(buffer, 1, sizeToRead, file);\n    if (readSize == sizeToRead) return readSize;   /* good */\n    if (feof(file)) return readSize;   /* good, reached end of file */\n    /* error */\n    perror(\"fread\");\n    exit(ERROR_fread);\n}\n\n/*! fwrite_orDie() :\n *\n * Write sizeToWrite bytes to a file pointed to by file, obtaining\n * them from a location given by buffer.\n *\n * Note: This function will send an error to stderr and exit if it\n * cannot write data to the given file pointer.\n *\n * @return The number of bytes written.\n */\nHEADER_FUNCTION size_t fwrite_orDie(const void* buffer, size_t sizeToWrite, FILE* file)\n{\n    size_t const writtenSize = fwrite(buffer, 1, sizeToWrite, file);\n    if (writtenSize == sizeToWrite) return sizeToWrite;   /* good */\n    /* error */\n    perror(\"fwrite\");\n    exit(ERROR_fwrite);\n}\n\n/*! malloc_orDie() :\n * Allocate memory.\n *\n * @return If successful this function returns a pointer to allo-\n * cated memory.  If there is an error, this function will send that\n * error to stderr and exit.\n */\nHEADER_FUNCTION void* malloc_orDie(size_t size)\n{\n    void* const buff = malloc(size);\n    if (buff) return buff;\n    /* error */\n    perror(\"malloc\");\n    exit(ERROR_malloc);\n}\n\n/*! loadFile_orDie() :\n * load file into buffer (memory).\n *\n * Note: This function will send an error to stderr and exit if it\n * cannot read data from the given file path.\n *\n * @return If successful this function will load file into buffer and\n * return file size, otherwise it will printout an error to stderr and exit.\n */\nHEADER_FUNCTION size_t loadFile_orDie(const char* fileName, void* buffer, size_t bufferSize)\n{\n    size_t const fileSize = fsize_orDie(fileName);\n    CHECK(fileSize <= bufferSize, \"File too large!\");\n\n    FILE* const inFile = fopen_orDie(fileName, \"rb\");\n    size_t const readSize = fread(buffer, 1, fileSize, inFile);\n    if (readSize != (size_t)fileSize) {\n        fprintf(stderr, \"fread: %s : %s \\n\", fileName, strerror(errno));\n        exit(ERROR_fread);\n    }\n    fclose(inFile);  /* can't fail, read only */\n    return fileSize;\n}\n\n/*! mallocAndLoadFile_orDie() :\n * allocate memory buffer and then load file into it.\n *\n * Note: This function will send an error to stderr and exit if memory allocation\n * fails or it cannot read data from the given file path.\n *\n * @return If successful this function will return buffer and bufferSize(=fileSize),\n * otherwise it will printout an error to stderr and exit.\n */\nHEADER_FUNCTION void* mallocAndLoadFile_orDie(const char* fileName, size_t* bufferSize)\n{\n    size_t const fileSize = fsize_orDie(fileName);\n    *bufferSize = fileSize;\n    void* const buffer = malloc_orDie(*bufferSize);\n    loadFile_orDie(fileName, buffer, *bufferSize);\n    return buffer;\n}\n\n/*! saveFile_orDie() :\n *\n * Save buffSize bytes to a given file path, obtaining them from a location pointed\n * to by buff.\n *\n * Note: This function will send an error to stderr and exit if it\n * cannot write to a given file.\n */\nHEADER_FUNCTION void saveFile_orDie(const char* fileName, const void* buff, size_t buffSize)\n{\n    FILE* const oFile = fopen_orDie(fileName, \"wb\");\n    size_t const wSize = fwrite(buff, 1, buffSize, oFile);\n    if (wSize != (size_t)buffSize) {\n        fprintf(stderr, \"fwrite: %s : %s \\n\", fileName, strerror(errno));\n        exit(ERROR_fwrite);\n    }\n    if (fclose(oFile)) {\n        perror(fileName);\n        exit(ERROR_fclose);\n    }\n}\n\n#endif\n"
  },
  {
    "path": "examples/dictionary_compression.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n**/\n\n/* This example deals with Dictionary compression,\n * its counterpart is `examples/dictionary_decompression.c` .\n * These examples presume that a dictionary already exists.\n * The main method to create a dictionary is `zstd --train`,\n * look at the CLI documentation for details.\n * Another possible method is to employ dictionary training API,\n * published in `lib/zdict.h` .\n**/\n\n#include <stdio.h>     // printf\n#include <stdlib.h>    // free\n#include <string.h>    // memset, strcat\n#include <zstd.h>      // presumes zstd library is installed\n#include \"common.h\"    // Helper functions, CHECK(), and CHECK_ZSTD()\n\n/* createDict() :\n** `dictFileName` is supposed already created using `zstd --train` */\nstatic ZSTD_CDict* createCDict_orDie(const char* dictFileName, int cLevel)\n{\n    size_t dictSize;\n    printf(\"loading dictionary %s \\n\", dictFileName);\n    void* const dictBuffer = mallocAndLoadFile_orDie(dictFileName, &dictSize);\n    ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, cLevel);\n    CHECK(cdict != NULL, \"ZSTD_createCDict() failed!\");\n    free(dictBuffer);\n    return cdict;\n}\n\n\nstatic void compress(const char* fname, const char* oname, const ZSTD_CDict* cdict)\n{\n    size_t fSize;\n    void* const fBuff = mallocAndLoadFile_orDie(fname, &fSize);\n    size_t const cBuffSize = ZSTD_compressBound(fSize);\n    void* const cBuff = malloc_orDie(cBuffSize);\n\n    /* Compress using the dictionary.\n     * This function writes the dictionary id, and content size into the header.\n     * But, it doesn't use a checksum. You can control these options using the\n     * advanced API: ZSTD_CCtx_setParameter(), ZSTD_CCtx_refCDict(),\n     * and ZSTD_compress2().\n     */\n    ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n    CHECK(cctx != NULL, \"ZSTD_createCCtx() failed!\");\n    size_t const cSize = ZSTD_compress_usingCDict(cctx, cBuff, cBuffSize, fBuff, fSize, cdict);\n    CHECK_ZSTD(cSize);\n\n    saveFile_orDie(oname, cBuff, cSize);\n\n    /* success */\n    printf(\"%25s : %6u -> %7u - %s \\n\", fname, (unsigned)fSize, (unsigned)cSize, oname);\n\n    ZSTD_freeCCtx(cctx);   /* never fails */\n    free(fBuff);\n    free(cBuff);\n}\n\n\nstatic char* createOutFilename_orDie(const char* filename)\n{\n    size_t const inL = strlen(filename);\n    size_t const outL = inL + 5;\n    void* outSpace = malloc_orDie(outL);\n    memset(outSpace, 0, outL);\n    strcat(outSpace, filename);\n    strcat(outSpace, \".zst\");\n    return (char*)outSpace;\n}\n\nint main(int argc, const char** argv)\n{\n    const char* const exeName = argv[0];\n    int const cLevel = 3;\n\n    if (argc<3) {\n        fprintf(stderr, \"wrong arguments\\n\");\n        fprintf(stderr, \"usage:\\n\");\n        fprintf(stderr, \"%s [FILES] dictionary\\n\", exeName);\n        return 1;\n    }\n\n    /* load dictionary only once */\n    const char* const dictName = argv[argc-1];\n    ZSTD_CDict* const dictPtr = createCDict_orDie(dictName, cLevel);\n\n    int u;\n    for (u=1; u<argc-1; u++) {\n        const char* inFilename = argv[u];\n        char* const outFilename = createOutFilename_orDie(inFilename);\n        compress(inFilename, outFilename, dictPtr);\n        free(outFilename);\n    }\n\n    ZSTD_freeCDict(dictPtr);\n    printf(\"All %u files compressed. \\n\", argc-2);\n    return 0;\n}\n"
  },
  {
    "path": "examples/dictionary_decompression.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n#include <stdio.h>     // printf\n#include <stdlib.h>    // free\n#include <zstd.h>      // presumes zstd library is installed\n#include \"common.h\"    // Helper functions, CHECK(), and CHECK_ZSTD()\n\n/* createDict() :\n   `dictFileName` is supposed to have been created using `zstd --train` */\nstatic ZSTD_DDict* createDict_orDie(const char* dictFileName)\n{\n    size_t dictSize;\n    printf(\"loading dictionary %s \\n\", dictFileName);\n    void* const dictBuffer = mallocAndLoadFile_orDie(dictFileName, &dictSize);\n    ZSTD_DDict* const ddict = ZSTD_createDDict(dictBuffer, dictSize);\n    CHECK(ddict != NULL, \"ZSTD_createDDict() failed!\");\n    free(dictBuffer);\n    return ddict;\n}\n\nstatic void decompress(const char* fname, const ZSTD_DDict* ddict)\n{\n    size_t cSize;\n    void* const cBuff = mallocAndLoadFile_orDie(fname, &cSize);\n    /* Read the content size from the frame header. For simplicity we require\n     * that it is always present. By default, zstd will write the content size\n     * in the header when it is known. If you can't guarantee that the frame\n     * content size is always written into the header, either use streaming\n     * decompression, or ZSTD_decompressBound().\n     */\n    unsigned long long const rSize = ZSTD_getFrameContentSize(cBuff, cSize);\n    CHECK(rSize != ZSTD_CONTENTSIZE_ERROR, \"%s: not compressed by zstd!\", fname);\n    CHECK(rSize != ZSTD_CONTENTSIZE_UNKNOWN, \"%s: original size unknown!\", fname);\n    void* const rBuff = malloc_orDie((size_t)rSize);\n\n    /* Check that the dictionary ID matches.\n     * If a non-zstd dictionary is used, then both will be zero.\n     * By default zstd always writes the dictionary ID into the frame.\n     * Zstd will check if there is a dictionary ID mismatch as well.\n     */\n    unsigned const expectedDictID = ZSTD_getDictID_fromDDict(ddict);\n    unsigned const actualDictID = ZSTD_getDictID_fromFrame(cBuff, cSize);\n    CHECK(actualDictID == expectedDictID,\n          \"DictID mismatch: expected %u got %u\",\n          expectedDictID,\n          actualDictID);\n\n    /* Decompress using the dictionary.\n     * If you need to control the decompression parameters, then use the\n     * advanced API: ZSTD_DCtx_setParameter(), ZSTD_DCtx_refDDict(), and\n     * ZSTD_decompressDCtx().\n     */\n    ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n    CHECK(dctx != NULL, \"ZSTD_createDCtx() failed!\");\n    size_t const dSize = ZSTD_decompress_usingDDict(dctx, rBuff, rSize, cBuff, cSize, ddict);\n    CHECK_ZSTD(dSize);\n    /* When zstd knows the content size, it will error if it doesn't match. */\n    CHECK(dSize == rSize, \"Impossible because zstd will check this condition!\");\n\n    /* success */\n    printf(\"%25s : %6u -> %7u \\n\", fname, (unsigned)cSize, (unsigned)rSize);\n\n    ZSTD_freeDCtx(dctx);\n    free(rBuff);\n    free(cBuff);\n}\n\n\nint main(int argc, const char** argv)\n{\n    const char* const exeName = argv[0];\n\n    if (argc<3) {\n        printf(\"wrong arguments\\n\");\n        printf(\"usage:\\n\");\n        printf(\"%s [FILES] dictionary\\n\", exeName);\n        return 1;\n    }\n\n    /* load dictionary only once */\n    const char* const dictName = argv[argc-1];\n    ZSTD_DDict* const dictPtr = createDict_orDie(dictName);\n\n    int u;\n    for (u=1; u<argc-1; u++) decompress(argv[u], dictPtr);\n\n    ZSTD_freeDDict(dictPtr);\n    printf(\"All %u files correctly decoded (in memory) \\n\", argc-2);\n    return 0;\n}\n"
  },
  {
    "path": "examples/multiple_simple_compression.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include <stdio.h>     // printf\n#include <stdlib.h>    // free\n#include <string.h>    // memcpy, strlen\n#include <zstd.h>      // presumes zstd library is installed\n#include \"common.h\"    // Helper functions, CHECK(), and CHECK_ZSTD()\n\ntypedef struct {\n    void* fBuffer;\n    void* cBuffer;\n    size_t fBufferSize;\n    size_t cBufferSize;\n    ZSTD_CCtx* cctx;\n} resources;\n\n/*\n * allocate memory for buffers big enough to compress all files\n * as well as memory for output file name (ofn)\n */\nstatic resources createResources_orDie(int argc, const char** argv, char **ofn, size_t* ofnBufferLen)\n{\n    size_t maxFilenameLength=0;\n    size_t maxFileSize = 0;\n\n    int argNb;\n    for (argNb = 1; argNb < argc; argNb++) {\n      const char* const filename = argv[argNb];\n      size_t const filenameLength = strlen(filename);\n      size_t const fileSize = fsize_orDie(filename);\n\n      if (filenameLength > maxFilenameLength) maxFilenameLength = filenameLength;\n      if (fileSize > maxFileSize) maxFileSize = fileSize;\n    }\n\n    resources ress;\n    ress.fBufferSize = maxFileSize;\n    ress.cBufferSize = ZSTD_compressBound(maxFileSize);\n\n    *ofnBufferLen = maxFilenameLength + 5;\n    *ofn = (char*)malloc_orDie(*ofnBufferLen);\n    ress.fBuffer = malloc_orDie(ress.fBufferSize);\n    ress.cBuffer = malloc_orDie(ress.cBufferSize);\n    ress.cctx = ZSTD_createCCtx();\n    CHECK(ress.cctx != NULL, \"ZSTD_createCCtx() failed!\");\n    return ress;\n}\n\nstatic void freeResources(resources ress, char *outFilename)\n{\n    free(ress.fBuffer);\n    free(ress.cBuffer);\n    ZSTD_freeCCtx(ress.cctx);   /* never fails */\n    free(outFilename);\n}\n\n/* compress with pre-allocated context (ZSTD_CCtx) and input/output buffers*/\nstatic void compressFile_orDie(resources ress, const char* fname, const char* oname)\n{\n    size_t fSize = loadFile_orDie(fname, ress.fBuffer, ress.fBufferSize);\n\n    /* Compress using the context.\n     * If you need more control over parameters, use the advanced API:\n     * ZSTD_CCtx_setParameter(), and ZSTD_compress2().\n     */\n    size_t const cSize = ZSTD_compressCCtx(ress.cctx, ress.cBuffer, ress.cBufferSize, ress.fBuffer, fSize, 1);\n    CHECK_ZSTD(cSize);\n\n    saveFile_orDie(oname, ress.cBuffer, cSize);\n\n    /* success */\n    printf(\"%25s : %6u -> %7u - %s \\n\", fname, (unsigned)fSize, (unsigned)cSize, oname);\n}\n\nint main(int argc, const char** argv)\n{\n    const char* const exeName = argv[0];\n\n    if (argc<2) {\n        printf(\"wrong arguments\\n\");\n        printf(\"usage:\\n\");\n        printf(\"%s FILE(s)\\n\", exeName);\n        return 1;\n    }\n\n    /* memory allocation for outFilename and resources */\n    char* outFilename;\n    size_t outFilenameBufferLen;\n    resources const ress = createResources_orDie(argc, argv, &outFilename, &outFilenameBufferLen);\n\n    /* compress files with shared context, input and output buffers */\n    int argNb;\n    for (argNb = 1; argNb < argc; argNb++) {\n        const char* const inFilename = argv[argNb];\n        size_t const inFilenameLen = strlen(inFilename);\n        CHECK(inFilenameLen + 5 <= outFilenameBufferLen, \"File name too long!\");\n        memcpy(outFilename, inFilename, inFilenameLen);\n        memcpy(outFilename+inFilenameLen, \".zst\", 5);\n        compressFile_orDie(ress, inFilename, outFilename);\n    }\n\n    /* free memory */\n    freeResources(ress,outFilename);\n\n    printf(\"compressed %i files \\n\", argc-1);\n\n    return 0;\n}\n"
  },
  {
    "path": "examples/multiple_streaming_compression.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/* The objective of this example is to show of to compress multiple successive files\n*  while preserving memory management.\n*  All structures and buffers will be created only once,\n*  and shared across all compression operations */\n\n#include <stdio.h>     // printf\n#include <stdlib.h>    // free\n#include <string.h>    // memset, strcat\n#include <zstd.h>      // presumes zstd library is installed\n#include \"common.h\"    // Helper functions, CHECK(), and CHECK_ZSTD()\n\ntypedef struct {\n    void* buffIn;\n    void* buffOut;\n    size_t buffInSize;\n    size_t buffOutSize;\n    ZSTD_CCtx* cctx;\n} resources;\n\nstatic resources createResources_orDie(int cLevel)\n{\n    resources ress;\n    ress.buffInSize = ZSTD_CStreamInSize();   /* can always read one full block */\n    ress.buffOutSize= ZSTD_CStreamOutSize();  /* can always flush a full block */\n    ress.buffIn = malloc_orDie(ress.buffInSize);\n    ress.buffOut= malloc_orDie(ress.buffOutSize);\n    ress.cctx = ZSTD_createCCtx();\n    CHECK(ress.cctx != NULL, \"ZSTD_createCCtx() failed!\");\n\n    /* Set any compression parameters you want here.\n     * They will persist for every compression operation.\n     * Here we set the compression level, and enable the checksum.\n     */\n    CHECK_ZSTD( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_compressionLevel, cLevel) );\n    CHECK_ZSTD( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_checksumFlag, 1) );\n    return ress;\n}\n\nstatic void freeResources(resources ress)\n{\n    ZSTD_freeCCtx(ress.cctx);\n    free(ress.buffIn);\n    free(ress.buffOut);\n}\n\nstatic void compressFile_orDie(resources ress, const char* fname, const char* outName)\n{\n    // Open the input and output files.\n    FILE* const fin  = fopen_orDie(fname, \"rb\");\n    FILE* const fout = fopen_orDie(outName, \"wb\");\n\n    /* Reset the context to a clean state to start a new compression operation.\n     * The parameters are sticky, so we keep the compression level and extra\n     * parameters that we set in createResources_orDie().\n     */\n    CHECK_ZSTD( ZSTD_CCtx_reset(ress.cctx, ZSTD_reset_session_only) );\n\n    size_t const toRead = ress.buffInSize;\n    size_t read;\n    while ( (read = fread_orDie(ress.buffIn, toRead, fin)) ) {\n        /* This loop is the same as streaming_compression.c.\n         * See that file for detailed comments.\n         */\n        int const lastChunk = (read < toRead);\n        ZSTD_EndDirective const mode = lastChunk ? ZSTD_e_end : ZSTD_e_continue;\n\n        ZSTD_inBuffer input = { ress.buffIn, read, 0 };\n        int finished;\n        do {\n            ZSTD_outBuffer output = { ress.buffOut, ress.buffOutSize, 0 };\n            size_t const remaining = ZSTD_compressStream2(ress.cctx, &output, &input, mode);\n            CHECK_ZSTD(remaining);\n            fwrite_orDie(ress.buffOut, output.pos, fout);\n            finished = lastChunk ? (remaining == 0) : (input.pos == input.size);\n        } while (!finished);\n        CHECK(input.pos == input.size,\n              \"Impossible: zstd only returns 0 when the input is completely consumed!\");\n    }\n\n    fclose_orDie(fout);\n    fclose_orDie(fin);\n}\n\nint main(int argc, const char** argv)\n{\n    const char* const exeName = argv[0];\n\n    if (argc<2) {\n        printf(\"wrong arguments\\n\");\n        printf(\"usage:\\n\");\n        printf(\"%s FILE(s)\\n\", exeName);\n        return 1;\n    }\n\n    int const cLevel = 7;\n    resources const ress = createResources_orDie(cLevel);\n    void* ofnBuffer = NULL;\n    size_t ofnbSize = 0;\n\n    int argNb;\n    for (argNb = 1; argNb < argc; argNb++) {\n        const char* const ifn = argv[argNb];\n        size_t const ifnSize = strlen(ifn);\n        size_t const ofnSize = ifnSize + 5;\n        if (ofnbSize <= ofnSize) {\n            ofnbSize = ofnSize + 16;\n            free(ofnBuffer);\n            ofnBuffer = malloc_orDie(ofnbSize);\n        }\n        memset(ofnBuffer, 0, ofnSize);\n        strcat(ofnBuffer, ifn);\n        strcat(ofnBuffer, \".zst\");\n        compressFile_orDie(ress, ifn, ofnBuffer);\n    }\n\n    freeResources(ress);\n    free(ofnBuffer);\n\n    printf(\"compressed %i files \\n\", argc-1);\n\n    return 0;\n}\n"
  },
  {
    "path": "examples/simple_compression.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include <stdio.h>     // printf\n#include <stdlib.h>    // free\n#include <string.h>    // strlen, strcat, memset\n#include <zstd.h>      // presumes zstd library is installed\n#include \"common.h\"    // Helper functions, CHECK(), and CHECK_ZSTD()\n\nstatic void compress_orDie(const char* fname, const char* oname)\n{\n    size_t fSize;\n    void* const fBuff = mallocAndLoadFile_orDie(fname, &fSize);\n    size_t const cBuffSize = ZSTD_compressBound(fSize);\n    void* const cBuff = malloc_orDie(cBuffSize);\n\n    /* Compress.\n     * If you are doing many compressions, you may want to reuse the context.\n     * See the multiple_simple_compression.c example.\n     */\n    size_t const cSize = ZSTD_compress(cBuff, cBuffSize, fBuff, fSize, 1);\n    CHECK_ZSTD(cSize);\n\n    saveFile_orDie(oname, cBuff, cSize);\n\n    /* success */\n    printf(\"%25s : %6u -> %7u - %s \\n\", fname, (unsigned)fSize, (unsigned)cSize, oname);\n\n    free(fBuff);\n    free(cBuff);\n}\n\nstatic char* createOutFilename_orDie(const char* filename)\n{\n    size_t const inL = strlen(filename);\n    size_t const outL = inL + 5;\n    void* const outSpace = malloc_orDie(outL);\n    memset(outSpace, 0, outL);\n    strcat(outSpace, filename);\n    strcat(outSpace, \".zst\");\n    return (char*)outSpace;\n}\n\nint main(int argc, const char** argv)\n{\n    const char* const exeName = argv[0];\n\n    if (argc!=2) {\n        printf(\"wrong arguments\\n\");\n        printf(\"usage:\\n\");\n        printf(\"%s FILE\\n\", exeName);\n        return 1;\n    }\n\n    const char* const inFilename = argv[1];\n\n    char* const outFilename = createOutFilename_orDie(inFilename);\n    compress_orDie(inFilename, outFilename);\n    free(outFilename);\n    return 0;\n}\n"
  },
  {
    "path": "examples/simple_decompression.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include <stdio.h>     // printf\n#include <stdlib.h>    // free\n#include <zstd.h>      // presumes zstd library is installed\n#include \"common.h\"    // Helper functions, CHECK(), and CHECK_ZSTD()\n\nstatic void decompress(const char* fname)\n{\n    size_t cSize;\n    void* const cBuff = mallocAndLoadFile_orDie(fname, &cSize);\n    /* Read the content size from the frame header. For simplicity we require\n     * that it is always present. By default, zstd will write the content size\n     * in the header when it is known. If you can't guarantee that the frame\n     * content size is always written into the header, either use streaming\n     * decompression, or ZSTD_decompressBound().\n     */\n    unsigned long long const rSize = ZSTD_getFrameContentSize(cBuff, cSize);\n    CHECK(rSize != ZSTD_CONTENTSIZE_ERROR, \"%s: not compressed by zstd!\", fname);\n    CHECK(rSize != ZSTD_CONTENTSIZE_UNKNOWN, \"%s: original size unknown!\", fname);\n\n    void* const rBuff = malloc_orDie((size_t)rSize);\n\n    /* Decompress.\n     * If you are doing many decompressions, you may want to reuse the context\n     * and use ZSTD_decompressDCtx(). If you want to set advanced parameters,\n     * use ZSTD_DCtx_setParameter().\n     */\n    size_t const dSize = ZSTD_decompress(rBuff, rSize, cBuff, cSize);\n    CHECK_ZSTD(dSize);\n    /* When zstd knows the content size, it will error if it doesn't match. */\n    CHECK(dSize == rSize, \"Impossible because zstd will check this condition!\");\n\n    /* success */\n    printf(\"%25s : %6u -> %7u \\n\", fname, (unsigned)cSize, (unsigned)rSize);\n\n    free(rBuff);\n    free(cBuff);\n}\n\nint main(int argc, const char** argv)\n{\n    const char* const exeName = argv[0];\n\n    if (argc!=2) {\n        printf(\"wrong arguments\\n\");\n        printf(\"usage:\\n\");\n        printf(\"%s FILE\\n\", exeName);\n        return 1;\n    }\n\n    decompress(argv[1]);\n\n    printf(\"%s correctly decoded (in memory). \\n\", argv[1]);\n\n    return 0;\n}\n"
  },
  {
    "path": "examples/streaming_compression.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n#include <stdio.h>     // printf\n#include <stdlib.h>    // free\n#include <string.h>    // memset, strcat, strlen\n#include <zstd.h>      // presumes zstd library is installed\n#include \"common.h\"    // Helper functions, CHECK(), and CHECK_ZSTD()\n\nstatic void compressFile_orDie(const char* fname, const char* outName, int cLevel,\n                               int nbThreads)\n{\n    fprintf (stderr, \"Starting compression of %s with level %d, using %d threads\\n\",\n             fname, cLevel, nbThreads);\n\n    /* Open the input and output files. */\n    FILE* const fin  = fopen_orDie(fname, \"rb\");\n    FILE* const fout = fopen_orDie(outName, \"wb\");\n    /* Create the input and output buffers.\n     * They may be any size, but we recommend using these functions to size them.\n     * Performance will only suffer significantly for very tiny buffers.\n     */\n    size_t const buffInSize = ZSTD_CStreamInSize();\n    void*  const buffIn  = malloc_orDie(buffInSize);\n    size_t const buffOutSize = ZSTD_CStreamOutSize();\n    void*  const buffOut = malloc_orDie(buffOutSize);\n\n    /* Create the context. */\n    ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n    CHECK(cctx != NULL, \"ZSTD_createCCtx() failed!\");\n\n    /* Set any parameters you want.\n     * Here we set the compression level, and enable the checksum.\n     */\n    CHECK_ZSTD( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, cLevel) );\n    CHECK_ZSTD( ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1) );\n    if (nbThreads > 1) {\n        size_t const r = ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, nbThreads);\n        if (ZSTD_isError(r)) {\n            fprintf (stderr, \"Note: the linked libzstd library doesn't support multithreading. \"\n                             \"Reverting to single-thread mode. \\n\");\n        }\n    }\n\n    /* This loop read from the input file, compresses that entire chunk,\n     * and writes all output produced to the output file.\n     */\n    size_t const toRead = buffInSize;\n    for (;;) {\n        size_t read = fread_orDie(buffIn, toRead, fin);\n        /* Select the flush mode.\n         * If the read may not be finished (read == toRead) we use\n         * ZSTD_e_continue. If this is the last chunk, we use ZSTD_e_end.\n         * Zstd optimizes the case where the first flush mode is ZSTD_e_end,\n         * since it knows it is compressing the entire source in one pass.\n         */\n        int const lastChunk = (read < toRead);\n        ZSTD_EndDirective const mode = lastChunk ? ZSTD_e_end : ZSTD_e_continue;\n        /* Set the input buffer to what we just read.\n         * We compress until the input buffer is empty, each time flushing the\n         * output.\n         */\n        ZSTD_inBuffer input = { buffIn, read, 0 };\n        int finished;\n        do {\n            /* Compress into the output buffer and write all of the output to\n             * the file so we can reuse the buffer next iteration.\n             */\n            ZSTD_outBuffer output = { buffOut, buffOutSize, 0 };\n            size_t const remaining = ZSTD_compressStream2(cctx, &output , &input, mode);\n            CHECK_ZSTD(remaining);\n            fwrite_orDie(buffOut, output.pos, fout);\n            /* If we're on the last chunk we're finished when zstd returns 0,\n             * which means its consumed all the input AND finished the frame.\n             * Otherwise, we're finished when we've consumed all the input.\n             */\n            finished = lastChunk ? (remaining == 0) : (input.pos == input.size);\n        } while (!finished);\n        CHECK(input.pos == input.size,\n              \"Impossible: zstd only returns 0 when the input is completely consumed!\");\n\n        if (lastChunk) {\n            break;\n        }\n    }\n\n    ZSTD_freeCCtx(cctx);\n    fclose_orDie(fout);\n    fclose_orDie(fin);\n    free(buffIn);\n    free(buffOut);\n}\n\n\nstatic char* createOutFilename_orDie(const char* filename)\n{\n    size_t const inL = strlen(filename);\n    size_t const outL = inL + 5;\n    void* const outSpace = malloc_orDie(outL);\n    memset(outSpace, 0, outL);\n    strcat(outSpace, filename);\n    strcat(outSpace, \".zst\");\n    return (char*)outSpace;\n}\n\nint main(int argc, const char** argv)\n{\n    const char* const exeName = argv[0];\n\n    if (argc < 2) {\n        printf(\"wrong arguments\\n\");\n        printf(\"usage:\\n\");\n        printf(\"%s FILE [LEVEL] [THREADS]\\n\", exeName);\n        return 1;\n    }\n\n    int cLevel = 1;\n    int nbThreads = 1;\n\n    if (argc >= 3) {\n      cLevel = atoi (argv[2]);\n      CHECK(cLevel != 0, \"can't parse LEVEL!\");\n    }\n\n    if (argc >= 4) {\n      nbThreads = atoi (argv[3]);\n      CHECK(nbThreads != 0, \"can't parse THREADS!\");\n    }\n\n    const char* const inFilename = argv[1];\n\n    char* const outFilename = createOutFilename_orDie(inFilename);\n    compressFile_orDie(inFilename, outFilename, cLevel, nbThreads);\n\n    free(outFilename);   /* not strictly required, since program execution stops there,\n                          * but some static analyzer may complain otherwise */\n    return 0;\n}\n"
  },
  {
    "path": "examples/streaming_compression_thread_pool.c",
    "content": "/*\n * Copyright (c) Martin Liska, SUSE, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n#include <stdio.h>     // printf\n#include <stdlib.h>    // free\n#include <string.h>    // memset, strcat, strlen\n#include <zstd.h>      // presumes zstd library is installed\n#include \"common.h\"    // Helper functions, CHECK(), and CHECK_ZSTD()\n#include <pthread.h>\n\ntypedef struct compress_args\n{\n  const char *fname;\n  char *outName;\n  int cLevel;\n#if defined(ZSTD_STATIC_LINKING_ONLY)\n  ZSTD_threadPool *pool;\n#endif\n} compress_args_t;\n\nstatic void *compressFile_orDie(void *data)\n{\n    const int nbThreads = 16;\n\n    compress_args_t *args = (compress_args_t *)data;\n    fprintf (stderr, \"Starting compression of %s with level %d, using %d threads\\n\", args->fname, args->cLevel, nbThreads);\n    /* Open the input and output files. */\n    FILE* const fin  = fopen_orDie(args->fname, \"rb\");\n    FILE* const fout = fopen_orDie(args->outName, \"wb\");\n    /* Create the input and output buffers.\n     * They may be any size, but we recommend using these functions to size them.\n     * Performance will only suffer significantly for very tiny buffers.\n     */\n    size_t const buffInSize = ZSTD_CStreamInSize();\n    void*  const buffIn  = malloc_orDie(buffInSize);\n    size_t const buffOutSize = ZSTD_CStreamOutSize();\n    void*  const buffOut = malloc_orDie(buffOutSize);\n\n    /* Create the context. */\n    ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n    CHECK(cctx != NULL, \"ZSTD_createCCtx() failed!\");\n\n#if defined(ZSTD_STATIC_LINKING_ONLY)\n    size_t r = ZSTD_CCtx_refThreadPool(cctx, args->pool);\n    CHECK(r == 0, \"ZSTD_CCtx_refThreadPool failed!\");\n#endif\n\n    /* Set any parameters you want.\n     * Here we set the compression level, and enable the checksum.\n     */\n    CHECK_ZSTD( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, args->cLevel) );\n    CHECK_ZSTD( ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1) );\n    ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, nbThreads);\n\n    /* This loop reads from the input file, compresses that entire chunk,\n     * and writes all output produced to the output file.\n     */\n    size_t const toRead = buffInSize;\n    for (;;) {\n        size_t read = fread_orDie(buffIn, toRead, fin);\n        /* Select the flush mode.\n         * If the read may not be finished (read == toRead) we use\n         * ZSTD_e_continue. If this is the last chunk, we use ZSTD_e_end.\n         * Zstd optimizes the case where the first flush mode is ZSTD_e_end,\n         * since it knows it is compressing the entire source in one pass.\n         */\n        int const lastChunk = (read < toRead);\n        ZSTD_EndDirective const mode = lastChunk ? ZSTD_e_end : ZSTD_e_continue;\n        /* Set the input buffer to what we just read.\n         * We compress until the input buffer is empty, each time flushing the\n         * output.\n         */\n        ZSTD_inBuffer input = { buffIn, read, 0 };\n        int finished;\n        do {\n            /* Compress into the output buffer and write all of the output to\n             * the file so we can reuse the buffer next iteration.\n             */\n            ZSTD_outBuffer output = { buffOut, buffOutSize, 0 };\n            size_t const remaining = ZSTD_compressStream2(cctx, &output , &input, mode);\n            CHECK_ZSTD(remaining);\n            fwrite_orDie(buffOut, output.pos, fout);\n            /* If we're on the last chunk we're finished when zstd returns 0,\n             * which means its consumed all the input AND finished the frame.\n             * Otherwise, we're finished when we've consumed all the input.\n             */\n            finished = lastChunk ? (remaining == 0) : (input.pos == input.size);\n        } while (!finished);\n        CHECK(input.pos == input.size,\n              \"Impossible: zstd only returns 0 when the input is completely consumed!\");\n\n        if (lastChunk) {\n            break;\n        }\n    }\n\n    fprintf (stderr, \"Finishing compression of %s\\n\", args->outName);\n\n    ZSTD_freeCCtx(cctx);\n    fclose_orDie(fout);\n    fclose_orDie(fin);\n    free(buffIn);\n    free(buffOut);\n    free(args->outName);\n\n    return NULL;\n}\n\n\nstatic char* createOutFilename_orDie(const char* filename)\n{\n    size_t const inL = strlen(filename);\n    size_t const outL = inL + 5;\n    void* const outSpace = malloc_orDie(outL);\n    memset(outSpace, 0, outL);\n    strcat(outSpace, filename);\n    strcat(outSpace, \".zst\");\n    return (char*)outSpace;\n}\n\nint main(int argc, const char** argv)\n{\n    const char* const exeName = argv[0];\n\n    if (argc<=3) {\n        printf(\"wrong arguments\\n\");\n        printf(\"usage:\\n\");\n        printf(\"%s POOL_SIZE LEVEL FILES\\n\", exeName);\n        return 1;\n    }\n\n    int pool_size = atoi (argv[1]);\n    CHECK(pool_size != 0, \"can't parse POOL_SIZE!\");\n\n    int level = atoi (argv[2]);\n    CHECK(level != 0, \"can't parse LEVEL!\");\n\n    argc -= 3;\n    argv += 3;\n\n#if defined(ZSTD_STATIC_LINKING_ONLY)\n    ZSTD_threadPool *pool = ZSTD_createThreadPool (pool_size);\n    CHECK(pool != NULL, \"ZSTD_createThreadPool() failed!\");\n    fprintf (stderr, \"Using shared thread pool of size %d\\n\", pool_size);\n#else\n    fprintf (stderr, \"All threads use its own thread pool\\n\");\n#endif\n\n    pthread_t *threads = malloc_orDie(argc * sizeof(pthread_t));\n    compress_args_t *args = malloc_orDie(argc * sizeof(compress_args_t));\n\n    for (unsigned i = 0; i < argc; i++)\n    {\n      args[i].fname = argv[i];\n      args[i].outName = createOutFilename_orDie(args[i].fname);\n      args[i].cLevel = level;\n#if defined(ZSTD_STATIC_LINKING_ONLY)\n      args[i].pool = pool;\n#endif\n\n      pthread_create (&threads[i], NULL, compressFile_orDie, &args[i]);\n    }\n\n    for (unsigned i = 0; i < argc; i++)\n      pthread_join (threads[i], NULL);\n\n#if defined(ZSTD_STATIC_LINKING_ONLY)\n    ZSTD_freeThreadPool (pool);\n#endif\n\n    return 0;\n}\n"
  },
  {
    "path": "examples/streaming_decompression.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n#include <stdio.h>     // fprintf\n#include <stdlib.h>    // free\n#include <zstd.h>      // presumes zstd library is installed\n#include \"common.h\"    // Helper functions, CHECK(), and CHECK_ZSTD()\n\nstatic void decompressFile_orDie(const char* fname)\n{\n    FILE* const fin  = fopen_orDie(fname, \"rb\");\n    size_t const buffInSize = ZSTD_DStreamInSize();\n    void*  const buffIn  = malloc_orDie(buffInSize);\n    FILE* const fout = stdout;\n    size_t const buffOutSize = ZSTD_DStreamOutSize();  /* Guarantee to successfully flush at least one complete compressed block in all circumstances. */\n    void*  const buffOut = malloc_orDie(buffOutSize);\n\n    ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n    CHECK(dctx != NULL, \"ZSTD_createDCtx() failed!\");\n\n    /* This loop assumes that the input file is one or more concatenated zstd\n     * streams. This example won't work if there is trailing non-zstd data at\n     * the end, but streaming decompression in general handles this case.\n     * ZSTD_decompressStream() returns 0 exactly when the frame is completed,\n     * and doesn't consume input after the frame.\n     */\n    size_t const toRead = buffInSize;\n    size_t read;\n    size_t lastRet = 0;\n    int isEmpty = 1;\n    while ( (read = fread_orDie(buffIn, toRead, fin)) ) {\n        isEmpty = 0;\n        ZSTD_inBuffer input = { buffIn, read, 0 };\n        /* Given a valid frame, zstd won't consume the last byte of the frame\n         * until it has flushed all of the decompressed data of the frame.\n         * Therefore, instead of checking if the return code is 0, we can\n         * decompress just check if input.pos < input.size.\n         */\n        while (input.pos < input.size) {\n            ZSTD_outBuffer output = { buffOut, buffOutSize, 0 };\n            /* The return code is zero if the frame is complete, but there may\n             * be multiple frames concatenated together. Zstd will automatically\n             * reset the context when a frame is complete. Still, calling\n             * ZSTD_DCtx_reset() can be useful to reset the context to a clean\n             * state, for instance if the last decompression call returned an\n             * error.\n             */\n            size_t const ret = ZSTD_decompressStream(dctx, &output , &input);\n            CHECK_ZSTD(ret);\n            fwrite_orDie(buffOut, output.pos, fout);\n            lastRet = ret;\n        }\n    }\n\n    if (isEmpty) {\n        fprintf(stderr, \"input is empty\\n\");\n        exit(1);\n    }\n\n    if (lastRet != 0) {\n        /* The last return value from ZSTD_decompressStream did not end on a\n         * frame, but we reached the end of the file! We assume this is an\n         * error, and the input was truncated.\n         */\n        fprintf(stderr, \"EOF before end of stream: %zu\\n\", lastRet);\n        exit(1);\n    }\n\n    ZSTD_freeDCtx(dctx);\n    fclose_orDie(fin);\n    fclose_orDie(fout);\n    free(buffIn);\n    free(buffOut);\n}\n\n\nint main(int argc, const char** argv)\n{\n    const char* const exeName = argv[0];\n\n    if (argc!=2) {\n        fprintf(stderr, \"wrong arguments\\n\");\n        fprintf(stderr, \"usage:\\n\");\n        fprintf(stderr, \"%s FILE\\n\", exeName);\n        return 1;\n    }\n\n    const char* const inFilename = argv[1];\n\n    decompressFile_orDie(inFilename);\n    return 0;\n}\n"
  },
  {
    "path": "examples/streaming_memory_usage.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/*===   Tuning parameter   ===*/\n#ifndef MAX_TESTED_LEVEL\n#define MAX_TESTED_LEVEL 12\n#endif\n\n\n/*===   Dependencies   ===*/\n#include <stdio.h>     // printf\n#define ZSTD_STATIC_LINKING_ONLY\n#include <zstd.h>      // presumes zstd library is installed\n#include \"common.h\"    // Helper functions, CHECK(), and CHECK_ZSTD()\n\n\n/*===   functions   ===*/\n\n/*! readU32FromChar() :\n    @return : unsigned integer value read from input in `char` format\n    allows and interprets K, KB, KiB, M, MB and MiB suffix.\n    Will also modify `*stringPtr`, advancing it to position where it stopped reading.\n    Note : function result can overflow if digit string > MAX_UINT */\nstatic unsigned readU32FromChar(const char** stringPtr)\n{\n    unsigned result = 0;\n    while ((**stringPtr >='0') && (**stringPtr <='9'))\n        result *= 10, result += **stringPtr - '0', (*stringPtr)++ ;\n    if ((**stringPtr=='K') || (**stringPtr=='M')) {\n        result <<= 10;\n        if (**stringPtr=='M') result <<= 10;\n        (*stringPtr)++ ;\n        if (**stringPtr=='i') (*stringPtr)++;\n        if (**stringPtr=='B') (*stringPtr)++;\n    }\n    return result;\n}\n\n\nint main(int argc, char const *argv[]) {\n\n    printf(\"\\n Zstandard (v%s) memory usage for streaming : \\n\\n\", ZSTD_versionString());\n\n    unsigned wLog = 0;\n    if (argc > 1) {\n        const char* valStr = argv[1];\n        wLog = readU32FromChar(&valStr);\n    }\n\n    int compressionLevel;\n    for (compressionLevel = 1; compressionLevel <= MAX_TESTED_LEVEL; compressionLevel++) {\n#define INPUT_SIZE 5\n#define COMPRESSED_SIZE 128\n        char const dataToCompress[INPUT_SIZE] = \"abcde\";\n        char compressedData[COMPRESSED_SIZE];\n        char decompressedData[INPUT_SIZE];\n        /* the ZSTD_CCtx_params structure is a way to save parameters and use\n         * them across multiple contexts. We use them here so we can call the\n         * function ZSTD_estimateCStreamSize_usingCCtxParams().\n         */\n        ZSTD_CCtx_params* const cctxParams = ZSTD_createCCtxParams();\n        CHECK(cctxParams != NULL, \"ZSTD_createCCtxParams() failed!\");\n\n        /* Set the compression level. */\n        CHECK_ZSTD( ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_compressionLevel, compressionLevel) );\n        /* Set the window log.\n         * The value 0 means use the default window log, which is equivalent to\n         * not setting it.\n         */\n        CHECK_ZSTD( ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_windowLog, wLog) );\n\n        /* Force the compressor to allocate the maximum memory size for a given\n         * level by not providing the pledged source size, or calling\n         * ZSTD_compressStream2() with ZSTD_e_end.\n         */\n        ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        CHECK(cctx != NULL, \"ZSTD_createCCtx() failed!\");\n        CHECK_ZSTD( ZSTD_CCtx_setParametersUsingCCtxParams(cctx, cctxParams) );\n        size_t compressedSize;\n        {\n            ZSTD_inBuffer inBuff = { dataToCompress, sizeof(dataToCompress), 0 };\n            ZSTD_outBuffer outBuff = { compressedData, sizeof(compressedData), 0 };\n            CHECK_ZSTD( ZSTD_compressStream(cctx, &outBuff, &inBuff) );\n            size_t const remaining = ZSTD_endStream(cctx, &outBuff);\n            CHECK_ZSTD(remaining);\n            CHECK(remaining == 0, \"Frame not flushed!\");\n            compressedSize = outBuff.pos;\n        }\n\n        ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n        CHECK(dctx != NULL, \"ZSTD_createDCtx() failed!\");\n        /* Set the maximum allowed window log.\n         * The value 0 means use the default window log, which is equivalent to\n         * not setting it.\n         */\n        CHECK_ZSTD( ZSTD_DCtx_setParameter(dctx, ZSTD_d_windowLogMax, wLog) );\n        /* forces decompressor to use maximum memory size, since the\n         * decompressed size is not stored in the frame header.\n         */\n        {   ZSTD_inBuffer inBuff = { compressedData, compressedSize, 0 };\n            ZSTD_outBuffer outBuff = { decompressedData, sizeof(decompressedData), 0 };\n            size_t const remaining = ZSTD_decompressStream(dctx, &outBuff, &inBuff);\n            CHECK_ZSTD(remaining);\n            CHECK(remaining == 0, \"Frame not complete!\");\n            CHECK(outBuff.pos == sizeof(dataToCompress), \"Bad decompression!\");\n        }\n\n        size_t const cstreamSize = ZSTD_sizeof_CStream(cctx);\n        size_t const cstreamEstimatedSize = ZSTD_estimateCStreamSize_usingCCtxParams(cctxParams);\n        size_t const dstreamSize = ZSTD_sizeof_DStream(dctx);\n        size_t const dstreamEstimatedSize = ZSTD_estimateDStreamSize_fromFrame(compressedData, compressedSize);\n\n        CHECK(cstreamSize <= cstreamEstimatedSize, \"Compression mem (%u) > estimated (%u)\",\n                (unsigned)cstreamSize, (unsigned)cstreamEstimatedSize);\n        CHECK(dstreamSize <= dstreamEstimatedSize, \"Decompression mem (%u) > estimated (%u)\",\n                (unsigned)dstreamSize, (unsigned)dstreamEstimatedSize);\n\n        printf(\"Level %2i : Compression Mem = %5u KB (estimated : %5u KB) ; Decompression Mem = %4u KB (estimated : %5u KB)\\n\",\n                compressionLevel,\n                (unsigned)(cstreamSize>>10), (unsigned)(cstreamEstimatedSize>>10),\n                (unsigned)(dstreamSize>>10), (unsigned)(dstreamEstimatedSize>>10));\n\n        ZSTD_freeDCtx(dctx);\n        ZSTD_freeCCtx(cctx);\n        ZSTD_freeCCtxParams(cctxParams);\n        if (wLog) break;  /* single test */\n    }\n    return 0;\n}\n"
  },
  {
    "path": "lib/.gitignore",
    "content": "# make install artefact\nlibzstd.pc\nlibzstd-nomt\n"
  },
  {
    "path": "lib/BUCK",
    "content": "cxx_library(\n    name='zstd',\n    header_namespace='',\n    exported_headers=['zstd.h'],\n    visibility=['PUBLIC'],\n    deps=[\n        ':common',\n        ':compress',\n        ':decompress',\n        ':deprecated',\n    ],\n)\n\ncxx_library(\n    name='compress',\n    header_namespace='',\n    visibility=['PUBLIC'],\n    exported_headers=subdir_glob([\n        ('compress', 'zstd*.h'),\n    ]),\n    srcs=glob(['compress/zstd*.c', 'compress/hist.c']),\n    deps=[':common'],\n)\n\ncxx_library(\n    name='decompress',\n    header_namespace='',\n    visibility=['PUBLIC'],\n    headers=subdir_glob([\n        ('decompress', '*_impl.h'),\n    ]),\n    srcs=glob(['decompress/zstd*.c']),\n    deps=[\n        ':common',\n        ':legacy',\n    ],\n)\n\ncxx_library(\n    name='deprecated',\n    header_namespace='',\n    visibility=['PUBLIC'],\n    exported_headers=subdir_glob([\n        ('deprecated', '*.h'),\n    ]),\n    srcs=glob(['deprecated/*.c']),\n    deps=[':common'],\n)\n\ncxx_library(\n    name='legacy',\n    header_namespace='',\n    visibility=['PUBLIC'],\n    exported_headers=subdir_glob([\n        ('legacy', '*.h'),\n    ]),\n    srcs=glob(['legacy/*.c']),\n    deps=[':common'],\n    exported_preprocessor_flags=[\n        '-DZSTD_LEGACY_SUPPORT=0',\n    ],\n)\n\ncxx_library(\n    name='zdict',\n    header_namespace='',\n    visibility=['PUBLIC'],\n    exported_headers=['zdict.h'],\n    headers=subdir_glob([\n        ('dictBuilder', 'divsufsort.h'),\n        ('dictBuilder', 'cover.h'),\n    ]),\n    srcs=glob(['dictBuilder/*.c']),\n    deps=[':common'],\n)\n\ncxx_library(\n    name='compiler',\n    header_namespace='',\n    visibility=['PUBLIC'],\n    exported_headers=subdir_glob([\n        ('common', 'compiler.h'),\n    ]),\n)\n\ncxx_library(\n    name='cpu',\n    header_namespace='',\n    visibility=['PUBLIC'],\n    exported_headers=subdir_glob([\n        ('common', 'cpu.h'),\n    ]),\n)\n\ncxx_library(\n    name='bitstream',\n    header_namespace='',\n    visibility=['PUBLIC'],\n    exported_headers=subdir_glob([\n        ('common', 'bitstream.h'),\n    ]),\n)\n\ncxx_library(\n    name='entropy',\n    header_namespace='',\n    visibility=['PUBLIC'],\n    exported_headers=subdir_glob([\n        ('common', 'fse.h'),\n        ('common', 'huf.h'),\n    ]),\n    srcs=[\n        'common/entropy_common.c',\n        'common/fse_decompress.c',\n        'compress/fse_compress.c',\n        'compress/huf_compress.c',\n        'decompress/huf_decompress.c',\n    ],\n    deps=[\n        ':debug',\n        ':bitstream',\n        ':compiler',\n        ':errors',\n        ':mem',\n    ],\n)\n\ncxx_library(\n    name='errors',\n    header_namespace='',\n    visibility=['PUBLIC'],\n    exported_headers=[\n        'zstd_errors.h',\n        'common/error_private.h',\n    ]\n    srcs=['common/error_private.c'],\n)\n\ncxx_library(\n    name='mem',\n    header_namespace='',\n    visibility=['PUBLIC'],\n    exported_headers=subdir_glob([\n        ('common', 'mem.h'),\n    ]),\n)\n\ncxx_library(\n    name='pool',\n    header_namespace='',\n    visibility=['PUBLIC'],\n    exported_headers=subdir_glob([\n        ('common', 'pool.h'),\n    ]),\n    srcs=['common/pool.c'],\n    deps=[\n        ':threading',\n        ':zstd_common',\n    ],\n)\n\ncxx_library(\n    name='threading',\n    header_namespace='',\n    visibility=['PUBLIC'],\n    exported_headers=subdir_glob([\n        ('common', 'threading.h'),\n    ]),\n    srcs=['common/threading.c'],\n    exported_preprocessor_flags=[\n        '-DZSTD_MULTITHREAD',\n    ],\n    exported_linker_flags=[\n        '-pthread',\n    ],\n)\n\ncxx_library(\n    name='xxhash',\n    header_namespace='',\n    visibility=['PUBLIC'],\n    exported_headers=subdir_glob([\n        ('common', 'xxhash.h'),\n    ]),\n    srcs=['common/xxhash.c'],\n    exported_preprocessor_flags=[\n        '-DXXH_NAMESPACE=ZSTD_',\n    ],\n)\n\ncxx_library(\n    name='zstd_common',\n    header_namespace='',\n    visibility=['PUBLIC'],\n    exported_headers=subdir_glob([\n        ('', 'zstd.h'),\n        ('common', 'zstd_internal.h'),\n    ]),\n    srcs=['common/zstd_common.c'],\n    deps=[\n        ':compiler',\n        ':errors',\n        ':mem',\n    ],\n)\n\ncxx_library(\n    name='debug',\n    header_namespace='',\n    visibility=['PUBLIC'],\n    exported_headers=subdir_glob([\n        ('common', 'debug.h'),\n    ]),\n    srcs=['common/debug.c'],\n)\n\ncxx_library(\n    name='common',\n    deps=[\n        ':debug',\n        ':bitstream',\n        ':compiler',\n        ':cpu',\n        ':entropy',\n        ':errors',\n        ':mem',\n        ':pool',\n        ':threading',\n        ':xxhash',\n        ':zstd_common',\n    ]\n)\n"
  },
  {
    "path": "lib/Makefile",
    "content": "# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ################################################################\n\n# default target (when running `make` with no argument)\nlib-release:\n\n# Modules\nZSTD_LIB_COMPRESSION ?= 1\nZSTD_LIB_DECOMPRESSION ?= 1\nZSTD_LIB_DICTBUILDER ?= 1\nZSTD_LIB_DEPRECATED ?= 0\n\n# Input variables for libzstd.mk\nifeq ($(ZSTD_LIB_COMPRESSION), 0)\n  ZSTD_LIB_DICTBUILDER = 0\n  ZSTD_LIB_DEPRECATED = 0\nendif\n\nifeq ($(ZSTD_LIB_DECOMPRESSION), 0)\n  ZSTD_LEGACY_SUPPORT = 0\n  ZSTD_LIB_DEPRECATED = 0\nendif\n\ninclude libzstd.mk\n\nZSTD_FILES := $(ZSTD_COMMON_FILES) $(ZSTD_LEGACY_FILES)\n\nifneq ($(ZSTD_LIB_COMPRESSION), 0)\n  ZSTD_FILES += $(ZSTD_COMPRESS_FILES)\nendif\n\nifneq ($(ZSTD_LIB_DECOMPRESSION), 0)\n  ZSTD_FILES += $(ZSTD_DECOMPRESS_FILES)\nendif\n\nifneq ($(ZSTD_LIB_DEPRECATED), 0)\n  ZSTD_FILES += $(ZSTD_DEPRECATED_FILES)\nendif\n\nifneq ($(ZSTD_LIB_DICTBUILDER), 0)\n  ZSTD_FILES += $(ZSTD_DICTBUILDER_FILES)\nendif\n\nZSTD_LOCAL_SRC := $(notdir $(ZSTD_FILES))\nZSTD_LOCAL_OBJ0 := $(ZSTD_LOCAL_SRC:.c=.o)\nZSTD_LOCAL_OBJ := $(ZSTD_LOCAL_OBJ0:.S=.o)\n\nVERSION := $(ZSTD_VERSION)\n\n# Note: by default, the static library is built single-threaded and dynamic library is built\n# multi-threaded. It is possible to force multi or single threaded builds by appending\n# -mt or -nomt to the build target (like lib-mt for multi-threaded, lib-nomt for single-threaded).\n\n\nCPPFLAGS_DYNLIB  += -DZSTD_MULTITHREAD # dynamic library build defaults to multi-threaded\nLDFLAGS_DYNLIB   += -pthread\nCPPFLAGS_STATICLIB +=                  # static library build defaults to single-threaded\n\n# pkg-config Libs.private points to LDFLAGS_DYNLIB\nPCLIB := $(LDFLAGS_DYNLIB)\n\nifeq ($(findstring GCC,$(CCVER)),GCC)\ndecompress/zstd_decompress_block.o : CFLAGS+=-fno-tree-vectorize\nendif\n\n\n# macOS linker doesn't support -soname, and use different extension\n# see : https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/DynamicLibraryDesignGuidelines.html\nUNAME_TARGET_SYSTEM ?= $(UNAME)\n\nifeq ($(UNAME_TARGET_SYSTEM), Darwin)\n  SHARED_EXT = dylib\n  SHARED_EXT_MAJOR = $(LIBVER_MAJOR).$(SHARED_EXT)\n  SHARED_EXT_VER = $(LIBVER).$(SHARED_EXT)\n  SONAME_FLAGS = -install_name $(LIBDIR)/libzstd.$(SHARED_EXT_MAJOR) -compatibility_version $(LIBVER_MAJOR) -current_version $(LIBVER)\nelse\n  ifeq ($(UNAME_TARGET_SYSTEM), AIX)\n    SONAME_FLAGS =\n  else\n    SONAME_FLAGS = -Wl,-soname=libzstd.$(SHARED_EXT).$(LIBVER_MAJOR)\n  endif\n  SHARED_EXT = so\n  SHARED_EXT_MAJOR = $(SHARED_EXT).$(LIBVER_MAJOR)\n  SHARED_EXT_VER = $(SHARED_EXT).$(LIBVER)\nendif\n\n\n.PHONY: all\nall: lib\n\n\n.PHONY: libzstd.a  # must be run every time\nlibzstd.a: CPPFLAGS += $(CPPFLAGS_STATICLIB)\n\nSET_CACHE_DIRECTORY = \\\n   +$(MAKE) --no-print-directory $@ \\\n    BUILD_DIR=obj/$(HASH_DIR) \\\n    CPPFLAGS=\"$(CPPFLAGS)\" \\\n    CFLAGS=\"$(CFLAGS)\" \\\n    LDFLAGS=\"$(LDFLAGS)\"\n\nifndef BUILD_DIR\n# determine BUILD_DIR from compilation flags\n\nlibzstd.a:\n\t$(SET_CACHE_DIRECTORY)\n\nelse\n# BUILD_DIR is defined\n\nZSTD_STATICLIB_DIR := $(BUILD_DIR)/static\nZSTD_STATICLIB := $(ZSTD_STATICLIB_DIR)/libzstd.a\nZSTD_STATICLIB_OBJ := $(addprefix $(ZSTD_STATICLIB_DIR)/,$(ZSTD_LOCAL_OBJ))\n$(ZSTD_STATICLIB): ARFLAGS = rcs\n$(ZSTD_STATICLIB): | $(ZSTD_STATICLIB_DIR)\n$(ZSTD_STATICLIB): $(ZSTD_STATICLIB_OBJ)\n  # Check for multithread flag at target execution time\n\t$(if $(filter -DZSTD_MULTITHREAD,$(CPPFLAGS)),\\\n    @echo compiling multi-threaded static library $(LIBVER),\\\n    @echo compiling single-threaded static library $(LIBVER))\n\t$(AR) $(ARFLAGS) $@ $^\n\nlibzstd.a: $(ZSTD_STATICLIB)\n\t$(CP) $< $@\n\nendif\n\nifneq (,$(filter Windows%,$(TARGET_SYSTEM)))\n\nLIBZSTD = dll/libzstd.dll\n$(LIBZSTD): $(ZSTD_FILES)\n\t@echo compiling dynamic library $(LIBVER)\n\t$(CC) $(FLAGS) -DZSTD_DLL_EXPORT=1 -Wl,--out-implib,dll/libzstd.dll.a -shared $^ -o $@\n\nelse  # not Windows\n\nLIBZSTD = libzstd.$(SHARED_EXT_VER)\n.PHONY: $(LIBZSTD)  # must be run every time\n$(LIBZSTD): CPPFLAGS += $(CPPFLAGS_DYNLIB)\n$(LIBZSTD): CFLAGS   += -fPIC -fvisibility=hidden\n$(LIBZSTD): LDFLAGS  += -shared $(LDFLAGS_DYNLIB)\n\nifndef BUILD_DIR\n# determine BUILD_DIR from compilation flags\n\n$(LIBZSTD):\n\t$(SET_CACHE_DIRECTORY)\n\nelse\n# BUILD_DIR is defined\n\nZSTD_DYNLIB_DIR := $(BUILD_DIR)/dynamic\nZSTD_DYNLIB := $(ZSTD_DYNLIB_DIR)/$(LIBZSTD)\nZSTD_DYNLIB_OBJ := $(addprefix $(ZSTD_DYNLIB_DIR)/,$(ZSTD_LOCAL_OBJ))\n\n$(ZSTD_DYNLIB): | $(ZSTD_DYNLIB_DIR)\n$(ZSTD_DYNLIB): $(ZSTD_DYNLIB_OBJ)\n# Check for multithread flag at target execution time\n\t$(if $(filter -DZSTD_MULTITHREAD,$(CPPFLAGS)),\\\n    @echo compiling multi-threaded dynamic library $(LIBVER),\\\n    @echo compiling single-threaded dynamic library $(LIBVER))\n\t$(CC) $(FLAGS) $^ $(SONAME_FLAGS) -o $@\n\t@echo creating versioned links\n\t$(LN) -sf $@ libzstd.$(SHARED_EXT_MAJOR)\n\t$(LN) -sf $@ libzstd.$(SHARED_EXT)\n\n$(LIBZSTD): $(ZSTD_DYNLIB)\n\t$(CP) $< $@\n\nendif  # ifndef BUILD_DIR\nendif  # if windows\n\n.PHONY: libzstd\nlibzstd : $(LIBZSTD)\n\n.PHONY: lib\nlib : libzstd.a libzstd\n\n\n# note : do not define lib-mt or lib-release as .PHONY\n# make does not consider implicit pattern rule for .PHONY target\n\n%-mt : CPPFLAGS_DYNLIB  := -DZSTD_MULTITHREAD\n%-mt : CPPFLAGS_STATICLIB := -DZSTD_MULTITHREAD\n%-mt : LDFLAGS_DYNLIB   := -pthread\n%-mt : PCLIB :=\n%-mt : PCMTLIB := $(LDFLAGS_DYNLIB)\n%-mt : %\n\t@echo multi-threaded build completed\n\n%-nomt : CPPFLAGS_DYNLIB  :=\n%-nomt : LDFLAGS_DYNLIB   :=\n%-nomt : CPPFLAGS_STATICLIB :=\n%-nomt : PCLIB :=\n%-nomt : %\n\t@echo single-threaded build completed\n\n%-release : DEBUGFLAGS :=\n%-release : %\n\t@echo release build completed\n\n\n# Generate .h dependencies automatically\n\n# -MMD: compiler generates dependency information as a side-effect of compilation, without system headers\n# -MP: adds phony target for each dependency other than main file.\nDEPFLAGS = -MMD -MP\n\n# ensure that ZSTD_DYNLIB_DIR exists prior to generating %.o\n$(ZSTD_DYNLIB_DIR)/%.o : %.c | $(ZSTD_DYNLIB_DIR)\n\t@echo CC $@\n\t$(COMPILE.c) $(DEPFLAGS) $(OUTPUT_OPTION) $<\n\n$(ZSTD_STATICLIB_DIR)/%.o : %.c | $(ZSTD_STATICLIB_DIR)\n\t@echo CC $@\n\t$(COMPILE.c) $(DEPFLAGS) $(OUTPUT_OPTION) $<\n\n$(ZSTD_DYNLIB_DIR)/%.o : %.S | $(ZSTD_DYNLIB_DIR)\n\t@echo AS $@\n\t$(COMPILE.S) $(OUTPUT_OPTION) $<\n\n$(ZSTD_STATICLIB_DIR)/%.o : %.S | $(ZSTD_STATICLIB_DIR)\n\t@echo AS $@\n\t$(COMPILE.S) $(OUTPUT_OPTION) $<\n\nMKDIR ?= mkdir -p\n$(BUILD_DIR) $(ZSTD_DYNLIB_DIR) $(ZSTD_STATICLIB_DIR):\n\t$(MKDIR) $@\n\nDEPFILES := $(ZSTD_DYNLIB_OBJ:.o=.d) $(ZSTD_STATICLIB_OBJ:.o=.d)\n$(DEPFILES):\n\n# The leading '-' means: do not fail is include fails (ex: directory does not exist yet)\n-include $(wildcard $(DEPFILES))\n\n\n# Special case : build library in single-thread mode _and_ without zstdmt_compress.c\n# Note : we still need threading.c and pool.c for the dictionary builder,\n# but they will correctly behave single-threaded.\nZSTDMT_FILES = zstdmt_compress.c\nZSTD_NOMT_FILES = $(filter-out $(ZSTDMT_FILES),$(notdir $(ZSTD_FILES)))\nlibzstd-nomt: CFLAGS += -fPIC -fvisibility=hidden\nlibzstd-nomt: LDFLAGS += -shared\nlibzstd-nomt: $(ZSTD_NOMT_FILES)\n\t@echo compiling single-thread dynamic library $(LIBVER)\n\t@echo files : $(ZSTD_NOMT_FILES)\n\t@if echo \"$(ZSTD_NOMT_FILES)\" | tr ' ' '\\n' | $(GREP) -q zstdmt; then \\\n        echo \"Error: Found zstdmt in list.\"; \\\n        exit 1; \\\n    fi\n\t$(CC) $(FLAGS) $^ $(SONAME_FLAGS) -o $@\n\n.PHONY: clean\nclean:\n\t$(RM) -r *.dSYM   # macOS-specific\n\t$(RM) core *.o *.a *.gcda *.$(SHARED_EXT) *.$(SHARED_EXT).* libzstd.pc\n\t$(RM) dll/libzstd.dll dll/libzstd.lib libzstd-nomt*\n\t$(RM) -r obj/*\n\t@echo Cleaning library completed\n\n#-----------------------------------------------------------------------------\n# make install is validated only for below listed environments\n#-----------------------------------------------------------------------------\nifneq (,$(filter $(INSTALL_OS_LIST),$(UNAME)))\n\nlib: libzstd.pc\n\nHAS_EXPLICIT_EXEC_PREFIX := $(if $(or $(EXEC_PREFIX),$(exec_prefix)),1,)\n\nDESTDIR     ?=\n# directory variables : GNU conventions prefer lowercase\n# see https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html\n# support both lower and uppercase (BSD), use uppercase in script\nprefix      ?= /usr/local\nPREFIX      ?= $(prefix)\nexec_prefix ?= $(PREFIX)\nEXEC_PREFIX ?= $(exec_prefix)\nlibdir      ?= $(EXEC_PREFIX)/lib\nLIBDIR      ?= $(libdir)\nincludedir  ?= $(PREFIX)/include\nINCLUDEDIR  ?= $(includedir)\n\nPCINCDIR := $(patsubst $(PREFIX)%,%,$(INCLUDEDIR))\nPCLIBDIR := $(patsubst $(EXEC_PREFIX)%,%,$(LIBDIR))\n\n# If we successfully stripped off a prefix, we'll add a reference to the\n# relevant pc variable.\nPCINCPREFIX := $(if $(findstring $(INCLUDEDIR),$(PCINCDIR)),,$${prefix})\nPCLIBPREFIX := $(if $(findstring $(LIBDIR),$(PCLIBDIR)),,$${exec_prefix})\n\n# If no explicit EXEC_PREFIX was set by the caller, write it out as a reference\n# to PREFIX, rather than as a resolved value.\nPCEXEC_PREFIX := $(if $(HAS_EXPLICIT_EXEC_PREFIX),$(EXEC_PREFIX),$${prefix})\n\n\nifneq ($(MT),)\n  PCLIB :=\n  PCMTLIB := $(LDFLAGS_DYNLIB)\nelse\n  PCLIB := $(LDFLAGS_DYNLIB)\nendif\n\nifneq (,$(filter FreeBSD NetBSD DragonFly,$(UNAME)))\n  PKGCONFIGDIR ?= $(PREFIX)/libdata/pkgconfig\nelse\n  PKGCONFIGDIR ?= $(LIBDIR)/pkgconfig\nendif\n\nifneq (,$(filter SunOS,$(UNAME)))\n  INSTALL ?= ginstall\nelse\n  INSTALL ?= install\nendif\n\nINSTALL_PROGRAM ?= $(INSTALL)\nINSTALL_DATA    ?= $(INSTALL) -m 644\n\n\n# pkg-config library define.\n# For static single-threaded library declare -pthread in Libs.private\n# For static multi-threaded library declare -pthread in Libs and Cflags\n.PHONY: libzstd.pc\nlibzstd.pc: libzstd.pc.in\n\t@echo creating pkgconfig\n\t@sed \\\n\t        -e 's|@PREFIX@|$(PREFIX)|' \\\n\t        -e 's|@EXEC_PREFIX@|$(PCEXEC_PREFIX)|' \\\n\t        -e 's|@INCLUDEDIR@|$(PCINCPREFIX)$(PCINCDIR)|' \\\n\t        -e 's|@LIBDIR@|$(PCLIBPREFIX)$(PCLIBDIR)|' \\\n\t        -e 's|@VERSION@|$(VERSION)|' \\\n\t        -e 's|@LIBS_MT@|$(PCMTLIB)|' \\\n\t        -e 's|@LIBS_PRIVATE@|$(PCLIB)|' \\\n\t        $< >$@\n\n.PHONY: install\ninstall: install-pc install-static install-shared install-includes\n\t@echo zstd static and shared library installed\n\n.PHONY: install-pc\ninstall-pc: libzstd.pc\n\t[ -e $(DESTDIR)$(PKGCONFIGDIR) ] || $(INSTALL) -d -m 755 $(DESTDIR)$(PKGCONFIGDIR)/\n\t$(INSTALL_DATA) libzstd.pc $(DESTDIR)$(PKGCONFIGDIR)/\n\n.PHONY: install-static\ninstall-static:\n\t# only generate libzstd.a if it's not already present\n\t[ -e libzstd.a ] || $(MAKE) libzstd.a-release\n\t[ -e $(DESTDIR)$(LIBDIR) ] || $(INSTALL) -d -m 755 $(DESTDIR)$(LIBDIR)/\n\t@echo Installing static library\n\t$(INSTALL_DATA) libzstd.a $(DESTDIR)$(LIBDIR)\n\n.PHONY: install-shared\ninstall-shared:\n\t# only generate libzstd.so if it's not already present\n\t[ -e $(LIBZSTD) ] || $(MAKE) libzstd-release\n\t[ -e $(DESTDIR)$(LIBDIR) ] || $(INSTALL) -d -m 755 $(DESTDIR)$(LIBDIR)/\n\t@echo Installing shared library\n\t$(INSTALL_PROGRAM) $(LIBZSTD) $(DESTDIR)$(LIBDIR)\n\t$(LN) -sf $(LIBZSTD) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT_MAJOR)\n\t$(LN) -sf $(LIBZSTD) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT)\n\n.PHONY: install-includes\ninstall-includes:\n\t[ -e $(DESTDIR)$(INCLUDEDIR) ] || $(INSTALL) -d -m 755 $(DESTDIR)$(INCLUDEDIR)/\n\t@echo Installing includes\n\t$(INSTALL_DATA) zstd.h $(DESTDIR)$(INCLUDEDIR)\n\t$(INSTALL_DATA) zstd_errors.h $(DESTDIR)$(INCLUDEDIR)\n\t$(INSTALL_DATA) zdict.h $(DESTDIR)$(INCLUDEDIR)\n\n.PHONY: uninstall\nuninstall:\n\t$(RM) $(DESTDIR)$(LIBDIR)/libzstd.a\n\t$(RM) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT)\n\t$(RM) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT_MAJOR)\n\t$(RM) $(DESTDIR)$(LIBDIR)/$(LIBZSTD)\n\t$(RM) $(DESTDIR)$(PKGCONFIGDIR)/libzstd.pc\n\t$(RM) $(DESTDIR)$(INCLUDEDIR)/zstd.h\n\t$(RM) $(DESTDIR)$(INCLUDEDIR)/zstd_errors.h\n\t$(RM) $(DESTDIR)$(INCLUDEDIR)/zdict.h\n\t@echo zstd libraries successfully uninstalled\n\nendif\n"
  },
  {
    "path": "lib/README.md",
    "content": "Zstandard library files\n================================\n\nThe __lib__ directory is split into several sub-directories,\nin order to make it easier to select or exclude features.\n\n\n#### Building\n\nA `Makefile` script is provided, supporting [Makefile conventions](https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html#Makefile-Conventions),\nincluding commands variables, staged install, directory variables and standard targets.\n- `make` : generates both static and dynamic libraries\n- `make install` : install libraries, headers and pkg-config in local system directories\n\n`libzstd` default scope includes compression, decompression, and dictionary builder.\nNote: starting v1.6.0, support for decoding legacy formats is disabled by default.\nSee _modular build_ below to learn how to enable it.\nThe scope can be reduced on demand (see paragraph _modular build_).\n\n#### Multiarch Support\n\nFor multiarch systems (like Debian/Ubuntu), libraries should be installed to architecture-specific directories.\nWhen creating packages for such systems, use the `LIBDIR` variable to specify the correct multiarch path:\n\n```bash\n# For x86_64 systems on Ubuntu/Debian:\nmake install PREFIX=/usr LIBDIR=/usr/lib/x86_64-linux-gnu\n\n# For ARM64 systems on Ubuntu/Debian:\nmake install PREFIX=/usr LIBDIR=/usr/lib/aarch64-linux-gnu\n```\n\nThis will not only install the files in the correct directories, but also generate the correct paths for `pkg-config`.\n\n#### Multithreading support\n\nWhen building with `make`, by default the dynamic library is multithreaded and static library is single-threaded (for compatibility reasons).\n\nEnabling multithreading requires 2 conditions :\n- set build macro `ZSTD_MULTITHREAD` (`-DZSTD_MULTITHREAD` for `gcc`)\n- for POSIX systems : compile with pthread (`-pthread` compilation flag for `gcc`)\n\nFor convenience, we provide a build target to generate multi and single threaded libraries:\n- Force enable multithreading on both dynamic and static libraries by appending `-mt` to the target, e.g. `make lib-mt`.\n  Note that the `.pc` generated on calling `make lib-mt` will already include the require Libs and Cflags.\n- Force disable multithreading on both dynamic and static libraries by appending `-nomt` to the target, e.g. `make lib-nomt`.\n- By default, as mentioned before, dynamic library is multithreaded, and static library is single-threaded, e.g. `make lib`.\n\nWhen linking a POSIX program with a multithreaded version of `libzstd`,\nnote that it's necessary to invoke the `-pthread` flag during link stage.\n\nThe `.pc` generated from `make install` or `make install-pc` always assume a single-threaded static library\nis compiled. To correctly generate a `.pc` for the multi-threaded static library, set `MT=1` as ENV variable.\n\nMultithreading capabilities are exposed\nvia the [advanced API defined in `lib/zstd.h`](https://github.com/facebook/zstd/blob/v1.4.3/lib/zstd.h#L351).\n\n\n#### API\n\nZstandard's stable API is exposed within [lib/zstd.h](zstd.h).\n\n\n#### Advanced API\n\nOptional advanced features are exposed via :\n\n- `lib/zstd_errors.h` : translates `size_t` function results\n                        into a `ZSTD_ErrorCode`, for accurate error handling.\n\n- `ZSTD_STATIC_LINKING_ONLY` : if this macro is defined _before_ including `zstd.h`,\n                          it unlocks access to the experimental API,\n                          exposed in the second part of `zstd.h`.\n                          All definitions in the experimental APIs are unstable,\n                          they may still change in the future, or even be removed.\n                          As a consequence, experimental definitions shall ___never be used with dynamic library___ !\n                          Only static linking is allowed.\n\n\n#### Modular build\n\nIt's possible to compile only a limited set of features within `libzstd`.\nThe file structure is designed to make this selection manually achievable for any build system :\n\n- Directory `lib/common` is always required, for all variants.\n\n- Compression source code lies in `lib/compress`\n\n- Decompression source code lies in `lib/decompress`\n\n- It's possible to include only `compress` or only `decompress`, they don't depend on each other.\n\n- `lib/dictBuilder` : makes it possible to generate dictionaries from a set of samples.\n        The API is exposed in `lib/dictBuilder/zdict.h`.\n        This module depends on both `lib/common` and `lib/compress` .\n\n- `lib/legacy` : makes it possible to decompress legacy zstd formats, starting from `v0.1.0`.\n        This module depends on `lib/common` and `lib/decompress`.\n        To enable this feature, define `ZSTD_LEGACY_SUPPORT` during compilation.\n        Specifying a number limits versions supported to that version onward.\n        For example, `ZSTD_LEGACY_SUPPORT=2` means : \"support legacy formats >= v0.2.0\".\n        Conversely, `ZSTD_LEGACY_SUPPORT=0` means \"do __not__ support legacy formats\".\n        By default, this build macro is set as `ZSTD_LEGACY_SUPPORT=0` (disabled).\n        Decoding supported legacy format is a transparent capability triggered within decompression functions.\n        It's also allowed to invoke legacy API directly, exposed in `lib/legacy/zstd_legacy.h`.\n        Each version does also provide its own set of advanced API.\n        For example, advanced API for version `v0.4` is exposed in `lib/legacy/zstd_v04.h` .\n\n- While invoking `make libzstd`, it's possible to define build macros\n        `ZSTD_LIB_COMPRESSION`, `ZSTD_LIB_DECOMPRESSION`, `ZSTD_LIB_DICTBUILDER`,\n        and `ZSTD_LIB_DEPRECATED` as `0` to forgo compilation of the\n        corresponding features. This will also disable compilation of all\n        dependencies (e.g. `ZSTD_LIB_COMPRESSION=0` will also disable\n        dictBuilder).\n\n- There are a number of options that can help minimize the binary size of\n  `libzstd`.\n\n  The first step is to select the components needed (using the above-described\n  `ZSTD_LIB_COMPRESSION` etc.).\n\n  The next step is to set `ZSTD_LIB_MINIFY` to `1` when invoking `make`. This\n  disables various optional components and changes the compilation flags to\n  prioritize space-saving.\n\n  Detailed options: Zstandard's code and build environment is set up by default\n  to optimize above all else for performance. In pursuit of this goal, Zstandard\n  makes significant trade-offs in code size. For example, Zstandard often has\n  more than one implementation of a particular component, with each\n  implementation optimized for different scenarios. For example, the Huffman\n  decoder has complementary implementations that decode the stream one symbol at\n  a time or two symbols at a time. Zstd normally includes both (and dispatches\n  between them at runtime), but by defining `HUF_FORCE_DECOMPRESS_X1` or\n  `HUF_FORCE_DECOMPRESS_X2`, you can force the use of one or the other, avoiding\n  compilation of the other. Similarly, `ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT`\n  and `ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG` force the compilation and use of\n  only one or the other of two decompression implementations. The smallest\n  binary is achieved by using `HUF_FORCE_DECOMPRESS_X1` and\n  `ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT` (implied by `ZSTD_LIB_MINIFY`).\n\n  On the compressor side, Zstd's compression levels map to several internal\n  strategies. In environments where the higher compression levels aren't used,\n  it is possible to exclude all but the fastest strategy with\n  `ZSTD_LIB_EXCLUDE_COMPRESSORS_DFAST_AND_UP=1`. (Note that this will change\n  the behavior of the default compression level.) Or if you want to retain the\n  default compressor as well, you can set\n  `ZSTD_LIB_EXCLUDE_COMPRESSORS_GREEDY_AND_UP=1`, at the cost of an additional\n  ~20KB or so.\n\n  For squeezing the last ounce of size out, you can also define\n  `ZSTD_NO_INLINE`, which disables inlining, and `ZSTD_STRIP_ERROR_STRINGS`,\n  which removes the error messages that are otherwise returned by\n  `ZSTD_getErrorName` (implied by `ZSTD_LIB_MINIFY`).\n\n  Finally, when integrating into your application, make sure you're doing link-\n  time optimization and unused symbol garbage collection (via some combination of,\n  e.g., `-flto`, `-ffat-lto-objects`, `-fuse-linker-plugin`,\n  `-ffunction-sections`, `-fdata-sections`, `-fmerge-all-constants`,\n  `-Wl,--gc-sections`, `-Wl,-z,norelro`, and an archiver that understands\n  the compiler's intermediate representation, e.g., `AR=gcc-ar`). Consult your\n  compiler's documentation.\n\n- While invoking `make libzstd`, the build macro `ZSTD_LEGACY_MULTITHREADED_API=1`\n  will expose the deprecated `ZSTDMT` API exposed by `zstdmt_compress.h` in\n  the shared library, which is now hidden by default.\n\n- The build macro `STATIC_BMI2` can be set to 1 to force usage of `bmi2` instructions.\n  It is generally not necessary to set this build macro,\n  because `STATIC_BMI2` will be automatically set to 1\n  on detecting the presence of the corresponding instruction set in the compilation target.\n  It's nonetheless available as an optional manual toggle for better control,\n  and can also be used to forcefully disable `bmi2` instructions by setting it to 0.\n\n- The build macro `DYNAMIC_BMI2` can be set to 1 or 0 in order to generate binaries\n  which can detect at runtime the presence of BMI2 instructions, and use them only if present.\n  These instructions contribute to better performance, notably on the decoder side.\n  By default, this feature is automatically enabled on detecting\n  the right instruction set (x64) and compiler (clang or gcc >= 5).\n  It's obviously disabled for different cpus,\n  or when BMI2 instruction set is _required_ by the compiler command line\n  (in this case, only the BMI2 code path is generated).\n  Setting this macro will either force to generate the BMI2 dispatcher (1)\n  or prevent it (0). It overrides automatic detection.\n\n- The build macro `ZSTD_NO_UNUSED_FUNCTIONS` can be defined to hide the definitions of functions\n  that zstd does not use. Not all unused functions are hidden, but they can be if needed.\n  Currently, this macro will hide function definitions in FSE and HUF that use an excessive\n  amount of stack space.\n\n- The build macro `ZSTD_NO_INTRINSICS` can be defined to disable all explicit intrinsics.\n  Compiler builtins are still used.\n\n- The build macro `ZSTD_DECODER_INTERNAL_BUFFER` can be set to control\n  the amount of extra memory used during decompression to store literals.\n  This defaults to 64kB.  Reducing this value reduces the memory footprint of\n  `ZSTD_DCtx` decompression contexts,\n  but might also result in a small decompression speed cost.\n\n- The C compiler macros `ZSTDLIB_VISIBLE`, `ZSTDERRORLIB_VISIBLE` and `ZDICTLIB_VISIBLE`\n  can be overridden to control the visibility of zstd's API. Additionally,\n  `ZSTDLIB_STATIC_API` and `ZDICTLIB_STATIC_API` can be overridden to control the visibility\n  of zstd's static API. Specifically, it can be set to `ZSTDLIB_HIDDEN` to hide the symbols\n  from the shared library. These macros default to `ZSTDLIB_VISIBILITY`,\n  `ZSTDERRORLIB_VSIBILITY`, and `ZDICTLIB_VISIBILITY` if unset, for backwards compatibility\n  with the old macro names.\n\n- The C compiler macro `HUF_DISABLE_FAST_DECODE` disables the newer Huffman fast C\n  and assembly decoding loops. You may want to use this macro if these loops are\n  slower on your platform.\n\n- The macro `ZDICT_QSORT` can enforce selection of a specific sorting variant,\n  which is useful when autodetection fails, for example with older versions of `musl`.\n  For this scenario, it can be set as `ZDICT_QSORT=ZDICT_QSORT_C90`.\n  Other selectable suffixes are `_GNU`, `_APPLE`, `_MSVC` and `_C11`.\n\n#### Windows : using MinGW+MSYS to create DLL\n\nDLL can be created using MinGW+MSYS with the `make libzstd` command.\nThis command creates `dll\\libzstd.dll` and the import library `dll\\libzstd.lib`.\nThe import library is only required with Visual C++.\nThe header file `zstd.h` and the dynamic library `dll\\libzstd.dll` are required to\ncompile a project using gcc/MinGW.\nThe dynamic library has to be added to linking options.\nIt means that if a project that uses ZSTD consists of a single `test-dll.c`\nfile it should be linked with `dll\\libzstd.dll`. For example:\n```\n    gcc $(CFLAGS) -Iinclude/ test-dll.c -o test-dll dll\\libzstd.dll\n```\nThe compiled executable will require ZSTD DLL which is available at `dll\\libzstd.dll`.\n\n\n#### Advanced Build options\n\nThe build system requires a hash function in order to\nseparate object files created with different compilation flags.\nBy default, it tries to use `md5sum` or equivalent.\nThe hash function can be manually switched by setting the `HASH` variable.\nFor example : `make HASH=xxhsum`\nThe hash function needs to generate at least 64-bit using hexadecimal format.\nWhen no hash function is found,\nthe Makefile just generates all object files into the same default directory,\nirrespective of compilation flags.\nThis functionality only matters if `libzstd` is compiled multiple times\nwith different build flags.\n\nThe build directory, where object files are stored\ncan also be manually controlled using variable `BUILD_DIR`,\nfor example `make BUILD_DIR=objectDir/v1`.\nIn which case, the hash function doesn't matter.\n\n\n#### Deprecated API\n\nObsolete API on their way out are stored in directory `lib/deprecated`.\nAt this stage, it contains older streaming prototypes, in `lib/deprecated/zbuff.h`.\nThese prototypes will be removed in some future version.\nConsider migrating code towards supported streaming API exposed in `zstd.h`.\n\n\n#### Miscellaneous\n\nThe other files are not source code. There are :\n\n - `BUCK` : support for `buck` build system (https://buckbuild.com/)\n - `Makefile` : `make` script to build and install zstd library (static and dynamic)\n - `README.md` : this file\n - `dll/` : resources directory for Windows compilation\n - `libzstd.pc.in` : script for `pkg-config` (used in `make install`)\n"
  },
  {
    "path": "lib/common/allocations.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* This file provides custom allocation primitives\n */\n\n#define ZSTD_DEPS_NEED_MALLOC\n#include \"zstd_deps.h\"   /* ZSTD_malloc, ZSTD_calloc, ZSTD_free, ZSTD_memset */\n\n#include \"compiler.h\" /* MEM_STATIC */\n#define ZSTD_STATIC_LINKING_ONLY\n#include \"../zstd.h\" /* ZSTD_customMem */\n\n#ifndef ZSTD_ALLOCATIONS_H\n#define ZSTD_ALLOCATIONS_H\n\n/* custom memory allocation functions */\n\nMEM_STATIC void* ZSTD_customMalloc(size_t size, ZSTD_customMem customMem)\n{\n    if (customMem.customAlloc)\n        return customMem.customAlloc(customMem.opaque, size);\n    return ZSTD_malloc(size);\n}\n\nMEM_STATIC void* ZSTD_customCalloc(size_t size, ZSTD_customMem customMem)\n{\n    if (customMem.customAlloc) {\n        /* calloc implemented as malloc+memset */\n        void* const ptr = customMem.customAlloc(customMem.opaque, size);\n\n        if (ptr == NULL) {\n            return NULL;\n        }\n\n        ZSTD_memset(ptr, 0, size);\n        return ptr;\n    }\n    return ZSTD_calloc(1, size);\n}\n\nMEM_STATIC void ZSTD_customFree(void* ptr, ZSTD_customMem customMem)\n{\n    if (ptr!=NULL) {\n        if (customMem.customFree)\n            customMem.customFree(customMem.opaque, ptr);\n        else\n            ZSTD_free(ptr);\n    }\n}\n\n#endif /* ZSTD_ALLOCATIONS_H */\n"
  },
  {
    "path": "lib/common/bits.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_BITS_H\n#define ZSTD_BITS_H\n\n#include \"mem.h\"\n\nMEM_STATIC unsigned ZSTD_countTrailingZeros32_fallback(U32 val)\n{\n    assert(val != 0);\n    {\n        static const U32 DeBruijnBytePos[32] = {0, 1, 28, 2, 29, 14, 24, 3,\n                                                30, 22, 20, 15, 25, 17, 4, 8,\n                                                31, 27, 13, 23, 21, 19, 16, 7,\n                                                26, 12, 18, 6, 11, 5, 10, 9};\n        return DeBruijnBytePos[((U32) ((val & (0-val)) * 0x077CB531U)) >> 27];\n    }\n}\n\nMEM_STATIC unsigned ZSTD_countTrailingZeros32(U32 val)\n{\n    assert(val != 0);\n#if defined(_MSC_VER)\n#  if STATIC_BMI2\n    return (unsigned)_tzcnt_u32(val);\n#  else\n    if (val != 0) {\n        unsigned long r;\n        _BitScanForward(&r, val);\n        return (unsigned)r;\n    } else {\n        __assume(0); /* Should not reach this code path */\n    }\n#  endif\n#elif defined(__GNUC__) && (__GNUC__ >= 4)\n    return (unsigned)__builtin_ctz(val);\n#elif defined(__ICCARM__)\n    return (unsigned)__builtin_ctz(val);\n#else\n    return ZSTD_countTrailingZeros32_fallback(val);\n#endif\n}\n\nMEM_STATIC unsigned ZSTD_countLeadingZeros32_fallback(U32 val)\n{\n    assert(val != 0);\n    {\n        static const U32 DeBruijnClz[32] = {0, 9, 1, 10, 13, 21, 2, 29,\n                                            11, 14, 16, 18, 22, 25, 3, 30,\n                                            8, 12, 20, 28, 15, 17, 24, 7,\n                                            19, 27, 23, 6, 26, 5, 4, 31};\n        val |= val >> 1;\n        val |= val >> 2;\n        val |= val >> 4;\n        val |= val >> 8;\n        val |= val >> 16;\n        return 31 - DeBruijnClz[(val * 0x07C4ACDDU) >> 27];\n    }\n}\n\nMEM_STATIC unsigned ZSTD_countLeadingZeros32(U32 val)\n{\n    assert(val != 0);\n#if defined(_MSC_VER)\n#  if STATIC_BMI2\n    return (unsigned)_lzcnt_u32(val);\n#  else\n    if (val != 0) {\n        unsigned long r;\n        _BitScanReverse(&r, val);\n        return (unsigned)(31 - r);\n    } else {\n        __assume(0); /* Should not reach this code path */\n    }\n#  endif\n#elif defined(__GNUC__) && (__GNUC__ >= 4)\n    return (unsigned)__builtin_clz(val);\n#elif defined(__ICCARM__)\n    return (unsigned)__builtin_clz(val);\n#else\n    return ZSTD_countLeadingZeros32_fallback(val);\n#endif\n}\n\nMEM_STATIC unsigned ZSTD_countTrailingZeros64(U64 val)\n{\n    assert(val != 0);\n#if defined(_MSC_VER) && defined(_WIN64)\n#  if STATIC_BMI2\n    return (unsigned)_tzcnt_u64(val);\n#  else\n    if (val != 0) {\n        unsigned long r;\n        _BitScanForward64(&r, val);\n        return (unsigned)r;\n    } else {\n        __assume(0); /* Should not reach this code path */\n    }\n#  endif\n#elif defined(__GNUC__) && (__GNUC__ >= 4) && defined(__LP64__)\n    return (unsigned)__builtin_ctzll(val);\n#elif defined(__ICCARM__)\n    return (unsigned)__builtin_ctzll(val);\n#else\n    {\n        U32 mostSignificantWord = (U32)(val >> 32);\n        U32 leastSignificantWord = (U32)val;\n        if (leastSignificantWord == 0) {\n            return 32 + ZSTD_countTrailingZeros32(mostSignificantWord);\n        } else {\n            return ZSTD_countTrailingZeros32(leastSignificantWord);\n        }\n    }\n#endif\n}\n\nMEM_STATIC unsigned ZSTD_countLeadingZeros64(U64 val)\n{\n    assert(val != 0);\n#if defined(_MSC_VER) && defined(_WIN64)\n#  if STATIC_BMI2\n    return (unsigned)_lzcnt_u64(val);\n#  else\n    if (val != 0) {\n        unsigned long r;\n        _BitScanReverse64(&r, val);\n        return (unsigned)(63 - r);\n    } else {\n        __assume(0); /* Should not reach this code path */\n    }\n#  endif\n#elif defined(__GNUC__) && (__GNUC__ >= 4)\n    return (unsigned)(__builtin_clzll(val));\n#elif defined(__ICCARM__)\n    return (unsigned)(__builtin_clzll(val));\n#else\n    {\n        U32 mostSignificantWord = (U32)(val >> 32);\n        U32 leastSignificantWord = (U32)val;\n        if (mostSignificantWord == 0) {\n            return 32 + ZSTD_countLeadingZeros32(leastSignificantWord);\n        } else {\n            return ZSTD_countLeadingZeros32(mostSignificantWord);\n        }\n    }\n#endif\n}\n\nMEM_STATIC unsigned ZSTD_NbCommonBytes(size_t val)\n{\n    if (MEM_isLittleEndian()) {\n        if (MEM_64bits()) {\n            return ZSTD_countTrailingZeros64((U64)val) >> 3;\n        } else {\n            return ZSTD_countTrailingZeros32((U32)val) >> 3;\n        }\n    } else {  /* Big Endian CPU */\n        if (MEM_64bits()) {\n            return ZSTD_countLeadingZeros64((U64)val) >> 3;\n        } else {\n            return ZSTD_countLeadingZeros32((U32)val) >> 3;\n        }\n    }\n}\n\nMEM_STATIC unsigned ZSTD_highbit32(U32 val)   /* compress, dictBuilder, decodeCorpus */\n{\n    assert(val != 0);\n    return 31 - ZSTD_countLeadingZeros32(val);\n}\n\n/* ZSTD_rotateRight_*():\n * Rotates a bitfield to the right by \"count\" bits.\n * https://en.wikipedia.org/w/index.php?title=Circular_shift&oldid=991635599#Implementing_circular_shifts\n */\nMEM_STATIC\nU64 ZSTD_rotateRight_U64(U64 const value, U32 count) {\n    assert(count < 64);\n    count &= 0x3F; /* for fickle pattern recognition */\n    return (value >> count) | (U64)(value << ((0U - count) & 0x3F));\n}\n\nMEM_STATIC\nU32 ZSTD_rotateRight_U32(U32 const value, U32 count) {\n    assert(count < 32);\n    count &= 0x1F; /* for fickle pattern recognition */\n    return (value >> count) | (U32)(value << ((0U - count) & 0x1F));\n}\n\nMEM_STATIC\nU16 ZSTD_rotateRight_U16(U16 const value, U32 count) {\n    assert(count < 16);\n    count &= 0x0F; /* for fickle pattern recognition */\n    return (value >> count) | (U16)(value << ((0U - count) & 0x0F));\n}\n\n#endif /* ZSTD_BITS_H */\n"
  },
  {
    "path": "lib/common/bitstream.h",
    "content": "/* ******************************************************************\n * bitstream\n * Part of FSE library\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * You can contact the author at :\n * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n#ifndef BITSTREAM_H_MODULE\n#define BITSTREAM_H_MODULE\n\n/*\n*  This API consists of small unitary functions, which must be inlined for best performance.\n*  Since link-time-optimization is not available for all compilers,\n*  these functions are defined into a .h to be included.\n*/\n\n/*-****************************************\n*  Dependencies\n******************************************/\n#include \"mem.h\"            /* unaligned access routines */\n#include \"compiler.h\"       /* UNLIKELY() */\n#include \"debug.h\"          /* assert(), DEBUGLOG(), RAWLOG() */\n#include \"error_private.h\"  /* error codes and messages */\n#include \"bits.h\"           /* ZSTD_highbit32 */\n\n/*=========================================\n*  Target specific\n=========================================*/\n#ifndef ZSTD_NO_INTRINSICS\n#  if (defined(__BMI__) || defined(__BMI2__)) && defined(__GNUC__)\n#    include <immintrin.h>   /* support for bextr (experimental)/bzhi */\n#  elif defined(__ICCARM__)\n#    include <intrinsics.h>\n#  endif\n#endif\n\n#define STREAM_ACCUMULATOR_MIN_32  25\n#define STREAM_ACCUMULATOR_MIN_64  57\n#define STREAM_ACCUMULATOR_MIN    ((U32)(MEM_32bits() ? STREAM_ACCUMULATOR_MIN_32 : STREAM_ACCUMULATOR_MIN_64))\n\n\n/*-******************************************\n*  bitStream encoding API (write forward)\n********************************************/\ntypedef size_t BitContainerType;\n/* bitStream can mix input from multiple sources.\n * A critical property of these streams is that they encode and decode in **reverse** direction.\n * So the first bit sequence you add will be the last to be read, like a LIFO stack.\n */\ntypedef struct {\n    BitContainerType bitContainer;\n    unsigned bitPos;\n    char*  startPtr;\n    char*  ptr;\n    char*  endPtr;\n} BIT_CStream_t;\n\nMEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* dstBuffer, size_t dstCapacity);\nMEM_STATIC void   BIT_addBits(BIT_CStream_t* bitC, BitContainerType value, unsigned nbBits);\nMEM_STATIC void   BIT_flushBits(BIT_CStream_t* bitC);\nMEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC);\n\n/* Start with initCStream, providing the size of buffer to write into.\n*  bitStream will never write outside of this buffer.\n*  `dstCapacity` must be >= sizeof(bitD->bitContainer), otherwise @return will be an error code.\n*\n*  bits are first added to a local register.\n*  Local register is BitContainerType, 64-bits on 64-bits systems, or 32-bits on 32-bits systems.\n*  Writing data into memory is an explicit operation, performed by the flushBits function.\n*  Hence keep track how many bits are potentially stored into local register to avoid register overflow.\n*  After a flushBits, a maximum of 7 bits might still be stored into local register.\n*\n*  Avoid storing elements of more than 24 bits if you want compatibility with 32-bits bitstream readers.\n*\n*  Last operation is to close the bitStream.\n*  The function returns the final size of CStream in bytes.\n*  If data couldn't fit into `dstBuffer`, it will return a 0 ( == not storable)\n*/\n\n\n/*-********************************************\n*  bitStream decoding API (read backward)\n**********************************************/\ntypedef struct {\n    BitContainerType bitContainer;\n    unsigned bitsConsumed;\n    const char* ptr;\n    const char* start;\n    const char* limitPtr;\n} BIT_DStream_t;\n\ntypedef enum { BIT_DStream_unfinished = 0,  /* fully refilled */\n               BIT_DStream_endOfBuffer = 1, /* still some bits left in bitstream */\n               BIT_DStream_completed = 2,   /* bitstream entirely consumed, bit-exact */\n               BIT_DStream_overflow = 3     /* user requested more bits than present in bitstream */\n    } BIT_DStream_status;  /* result of BIT_reloadDStream() */\n\nMEM_STATIC size_t   BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize);\nFORCE_INLINE_TEMPLATE BitContainerType BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);\nFORCE_INLINE_TEMPLATE BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD);\nMEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);\n\n\n/* Start by invoking BIT_initDStream().\n*  A chunk of the bitStream is then stored into a local register.\n*  Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (BitContainerType).\n*  You can then retrieve bitFields stored into the local register, **in reverse order**.\n*  Local register is explicitly reloaded from memory by the BIT_reloadDStream() method.\n*  A reload guarantee a minimum of ((8*sizeof(bitD->bitContainer))-7) bits when its result is BIT_DStream_unfinished.\n*  Otherwise, it can be less than that, so proceed accordingly.\n*  Checking if DStream has reached its end can be performed with BIT_endOfDStream().\n*/\n\n\n/*-****************************************\n*  unsafe API\n******************************************/\nMEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, BitContainerType value, unsigned nbBits);\n/* faster, but works only if value is \"clean\", meaning all high bits above nbBits are 0 */\n\nMEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC);\n/* unsafe version; does not check buffer overflow */\n\nMEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);\n/* faster, but works only if nbBits >= 1 */\n\n/*=====    Local Constants   =====*/\nstatic const unsigned BIT_mask[] = {\n    0,          1,         3,         7,         0xF,       0x1F,\n    0x3F,       0x7F,      0xFF,      0x1FF,     0x3FF,     0x7FF,\n    0xFFF,      0x1FFF,    0x3FFF,    0x7FFF,    0xFFFF,    0x1FFFF,\n    0x3FFFF,    0x7FFFF,   0xFFFFF,   0x1FFFFF,  0x3FFFFF,  0x7FFFFF,\n    0xFFFFFF,   0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF, 0x1FFFFFFF,\n    0x3FFFFFFF, 0x7FFFFFFF}; /* up to 31 bits */\n#define BIT_MASK_SIZE (sizeof(BIT_mask) / sizeof(BIT_mask[0]))\n\n/*-**************************************************************\n*  bitStream encoding\n****************************************************************/\n/*! BIT_initCStream() :\n *  `dstCapacity` must be > sizeof(size_t)\n *  @return : 0 if success,\n *            otherwise an error code (can be tested using ERR_isError()) */\nMEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC,\n                                  void* startPtr, size_t dstCapacity)\n{\n    bitC->bitContainer = 0;\n    bitC->bitPos = 0;\n    bitC->startPtr = (char*)startPtr;\n    bitC->ptr = bitC->startPtr;\n    bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->bitContainer);\n    if (dstCapacity <= sizeof(bitC->bitContainer)) return ERROR(dstSize_tooSmall);\n    return 0;\n}\n\nFORCE_INLINE_TEMPLATE BitContainerType BIT_getLowerBits(BitContainerType bitContainer, U32 const nbBits)\n{\n#if STATIC_BMI2 && !defined(ZSTD_NO_INTRINSICS)\n#  if (defined(__x86_64__) || defined(_M_X64)) && !defined(__ILP32__)\n    return _bzhi_u64(bitContainer, nbBits);\n#  else\n    DEBUG_STATIC_ASSERT(sizeof(bitContainer) == sizeof(U32));\n    return _bzhi_u32(bitContainer, nbBits);\n#  endif\n#else\n    assert(nbBits < BIT_MASK_SIZE);\n    return bitContainer & BIT_mask[nbBits];\n#endif\n}\n\n/*! BIT_addBits() :\n *  can add up to 31 bits into `bitC`.\n *  Note : does not check for register overflow ! */\nMEM_STATIC void BIT_addBits(BIT_CStream_t* bitC,\n                            BitContainerType value, unsigned nbBits)\n{\n    DEBUG_STATIC_ASSERT(BIT_MASK_SIZE == 32);\n    assert(nbBits < BIT_MASK_SIZE);\n    assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8);\n    bitC->bitContainer |= BIT_getLowerBits(value, nbBits) << bitC->bitPos;\n    bitC->bitPos += nbBits;\n}\n\n/*! BIT_addBitsFast() :\n *  works only if `value` is _clean_,\n *  meaning all high bits above nbBits are 0 */\nMEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC,\n                                BitContainerType value, unsigned nbBits)\n{\n    assert((value>>nbBits) == 0);\n    assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8);\n    bitC->bitContainer |= value << bitC->bitPos;\n    bitC->bitPos += nbBits;\n}\n\n/*! BIT_flushBitsFast() :\n *  assumption : bitContainer has not overflowed\n *  unsafe version; does not check buffer overflow */\nMEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC)\n{\n    size_t const nbBytes = bitC->bitPos >> 3;\n    assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8);\n    assert(bitC->ptr <= bitC->endPtr);\n    MEM_writeLEST(bitC->ptr, bitC->bitContainer);\n    bitC->ptr += nbBytes;\n    bitC->bitPos &= 7;\n    bitC->bitContainer >>= nbBytes*8;\n}\n\n/*! BIT_flushBits() :\n *  assumption : bitContainer has not overflowed\n *  safe version; check for buffer overflow, and prevents it.\n *  note : does not signal buffer overflow.\n *  overflow will be revealed later on using BIT_closeCStream() */\nMEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC)\n{\n    size_t const nbBytes = bitC->bitPos >> 3;\n    assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8);\n    assert(bitC->ptr <= bitC->endPtr);\n    MEM_writeLEST(bitC->ptr, bitC->bitContainer);\n    bitC->ptr += nbBytes;\n    if (bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr;\n    bitC->bitPos &= 7;\n    bitC->bitContainer >>= nbBytes*8;\n}\n\n/*! BIT_closeCStream() :\n *  @return : size of CStream, in bytes,\n *            or 0 if it could not fit into dstBuffer */\nMEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC)\n{\n    BIT_addBitsFast(bitC, 1, 1);   /* endMark */\n    BIT_flushBits(bitC);\n    if (bitC->ptr >= bitC->endPtr) return 0; /* overflow detected */\n    return (size_t)(bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0);\n}\n\n\n/*-********************************************************\n*  bitStream decoding\n**********************************************************/\n/*! BIT_initDStream() :\n *  Initialize a BIT_DStream_t.\n * `bitD` : a pointer to an already allocated BIT_DStream_t structure.\n * `srcSize` must be the *exact* size of the bitStream, in bytes.\n * @return : size of stream (== srcSize), or an errorCode if a problem is detected\n */\nMEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize)\n{\n    if (srcSize < 1) { ZSTD_memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }\n\n    bitD->start = (const char*)srcBuffer;\n    bitD->limitPtr = bitD->start + sizeof(bitD->bitContainer);\n\n    if (srcSize >=  sizeof(bitD->bitContainer)) {  /* normal case */\n        bitD->ptr   = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer);\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];\n          bitD->bitsConsumed = lastByte ? 8 - ZSTD_highbit32(lastByte) : 0;  /* ensures bitsConsumed is always set */\n          if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }\n    } else {\n        bitD->ptr   = bitD->start;\n        bitD->bitContainer = *(const BYTE*)(bitD->start);\n        switch(srcSize)\n        {\n        case 7: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);\n                ZSTD_FALLTHROUGH;\n\n        case 6: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);\n                ZSTD_FALLTHROUGH;\n\n        case 5: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);\n                ZSTD_FALLTHROUGH;\n\n        case 4: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[3]) << 24;\n                ZSTD_FALLTHROUGH;\n\n        case 3: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[2]) << 16;\n                ZSTD_FALLTHROUGH;\n\n        case 2: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[1]) <<  8;\n                ZSTD_FALLTHROUGH;\n\n        default: break;\n        }\n        {   BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];\n            bitD->bitsConsumed = lastByte ? 8 - ZSTD_highbit32(lastByte) : 0;\n            if (lastByte == 0) return ERROR(corruption_detected);  /* endMark not present */\n        }\n        bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8;\n    }\n\n    return srcSize;\n}\n\nFORCE_INLINE_TEMPLATE BitContainerType BIT_getUpperBits(BitContainerType bitContainer, U32 const start)\n{\n    return bitContainer >> start;\n}\n\nFORCE_INLINE_TEMPLATE BitContainerType BIT_getMiddleBits(BitContainerType bitContainer, U32 const start, U32 const nbBits)\n{\n    U32 const regMask = sizeof(bitContainer)*8 - 1;\n    /* if start > regMask, bitstream is corrupted, and result is undefined */\n    assert(nbBits < BIT_MASK_SIZE);\n    /* x86 transform & ((1 << nbBits) - 1) to bzhi instruction, it is better\n     * than accessing memory. When bmi2 instruction is not present, we consider\n     * such cpus old (pre-Haswell, 2013) and their performance is not of that\n     * importance.\n     */\n#if defined(__x86_64__) || defined(_M_X64)\n    return (bitContainer >> (start & regMask)) & ((((U64)1) << nbBits) - 1);\n#else\n    return (bitContainer >> (start & regMask)) & BIT_mask[nbBits];\n#endif\n}\n\n/*! BIT_lookBits() :\n *  Provides next n bits from local register.\n *  local register is not modified.\n *  On 32-bits, maxNbBits==24.\n *  On 64-bits, maxNbBits==56.\n * @return : value extracted */\nFORCE_INLINE_TEMPLATE BitContainerType BIT_lookBits(const BIT_DStream_t*  bitD, U32 nbBits)\n{\n    /* arbitrate between double-shift and shift+mask */\n#if 1\n    /* if bitD->bitsConsumed + nbBits > sizeof(bitD->bitContainer)*8,\n     * bitstream is likely corrupted, and result is undefined */\n    return BIT_getMiddleBits(bitD->bitContainer, (sizeof(bitD->bitContainer)*8) - bitD->bitsConsumed - nbBits, nbBits);\n#else\n    /* this code path is slower on my os-x laptop */\n    U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;\n    return ((bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> 1) >> ((regMask-nbBits) & regMask);\n#endif\n}\n\n/*! BIT_lookBitsFast() :\n *  unsafe version; only works if nbBits >= 1 */\nMEM_STATIC BitContainerType BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits)\n{\n    U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;\n    assert(nbBits >= 1);\n    return (bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> (((regMask+1)-nbBits) & regMask);\n}\n\nFORCE_INLINE_TEMPLATE void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)\n{\n    bitD->bitsConsumed += nbBits;\n}\n\n/*! BIT_readBits() :\n *  Read (consume) next n bits from local register and update.\n *  Pay attention to not read more than nbBits contained into local register.\n * @return : extracted value. */\nFORCE_INLINE_TEMPLATE BitContainerType BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits)\n{\n    BitContainerType const value = BIT_lookBits(bitD, nbBits);\n    BIT_skipBits(bitD, nbBits);\n    return value;\n}\n\n/*! BIT_readBitsFast() :\n *  unsafe version; only works if nbBits >= 1 */\nMEM_STATIC BitContainerType BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits)\n{\n    BitContainerType const value = BIT_lookBitsFast(bitD, nbBits);\n    assert(nbBits >= 1);\n    BIT_skipBits(bitD, nbBits);\n    return value;\n}\n\n/*! BIT_reloadDStream_internal() :\n *  Simple variant of BIT_reloadDStream(), with two conditions:\n *  1. bitstream is valid : bitsConsumed <= sizeof(bitD->bitContainer)*8\n *  2. look window is valid after shifted down : bitD->ptr >= bitD->start\n */\nMEM_STATIC BIT_DStream_status BIT_reloadDStream_internal(BIT_DStream_t* bitD)\n{\n    assert(bitD->bitsConsumed <= sizeof(bitD->bitContainer)*8);\n    bitD->ptr -= bitD->bitsConsumed >> 3;\n    assert(bitD->ptr >= bitD->start);\n    bitD->bitsConsumed &= 7;\n    bitD->bitContainer = MEM_readLEST(bitD->ptr);\n    return BIT_DStream_unfinished;\n}\n\n/*! BIT_reloadDStreamFast() :\n *  Similar to BIT_reloadDStream(), but with two differences:\n *  1. bitsConsumed <= sizeof(bitD->bitContainer)*8 must hold!\n *  2. Returns BIT_DStream_overflow when bitD->ptr < bitD->limitPtr, at this\n *     point you must use BIT_reloadDStream() to reload.\n */\nMEM_STATIC BIT_DStream_status BIT_reloadDStreamFast(BIT_DStream_t* bitD)\n{\n    if (UNLIKELY(bitD->ptr < bitD->limitPtr))\n        return BIT_DStream_overflow;\n    return BIT_reloadDStream_internal(bitD);\n}\n\n/*! BIT_reloadDStream() :\n *  Refill `bitD` from buffer previously set in BIT_initDStream() .\n *  This function is safe, it guarantees it will not never beyond src buffer.\n * @return : status of `BIT_DStream_t` internal register.\n *           when status == BIT_DStream_unfinished, internal register is filled with at least 25 or 57 bits */\nFORCE_INLINE_TEMPLATE BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)\n{\n    /* note : once in overflow mode, a bitstream remains in this mode until it's reset */\n    if (UNLIKELY(bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))) {\n        static const BitContainerType zeroFilled = 0;\n        bitD->ptr = (const char*)&zeroFilled; /* aliasing is allowed for char */\n        /* overflow detected, erroneous scenario or end of stream: no update */\n        return BIT_DStream_overflow;\n    }\n\n    assert(bitD->ptr >= bitD->start);\n\n    if (bitD->ptr >= bitD->limitPtr) {\n        return BIT_reloadDStream_internal(bitD);\n    }\n    if (bitD->ptr == bitD->start) {\n        /* reached end of bitStream => no update */\n        if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;\n        return BIT_DStream_completed;\n    }\n    /* start < ptr < limitPtr => cautious update */\n    {   U32 nbBytes = bitD->bitsConsumed >> 3;\n        BIT_DStream_status result = BIT_DStream_unfinished;\n        if (bitD->ptr - nbBytes < bitD->start) {\n            nbBytes = (U32)(bitD->ptr - bitD->start);  /* ptr > start */\n            result = BIT_DStream_endOfBuffer;\n        }\n        bitD->ptr -= nbBytes;\n        bitD->bitsConsumed -= nbBytes*8;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);   /* reminder : srcSize > sizeof(bitD->bitContainer), otherwise bitD->ptr == bitD->start */\n        return result;\n    }\n}\n\n/*! BIT_endOfDStream() :\n * @return : 1 if DStream has _exactly_ reached its end (all bits consumed).\n */\nMEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)\n{\n    return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));\n}\n\n#endif /* BITSTREAM_H_MODULE */\n"
  },
  {
    "path": "lib/common/compiler.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_COMPILER_H\n#define ZSTD_COMPILER_H\n\n#include <stddef.h>\n\n#include \"portability_macros.h\"\n\n/*-*******************************************************\n*  Compiler specifics\n*********************************************************/\n/* force inlining */\n\n#if !defined(ZSTD_NO_INLINE)\n#if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */\n#  define INLINE_KEYWORD inline\n#else\n#  define INLINE_KEYWORD\n#endif\n\n#if defined(__GNUC__) || defined(__IAR_SYSTEMS_ICC__)\n#  define FORCE_INLINE_ATTR __attribute__((always_inline))\n#elif defined(_MSC_VER)\n#  define FORCE_INLINE_ATTR __forceinline\n#else\n#  define FORCE_INLINE_ATTR\n#endif\n\n#else\n\n#define INLINE_KEYWORD\n#define FORCE_INLINE_ATTR\n\n#endif\n\n/**\n  On MSVC qsort requires that functions passed into it use the __cdecl calling conversion(CC).\n  This explicitly marks such functions as __cdecl so that the code will still compile\n  if a CC other than __cdecl has been made the default.\n*/\n#if  defined(_MSC_VER)\n#  define WIN_CDECL __cdecl\n#else\n#  define WIN_CDECL\n#endif\n\n/* UNUSED_ATTR tells the compiler it is okay if the function is unused. */\n#if defined(__GNUC__) || defined(__IAR_SYSTEMS_ICC__)\n#  define UNUSED_ATTR __attribute__((unused))\n#else\n#  define UNUSED_ATTR\n#endif\n\n/**\n * FORCE_INLINE_TEMPLATE is used to define C \"templates\", which take constant\n * parameters. They must be inlined for the compiler to eliminate the constant\n * branches.\n */\n#define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR UNUSED_ATTR\n/**\n * HINT_INLINE is used to help the compiler generate better code. It is *not*\n * used for \"templates\", so it can be tweaked based on the compilers\n * performance.\n *\n * gcc-4.8 and gcc-4.9 have been shown to benefit from leaving off the\n * always_inline attribute.\n *\n * clang up to 5.0.0 (trunk) benefit tremendously from the always_inline\n * attribute.\n */\n#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 && __GNUC__ < 5\n#  define HINT_INLINE static INLINE_KEYWORD\n#else\n#  define HINT_INLINE FORCE_INLINE_TEMPLATE\n#endif\n\n/* \"soft\" inline :\n * The compiler is free to select if it's a good idea to inline or not.\n * The main objective is to silence compiler warnings\n * when a defined function in included but not used.\n *\n * Note : this macro is prefixed `MEM_` because it used to be provided by `mem.h` unit.\n * Updating the prefix is probably preferable, but requires a fairly large codemod,\n * since this name is used everywhere.\n */\n#ifndef MEM_STATIC  /* already defined in Linux Kernel mem.h */\n#if defined(__GNUC__)\n#  define MEM_STATIC static __inline UNUSED_ATTR\n#elif defined(__IAR_SYSTEMS_ICC__)\n#  define MEM_STATIC static inline UNUSED_ATTR\n#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n#  define MEM_STATIC static inline\n#elif defined(_MSC_VER)\n#  define MEM_STATIC static __inline\n#else\n#  define MEM_STATIC static  /* this version may generate warnings for unused static functions; disable the relevant warning */\n#endif\n#endif\n\n/* force no inlining */\n#ifdef _MSC_VER\n#  define FORCE_NOINLINE static __declspec(noinline)\n#else\n#  if defined(__GNUC__) || defined(__IAR_SYSTEMS_ICC__)\n#    define FORCE_NOINLINE static __attribute__((__noinline__))\n#  else\n#    define FORCE_NOINLINE static\n#  endif\n#endif\n\n\n/* target attribute */\n#if defined(__GNUC__) || defined(__IAR_SYSTEMS_ICC__)\n#  define TARGET_ATTRIBUTE(target) __attribute__((__target__(target)))\n#else\n#  define TARGET_ATTRIBUTE(target)\n#endif\n\n/* Target attribute for BMI2 dynamic dispatch.\n * Enable lzcnt, bmi, and bmi2.\n * We test for bmi1 & bmi2. lzcnt is included in bmi1.\n */\n#define BMI2_TARGET_ATTRIBUTE TARGET_ATTRIBUTE(\"lzcnt,bmi,bmi2\")\n\n/* prefetch\n * can be disabled, by declaring NO_PREFETCH build macro */\n#if defined(NO_PREFETCH)\n#  define PREFETCH_L1(ptr)  do { (void)(ptr); } while (0)  /* disabled */\n#  define PREFETCH_L2(ptr)  do { (void)(ptr); } while (0)  /* disabled */\n#else\n#  if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) && !defined(_M_ARM64EC)  /* _mm_prefetch() is not defined outside of x86/x64 */\n#    include <mmintrin.h>   /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */\n#    define PREFETCH_L1(ptr)  _mm_prefetch((const char*)(ptr), _MM_HINT_T0)\n#    define PREFETCH_L2(ptr)  _mm_prefetch((const char*)(ptr), _MM_HINT_T1)\n#  elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) )\n#    define PREFETCH_L1(ptr)  __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */)\n#    define PREFETCH_L2(ptr)  __builtin_prefetch((ptr), 0 /* rw==read */, 2 /* locality */)\n#  elif defined(__aarch64__)\n#    define PREFETCH_L1(ptr)  do { __asm__ __volatile__(\"prfm pldl1keep, %0\" ::\"Q\"(*(ptr))); } while (0)\n#    define PREFETCH_L2(ptr)  do { __asm__ __volatile__(\"prfm pldl2keep, %0\" ::\"Q\"(*(ptr))); } while (0)\n#  else\n#    define PREFETCH_L1(ptr) do { (void)(ptr); } while (0)  /* disabled */\n#    define PREFETCH_L2(ptr) do { (void)(ptr); } while (0)  /* disabled */\n#  endif\n#endif  /* NO_PREFETCH */\n\n#define CACHELINE_SIZE 64\n\n#define PREFETCH_AREA(p, s)                              \\\n    do {                                                 \\\n        const char* const _ptr = (const char*)(p);       \\\n        size_t const _size = (size_t)(s);                \\\n        size_t _pos;                                     \\\n        for (_pos=0; _pos<_size; _pos+=CACHELINE_SIZE) { \\\n            PREFETCH_L2(_ptr + _pos);                    \\\n        }                                                \\\n    } while (0)\n\n/* vectorization\n * older GCC (pre gcc-4.3 picked as the cutoff) uses a different syntax,\n * and some compilers, like Intel ICC and MCST LCC, do not support it at all. */\n#if !defined(__INTEL_COMPILER) && !defined(__clang__) && defined(__GNUC__) && !defined(__LCC__)\n#  if (__GNUC__ == 4 && __GNUC_MINOR__ > 3) || (__GNUC__ >= 5)\n#    define DONT_VECTORIZE __attribute__((optimize(\"no-tree-vectorize\")))\n#  else\n#    define DONT_VECTORIZE _Pragma(\"GCC optimize(\\\"no-tree-vectorize\\\")\")\n#  endif\n#else\n#  define DONT_VECTORIZE\n#endif\n\n/* Tell the compiler that a branch is likely or unlikely.\n * Only use these macros if it causes the compiler to generate better code.\n * If you can remove a LIKELY/UNLIKELY annotation without speed changes in gcc\n * and clang, please do.\n */\n#if defined(__GNUC__)\n#define LIKELY(x) (__builtin_expect((x), 1))\n#define UNLIKELY(x) (__builtin_expect((x), 0))\n#else\n#define LIKELY(x) (x)\n#define UNLIKELY(x) (x)\n#endif\n\n#if __has_builtin(__builtin_unreachable) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)))\n#  define ZSTD_UNREACHABLE do { assert(0), __builtin_unreachable(); } while (0)\n#else\n#  define ZSTD_UNREACHABLE do { assert(0); } while (0)\n#endif\n\n/* disable warnings */\n#ifdef _MSC_VER    /* Visual Studio */\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4100)        /* disable: C4100: unreferenced formal parameter */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4204)        /* disable: C4204: non-constant aggregate initializer */\n#  pragma warning(disable : 4214)        /* disable: C4214: non-int bitfields */\n#  pragma warning(disable : 4324)        /* disable: C4324: padded structure */\n#endif\n\n/* compile time determination of SIMD support */\n#if !defined(ZSTD_NO_INTRINSICS)\n#  if defined(__AVX2__)\n#    define ZSTD_ARCH_X86_AVX2\n#  endif\n#  if defined(__SSE2__) || defined(_M_X64) || (defined (_M_IX86) && defined(_M_IX86_FP) && (_M_IX86_FP >= 2))\n#    define ZSTD_ARCH_X86_SSE2\n#  endif\n#  if defined(__ARM_NEON) || defined(_M_ARM64)\n#    define ZSTD_ARCH_ARM_NEON\n#  endif\n#  if defined(__ARM_FEATURE_SVE)\n#    define ZSTD_ARCH_ARM_SVE\n#  endif\n#  if defined(__ARM_FEATURE_SVE2)\n#    define ZSTD_ARCH_ARM_SVE2\n#  endif\n#  if defined(__riscv) && defined(__riscv_vector)\n#    if ((defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 14) || \\\n        (defined(__clang__) && __clang_major__ >= 19))\n        #define ZSTD_ARCH_RISCV_RVV\n#  endif\n#endif\n#\n#  if defined(ZSTD_ARCH_X86_AVX2)\n#    include <immintrin.h>\n#  endif\n#  if defined(ZSTD_ARCH_X86_SSE2)\n#    include <emmintrin.h>\n#  elif defined(ZSTD_ARCH_ARM_NEON)\n#    include <arm_neon.h>\n#  endif\n#  if defined(ZSTD_ARCH_ARM_SVE) || defined(ZSTD_ARCH_ARM_SVE2)\n#    include <arm_sve.h>\n#  endif\n#  if defined(ZSTD_ARCH_RISCV_RVV)\n#    include <riscv_vector.h>\n#  endif\n#endif\n\n/* C-language Attributes are added in C23. */\n#if defined(__STDC_VERSION__) && (__STDC_VERSION__ > 201710L) && defined(__has_c_attribute)\n# define ZSTD_HAS_C_ATTRIBUTE(x) __has_c_attribute(x)\n#else\n# define ZSTD_HAS_C_ATTRIBUTE(x) 0\n#endif\n\n/* Only use C++ attributes in C++. Some compilers report support for C++\n * attributes when compiling with C.\n */\n#if defined(__cplusplus) && defined(__has_cpp_attribute)\n# define ZSTD_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)\n#else\n# define ZSTD_HAS_CPP_ATTRIBUTE(x) 0\n#endif\n\n/* Define ZSTD_FALLTHROUGH macro for annotating switch case with the 'fallthrough' attribute.\n * - C23: https://en.cppreference.com/w/c/language/attributes/fallthrough\n * - CPP17: https://en.cppreference.com/w/cpp/language/attributes/fallthrough\n * - Else: __attribute__((__fallthrough__))\n */\n#ifndef ZSTD_FALLTHROUGH\n# if ZSTD_HAS_C_ATTRIBUTE(fallthrough)\n#  define ZSTD_FALLTHROUGH [[fallthrough]]\n# elif ZSTD_HAS_CPP_ATTRIBUTE(fallthrough)\n#  define ZSTD_FALLTHROUGH [[fallthrough]]\n# elif __has_attribute(__fallthrough__)\n/* Leading semicolon is to satisfy gcc-11 with -pedantic. Without the semicolon\n * gcc complains about: a label can only be part of a statement and a declaration is not a statement.\n */\n#  define ZSTD_FALLTHROUGH ; __attribute__((__fallthrough__))\n# else\n#  define ZSTD_FALLTHROUGH\n# endif\n#endif\n\n/*-**************************************************************\n*  Alignment\n*****************************************************************/\n\n/* @return 1 if @u is a 2^n value, 0 otherwise\n * useful to check a value is valid for alignment restrictions */\nMEM_STATIC int ZSTD_isPower2(size_t u) {\n    return (u & (u-1)) == 0;\n}\n\n/* this test was initially positioned in mem.h,\n * but this file is removed (or replaced) for linux kernel\n * so it's now hosted in compiler.h,\n * which remains valid for both user & kernel spaces.\n */\n\n#ifndef ZSTD_ALIGNOF\n# if defined(__GNUC__) || defined(_MSC_VER)\n/* covers gcc, clang & MSVC */\n/* note : this section must come first, before C11,\n * due to a limitation in the kernel source generator */\n#  define ZSTD_ALIGNOF(T) __alignof(T)\n\n# elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)\n/* C11 support */\n#  include <stdalign.h>\n#  define ZSTD_ALIGNOF(T) alignof(T)\n\n# else\n/* No known support for alignof() - imperfect backup */\n#  define ZSTD_ALIGNOF(T) (sizeof(void*) < sizeof(T) ? sizeof(void*) : sizeof(T))\n\n# endif\n#endif /* ZSTD_ALIGNOF */\n\n#ifndef ZSTD_ALIGNED\n/* C90-compatible alignment macro (GCC/Clang). Adjust for other compilers if needed. */\n# if defined(__GNUC__) || defined(__clang__)\n#  define ZSTD_ALIGNED(a) __attribute__((aligned(a)))\n# elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */\n#  define ZSTD_ALIGNED(a) _Alignas(a)\n#elif defined(_MSC_VER)\n#  define ZSTD_ALIGNED(n) __declspec(align(n))\n# else\n   /* this compiler will require its own alignment instruction */\n#  define ZSTD_ALIGNED(...)\n# endif\n#endif /* ZSTD_ALIGNED */\n\n\n/*-**************************************************************\n*  Sanitizer\n*****************************************************************/\n\n/**\n * Zstd relies on pointer overflow in its decompressor.\n * We add this attribute to functions that rely on pointer overflow.\n */\n#ifndef ZSTD_ALLOW_POINTER_OVERFLOW_ATTR\n#  if __has_attribute(no_sanitize)\n#    if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 8\n       /* gcc < 8 only has signed-integer-overlow which triggers on pointer overflow */\n#      define ZSTD_ALLOW_POINTER_OVERFLOW_ATTR __attribute__((no_sanitize(\"signed-integer-overflow\")))\n#    else\n       /* older versions of clang [3.7, 5.0) will warn that pointer-overflow is ignored. */\n#      define ZSTD_ALLOW_POINTER_OVERFLOW_ATTR __attribute__((no_sanitize(\"pointer-overflow\")))\n#    endif\n#  else\n#    define ZSTD_ALLOW_POINTER_OVERFLOW_ATTR\n#  endif\n#endif\n\n/**\n * Helper function to perform a wrapped pointer difference without triggering\n * UBSAN.\n *\n * @returns lhs - rhs with wrapping\n */\nMEM_STATIC\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nptrdiff_t ZSTD_wrappedPtrDiff(unsigned char const* lhs, unsigned char const* rhs)\n{\n    return lhs - rhs;\n}\n\n/**\n * Helper function to perform a wrapped pointer add without triggering UBSAN.\n *\n * @return ptr + add with wrapping\n */\nMEM_STATIC\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nconst void* ZSTD_wrappedPtrAdd(const void* ptr, ptrdiff_t add)\n{\n    return (const char*)ptr + add;\n}\n\n/**\n * Helper function to perform a wrapped pointer subtraction without triggering\n * UBSAN.\n *\n * @return ptr - sub with wrapping\n */\nMEM_STATIC\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nconst void* ZSTD_wrappedPtrSub(const void* ptr, ptrdiff_t sub)\n{\n    return (const char*)ptr - sub;\n}\n\n/**\n * Helper function to add to a pointer that works around C's undefined behavior\n * of adding 0 to NULL.\n *\n * @returns `ptr + add` except it defines `NULL + 0 == NULL`.\n */\nMEM_STATIC\nvoid* ZSTD_maybeNullPtrAdd(void* ptr, ptrdiff_t add)\n{\n    return add > 0 ? (char*)ptr + add : ptr;\n}\n\n/* Issue #3240 reports an ASAN failure on an llvm-mingw build. Out of an\n * abundance of caution, disable our custom poisoning on mingw. */\n#ifdef __MINGW32__\n#ifndef ZSTD_ASAN_DONT_POISON_WORKSPACE\n#define ZSTD_ASAN_DONT_POISON_WORKSPACE 1\n#endif\n#ifndef ZSTD_MSAN_DONT_POISON_WORKSPACE\n#define ZSTD_MSAN_DONT_POISON_WORKSPACE 1\n#endif\n#endif\n\n#if ZSTD_MEMORY_SANITIZER && !defined(ZSTD_MSAN_DONT_POISON_WORKSPACE)\n/* Not all platforms that support msan provide sanitizers/msan_interface.h.\n * We therefore declare the functions we need ourselves, rather than trying to\n * include the header file... */\n#include <stddef.h>  /* size_t */\n#define ZSTD_DEPS_NEED_STDINT\n#include \"zstd_deps.h\"  /* intptr_t */\n\n/* Make memory region fully initialized (without changing its contents). */\nvoid __msan_unpoison(const volatile void *a, size_t size);\n\n/* Make memory region fully uninitialized (without changing its contents).\n   This is a legacy interface that does not update origin information. Use\n   __msan_allocated_memory() instead. */\nvoid __msan_poison(const volatile void *a, size_t size);\n\n/* Returns the offset of the first (at least partially) poisoned byte in the\n   memory range, or -1 if the whole range is good. */\nintptr_t __msan_test_shadow(const volatile void *x, size_t size);\n\n/* Print shadow and origin for the memory range to stderr in a human-readable\n   format. */\nvoid __msan_print_shadow(const volatile void *x, size_t size);\n#endif\n\n#if ZSTD_ADDRESS_SANITIZER && !defined(ZSTD_ASAN_DONT_POISON_WORKSPACE)\n/* Not all platforms that support asan provide sanitizers/asan_interface.h.\n * We therefore declare the functions we need ourselves, rather than trying to\n * include the header file... */\n#include <stddef.h>  /* size_t */\n\n/**\n * Marks a memory region (<c>[addr, addr+size)</c>) as unaddressable.\n *\n * This memory must be previously allocated by your program. Instrumented\n * code is forbidden from accessing addresses in this region until it is\n * unpoisoned. This function is not guaranteed to poison the entire region -\n * it could poison only a subregion of <c>[addr, addr+size)</c> due to ASan\n * alignment restrictions.\n *\n * \\note This function is not thread-safe because no two threads can poison or\n * unpoison memory in the same memory region simultaneously.\n *\n * \\param addr Start of memory region.\n * \\param size Size of memory region. */\nvoid __asan_poison_memory_region(void const volatile *addr, size_t size);\n\n/**\n * Marks a memory region (<c>[addr, addr+size)</c>) as addressable.\n *\n * This memory must be previously allocated by your program. Accessing\n * addresses in this region is allowed until this region is poisoned again.\n * This function could unpoison a super-region of <c>[addr, addr+size)</c> due\n * to ASan alignment restrictions.\n *\n * \\note This function is not thread-safe because no two threads can\n * poison or unpoison memory in the same memory region simultaneously.\n *\n * \\param addr Start of memory region.\n * \\param size Size of memory region. */\nvoid __asan_unpoison_memory_region(void const volatile *addr, size_t size);\n#endif\n\n#endif /* ZSTD_COMPILER_H */\n"
  },
  {
    "path": "lib/common/cpu.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_COMMON_CPU_H\n#define ZSTD_COMMON_CPU_H\n\n/**\n * Implementation taken from folly/CpuId.h\n * https://github.com/facebook/folly/blob/master/folly/CpuId.h\n */\n\n#include \"mem.h\"\n\n#ifdef _MSC_VER\n#include <intrin.h>\n#endif\n\ntypedef struct {\n    U32 f1c;\n    U32 f1d;\n    U32 f7b;\n    U32 f7c;\n} ZSTD_cpuid_t;\n\nMEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void) {\n    U32 f1c = 0;\n    U32 f1d = 0;\n    U32 f7b = 0;\n    U32 f7c = 0;\n#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))\n#if !defined(_M_X64) || !defined(__clang__) || __clang_major__ >= 16\n    int reg[4];\n    __cpuid((int*)reg, 0);\n    {\n        int const n = reg[0];\n        if (n >= 1) {\n            __cpuid((int*)reg, 1);\n            f1c = (U32)reg[2];\n            f1d = (U32)reg[3];\n        }\n        if (n >= 7) {\n            __cpuidex((int*)reg, 7, 0);\n            f7b = (U32)reg[1];\n            f7c = (U32)reg[2];\n        }\n    }\n#else\n    /* Clang compiler has a bug (fixed in https://reviews.llvm.org/D101338) in\n     * which the `__cpuid` intrinsic does not save and restore `rbx` as it needs\n     * to due to being a reserved register. So in that case, do the `cpuid`\n     * ourselves. Clang supports inline assembly anyway.\n     */\n    U32 n;\n    __asm__(\n        \"pushq %%rbx\\n\\t\"\n        \"cpuid\\n\\t\"\n        \"popq %%rbx\\n\\t\"\n        : \"=a\"(n)\n        : \"a\"(0)\n        : \"rcx\", \"rdx\");\n    if (n >= 1) {\n      U32 f1a;\n      __asm__(\n          \"pushq %%rbx\\n\\t\"\n          \"cpuid\\n\\t\"\n          \"popq %%rbx\\n\\t\"\n          : \"=a\"(f1a), \"=c\"(f1c), \"=d\"(f1d)\n          : \"a\"(1)\n          :);\n    }\n    if (n >= 7) {\n      __asm__(\n          \"pushq %%rbx\\n\\t\"\n          \"cpuid\\n\\t\"\n          \"movq %%rbx, %%rax\\n\\t\"\n          \"popq %%rbx\"\n          : \"=a\"(f7b), \"=c\"(f7c)\n          : \"a\"(7), \"c\"(0)\n          : \"rdx\");\n    }\n#endif\n#elif defined(__i386__) && defined(__PIC__) && !defined(__clang__) && defined(__GNUC__)\n    /* The following block like the normal cpuid branch below, but gcc\n     * reserves ebx for use of its pic register so we must specially\n     * handle the save and restore to avoid clobbering the register\n     */\n    U32 n;\n    __asm__(\n        \"pushl %%ebx\\n\\t\"\n        \"cpuid\\n\\t\"\n        \"popl %%ebx\\n\\t\"\n        : \"=a\"(n)\n        : \"a\"(0)\n        : \"ecx\", \"edx\");\n    if (n >= 1) {\n      U32 f1a;\n      __asm__(\n          \"pushl %%ebx\\n\\t\"\n          \"cpuid\\n\\t\"\n          \"popl %%ebx\\n\\t\"\n          : \"=a\"(f1a), \"=c\"(f1c), \"=d\"(f1d)\n          : \"a\"(1));\n    }\n    if (n >= 7) {\n      __asm__(\n          \"pushl %%ebx\\n\\t\"\n          \"cpuid\\n\\t\"\n          \"movl %%ebx, %%eax\\n\\t\"\n          \"popl %%ebx\"\n          : \"=a\"(f7b), \"=c\"(f7c)\n          : \"a\"(7), \"c\"(0)\n          : \"edx\");\n    }\n#elif defined(__x86_64__) || defined(_M_X64) || defined(__i386__)\n    U32 n;\n    __asm__(\"cpuid\" : \"=a\"(n) : \"a\"(0) : \"ebx\", \"ecx\", \"edx\");\n    if (n >= 1) {\n      U32 f1a;\n      __asm__(\"cpuid\" : \"=a\"(f1a), \"=c\"(f1c), \"=d\"(f1d) : \"a\"(1) : \"ebx\");\n    }\n    if (n >= 7) {\n      U32 f7a;\n      __asm__(\"cpuid\"\n              : \"=a\"(f7a), \"=b\"(f7b), \"=c\"(f7c)\n              : \"a\"(7), \"c\"(0)\n              : \"edx\");\n    }\n#endif\n    {\n        ZSTD_cpuid_t cpuid;\n        cpuid.f1c = f1c;\n        cpuid.f1d = f1d;\n        cpuid.f7b = f7b;\n        cpuid.f7c = f7c;\n        return cpuid;\n    }\n}\n\n#define X(name, r, bit)                                                        \\\n  MEM_STATIC int ZSTD_cpuid_##name(ZSTD_cpuid_t const cpuid) {                 \\\n    return ((cpuid.r) & (1U << bit)) != 0;                                     \\\n  }\n\n/* cpuid(1): Processor Info and Feature Bits. */\n#define C(name, bit) X(name, f1c, bit)\n  C(sse3, 0)\n  C(pclmuldq, 1)\n  C(dtes64, 2)\n  C(monitor, 3)\n  C(dscpl, 4)\n  C(vmx, 5)\n  C(smx, 6)\n  C(eist, 7)\n  C(tm2, 8)\n  C(ssse3, 9)\n  C(cnxtid, 10)\n  C(fma, 12)\n  C(cx16, 13)\n  C(xtpr, 14)\n  C(pdcm, 15)\n  C(pcid, 17)\n  C(dca, 18)\n  C(sse41, 19)\n  C(sse42, 20)\n  C(x2apic, 21)\n  C(movbe, 22)\n  C(popcnt, 23)\n  C(tscdeadline, 24)\n  C(aes, 25)\n  C(xsave, 26)\n  C(osxsave, 27)\n  C(avx, 28)\n  C(f16c, 29)\n  C(rdrand, 30)\n#undef C\n#define D(name, bit) X(name, f1d, bit)\n  D(fpu, 0)\n  D(vme, 1)\n  D(de, 2)\n  D(pse, 3)\n  D(tsc, 4)\n  D(msr, 5)\n  D(pae, 6)\n  D(mce, 7)\n  D(cx8, 8)\n  D(apic, 9)\n  D(sep, 11)\n  D(mtrr, 12)\n  D(pge, 13)\n  D(mca, 14)\n  D(cmov, 15)\n  D(pat, 16)\n  D(pse36, 17)\n  D(psn, 18)\n  D(clfsh, 19)\n  D(ds, 21)\n  D(acpi, 22)\n  D(mmx, 23)\n  D(fxsr, 24)\n  D(sse, 25)\n  D(sse2, 26)\n  D(ss, 27)\n  D(htt, 28)\n  D(tm, 29)\n  D(pbe, 31)\n#undef D\n\n/* cpuid(7): Extended Features. */\n#define B(name, bit) X(name, f7b, bit)\n  B(bmi1, 3)\n  B(hle, 4)\n  B(avx2, 5)\n  B(smep, 7)\n  B(bmi2, 8)\n  B(erms, 9)\n  B(invpcid, 10)\n  B(rtm, 11)\n  B(mpx, 14)\n  B(avx512f, 16)\n  B(avx512dq, 17)\n  B(rdseed, 18)\n  B(adx, 19)\n  B(smap, 20)\n  B(avx512ifma, 21)\n  B(pcommit, 22)\n  B(clflushopt, 23)\n  B(clwb, 24)\n  B(avx512pf, 26)\n  B(avx512er, 27)\n  B(avx512cd, 28)\n  B(sha, 29)\n  B(avx512bw, 30)\n  B(avx512vl, 31)\n#undef B\n#define C(name, bit) X(name, f7c, bit)\n  C(prefetchwt1, 0)\n  C(avx512vbmi, 1)\n#undef C\n\n#undef X\n\n#endif /* ZSTD_COMMON_CPU_H */\n"
  },
  {
    "path": "lib/common/debug.c",
    "content": "/* ******************************************************************\n * debug\n * Part of FSE library\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * You can contact the author at :\n * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n\n/*\n * This module only hosts one global variable\n * which can be used to dynamically influence the verbosity of traces,\n * such as DEBUGLOG and RAWLOG\n */\n\n#include \"debug.h\"\n\n#if !defined(ZSTD_LINUX_KERNEL) || (DEBUGLEVEL>=2)\n/* We only use this when DEBUGLEVEL>=2, but we get -Werror=pedantic errors if a\n * translation unit is empty. So remove this from Linux kernel builds, but\n * otherwise just leave it in.\n */\nint g_debuglevel = DEBUGLEVEL;\n#endif\n"
  },
  {
    "path": "lib/common/debug.h",
    "content": "/* ******************************************************************\n * debug\n * Part of FSE library\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * You can contact the author at :\n * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n\n/*\n * The purpose of this header is to enable debug functions.\n * They regroup assert(), DEBUGLOG() and RAWLOG() for run-time,\n * and DEBUG_STATIC_ASSERT() for compile-time.\n *\n * By default, DEBUGLEVEL==0, which means run-time debug is disabled.\n *\n * Level 1 enables assert() only.\n * Starting level 2, traces can be generated and pushed to stderr.\n * The higher the level, the more verbose the traces.\n *\n * It's possible to dynamically adjust level using variable g_debug_level,\n * which is only declared if DEBUGLEVEL>=2,\n * and is a global variable, not multi-thread protected (use with care)\n */\n\n#ifndef DEBUG_H_12987983217\n#define DEBUG_H_12987983217\n\n\n/* static assert is triggered at compile time, leaving no runtime artefact.\n * static assert only works with compile-time constants.\n * Also, this variant can only be used inside a function. */\n#define DEBUG_STATIC_ASSERT(c) (void)sizeof(char[(c) ? 1 : -1])\n\n\n/* DEBUGLEVEL is expected to be defined externally,\n * typically through compiler command line.\n * Value must be a number. */\n#ifndef DEBUGLEVEL\n#  define DEBUGLEVEL 0\n#endif\n\n\n/* recommended values for DEBUGLEVEL :\n * 0 : release mode, no debug, all run-time checks disabled\n * 1 : enables assert() only, no display\n * 2 : reserved, for currently active debug path\n * 3 : events once per object lifetime (CCtx, CDict, etc.)\n * 4 : events once per frame\n * 5 : events once per block\n * 6 : events once per sequence (verbose)\n * 7+: events at every position (*very* verbose)\n *\n * It's generally inconvenient to output traces > 5.\n * In which case, it's possible to selectively trigger high verbosity levels\n * by modifying g_debug_level.\n */\n\n#if (DEBUGLEVEL>=1)\n#  define ZSTD_DEPS_NEED_ASSERT\n#  include \"zstd_deps.h\"\n#else\n#  ifndef assert   /* assert may be already defined, due to prior #include <assert.h> */\n#    define assert(condition) ((void)0)   /* disable assert (default) */\n#  endif\n#endif\n\n#if (DEBUGLEVEL>=2)\n#  define ZSTD_DEPS_NEED_IO\n#  include \"zstd_deps.h\"\nextern int g_debuglevel; /* the variable is only declared,\n                            it actually lives in debug.c,\n                            and is shared by the whole process.\n                            It's not thread-safe.\n                            It's useful when enabling very verbose levels\n                            on selective conditions (such as position in src) */\n\n#  define RAWLOG(l, ...)                   \\\n    do {                                   \\\n        if (l<=g_debuglevel) {             \\\n            ZSTD_DEBUG_PRINT(__VA_ARGS__); \\\n        }                                  \\\n    } while (0)\n\n#define STRINGIFY(x) #x\n#define TOSTRING(x) STRINGIFY(x)\n#define LINE_AS_STRING TOSTRING(__LINE__)\n\n#  define DEBUGLOG(l, ...)                               \\\n    do {                                                 \\\n        if (l<=g_debuglevel) {                           \\\n            ZSTD_DEBUG_PRINT(__FILE__ \":\" LINE_AS_STRING \": \" __VA_ARGS__); \\\n            ZSTD_DEBUG_PRINT(\" \\n\");                     \\\n        }                                                \\\n    } while (0)\n#else\n#  define RAWLOG(l, ...)   do { } while (0)    /* disabled */\n#  define DEBUGLOG(l, ...) do { } while (0)    /* disabled */\n#endif\n\n#endif /* DEBUG_H_12987983217 */\n"
  },
  {
    "path": "lib/common/entropy_common.c",
    "content": "/* ******************************************************************\n * Common functions of New Generation Entropy library\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n *  You can contact the author at :\n *  - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *  - Public forum : https://groups.google.com/forum/#!forum/lz4c\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n/* *************************************\n*  Dependencies\n***************************************/\n#include \"mem.h\"\n#include \"error_private.h\"       /* ERR_*, ERROR */\n#define FSE_STATIC_LINKING_ONLY  /* FSE_MIN_TABLELOG */\n#include \"fse.h\"\n#include \"huf.h\"\n#include \"bits.h\"                /* ZSDT_highbit32, ZSTD_countTrailingZeros32 */\n\n\n/*===   Version   ===*/\nunsigned FSE_versionNumber(void) { return FSE_VERSION_NUMBER; }\n\n\n/*===   Error Management   ===*/\nunsigned FSE_isError(size_t code) { return ERR_isError(code); }\nconst char* FSE_getErrorName(size_t code) { return ERR_getErrorName(code); }\n\nunsigned HUF_isError(size_t code) { return ERR_isError(code); }\nconst char* HUF_getErrorName(size_t code) { return ERR_getErrorName(code); }\n\n\n/*-**************************************************************\n*  FSE NCount encoding-decoding\n****************************************************************/\nFORCE_INLINE_TEMPLATE\nsize_t FSE_readNCount_body(short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n                           const void* headerBuffer, size_t hbSize)\n{\n    const BYTE* const istart = (const BYTE*) headerBuffer;\n    const BYTE* const iend = istart + hbSize;\n    const BYTE* ip = istart;\n    int nbBits;\n    int remaining;\n    int threshold;\n    U32 bitStream;\n    int bitCount;\n    unsigned charnum = 0;\n    unsigned const maxSV1 = *maxSVPtr + 1;\n    int previous0 = 0;\n\n    if (hbSize < 8) {\n        /* This function only works when hbSize >= 8 */\n        char buffer[8] = {0};\n        ZSTD_memcpy(buffer, headerBuffer, hbSize);\n        {   size_t const countSize = FSE_readNCount(normalizedCounter, maxSVPtr, tableLogPtr,\n                                                    buffer, sizeof(buffer));\n            if (FSE_isError(countSize)) return countSize;\n            if (countSize > hbSize) return ERROR(corruption_detected);\n            return countSize;\n    }   }\n    assert(hbSize >= 8);\n\n    /* init */\n    ZSTD_memset(normalizedCounter, 0, (*maxSVPtr+1) * sizeof(normalizedCounter[0]));   /* all symbols not present in NCount have a frequency of 0 */\n    bitStream = MEM_readLE32(ip);\n    nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG;   /* extract tableLog */\n    if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);\n    bitStream >>= 4;\n    bitCount = 4;\n    *tableLogPtr = nbBits;\n    remaining = (1<<nbBits)+1;\n    threshold = 1<<nbBits;\n    nbBits++;\n\n    for (;;) {\n        if (previous0) {\n            /* Count the number of repeats. Each time the\n             * 2-bit repeat code is 0b11 there is another\n             * repeat.\n             * Avoid UB by setting the high bit to 1.\n             */\n            int repeats = ZSTD_countTrailingZeros32(~bitStream | 0x80000000) >> 1;\n            while (repeats >= 12) {\n                charnum += 3 * 12;\n                if (LIKELY(ip <= iend-7)) {\n                    ip += 3;\n                } else {\n                    bitCount -= (int)(8 * (iend - 7 - ip));\n                    bitCount &= 31;\n                    ip = iend - 4;\n                }\n                bitStream = MEM_readLE32(ip) >> bitCount;\n                repeats = ZSTD_countTrailingZeros32(~bitStream | 0x80000000) >> 1;\n            }\n            charnum += 3 * repeats;\n            bitStream >>= 2 * repeats;\n            bitCount += 2 * repeats;\n\n            /* Add the final repeat which isn't 0b11. */\n            assert((bitStream & 3) < 3);\n            charnum += bitStream & 3;\n            bitCount += 2;\n\n            /* This is an error, but break and return an error\n             * at the end, because returning out of a loop makes\n             * it harder for the compiler to optimize.\n             */\n            if (charnum >= maxSV1) break;\n\n            /* We don't need to set the normalized count to 0\n             * because we already memset the whole buffer to 0.\n             */\n\n            if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {\n                assert((bitCount >> 3) <= 3); /* For first condition to work */\n                ip += bitCount>>3;\n                bitCount &= 7;\n            } else {\n                bitCount -= (int)(8 * (iend - 4 - ip));\n                bitCount &= 31;\n                ip = iend - 4;\n            }\n            bitStream = MEM_readLE32(ip) >> bitCount;\n        }\n        {\n            int const max = (2*threshold-1) - remaining;\n            int count;\n\n            if ((bitStream & (threshold-1)) < (U32)max) {\n                count = bitStream & (threshold-1);\n                bitCount += nbBits-1;\n            } else {\n                count = bitStream & (2*threshold-1);\n                if (count >= threshold) count -= max;\n                bitCount += nbBits;\n            }\n\n            count--;   /* extra accuracy */\n            /* When it matters (small blocks), this is a\n             * predictable branch, because we don't use -1.\n             */\n            if (count >= 0) {\n                remaining -= count;\n            } else {\n                assert(count == -1);\n                remaining += count;\n            }\n            normalizedCounter[charnum++] = (short)count;\n            previous0 = !count;\n\n            assert(threshold > 1);\n            if (remaining < threshold) {\n                /* This branch can be folded into the\n                 * threshold update condition because we\n                 * know that threshold > 1.\n                 */\n                if (remaining <= 1) break;\n                nbBits = ZSTD_highbit32(remaining) + 1;\n                threshold = 1 << (nbBits - 1);\n            }\n            if (charnum >= maxSV1) break;\n\n            if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {\n                ip += bitCount>>3;\n                bitCount &= 7;\n            } else {\n                bitCount -= (int)(8 * (iend - 4 - ip));\n                bitCount &= 31;\n                ip = iend - 4;\n            }\n            bitStream = MEM_readLE32(ip) >> bitCount;\n    }   }\n    if (remaining != 1) return ERROR(corruption_detected);\n    /* Only possible when there are too many zeros. */\n    if (charnum > maxSV1) return ERROR(maxSymbolValue_tooSmall);\n    if (bitCount > 32) return ERROR(corruption_detected);\n    *maxSVPtr = charnum-1;\n\n    ip += (bitCount+7)>>3;\n    return ip-istart;\n}\n\n/* Avoids the FORCE_INLINE of the _body() function. */\nstatic size_t FSE_readNCount_body_default(\n        short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n        const void* headerBuffer, size_t hbSize)\n{\n    return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);\n}\n\n#if DYNAMIC_BMI2\nBMI2_TARGET_ATTRIBUTE static size_t FSE_readNCount_body_bmi2(\n        short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n        const void* headerBuffer, size_t hbSize)\n{\n    return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);\n}\n#endif\n\nsize_t FSE_readNCount_bmi2(\n        short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n        const void* headerBuffer, size_t hbSize, int bmi2)\n{\n#if DYNAMIC_BMI2\n    if (bmi2) {\n        return FSE_readNCount_body_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);\n    }\n#endif\n    (void)bmi2;\n    return FSE_readNCount_body_default(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);\n}\n\nsize_t FSE_readNCount(\n        short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n        const void* headerBuffer, size_t hbSize)\n{\n    return FSE_readNCount_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize, /* bmi2 */ 0);\n}\n\n\n/*! HUF_readStats() :\n    Read compact Huffman tree, saved by HUF_writeCTable().\n    `huffWeight` is destination buffer.\n    `rankStats` is assumed to be a table of at least HUF_TABLELOG_MAX U32.\n    @return : size read from `src` , or an error Code .\n    Note : Needed by HUF_readCTable() and HUF_readDTableX?() .\n*/\nsize_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                     U32* nbSymbolsPtr, U32* tableLogPtr,\n                     const void* src, size_t srcSize)\n{\n    U32 wksp[HUF_READ_STATS_WORKSPACE_SIZE_U32];\n    return HUF_readStats_wksp(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, wksp, sizeof(wksp), /* flags */ 0);\n}\n\nFORCE_INLINE_TEMPLATE size_t\nHUF_readStats_body(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                   U32* nbSymbolsPtr, U32* tableLogPtr,\n                   const void* src, size_t srcSize,\n                   void* workSpace, size_t wkspSize,\n                   int bmi2)\n{\n    U32 weightTotal;\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize;\n    size_t oSize;\n\n    if (!srcSize) return ERROR(srcSize_wrong);\n    iSize = ip[0];\n    /* ZSTD_memset(huffWeight, 0, hwSize);   *//* is not necessary, even though some analyzer complain ... */\n\n    if (iSize >= 128) {  /* special header */\n        oSize = iSize - 127;\n        iSize = ((oSize+1)/2);\n        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n        if (oSize >= hwSize) return ERROR(corruption_detected);\n        ip += 1;\n        {   U32 n;\n            for (n=0; n<oSize; n+=2) {\n                huffWeight[n]   = ip[n/2] >> 4;\n                huffWeight[n+1] = ip[n/2] & 15;\n    }   }   }\n    else  {   /* header compressed with FSE (normal case) */\n        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n        /* max (hwSize-1) values decoded, as last one is implied */\n        oSize = FSE_decompress_wksp_bmi2(huffWeight, hwSize-1, ip+1, iSize, 6, workSpace, wkspSize, bmi2);\n        if (FSE_isError(oSize)) return oSize;\n    }\n\n    /* collect weight stats */\n    ZSTD_memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32));\n    weightTotal = 0;\n    {   U32 n; for (n=0; n<oSize; n++) {\n            if (huffWeight[n] > HUF_TABLELOG_MAX) return ERROR(corruption_detected);\n            rankStats[huffWeight[n]]++;\n            weightTotal += (1 << huffWeight[n]) >> 1;\n    }   }\n    if (weightTotal == 0) return ERROR(corruption_detected);\n\n    /* get last non-null symbol weight (implied, total must be 2^n) */\n    {   U32 const tableLog = ZSTD_highbit32(weightTotal) + 1;\n        if (tableLog > HUF_TABLELOG_MAX) return ERROR(corruption_detected);\n        *tableLogPtr = tableLog;\n        /* determine last weight */\n        {   U32 const total = 1 << tableLog;\n            U32 const rest = total - weightTotal;\n            U32 const verif = 1 << ZSTD_highbit32(rest);\n            U32 const lastWeight = ZSTD_highbit32(rest) + 1;\n            if (verif != rest) return ERROR(corruption_detected);    /* last value must be a clean power of 2 */\n            huffWeight[oSize] = (BYTE)lastWeight;\n            rankStats[lastWeight]++;\n    }   }\n\n    /* check tree construction validity */\n    if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected);   /* by construction : at least 2 elts of rank 1, must be even */\n\n    /* results */\n    *nbSymbolsPtr = (U32)(oSize+1);\n    return iSize+1;\n}\n\n/* Avoids the FORCE_INLINE of the _body() function. */\nstatic size_t HUF_readStats_body_default(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                     U32* nbSymbolsPtr, U32* tableLogPtr,\n                     const void* src, size_t srcSize,\n                     void* workSpace, size_t wkspSize)\n{\n    return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 0);\n}\n\n#if DYNAMIC_BMI2\nstatic BMI2_TARGET_ATTRIBUTE size_t HUF_readStats_body_bmi2(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                     U32* nbSymbolsPtr, U32* tableLogPtr,\n                     const void* src, size_t srcSize,\n                     void* workSpace, size_t wkspSize)\n{\n    return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 1);\n}\n#endif\n\nsize_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                     U32* nbSymbolsPtr, U32* tableLogPtr,\n                     const void* src, size_t srcSize,\n                     void* workSpace, size_t wkspSize,\n                     int flags)\n{\n#if DYNAMIC_BMI2\n    if (flags & HUF_flags_bmi2) {\n        return HUF_readStats_body_bmi2(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize);\n    }\n#endif\n    (void)flags;\n    return HUF_readStats_body_default(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize);\n}\n"
  },
  {
    "path": "lib/common/error_private.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* The purpose of this file is to have a single list of error strings embedded in binary */\n\n#include \"error_private.h\"\n\nconst char* ERR_getErrorString(ERR_enum code)\n{\n#ifdef ZSTD_STRIP_ERROR_STRINGS\n    (void)code;\n    return \"Error strings stripped\";\n#else\n    static const char* const notErrorCode = \"Unspecified error code\";\n    switch( code )\n    {\n    case PREFIX(no_error): return \"No error detected\";\n    case PREFIX(GENERIC):  return \"Error (generic)\";\n    case PREFIX(prefix_unknown): return \"Unknown frame descriptor\";\n    case PREFIX(version_unsupported): return \"Version not supported\";\n    case PREFIX(frameParameter_unsupported): return \"Unsupported frame parameter\";\n    case PREFIX(frameParameter_windowTooLarge): return \"Frame requires too much memory for decoding\";\n    case PREFIX(corruption_detected): return \"Data corruption detected\";\n    case PREFIX(checksum_wrong): return \"Restored data doesn't match checksum\";\n    case PREFIX(literals_headerWrong): return \"Header of Literals' block doesn't respect format specification\";\n    case PREFIX(parameter_unsupported): return \"Unsupported parameter\";\n    case PREFIX(parameter_combination_unsupported): return \"Unsupported combination of parameters\";\n    case PREFIX(parameter_outOfBound): return \"Parameter is out of bound\";\n    case PREFIX(init_missing): return \"Context should be init first\";\n    case PREFIX(memory_allocation): return \"Allocation error : not enough memory\";\n    case PREFIX(workSpace_tooSmall): return \"workSpace buffer is not large enough\";\n    case PREFIX(stage_wrong): return \"Operation not authorized at current processing stage\";\n    case PREFIX(tableLog_tooLarge): return \"tableLog requires too much memory : unsupported\";\n    case PREFIX(maxSymbolValue_tooLarge): return \"Unsupported max Symbol Value : too large\";\n    case PREFIX(maxSymbolValue_tooSmall): return \"Specified maxSymbolValue is too small\";\n    case PREFIX(cannotProduce_uncompressedBlock): return \"This mode cannot generate an uncompressed block\";\n    case PREFIX(stabilityCondition_notRespected): return \"pledged buffer stability condition is not respected\";\n    case PREFIX(dictionary_corrupted): return \"Dictionary is corrupted\";\n    case PREFIX(dictionary_wrong): return \"Dictionary mismatch\";\n    case PREFIX(dictionaryCreation_failed): return \"Cannot create Dictionary from provided samples\";\n    case PREFIX(dstSize_tooSmall): return \"Destination buffer is too small\";\n    case PREFIX(srcSize_wrong): return \"Src size is incorrect\";\n    case PREFIX(dstBuffer_null): return \"Operation on NULL destination buffer\";\n    case PREFIX(noForwardProgress_destFull): return \"Operation made no progress over multiple calls, due to output buffer being full\";\n    case PREFIX(noForwardProgress_inputEmpty): return \"Operation made no progress over multiple calls, due to input being empty\";\n        /* following error codes are not stable and may be removed or changed in a future version */\n    case PREFIX(frameIndex_tooLarge): return \"Frame index is too large\";\n    case PREFIX(seekableIO): return \"An I/O error occurred when reading/seeking\";\n    case PREFIX(dstBuffer_wrong): return \"Destination buffer is wrong\";\n    case PREFIX(srcBuffer_wrong): return \"Source buffer is wrong\";\n    case PREFIX(sequenceProducer_failed): return \"Block-level external sequence producer returned an error code\";\n    case PREFIX(externalSequences_invalid): return \"External sequences are not valid\";\n    case PREFIX(maxCode):\n    default: return notErrorCode;\n    }\n#endif\n}\n"
  },
  {
    "path": "lib/common/error_private.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* Note : this module is expected to remain private, do not expose it */\n\n#ifndef ERROR_H_MODULE\n#define ERROR_H_MODULE\n\n/* ****************************************\n*  Dependencies\n******************************************/\n#include \"../zstd_errors.h\"  /* enum list */\n#include \"compiler.h\"\n#include \"debug.h\"\n#include \"zstd_deps.h\"       /* size_t */\n\n/* ****************************************\n*  Compiler-specific\n******************************************/\n#if defined(__GNUC__)\n#  define ERR_STATIC static __attribute__((unused))\n#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n#  define ERR_STATIC static inline\n#elif defined(_MSC_VER)\n#  define ERR_STATIC static __inline\n#else\n#  define ERR_STATIC static  /* this version may generate warnings for unused static functions; disable the relevant warning */\n#endif\n\n\n/*-****************************************\n*  Customization (error_public.h)\n******************************************/\ntypedef ZSTD_ErrorCode ERR_enum;\n#define PREFIX(name) ZSTD_error_##name\n\n\n/*-****************************************\n*  Error codes handling\n******************************************/\n#undef ERROR   /* already defined on Visual Studio */\n#define ERROR(name) ZSTD_ERROR(name)\n#define ZSTD_ERROR(name) ((size_t)-PREFIX(name))\n\nERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }\n\nERR_STATIC ERR_enum ERR_getErrorCode(size_t code) { if (!ERR_isError(code)) return (ERR_enum)0; return (ERR_enum) (0-code); }\n\n/* check and forward error code */\n#define CHECK_V_F(e, f)     \\\n    size_t const e = f;     \\\n    do {                    \\\n        if (ERR_isError(e)) \\\n            return e;       \\\n    } while (0)\n#define CHECK_F(f)   do { CHECK_V_F(_var_err__, f); } while (0)\n\n\n/*-****************************************\n*  Error Strings\n******************************************/\n\nconst char* ERR_getErrorString(ERR_enum code);   /* error_private.c */\n\nERR_STATIC const char* ERR_getErrorName(size_t code)\n{\n    return ERR_getErrorString(ERR_getErrorCode(code));\n}\n\n/**\n * Ignore: this is an internal helper.\n *\n * This is a helper function to help force C99-correctness during compilation.\n * Under strict compilation modes, variadic macro arguments can't be empty.\n * However, variadic function arguments can be. Using a function therefore lets\n * us statically check that at least one (string) argument was passed,\n * independent of the compilation flags.\n */\nstatic INLINE_KEYWORD UNUSED_ATTR\nvoid _force_has_format_string(const char *format, ...) {\n  (void)format;\n}\n\n/**\n * Ignore: this is an internal helper.\n *\n * We want to force this function invocation to be syntactically correct, but\n * we don't want to force runtime evaluation of its arguments.\n */\n#define _FORCE_HAS_FORMAT_STRING(...)              \\\n    do {                                           \\\n        if (0) {                                   \\\n            _force_has_format_string(__VA_ARGS__); \\\n        }                                          \\\n    } while (0)\n\n#define ERR_QUOTE(str) #str\n\n/**\n * Return the specified error if the condition evaluates to true.\n *\n * In debug modes, prints additional information.\n * In order to do that (particularly, printing the conditional that failed),\n * this can't just wrap RETURN_ERROR().\n */\n#define RETURN_ERROR_IF(cond, err, ...)                                        \\\n    do {                                                                       \\\n        if (cond) {                                                            \\\n            RAWLOG(3, \"%s:%d: ERROR!: check %s failed, returning %s\",          \\\n                  __FILE__, __LINE__, ERR_QUOTE(cond), ERR_QUOTE(ERROR(err))); \\\n            _FORCE_HAS_FORMAT_STRING(__VA_ARGS__);                             \\\n            RAWLOG(3, \": \" __VA_ARGS__);                                       \\\n            RAWLOG(3, \"\\n\");                                                   \\\n            return ERROR(err);                                                 \\\n        }                                                                      \\\n    } while (0)\n\n/**\n * Unconditionally return the specified error.\n *\n * In debug modes, prints additional information.\n */\n#define RETURN_ERROR(err, ...)                                               \\\n    do {                                                                     \\\n        RAWLOG(3, \"%s:%d: ERROR!: unconditional check failed, returning %s\", \\\n              __FILE__, __LINE__, ERR_QUOTE(ERROR(err)));                    \\\n        _FORCE_HAS_FORMAT_STRING(__VA_ARGS__);                               \\\n        RAWLOG(3, \": \" __VA_ARGS__);                                         \\\n        RAWLOG(3, \"\\n\");                                                     \\\n        return ERROR(err);                                                   \\\n    } while(0)\n\n/**\n * If the provided expression evaluates to an error code, returns that error code.\n *\n * In debug modes, prints additional information.\n */\n#define FORWARD_IF_ERROR(err, ...)                                                 \\\n    do {                                                                           \\\n        size_t const err_code = (err);                                             \\\n        if (ERR_isError(err_code)) {                                               \\\n            RAWLOG(3, \"%s:%d: ERROR!: forwarding error in %s: %s\",                 \\\n                  __FILE__, __LINE__, ERR_QUOTE(err), ERR_getErrorName(err_code)); \\\n            _FORCE_HAS_FORMAT_STRING(__VA_ARGS__);                                 \\\n            RAWLOG(3, \": \" __VA_ARGS__);                                           \\\n            RAWLOG(3, \"\\n\");                                                       \\\n            return err_code;                                                       \\\n        }                                                                          \\\n    } while(0)\n\n#endif /* ERROR_H_MODULE */\n"
  },
  {
    "path": "lib/common/fse.h",
    "content": "/* ******************************************************************\n * FSE : Finite State Entropy codec\n * Public Prototypes declaration\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * You can contact the author at :\n * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n#ifndef FSE_H\n#define FSE_H\n\n\n/*-*****************************************\n*  Dependencies\n******************************************/\n#include \"zstd_deps.h\"    /* size_t, ptrdiff_t */\n\n/*-*****************************************\n*  FSE_PUBLIC_API : control library symbols visibility\n******************************************/\n#if defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) && defined(__GNUC__) && (__GNUC__ >= 4)\n#  define FSE_PUBLIC_API __attribute__ ((visibility (\"default\")))\n#elif defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1)   /* Visual expected */\n#  define FSE_PUBLIC_API __declspec(dllexport)\n#elif defined(FSE_DLL_IMPORT) && (FSE_DLL_IMPORT==1)\n#  define FSE_PUBLIC_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/\n#else\n#  define FSE_PUBLIC_API\n#endif\n\n/*------   Version   ------*/\n#define FSE_VERSION_MAJOR    0\n#define FSE_VERSION_MINOR    9\n#define FSE_VERSION_RELEASE  0\n\n#define FSE_LIB_VERSION FSE_VERSION_MAJOR.FSE_VERSION_MINOR.FSE_VERSION_RELEASE\n#define FSE_QUOTE(str) #str\n#define FSE_EXPAND_AND_QUOTE(str) FSE_QUOTE(str)\n#define FSE_VERSION_STRING FSE_EXPAND_AND_QUOTE(FSE_LIB_VERSION)\n\n#define FSE_VERSION_NUMBER  (FSE_VERSION_MAJOR *100*100 + FSE_VERSION_MINOR *100 + FSE_VERSION_RELEASE)\nFSE_PUBLIC_API unsigned FSE_versionNumber(void);   /**< library version number; to be used when checking dll version */\n\n\n/*-*****************************************\n*  Tool functions\n******************************************/\nFSE_PUBLIC_API size_t FSE_compressBound(size_t size);       /* maximum compressed size */\n\n/* Error Management */\nFSE_PUBLIC_API unsigned    FSE_isError(size_t code);        /* tells if a return value is an error code */\nFSE_PUBLIC_API const char* FSE_getErrorName(size_t code);   /* provides error code string (useful for debugging) */\n\n\n/*-*****************************************\n*  FSE detailed API\n******************************************/\n/*!\nFSE_compress() does the following:\n1. count symbol occurrence from source[] into table count[] (see hist.h)\n2. normalize counters so that sum(count[]) == Power_of_2 (2^tableLog)\n3. save normalized counters to memory buffer using writeNCount()\n4. build encoding table 'CTable' from normalized counters\n5. encode the data stream using encoding table 'CTable'\n\nFSE_decompress() does the following:\n1. read normalized counters with readNCount()\n2. build decoding table 'DTable' from normalized counters\n3. decode the data stream using decoding table 'DTable'\n\nThe following API allows targeting specific sub-functions for advanced tasks.\nFor example, it's possible to compress several blocks using the same 'CTable',\nor to save and provide normalized distribution using external method.\n*/\n\n/* *** COMPRESSION *** */\n\n/*! FSE_optimalTableLog():\n    dynamically downsize 'tableLog' when conditions are met.\n    It saves CPU time, by using smaller tables, while preserving or even improving compression ratio.\n    @return : recommended tableLog (necessarily <= 'maxTableLog') */\nFSE_PUBLIC_API unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);\n\n/*! FSE_normalizeCount():\n    normalize counts so that sum(count[]) == Power_of_2 (2^tableLog)\n    'normalizedCounter' is a table of short, of minimum size (maxSymbolValue+1).\n    useLowProbCount is a boolean parameter which trades off compressed size for\n    faster header decoding. When it is set to 1, the compressed data will be slightly\n    smaller. And when it is set to 0, FSE_readNCount() and FSE_buildDTable() will be\n    faster. If you are compressing a small amount of data (< 2 KB) then useLowProbCount=0\n    is a good default, since header deserialization makes a big speed difference.\n    Otherwise, useLowProbCount=1 is a good default, since the speed difference is small.\n    @return : tableLog,\n              or an errorCode, which can be tested using FSE_isError() */\nFSE_PUBLIC_API size_t FSE_normalizeCount(short* normalizedCounter, unsigned tableLog,\n                    const unsigned* count, size_t srcSize, unsigned maxSymbolValue, unsigned useLowProbCount);\n\n/*! FSE_NCountWriteBound():\n    Provides the maximum possible size of an FSE normalized table, given 'maxSymbolValue' and 'tableLog'.\n    Typically useful for allocation purpose. */\nFSE_PUBLIC_API size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog);\n\n/*! FSE_writeNCount():\n    Compactly save 'normalizedCounter' into 'buffer'.\n    @return : size of the compressed table,\n              or an errorCode, which can be tested using FSE_isError(). */\nFSE_PUBLIC_API size_t FSE_writeNCount (void* buffer, size_t bufferSize,\n                                 const short* normalizedCounter,\n                                 unsigned maxSymbolValue, unsigned tableLog);\n\n/*! Constructor and Destructor of FSE_CTable.\n    Note that FSE_CTable size depends on 'tableLog' and 'maxSymbolValue' */\ntypedef unsigned FSE_CTable;   /* don't allocate that. It's only meant to be more restrictive than void* */\n\n/*! FSE_buildCTable():\n    Builds `ct`, which must be already allocated, using FSE_createCTable().\n    @return : 0, or an errorCode, which can be tested using FSE_isError() */\nFSE_PUBLIC_API size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);\n\n/*! FSE_compress_usingCTable():\n    Compress `src` using `ct` into `dst` which must be already allocated.\n    @return : size of compressed data (<= `dstCapacity`),\n              or 0 if compressed data could not fit into `dst`,\n              or an errorCode, which can be tested using FSE_isError() */\nFSE_PUBLIC_API size_t FSE_compress_usingCTable (void* dst, size_t dstCapacity, const void* src, size_t srcSize, const FSE_CTable* ct);\n\n/*!\nTutorial :\n----------\nThe first step is to count all symbols. FSE_count() does this job very fast.\nResult will be saved into 'count', a table of unsigned int, which must be already allocated, and have 'maxSymbolValuePtr[0]+1' cells.\n'src' is a table of bytes of size 'srcSize'. All values within 'src' MUST be <= maxSymbolValuePtr[0]\nmaxSymbolValuePtr[0] will be updated, with its real value (necessarily <= original value)\nFSE_count() will return the number of occurrence of the most frequent symbol.\nThis can be used to know if there is a single symbol within 'src', and to quickly evaluate its compressibility.\nIf there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()).\n\nThe next step is to normalize the frequencies.\nFSE_normalizeCount() will ensure that sum of frequencies is == 2 ^'tableLog'.\nIt also guarantees a minimum of 1 to any Symbol with frequency >= 1.\nYou can use 'tableLog'==0 to mean \"use default tableLog value\".\nIf you are unsure of which tableLog value to use, you can ask FSE_optimalTableLog(),\nwhich will provide the optimal valid tableLog given sourceSize, maxSymbolValue, and a user-defined maximum (0 means \"default\").\n\nThe result of FSE_normalizeCount() will be saved into a table,\ncalled 'normalizedCounter', which is a table of signed short.\n'normalizedCounter' must be already allocated, and have at least 'maxSymbolValue+1' cells.\nThe return value is tableLog if everything proceeded as expected.\nIt is 0 if there is a single symbol within distribution.\nIf there is an error (ex: invalid tableLog value), the function will return an ErrorCode (which can be tested using FSE_isError()).\n\n'normalizedCounter' can be saved in a compact manner to a memory area using FSE_writeNCount().\n'buffer' must be already allocated.\nFor guaranteed success, buffer size must be at least FSE_headerBound().\nThe result of the function is the number of bytes written into 'buffer'.\nIf there is an error, the function will return an ErrorCode (which can be tested using FSE_isError(); ex : buffer size too small).\n\n'normalizedCounter' can then be used to create the compression table 'CTable'.\nThe space required by 'CTable' must be already allocated, using FSE_createCTable().\nYou can then use FSE_buildCTable() to fill 'CTable'.\nIf there is an error, both functions will return an ErrorCode (which can be tested using FSE_isError()).\n\n'CTable' can then be used to compress 'src', with FSE_compress_usingCTable().\nSimilar to FSE_count(), the convention is that 'src' is assumed to be a table of char of size 'srcSize'\nThe function returns the size of compressed data (without header), necessarily <= `dstCapacity`.\nIf it returns '0', compressed data could not fit into 'dst'.\nIf there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()).\n*/\n\n\n/* *** DECOMPRESSION *** */\n\n/*! FSE_readNCount():\n    Read compactly saved 'normalizedCounter' from 'rBuffer'.\n    @return : size read from 'rBuffer',\n              or an errorCode, which can be tested using FSE_isError().\n              maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */\nFSE_PUBLIC_API size_t FSE_readNCount (short* normalizedCounter,\n                           unsigned* maxSymbolValuePtr, unsigned* tableLogPtr,\n                           const void* rBuffer, size_t rBuffSize);\n\n/*! FSE_readNCount_bmi2():\n * Same as FSE_readNCount() but pass bmi2=1 when your CPU supports BMI2 and 0 otherwise.\n */\nFSE_PUBLIC_API size_t FSE_readNCount_bmi2(short* normalizedCounter,\n                           unsigned* maxSymbolValuePtr, unsigned* tableLogPtr,\n                           const void* rBuffer, size_t rBuffSize, int bmi2);\n\ntypedef unsigned FSE_DTable;   /* don't allocate that. It's just a way to be more restrictive than void* */\n\n/*!\nTutorial :\n----------\n(Note : these functions only decompress FSE-compressed blocks.\n If block is uncompressed, use memcpy() instead\n If block is a single repeated byte, use memset() instead )\n\nThe first step is to obtain the normalized frequencies of symbols.\nThis can be performed by FSE_readNCount() if it was saved using FSE_writeNCount().\n'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short.\nIn practice, that means it's necessary to know 'maxSymbolValue' beforehand,\nor size the table to handle worst case situations (typically 256).\nFSE_readNCount() will provide 'tableLog' and 'maxSymbolValue'.\nThe result of FSE_readNCount() is the number of bytes read from 'rBuffer'.\nNote that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that.\nIf there is an error, the function will return an error code, which can be tested using FSE_isError().\n\nThe next step is to build the decompression tables 'FSE_DTable' from 'normalizedCounter'.\nThis is performed by the function FSE_buildDTable().\nThe space required by 'FSE_DTable' must be already allocated using FSE_createDTable().\nIf there is an error, the function will return an error code, which can be tested using FSE_isError().\n\n`FSE_DTable` can then be used to decompress `cSrc`, with FSE_decompress_usingDTable().\n`cSrcSize` must be strictly correct, otherwise decompression will fail.\nFSE_decompress_usingDTable() result will tell how many bytes were regenerated (<=`dstCapacity`).\nIf there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small)\n*/\n\n#endif  /* FSE_H */\n\n\n#if defined(FSE_STATIC_LINKING_ONLY) && !defined(FSE_H_FSE_STATIC_LINKING_ONLY)\n#define FSE_H_FSE_STATIC_LINKING_ONLY\n#include \"bitstream.h\"\n\n/* *****************************************\n*  Static allocation\n*******************************************/\n/* FSE buffer bounds */\n#define FSE_NCOUNTBOUND 512\n#define FSE_BLOCKBOUND(size) ((size) + ((size)>>7) + 4 /* fse states */ + sizeof(size_t) /* bitContainer */)\n#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size))   /* Macro version, useful for static allocation */\n\n/* It is possible to statically allocate FSE CTable/DTable as a table of FSE_CTable/FSE_DTable using below macros */\n#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue)   (1 + (1<<((maxTableLog)-1)) + (((maxSymbolValue)+1)*2))\n#define FSE_DTABLE_SIZE_U32(maxTableLog)                   (1 + (1<<(maxTableLog)))\n\n/* or use the size to malloc() space directly. Pay attention to alignment restrictions though */\n#define FSE_CTABLE_SIZE(maxTableLog, maxSymbolValue)   (FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(FSE_CTable))\n#define FSE_DTABLE_SIZE(maxTableLog)                   (FSE_DTABLE_SIZE_U32(maxTableLog) * sizeof(FSE_DTable))\n\n\n/* *****************************************\n *  FSE advanced API\n ***************************************** */\n\nunsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus);\n/**< same as FSE_optimalTableLog(), which used `minus==2` */\n\nsize_t FSE_buildCTable_rle (FSE_CTable* ct, unsigned char symbolValue);\n/**< build a fake FSE_CTable, designed to compress always the same symbolValue */\n\n/* FSE_buildCTable_wksp() :\n * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`).\n * `wkspSize` must be >= `FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog)` of `unsigned`.\n * See FSE_buildCTable_wksp() for breakdown of workspace usage.\n */\n#define FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog) (((maxSymbolValue + 2) + (1ull << (tableLog)))/2 + sizeof(U64)/sizeof(U32) /* additional 8 bytes for potential table overwrite */)\n#define FSE_BUILD_CTABLE_WORKSPACE_SIZE(maxSymbolValue, tableLog) (sizeof(unsigned) * FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog))\nsize_t FSE_buildCTable_wksp(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);\n\n#define FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) (sizeof(short) * (maxSymbolValue + 1) + (1ULL << maxTableLog) + 8)\n#define FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ((FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) + sizeof(unsigned) - 1) / sizeof(unsigned))\nFSE_PUBLIC_API size_t FSE_buildDTable_wksp(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);\n/**< Same as FSE_buildDTable(), using an externally allocated `workspace` produced with `FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxSymbolValue)` */\n\n#define FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) (FSE_DTABLE_SIZE_U32(maxTableLog) + 1 + FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) + (FSE_MAX_SYMBOL_VALUE + 1) / 2 + 1)\n#define FSE_DECOMPRESS_WKSP_SIZE(maxTableLog, maxSymbolValue) (FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(unsigned))\nsize_t FSE_decompress_wksp_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize, int bmi2);\n/**< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DECOMPRESS_WKSP_SIZE_U32(maxLog, maxSymbolValue)`.\n * Set bmi2 to 1 if your CPU supports BMI2 or 0 if it doesn't */\n\ntypedef enum {\n   FSE_repeat_none,  /**< Cannot use the previous table */\n   FSE_repeat_check, /**< Can use the previous table but it must be checked */\n   FSE_repeat_valid  /**< Can use the previous table and it is assumed to be valid */\n } FSE_repeat;\n\n/* *****************************************\n*  FSE symbol compression API\n*******************************************/\n/*!\n   This API consists of small unitary functions, which highly benefit from being inlined.\n   Hence their body are included in next section.\n*/\ntypedef struct {\n    ptrdiff_t   value;\n    const void* stateTable;\n    const void* symbolTT;\n    unsigned    stateLog;\n} FSE_CState_t;\n\nstatic void FSE_initCState(FSE_CState_t* CStatePtr, const FSE_CTable* ct);\n\nstatic void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* CStatePtr, unsigned symbol);\n\nstatic void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* CStatePtr);\n\n/**<\nThese functions are inner components of FSE_compress_usingCTable().\nThey allow the creation of custom streams, mixing multiple tables and bit sources.\n\nA key property to keep in mind is that encoding and decoding are done **in reverse direction**.\nSo the first symbol you will encode is the last you will decode, like a LIFO stack.\n\nYou will need a few variables to track your CStream. They are :\n\nFSE_CTable    ct;         // Provided by FSE_buildCTable()\nBIT_CStream_t bitStream;  // bitStream tracking structure\nFSE_CState_t  state;      // State tracking structure (can have several)\n\n\nThe first thing to do is to init bitStream and state.\n    size_t errorCode = BIT_initCStream(&bitStream, dstBuffer, maxDstSize);\n    FSE_initCState(&state, ct);\n\nNote that BIT_initCStream() can produce an error code, so its result should be tested, using FSE_isError();\nYou can then encode your input data, byte after byte.\nFSE_encodeSymbol() outputs a maximum of 'tableLog' bits at a time.\nRemember decoding will be done in reverse direction.\n    FSE_encodeByte(&bitStream, &state, symbol);\n\nAt any time, you can also add any bit sequence.\nNote : maximum allowed nbBits is 25, for compatibility with 32-bits decoders\n    BIT_addBits(&bitStream, bitField, nbBits);\n\nThe above methods don't commit data to memory, they just store it into local register, for speed.\nLocal register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).\nWriting data to memory is a manual operation, performed by the flushBits function.\n    BIT_flushBits(&bitStream);\n\nYour last FSE encoding operation shall be to flush your last state value(s).\n    FSE_flushState(&bitStream, &state);\n\nFinally, you must close the bitStream.\nThe function returns the size of CStream in bytes.\nIf data couldn't fit into dstBuffer, it will return a 0 ( == not compressible)\nIf there is an error, it returns an errorCode (which can be tested using FSE_isError()).\n    size_t size = BIT_closeCStream(&bitStream);\n*/\n\n\n/* *****************************************\n*  FSE symbol decompression API\n*******************************************/\ntypedef struct {\n    size_t      state;\n    const void* table;   /* precise table may vary, depending on U16 */\n} FSE_DState_t;\n\n\nstatic void     FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt);\n\nstatic unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);\n\nstatic unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr);\n\n/**<\nLet's now decompose FSE_decompress_usingDTable() into its unitary components.\nYou will decode FSE-encoded symbols from the bitStream,\nand also any other bitFields you put in, **in reverse order**.\n\nYou will need a few variables to track your bitStream. They are :\n\nBIT_DStream_t DStream;    // Stream context\nFSE_DState_t  DState;     // State context. Multiple ones are possible\nFSE_DTable*   DTablePtr;  // Decoding table, provided by FSE_buildDTable()\n\nThe first thing to do is to init the bitStream.\n    errorCode = BIT_initDStream(&DStream, srcBuffer, srcSize);\n\nYou should then retrieve your initial state(s)\n(in reverse flushing order if you have several ones) :\n    errorCode = FSE_initDState(&DState, &DStream, DTablePtr);\n\nYou can then decode your data, symbol after symbol.\nFor information the maximum number of bits read by FSE_decodeSymbol() is 'tableLog'.\nKeep in mind that symbols are decoded in reverse order, like a LIFO stack (last in, first out).\n    unsigned char symbol = FSE_decodeSymbol(&DState, &DStream);\n\nYou can retrieve any bitfield you eventually stored into the bitStream (in reverse order)\nNote : maximum allowed nbBits is 25, for 32-bits compatibility\n    size_t bitField = BIT_readBits(&DStream, nbBits);\n\nAll above operations only read from local register (which size depends on size_t).\nRefueling the register from memory is manually performed by the reload method.\n    endSignal = FSE_reloadDStream(&DStream);\n\nBIT_reloadDStream() result tells if there is still some more data to read from DStream.\nBIT_DStream_unfinished : there is still some data left into the DStream.\nBIT_DStream_endOfBuffer : Dstream reached end of buffer. Its container may no longer be completely filled.\nBIT_DStream_completed : Dstream reached its exact end, corresponding in general to decompression completed.\nBIT_DStream_tooFar : Dstream went too far. Decompression result is corrupted.\n\nWhen reaching end of buffer (BIT_DStream_endOfBuffer), progress slowly, notably if you decode multiple symbols per loop,\nto properly detect the exact end of stream.\nAfter each decoded symbol, check if DStream is fully consumed using this simple test :\n    BIT_reloadDStream(&DStream) >= BIT_DStream_completed\n\nWhen it's done, verify decompression is fully completed, by checking both DStream and the relevant states.\nChecking if DStream has reached its end is performed by :\n    BIT_endOfDStream(&DStream);\nCheck also the states. There might be some symbols left there, if some high probability ones (>50%) are possible.\n    FSE_endOfDState(&DState);\n*/\n\n\n/* *****************************************\n*  FSE unsafe API\n*******************************************/\nstatic unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);\n/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */\n\n\n/* *****************************************\n*  Implementation of inlined functions\n*******************************************/\ntypedef struct {\n    int deltaFindState;\n    U32 deltaNbBits;\n} FSE_symbolCompressionTransform; /* total 8 bytes */\n\nMEM_STATIC void FSE_initCState(FSE_CState_t* statePtr, const FSE_CTable* ct)\n{\n    const void* ptr = ct;\n    const U16* u16ptr = (const U16*) ptr;\n    const U32 tableLog = MEM_read16(ptr);\n    statePtr->value = (ptrdiff_t)1<<tableLog;\n    statePtr->stateTable = u16ptr+2;\n    statePtr->symbolTT = ct + 1 + (tableLog ? (1<<(tableLog-1)) : 1);\n    statePtr->stateLog = tableLog;\n}\n\n\n/*! FSE_initCState2() :\n*   Same as FSE_initCState(), but the first symbol to include (which will be the last to be read)\n*   uses the smallest state value possible, saving the cost of this symbol */\nMEM_STATIC void FSE_initCState2(FSE_CState_t* statePtr, const FSE_CTable* ct, U32 symbol)\n{\n    FSE_initCState(statePtr, ct);\n    {   const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];\n        const U16* stateTable = (const U16*)(statePtr->stateTable);\n        U32 nbBitsOut  = (U32)((symbolTT.deltaNbBits + (1<<15)) >> 16);\n        statePtr->value = (nbBitsOut << 16) - symbolTT.deltaNbBits;\n        statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];\n    }\n}\n\nMEM_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, unsigned symbol)\n{\n    FSE_symbolCompressionTransform const symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];\n    const U16* const stateTable = (const U16*)(statePtr->stateTable);\n    U32 const nbBitsOut  = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16);\n    BIT_addBits(bitC, (BitContainerType)statePtr->value, nbBitsOut);\n    statePtr->value = stateTable[ (statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];\n}\n\nMEM_STATIC void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* statePtr)\n{\n    BIT_addBits(bitC, (BitContainerType)statePtr->value, statePtr->stateLog);\n    BIT_flushBits(bitC);\n}\n\n\n/* FSE_getMaxNbBits() :\n * Approximate maximum cost of a symbol, in bits.\n * Fractional get rounded up (i.e. a symbol with a normalized frequency of 3 gives the same result as a frequency of 2)\n * note 1 : assume symbolValue is valid (<= maxSymbolValue)\n * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */\nMEM_STATIC U32 FSE_getMaxNbBits(const void* symbolTTPtr, U32 symbolValue)\n{\n    const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr;\n    return (symbolTT[symbolValue].deltaNbBits + ((1<<16)-1)) >> 16;\n}\n\n/* FSE_bitCost() :\n * Approximate symbol cost, as fractional value, using fixed-point format (accuracyLog fractional bits)\n * note 1 : assume symbolValue is valid (<= maxSymbolValue)\n * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */\nMEM_STATIC U32 FSE_bitCost(const void* symbolTTPtr, U32 tableLog, U32 symbolValue, U32 accuracyLog)\n{\n    const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr;\n    U32 const minNbBits = symbolTT[symbolValue].deltaNbBits >> 16;\n    U32 const threshold = (minNbBits+1) << 16;\n    assert(tableLog < 16);\n    assert(accuracyLog < 31-tableLog);  /* ensure enough room for renormalization double shift */\n    {   U32 const tableSize = 1 << tableLog;\n        U32 const deltaFromThreshold = threshold - (symbolTT[symbolValue].deltaNbBits + tableSize);\n        U32 const normalizedDeltaFromThreshold = (deltaFromThreshold << accuracyLog) >> tableLog;   /* linear interpolation (very approximate) */\n        U32 const bitMultiplier = 1 << accuracyLog;\n        assert(symbolTT[symbolValue].deltaNbBits + tableSize <= threshold);\n        assert(normalizedDeltaFromThreshold <= bitMultiplier);\n        return (minNbBits+1)*bitMultiplier - normalizedDeltaFromThreshold;\n    }\n}\n\n\n/* ======    Decompression    ====== */\n\ntypedef struct {\n    U16 tableLog;\n    U16 fastMode;\n} FSE_DTableHeader;   /* sizeof U32 */\n\ntypedef struct\n{\n    unsigned short newState;\n    unsigned char  symbol;\n    unsigned char  nbBits;\n} FSE_decode_t;   /* size == U32 */\n\nMEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt)\n{\n    const void* ptr = dt;\n    const FSE_DTableHeader* const DTableH = (const FSE_DTableHeader*)ptr;\n    DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog);\n    BIT_reloadDStream(bitD);\n    DStatePtr->table = dt + 1;\n}\n\nMEM_STATIC BYTE FSE_peekSymbol(const FSE_DState_t* DStatePtr)\n{\n    FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    return DInfo.symbol;\n}\n\nMEM_STATIC void FSE_updateState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)\n{\n    FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    U32 const nbBits = DInfo.nbBits;\n    size_t const lowBits = BIT_readBits(bitD, nbBits);\n    DStatePtr->state = DInfo.newState + lowBits;\n}\n\nMEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)\n{\n    FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    U32 const nbBits = DInfo.nbBits;\n    BYTE const symbol = DInfo.symbol;\n    size_t const lowBits = BIT_readBits(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\n/*! FSE_decodeSymbolFast() :\n    unsafe, only works if no symbol has a probability > 50% */\nMEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)\n{\n    FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    U32 const nbBits = DInfo.nbBits;\n    BYTE const symbol = DInfo.symbol;\n    size_t const lowBits = BIT_readBitsFast(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\nMEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)\n{\n    return DStatePtr->state == 0;\n}\n\n\n\n#ifndef FSE_COMMONDEFS_ONLY\n\n/* **************************************************************\n*  Tuning parameters\n****************************************************************/\n/*!MEMORY_USAGE :\n*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n*  Increasing memory usage improves compression ratio\n*  Reduced memory usage can improve speed, due to cache effect\n*  Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */\n#ifndef FSE_MAX_MEMORY_USAGE\n#  define FSE_MAX_MEMORY_USAGE 14\n#endif\n#ifndef FSE_DEFAULT_MEMORY_USAGE\n#  define FSE_DEFAULT_MEMORY_USAGE 13\n#endif\n#if (FSE_DEFAULT_MEMORY_USAGE > FSE_MAX_MEMORY_USAGE)\n#  error \"FSE_DEFAULT_MEMORY_USAGE must be <= FSE_MAX_MEMORY_USAGE\"\n#endif\n\n/*!FSE_MAX_SYMBOL_VALUE :\n*  Maximum symbol value authorized.\n*  Required for proper stack allocation */\n#ifndef FSE_MAX_SYMBOL_VALUE\n#  define FSE_MAX_SYMBOL_VALUE 255\n#endif\n\n/* **************************************************************\n*  template functions type & suffix\n****************************************************************/\n#define FSE_FUNCTION_TYPE BYTE\n#define FSE_FUNCTION_EXTENSION\n#define FSE_DECODE_TYPE FSE_decode_t\n\n\n#endif   /* !FSE_COMMONDEFS_ONLY */\n\n\n/* ***************************************************************\n*  Constants\n*****************************************************************/\n#define FSE_MAX_TABLELOG  (FSE_MAX_MEMORY_USAGE-2)\n#define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG)\n#define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1)\n#define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2)\n#define FSE_MIN_TABLELOG 5\n\n#define FSE_TABLELOG_ABSOLUTE_MAX 15\n#if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX\n#  error \"FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported\"\n#endif\n\n#define FSE_TABLESTEP(tableSize) (((tableSize)>>1) + ((tableSize)>>3) + 3)\n\n#endif /* FSE_STATIC_LINKING_ONLY */\n"
  },
  {
    "path": "lib/common/fse_decompress.c",
    "content": "/* ******************************************************************\n * FSE : Finite State Entropy decoder\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n *  You can contact the author at :\n *  - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *  - Public forum : https://groups.google.com/forum/#!forum/lz4c\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n\n/* **************************************************************\n*  Includes\n****************************************************************/\n#include \"debug.h\"      /* assert */\n#include \"bitstream.h\"\n#include \"compiler.h\"\n#define FSE_STATIC_LINKING_ONLY\n#include \"fse.h\"\n#include \"error_private.h\"\n#include \"zstd_deps.h\"  /* ZSTD_memcpy */\n#include \"bits.h\"       /* ZSTD_highbit32 */\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n#define FSE_isError ERR_isError\n#define FSE_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c)   /* use only *after* variable declarations */\n\n\n/* **************************************************************\n*  Templates\n****************************************************************/\n/*\n  designed to be included\n  for type-specific functions (template emulation in C)\n  Objective is to write these functions only once, for improved maintenance\n*/\n\n/* safety checks */\n#ifndef FSE_FUNCTION_EXTENSION\n#  error \"FSE_FUNCTION_EXTENSION must be defined\"\n#endif\n#ifndef FSE_FUNCTION_TYPE\n#  error \"FSE_FUNCTION_TYPE must be defined\"\n#endif\n\n/* Function names */\n#define FSE_CAT(X,Y) X##Y\n#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y)\n#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y)\n\nstatic size_t FSE_buildDTable_internal(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize)\n{\n    void* const tdPtr = dt+1;   /* because *dt is unsigned, 32-bits aligned on 32-bits */\n    FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*) (tdPtr);\n    U16* symbolNext = (U16*)workSpace;\n    BYTE* spread = (BYTE*)(symbolNext + maxSymbolValue + 1);\n\n    U32 const maxSV1 = maxSymbolValue + 1;\n    U32 const tableSize = 1 << tableLog;\n    U32 highThreshold = tableSize-1;\n\n    /* Sanity Checks */\n    if (FSE_BUILD_DTABLE_WKSP_SIZE(tableLog, maxSymbolValue) > wkspSize) return ERROR(maxSymbolValue_tooLarge);\n    if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);\n    if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);\n\n    /* Init, lay down lowprob symbols */\n    {   FSE_DTableHeader DTableH;\n        DTableH.tableLog = (U16)tableLog;\n        DTableH.fastMode = 1;\n        {   S16 const largeLimit= (S16)(1 << (tableLog-1));\n            U32 s;\n            for (s=0; s<maxSV1; s++) {\n                if (normalizedCounter[s]==-1) {\n                    tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s;\n                    symbolNext[s] = 1;\n                } else {\n                    if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;\n                    symbolNext[s] = (U16)normalizedCounter[s];\n        }   }   }\n        ZSTD_memcpy(dt, &DTableH, sizeof(DTableH));\n    }\n\n    /* Spread symbols */\n    if (highThreshold == tableSize - 1) {\n        size_t const tableMask = tableSize-1;\n        size_t const step = FSE_TABLESTEP(tableSize);\n        /* First lay down the symbols in order.\n         * We use a uint64_t to lay down 8 bytes at a time. This reduces branch\n         * misses since small blocks generally have small table logs, so nearly\n         * all symbols have counts <= 8. We ensure we have 8 bytes at the end of\n         * our buffer to handle the over-write.\n         */\n        {   U64 const add = 0x0101010101010101ull;\n            size_t pos = 0;\n            U64 sv = 0;\n            U32 s;\n            for (s=0; s<maxSV1; ++s, sv += add) {\n                int i;\n                int const n = normalizedCounter[s];\n                MEM_write64(spread + pos, sv);\n                for (i = 8; i < n; i += 8) {\n                    MEM_write64(spread + pos + i, sv);\n                }\n                pos += (size_t)n;\n        }   }\n        /* Now we spread those positions across the table.\n         * The benefit of doing it in two stages is that we avoid the\n         * variable size inner loop, which caused lots of branch misses.\n         * Now we can run through all the positions without any branch misses.\n         * We unroll the loop twice, since that is what empirically worked best.\n         */\n        {\n            size_t position = 0;\n            size_t s;\n            size_t const unroll = 2;\n            assert(tableSize % unroll == 0); /* FSE_MIN_TABLELOG is 5 */\n            for (s = 0; s < (size_t)tableSize; s += unroll) {\n                size_t u;\n                for (u = 0; u < unroll; ++u) {\n                    size_t const uPosition = (position + (u * step)) & tableMask;\n                    tableDecode[uPosition].symbol = spread[s + u];\n                }\n                position = (position + (unroll * step)) & tableMask;\n            }\n            assert(position == 0);\n        }\n    } else {\n        U32 const tableMask = tableSize-1;\n        U32 const step = FSE_TABLESTEP(tableSize);\n        U32 s, position = 0;\n        for (s=0; s<maxSV1; s++) {\n            int i;\n            for (i=0; i<normalizedCounter[s]; i++) {\n                tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;\n                position = (position + step) & tableMask;\n                while (position > highThreshold) position = (position + step) & tableMask;   /* lowprob area */\n        }   }\n        if (position!=0) return ERROR(GENERIC);   /* position must reach all cells once, otherwise normalizedCounter is incorrect */\n    }\n\n    /* Build Decoding table */\n    {   U32 u;\n        for (u=0; u<tableSize; u++) {\n            FSE_FUNCTION_TYPE const symbol = (FSE_FUNCTION_TYPE)(tableDecode[u].symbol);\n            U32 const nextState = symbolNext[symbol]++;\n            tableDecode[u].nbBits = (BYTE) (tableLog - ZSTD_highbit32(nextState) );\n            tableDecode[u].newState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);\n    }   }\n\n    return 0;\n}\n\nsize_t FSE_buildDTable_wksp(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize)\n{\n    return FSE_buildDTable_internal(dt, normalizedCounter, maxSymbolValue, tableLog, workSpace, wkspSize);\n}\n\n\n#ifndef FSE_COMMONDEFS_ONLY\n\n/*-*******************************************************\n*  Decompression (Byte symbols)\n*********************************************************/\n\nFORCE_INLINE_TEMPLATE size_t FSE_decompress_usingDTable_generic(\n          void* dst, size_t maxDstSize,\n    const void* cSrc, size_t cSrcSize,\n    const FSE_DTable* dt, const unsigned fast)\n{\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* op = ostart;\n    BYTE* const omax = op + maxDstSize;\n    BYTE* const olimit = omax-3;\n\n    BIT_DStream_t bitD;\n    FSE_DState_t state1;\n    FSE_DState_t state2;\n\n    /* Init */\n    CHECK_F(BIT_initDStream(&bitD, cSrc, cSrcSize));\n\n    FSE_initDState(&state1, &bitD, dt);\n    FSE_initDState(&state2, &bitD, dt);\n\n    RETURN_ERROR_IF(BIT_reloadDStream(&bitD)==BIT_DStream_overflow, corruption_detected, \"\");\n\n#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD)\n\n    /* 4 symbols per loop */\n    for ( ; (BIT_reloadDStream(&bitD)==BIT_DStream_unfinished) & (op<olimit) ; op+=4) {\n        op[0] = FSE_GETSYMBOL(&state1);\n\n        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BIT_reloadDStream(&bitD);\n\n        op[1] = FSE_GETSYMBOL(&state2);\n\n        if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            { if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) { op+=2; break; } }\n\n        op[2] = FSE_GETSYMBOL(&state1);\n\n        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BIT_reloadDStream(&bitD);\n\n        op[3] = FSE_GETSYMBOL(&state2);\n    }\n\n    /* tail */\n    /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */\n    while (1) {\n        if (op>(omax-2)) return ERROR(dstSize_tooSmall);\n        *op++ = FSE_GETSYMBOL(&state1);\n        if (BIT_reloadDStream(&bitD)==BIT_DStream_overflow) {\n            *op++ = FSE_GETSYMBOL(&state2);\n            break;\n        }\n\n        if (op>(omax-2)) return ERROR(dstSize_tooSmall);\n        *op++ = FSE_GETSYMBOL(&state2);\n        if (BIT_reloadDStream(&bitD)==BIT_DStream_overflow) {\n            *op++ = FSE_GETSYMBOL(&state1);\n            break;\n    }   }\n\n    assert(op >= ostart);\n    return (size_t)(op-ostart);\n}\n\ntypedef struct {\n    short ncount[FSE_MAX_SYMBOL_VALUE + 1];\n} FSE_DecompressWksp;\n\n\nFORCE_INLINE_TEMPLATE size_t FSE_decompress_wksp_body(\n        void* dst, size_t dstCapacity,\n        const void* cSrc, size_t cSrcSize,\n        unsigned maxLog, void* workSpace, size_t wkspSize,\n        int bmi2)\n{\n    const BYTE* const istart = (const BYTE*)cSrc;\n    const BYTE* ip = istart;\n    unsigned tableLog;\n    unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;\n    FSE_DecompressWksp* const wksp = (FSE_DecompressWksp*)workSpace;\n    size_t const dtablePos = sizeof(FSE_DecompressWksp) / sizeof(FSE_DTable);\n    FSE_DTable* const dtable = (FSE_DTable*)workSpace + dtablePos;\n\n    FSE_STATIC_ASSERT((FSE_MAX_SYMBOL_VALUE + 1) % 2 == 0);\n    if (wkspSize < sizeof(*wksp)) return ERROR(GENERIC);\n\n    /* correct offset to dtable depends on this property */\n    FSE_STATIC_ASSERT(sizeof(FSE_DecompressWksp) % sizeof(FSE_DTable) == 0);\n\n    /* normal FSE decoding mode */\n    {   size_t const NCountLength =\n            FSE_readNCount_bmi2(wksp->ncount, &maxSymbolValue, &tableLog, istart, cSrcSize, bmi2);\n        if (FSE_isError(NCountLength)) return NCountLength;\n        if (tableLog > maxLog) return ERROR(tableLog_tooLarge);\n        assert(NCountLength <= cSrcSize);\n        ip += NCountLength;\n        cSrcSize -= NCountLength;\n    }\n\n    if (FSE_DECOMPRESS_WKSP_SIZE(tableLog, maxSymbolValue) > wkspSize) return ERROR(tableLog_tooLarge);\n    assert(sizeof(*wksp) + FSE_DTABLE_SIZE(tableLog) <= wkspSize);\n    workSpace = (BYTE*)workSpace + sizeof(*wksp) + FSE_DTABLE_SIZE(tableLog);\n    wkspSize -= sizeof(*wksp) + FSE_DTABLE_SIZE(tableLog);\n\n    CHECK_F( FSE_buildDTable_internal(dtable, wksp->ncount, maxSymbolValue, tableLog, workSpace, wkspSize) );\n\n    {\n        const void* ptr = dtable;\n        const FSE_DTableHeader* DTableH = (const FSE_DTableHeader*)ptr;\n        const U32 fastMode = DTableH->fastMode;\n\n        /* select fast mode (static) */\n        if (fastMode) return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, dtable, 1);\n        return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, dtable, 0);\n    }\n}\n\n/* Avoids the FORCE_INLINE of the _body() function. */\nstatic size_t FSE_decompress_wksp_body_default(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize)\n{\n    return FSE_decompress_wksp_body(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, 0);\n}\n\n#if DYNAMIC_BMI2\nBMI2_TARGET_ATTRIBUTE static size_t FSE_decompress_wksp_body_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize)\n{\n    return FSE_decompress_wksp_body(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, 1);\n}\n#endif\n\nsize_t FSE_decompress_wksp_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize, int bmi2)\n{\n#if DYNAMIC_BMI2\n    if (bmi2) {\n        return FSE_decompress_wksp_body_bmi2(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize);\n    }\n#endif\n    (void)bmi2;\n    return FSE_decompress_wksp_body_default(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize);\n}\n\n#endif   /* FSE_COMMONDEFS_ONLY */\n"
  },
  {
    "path": "lib/common/huf.h",
    "content": "/* ******************************************************************\n * huff0 huffman codec,\n * part of Finite State Entropy library\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * You can contact the author at :\n * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n#ifndef HUF_H_298734234\n#define HUF_H_298734234\n\n/* *** Dependencies *** */\n#include \"zstd_deps.h\"    /* size_t */\n#include \"mem.h\"          /* U32 */\n#define FSE_STATIC_LINKING_ONLY\n#include \"fse.h\"\n\n/* ***   Tool functions *** */\n#define HUF_BLOCKSIZE_MAX (128 * 1024)   /**< maximum input size for a single block compressed with HUF_compress */\nsize_t HUF_compressBound(size_t size);   /**< maximum compressed size (worst case) */\n\n/* Error Management */\nunsigned    HUF_isError(size_t code);       /**< tells if a return value is an error code */\nconst char* HUF_getErrorName(size_t code);  /**< provides error code string (useful for debugging) */\n\n\n#define HUF_WORKSPACE_SIZE ((8 << 10) + 512 /* sorting scratch space */)\n#define HUF_WORKSPACE_SIZE_U64 (HUF_WORKSPACE_SIZE / sizeof(U64))\n\n/* *** Constants *** */\n#define HUF_TABLELOG_MAX      12      /* max runtime value of tableLog (due to static allocation); can be modified up to HUF_TABLELOG_ABSOLUTEMAX */\n#define HUF_TABLELOG_DEFAULT  11      /* default tableLog value when none specified */\n#define HUF_SYMBOLVALUE_MAX  255\n\n#define HUF_TABLELOG_ABSOLUTEMAX  12  /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */\n#if (HUF_TABLELOG_MAX > HUF_TABLELOG_ABSOLUTEMAX)\n#  error \"HUF_TABLELOG_MAX is too large !\"\n#endif\n\n\n/* ****************************************\n*  Static allocation\n******************************************/\n/* HUF buffer bounds */\n#define HUF_CTABLEBOUND 129\n#define HUF_BLOCKBOUND(size) (size + (size>>8) + 8)   /* only true when incompressible is pre-filtered with fast heuristic */\n#define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size))   /* Macro version, useful for static allocation */\n\n/* static allocation of HUF's Compression Table */\n/* this is a private definition, just exposed for allocation and strict aliasing purpose. never EVER access its members directly */\ntypedef size_t HUF_CElt;   /* consider it an incomplete type */\n#define HUF_CTABLE_SIZE_ST(maxSymbolValue)   ((maxSymbolValue)+2)   /* Use tables of size_t, for proper alignment */\n#define HUF_CTABLE_SIZE(maxSymbolValue)       (HUF_CTABLE_SIZE_ST(maxSymbolValue) * sizeof(size_t))\n#define HUF_CREATE_STATIC_CTABLE(name, maxSymbolValue) \\\n    HUF_CElt name[HUF_CTABLE_SIZE_ST(maxSymbolValue)] /* no final ; */\n\n/* static allocation of HUF's DTable */\ntypedef U32 HUF_DTable;\n#define HUF_DTABLE_SIZE(maxTableLog)   (1 + (1<<(maxTableLog)))\n#define HUF_CREATE_STATIC_DTABLEX1(DTable, maxTableLog) \\\n        HUF_DTable DTable[HUF_DTABLE_SIZE((maxTableLog)-1)] = { ((U32)((maxTableLog)-1) * 0x01000001) }\n#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \\\n        HUF_DTable DTable[HUF_DTABLE_SIZE(maxTableLog)] = { ((U32)(maxTableLog) * 0x01000001) }\n\n\n/* ****************************************\n*  Advanced decompression functions\n******************************************/\n\n/**\n * Huffman flags bitset.\n * For all flags, 0 is the default value.\n */\ntypedef enum {\n    /**\n     * If compiled with DYNAMIC_BMI2: Set flag only if the CPU supports BMI2 at runtime.\n     * Otherwise: Ignored.\n     */\n    HUF_flags_bmi2 = (1 << 0),\n    /**\n     * If set: Test possible table depths to find the one that produces the smallest header + encoded size.\n     * If unset: Use heuristic to find the table depth.\n     */\n    HUF_flags_optimalDepth = (1 << 1),\n    /**\n     * If set: If the previous table can encode the input, always reuse the previous table.\n     * If unset: If the previous table can encode the input, reuse the previous table if it results in a smaller output.\n     */\n    HUF_flags_preferRepeat = (1 << 2),\n    /**\n     * If set: Sample the input and check if the sample is uncompressible, if it is then don't attempt to compress.\n     * If unset: Always histogram the entire input.\n     */\n    HUF_flags_suspectUncompressible = (1 << 3),\n    /**\n     * If set: Don't use assembly implementations\n     * If unset: Allow using assembly implementations\n     */\n    HUF_flags_disableAsm = (1 << 4),\n    /**\n     * If set: Don't use the fast decoding loop, always use the fallback decoding loop.\n     * If unset: Use the fast decoding loop when possible.\n     */\n    HUF_flags_disableFast = (1 << 5)\n} HUF_flags_e;\n\n\n/* ****************************************\n *  HUF detailed API\n * ****************************************/\n#define HUF_OPTIMAL_DEPTH_THRESHOLD ZSTD_btultra\n\n/*! HUF_compress() does the following:\n *  1. count symbol occurrence from source[] into table count[] using FSE_count() (exposed within \"fse.h\")\n *  2. (optional) refine tableLog using HUF_optimalTableLog()\n *  3. build Huffman table from count using HUF_buildCTable()\n *  4. save Huffman table to memory buffer using HUF_writeCTable()\n *  5. encode the data stream using HUF_compress4X_usingCTable()\n *\n *  The following API allows targeting specific sub-functions for advanced tasks.\n *  For example, it's possible to compress several blocks using the same 'CTable',\n *  or to save and regenerate 'CTable' using external methods.\n */\nunsigned HUF_minTableLog(unsigned symbolCardinality);\nunsigned HUF_cardinality(const unsigned* count, unsigned maxSymbolValue);\nunsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, void* workSpace,\n size_t wkspSize, HUF_CElt* table, const unsigned* count, int flags); /* table is used as scratch space for building and testing tables, not a return value */\nsize_t HUF_writeCTable_wksp(void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog, void* workspace, size_t workspaceSize);\nsize_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int flags);\nsize_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue);\nint HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue);\n\ntypedef enum {\n   HUF_repeat_none,  /**< Cannot use the previous table */\n   HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1, 4}X_repeat */\n   HUF_repeat_valid  /**< Can use the previous table and it is assumed to be valid */\n } HUF_repeat;\n\n/** HUF_compress4X_repeat() :\n *  Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.\n *  If it uses hufTable it does not modify hufTable or repeat.\n *  If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.\n *  If preferRepeat then the old table will always be used if valid.\n *  If suspectUncompressible then some sampling checks will be run to potentially skip huffman coding */\nsize_t HUF_compress4X_repeat(void* dst, size_t dstSize,\n                       const void* src, size_t srcSize,\n                       unsigned maxSymbolValue, unsigned tableLog,\n                       void* workSpace, size_t wkspSize,    /**< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */\n                       HUF_CElt* hufTable, HUF_repeat* repeat, int flags);\n\n/** HUF_buildCTable_wksp() :\n *  Same as HUF_buildCTable(), but using externally allocated scratch buffer.\n * `workSpace` must be aligned on 4-bytes boundaries, and its size must be >= HUF_CTABLE_WORKSPACE_SIZE.\n */\n#define HUF_CTABLE_WORKSPACE_SIZE_U32 ((4 * (HUF_SYMBOLVALUE_MAX + 1)) + 192)\n#define HUF_CTABLE_WORKSPACE_SIZE (HUF_CTABLE_WORKSPACE_SIZE_U32 * sizeof(unsigned))\nsize_t HUF_buildCTable_wksp (HUF_CElt* tree,\n                       const unsigned* count, U32 maxSymbolValue, U32 maxNbBits,\n                             void* workSpace, size_t wkspSize);\n\n/*! HUF_readStats() :\n *  Read compact Huffman tree, saved by HUF_writeCTable().\n * `huffWeight` is destination buffer.\n * @return : size read from `src` , or an error Code .\n *  Note : Needed by HUF_readCTable() and HUF_readDTableXn() . */\nsize_t HUF_readStats(BYTE* huffWeight, size_t hwSize,\n                     U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr,\n                     const void* src, size_t srcSize);\n\n/*! HUF_readStats_wksp() :\n * Same as HUF_readStats() but takes an external workspace which must be\n * 4-byte aligned and its size must be >= HUF_READ_STATS_WORKSPACE_SIZE.\n * If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0.\n */\n#define HUF_READ_STATS_WORKSPACE_SIZE_U32 FSE_DECOMPRESS_WKSP_SIZE_U32(6, HUF_TABLELOG_MAX-1)\n#define HUF_READ_STATS_WORKSPACE_SIZE (HUF_READ_STATS_WORKSPACE_SIZE_U32 * sizeof(unsigned))\nsize_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize,\n                          U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr,\n                          const void* src, size_t srcSize,\n                          void* workspace, size_t wkspSize,\n                          int flags);\n\n/** HUF_readCTable() :\n *  Loading a CTable saved with HUF_writeCTable() */\nsize_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned *hasZeroWeights);\n\n/** HUF_getNbBitsFromCTable() :\n *  Read nbBits from CTable symbolTable, for symbol `symbolValue` presumed <= HUF_SYMBOLVALUE_MAX\n *  Note 1 : If symbolValue > HUF_readCTableHeader(symbolTable).maxSymbolValue, returns 0\n *  Note 2 : is not inlined, as HUF_CElt definition is private\n */\nU32 HUF_getNbBitsFromCTable(const HUF_CElt* symbolTable, U32 symbolValue);\n\ntypedef struct {\n    BYTE tableLog;\n    BYTE maxSymbolValue;\n    BYTE unused[sizeof(size_t) - 2];\n} HUF_CTableHeader;\n\n/** HUF_readCTableHeader() :\n *  @returns The header from the CTable specifying the tableLog and the maxSymbolValue.\n */\nHUF_CTableHeader HUF_readCTableHeader(HUF_CElt const* ctable);\n\n/*\n * HUF_decompress() does the following:\n * 1. select the decompression algorithm (X1, X2) based on pre-computed heuristics\n * 2. build Huffman table from save, using HUF_readDTableX?()\n * 3. decode 1 or 4 segments in parallel using HUF_decompress?X?_usingDTable()\n */\n\n/** HUF_selectDecoder() :\n *  Tells which decoder is likely to decode faster,\n *  based on a set of pre-computed metrics.\n * @return : 0==HUF_decompress4X1, 1==HUF_decompress4X2 .\n *  Assumption : 0 < dstSize <= 128 KB */\nU32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize);\n\n/**\n *  The minimum workspace size for the `workSpace` used in\n *  HUF_readDTableX1_wksp() and HUF_readDTableX2_wksp().\n *\n *  The space used depends on HUF_TABLELOG_MAX, ranging from ~1500 bytes when\n *  HUF_TABLE_LOG_MAX=12 to ~1850 bytes when HUF_TABLE_LOG_MAX=15.\n *  Buffer overflow errors may potentially occur if code modifications result in\n *  a required workspace size greater than that specified in the following\n *  macro.\n */\n#define HUF_DECOMPRESS_WORKSPACE_SIZE ((2 << 10) + (1 << 9))\n#define HUF_DECOMPRESS_WORKSPACE_SIZE_U32 (HUF_DECOMPRESS_WORKSPACE_SIZE / sizeof(U32))\n\n\n/* ====================== */\n/* single stream variants */\n/* ====================== */\n\nsize_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int flags);\n/** HUF_compress1X_repeat() :\n *  Same as HUF_compress1X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.\n *  If it uses hufTable it does not modify hufTable or repeat.\n *  If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.\n *  If preferRepeat then the old table will always be used if valid.\n *  If suspectUncompressible then some sampling checks will be run to potentially skip huffman coding */\nsize_t HUF_compress1X_repeat(void* dst, size_t dstSize,\n                       const void* src, size_t srcSize,\n                       unsigned maxSymbolValue, unsigned tableLog,\n                       void* workSpace, size_t wkspSize,   /**< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */\n                       HUF_CElt* hufTable, HUF_repeat* repeat, int flags);\n\nsize_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags);\n#ifndef HUF_FORCE_DECOMPRESS_X1\nsize_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags);   /**< double-symbols decoder */\n#endif\n\n/* BMI2 variants.\n * If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0.\n */\nsize_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int flags);\n#ifndef HUF_FORCE_DECOMPRESS_X2\nsize_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags);\n#endif\nsize_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int flags);\nsize_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags);\n#ifndef HUF_FORCE_DECOMPRESS_X2\nsize_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int flags);\n#endif\n#ifndef HUF_FORCE_DECOMPRESS_X1\nsize_t HUF_readDTableX2_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int flags);\n#endif\n\n#endif   /* HUF_H_298734234 */\n"
  },
  {
    "path": "lib/common/mem.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef MEM_H_MODULE\n#define MEM_H_MODULE\n\n/*-****************************************\n*  Dependencies\n******************************************/\n#include <stddef.h>  /* size_t, ptrdiff_t */\n#include \"compiler.h\"  /* __has_builtin */\n#include \"debug.h\"  /* DEBUG_STATIC_ASSERT */\n#include \"zstd_deps.h\"  /* ZSTD_memcpy */\n\n\n/*-****************************************\n*  Compiler specifics\n******************************************/\n#if defined(_MSC_VER)   /* Visual Studio */\n#   include <stdlib.h>  /* _byteswap_ulong */\n#   include <intrin.h>  /* _byteswap_* */\n#elif defined(__ICCARM__)\n#   include <intrinsics.h>\n#endif\n\n/*-**************************************************************\n*  Basic Types\n*****************************************************************/\n#if  !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )\n#  if defined(_AIX)\n#    include <inttypes.h>\n#  else\n#    include <stdint.h> /* intptr_t */\n#  endif\n  typedef   uint8_t BYTE;\n  typedef   uint8_t U8;\n  typedef    int8_t S8;\n  typedef  uint16_t U16;\n  typedef   int16_t S16;\n  typedef  uint32_t U32;\n  typedef   int32_t S32;\n  typedef  uint64_t U64;\n  typedef   int64_t S64;\n#else\n# include <limits.h>\n#if CHAR_BIT != 8\n#  error \"this implementation requires char to be exactly 8-bit type\"\n#endif\n  typedef unsigned char      BYTE;\n  typedef unsigned char      U8;\n  typedef   signed char      S8;\n#if USHRT_MAX != 65535\n#  error \"this implementation requires short to be exactly 16-bit type\"\n#endif\n  typedef unsigned short      U16;\n  typedef   signed short      S16;\n#if UINT_MAX != 4294967295\n#  error \"this implementation requires int to be exactly 32-bit type\"\n#endif\n  typedef unsigned int        U32;\n  typedef   signed int        S32;\n/* note : there are no limits defined for long long type in C90.\n * limits exist in C99, however, in such case, <stdint.h> is preferred */\n  typedef unsigned long long  U64;\n  typedef   signed long long  S64;\n#endif\n\n/*-**************************************************************\n*  Memory I/O API\n*****************************************************************/\n/*=== Static platform detection ===*/\nMEM_STATIC unsigned MEM_32bits(void);\nMEM_STATIC unsigned MEM_64bits(void);\nMEM_STATIC unsigned MEM_isLittleEndian(void);\n\n/*=== Native unaligned read/write ===*/\nMEM_STATIC U16 MEM_read16(const void* memPtr);\nMEM_STATIC U32 MEM_read32(const void* memPtr);\nMEM_STATIC U64 MEM_read64(const void* memPtr);\nMEM_STATIC size_t MEM_readST(const void* memPtr);\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value);\nMEM_STATIC void MEM_write32(void* memPtr, U32 value);\nMEM_STATIC void MEM_write64(void* memPtr, U64 value);\n\n/*=== Little endian unaligned read/write ===*/\nMEM_STATIC U16 MEM_readLE16(const void* memPtr);\nMEM_STATIC U32 MEM_readLE24(const void* memPtr);\nMEM_STATIC U32 MEM_readLE32(const void* memPtr);\nMEM_STATIC U64 MEM_readLE64(const void* memPtr);\nMEM_STATIC size_t MEM_readLEST(const void* memPtr);\n\nMEM_STATIC void MEM_writeLE16(void* memPtr, U16 val);\nMEM_STATIC void MEM_writeLE24(void* memPtr, U32 val);\nMEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32);\nMEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64);\nMEM_STATIC void MEM_writeLEST(void* memPtr, size_t val);\n\n/*=== Big endian unaligned read/write ===*/\nMEM_STATIC U32 MEM_readBE32(const void* memPtr);\nMEM_STATIC U64 MEM_readBE64(const void* memPtr);\nMEM_STATIC size_t MEM_readBEST(const void* memPtr);\n\nMEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32);\nMEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64);\nMEM_STATIC void MEM_writeBEST(void* memPtr, size_t val);\n\n/*=== Byteswap ===*/\nMEM_STATIC U32 MEM_swap32(U32 in);\nMEM_STATIC U64 MEM_swap64(U64 in);\nMEM_STATIC size_t MEM_swapST(size_t in);\n\n\n/*-**************************************************************\n*  Memory I/O Implementation\n*****************************************************************/\n/* MEM_FORCE_MEMORY_ACCESS : For accessing unaligned memory:\n * Method 0 : always use `memcpy()`. Safe and portable.\n * Method 1 : Use compiler extension to set unaligned access.\n * Method 2 : direct access. This method is portable but violate C standard.\n *            It can generate buggy code on targets depending on alignment.\n * Default  : method 1 if supported, else method 0\n */\n#ifndef MEM_FORCE_MEMORY_ACCESS   /* can be defined externally, on command line for example */\n#  ifdef __GNUC__\n#    define MEM_FORCE_MEMORY_ACCESS 1\n#  endif\n#endif\n\nMEM_STATIC unsigned MEM_32bits(void) { return sizeof(size_t)==4; }\nMEM_STATIC unsigned MEM_64bits(void) { return sizeof(size_t)==8; }\n\nMEM_STATIC unsigned MEM_isLittleEndian(void)\n{\n#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)\n    return 1;\n#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)\n    return 0;\n#elif defined(__clang__) && __LITTLE_ENDIAN__\n    return 1;\n#elif defined(__clang__) && __BIG_ENDIAN__\n    return 0;\n#elif defined(_MSC_VER) && (_M_X64 || _M_IX86)\n    return 1;\n#elif defined(__DMC__) && defined(_M_IX86)\n    return 1;\n#elif defined(__IAR_SYSTEMS_ICC__) && __LITTLE_ENDIAN__\n    return 1;\n#else\n    const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */\n    return one.c[0];\n#endif\n}\n\n#if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2)\n\n/* violates C standard, by lying on structure alignment.\nOnly use if no other choice to achieve best performance on target platform */\nMEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }\nMEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }\nMEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }\nMEM_STATIC size_t MEM_readST(const void* memPtr) { return *(const size_t*) memPtr; }\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }\nMEM_STATIC void MEM_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; }\nMEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(U64*)memPtr = value; }\n\n#elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1)\n\ntypedef __attribute__((aligned(1))) U16 unalign16;\ntypedef __attribute__((aligned(1))) U32 unalign32;\ntypedef __attribute__((aligned(1))) U64 unalign64;\ntypedef __attribute__((aligned(1))) size_t unalignArch;\n\nMEM_STATIC U16 MEM_read16(const void* ptr) { return *(const unalign16*)ptr; }\nMEM_STATIC U32 MEM_read32(const void* ptr) { return *(const unalign32*)ptr; }\nMEM_STATIC U64 MEM_read64(const void* ptr) { return *(const unalign64*)ptr; }\nMEM_STATIC size_t MEM_readST(const void* ptr) { return *(const unalignArch*)ptr; }\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(unalign16*)memPtr = value; }\nMEM_STATIC void MEM_write32(void* memPtr, U32 value) { *(unalign32*)memPtr = value; }\nMEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(unalign64*)memPtr = value; }\n\n#else\n\n/* default method, safe and standard.\n   can sometimes prove slower */\n\nMEM_STATIC U16 MEM_read16(const void* memPtr)\n{\n    U16 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U32 MEM_read32(const void* memPtr)\n{\n    U32 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U64 MEM_read64(const void* memPtr)\n{\n    U64 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC size_t MEM_readST(const void* memPtr)\n{\n    size_t val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value)\n{\n    ZSTD_memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC void MEM_write32(void* memPtr, U32 value)\n{\n    ZSTD_memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC void MEM_write64(void* memPtr, U64 value)\n{\n    ZSTD_memcpy(memPtr, &value, sizeof(value));\n}\n\n#endif /* MEM_FORCE_MEMORY_ACCESS */\n\nMEM_STATIC U32 MEM_swap32_fallback(U32 in)\n{\n    return  ((in << 24) & 0xff000000 ) |\n            ((in <<  8) & 0x00ff0000 ) |\n            ((in >>  8) & 0x0000ff00 ) |\n            ((in >> 24) & 0x000000ff );\n}\n\nMEM_STATIC U32 MEM_swap32(U32 in)\n{\n#if defined(_MSC_VER)     /* Visual Studio */\n    return _byteswap_ulong(in);\n#elif (defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) \\\n  || (defined(__clang__) && __has_builtin(__builtin_bswap32))\n    return __builtin_bswap32(in);\n#elif defined(__ICCARM__)\n    return __REV(in);\n#else\n    return MEM_swap32_fallback(in);\n#endif\n}\n\nMEM_STATIC U64 MEM_swap64_fallback(U64 in)\n{\n     return  ((in << 56) & 0xff00000000000000ULL) |\n            ((in << 40) & 0x00ff000000000000ULL) |\n            ((in << 24) & 0x0000ff0000000000ULL) |\n            ((in << 8)  & 0x000000ff00000000ULL) |\n            ((in >> 8)  & 0x00000000ff000000ULL) |\n            ((in >> 24) & 0x0000000000ff0000ULL) |\n            ((in >> 40) & 0x000000000000ff00ULL) |\n            ((in >> 56) & 0x00000000000000ffULL);\n}\n\nMEM_STATIC U64 MEM_swap64(U64 in)\n{\n#if defined(_MSC_VER)     /* Visual Studio */\n    return _byteswap_uint64(in);\n#elif (defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) \\\n  || (defined(__clang__) && __has_builtin(__builtin_bswap64))\n    return __builtin_bswap64(in);\n#else\n    return MEM_swap64_fallback(in);\n#endif\n}\n\nMEM_STATIC size_t MEM_swapST(size_t in)\n{\n    if (MEM_32bits())\n        return (size_t)MEM_swap32((U32)in);\n    else\n        return (size_t)MEM_swap64((U64)in);\n}\n\n/*=== Little endian r/w ===*/\n\nMEM_STATIC U16 MEM_readLE16(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read16(memPtr);\n    else {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U16)(p[0] + (p[1]<<8));\n    }\n}\n\nMEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)\n{\n    if (MEM_isLittleEndian()) {\n        MEM_write16(memPtr, val);\n    } else {\n        BYTE* p = (BYTE*)memPtr;\n        p[0] = (BYTE)val;\n        p[1] = (BYTE)(val>>8);\n    }\n}\n\nMEM_STATIC U32 MEM_readLE24(const void* memPtr)\n{\n    return (U32)MEM_readLE16(memPtr) + ((U32)(((const BYTE*)memPtr)[2]) << 16);\n}\n\nMEM_STATIC void MEM_writeLE24(void* memPtr, U32 val)\n{\n    MEM_writeLE16(memPtr, (U16)val);\n    ((BYTE*)memPtr)[2] = (BYTE)(val>>16);\n}\n\nMEM_STATIC U32 MEM_readLE32(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read32(memPtr);\n    else\n        return MEM_swap32(MEM_read32(memPtr));\n}\n\nMEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32)\n{\n    if (MEM_isLittleEndian())\n        MEM_write32(memPtr, val32);\n    else\n        MEM_write32(memPtr, MEM_swap32(val32));\n}\n\nMEM_STATIC U64 MEM_readLE64(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read64(memPtr);\n    else\n        return MEM_swap64(MEM_read64(memPtr));\n}\n\nMEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64)\n{\n    if (MEM_isLittleEndian())\n        MEM_write64(memPtr, val64);\n    else\n        MEM_write64(memPtr, MEM_swap64(val64));\n}\n\nMEM_STATIC size_t MEM_readLEST(const void* memPtr)\n{\n    if (MEM_32bits())\n        return (size_t)MEM_readLE32(memPtr);\n    else\n        return (size_t)MEM_readLE64(memPtr);\n}\n\nMEM_STATIC void MEM_writeLEST(void* memPtr, size_t val)\n{\n    if (MEM_32bits())\n        MEM_writeLE32(memPtr, (U32)val);\n    else\n        MEM_writeLE64(memPtr, (U64)val);\n}\n\n/*=== Big endian r/w ===*/\n\nMEM_STATIC U32 MEM_readBE32(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_swap32(MEM_read32(memPtr));\n    else\n        return MEM_read32(memPtr);\n}\n\nMEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32)\n{\n    if (MEM_isLittleEndian())\n        MEM_write32(memPtr, MEM_swap32(val32));\n    else\n        MEM_write32(memPtr, val32);\n}\n\nMEM_STATIC U64 MEM_readBE64(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_swap64(MEM_read64(memPtr));\n    else\n        return MEM_read64(memPtr);\n}\n\nMEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64)\n{\n    if (MEM_isLittleEndian())\n        MEM_write64(memPtr, MEM_swap64(val64));\n    else\n        MEM_write64(memPtr, val64);\n}\n\nMEM_STATIC size_t MEM_readBEST(const void* memPtr)\n{\n    if (MEM_32bits())\n        return (size_t)MEM_readBE32(memPtr);\n    else\n        return (size_t)MEM_readBE64(memPtr);\n}\n\nMEM_STATIC void MEM_writeBEST(void* memPtr, size_t val)\n{\n    if (MEM_32bits())\n        MEM_writeBE32(memPtr, (U32)val);\n    else\n        MEM_writeBE64(memPtr, (U64)val);\n}\n\n/* code only tested on 32 and 64 bits systems */\nMEM_STATIC void MEM_check(void) { DEBUG_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); }\n\n#endif /* MEM_H_MODULE */\n"
  },
  {
    "path": "lib/common/pool.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/* ======   Dependencies   ======= */\n#include \"../common/allocations.h\"  /* ZSTD_customCalloc, ZSTD_customFree */\n#include \"zstd_deps.h\" /* size_t */\n#include \"debug.h\"     /* assert */\n#include \"pool.h\"\n\n/* ======   Compiler specifics   ====== */\n#if defined(_MSC_VER)\n#  pragma warning(disable : 4204)        /* disable: C4204: non-constant aggregate initializer */\n#endif\n\n\n#ifdef ZSTD_MULTITHREAD\n\n#include \"threading.h\"   /* pthread adaptation */\n\n/* A job is a function and an opaque argument */\ntypedef struct POOL_job_s {\n    POOL_function function;\n    void *opaque;\n} POOL_job;\n\nstruct POOL_ctx_s {\n    ZSTD_customMem customMem;\n    /* Keep track of the threads */\n    ZSTD_pthread_t* threads;\n    size_t threadCapacity;\n    size_t threadLimit;\n\n    /* The queue is a circular buffer */\n    POOL_job *queue;\n    size_t queueHead;\n    size_t queueTail;\n    size_t queueSize;\n\n    /* The number of threads working on jobs */\n    size_t numThreadsBusy;\n    /* Indicates if the queue is empty */\n    int queueEmpty;\n\n    /* The mutex protects the queue */\n    ZSTD_pthread_mutex_t queueMutex;\n    /* Condition variable for pushers to wait on when the queue is full */\n    ZSTD_pthread_cond_t queuePushCond;\n    /* Condition variables for poppers to wait on when the queue is empty */\n    ZSTD_pthread_cond_t queuePopCond;\n    /* Indicates if the queue is shutting down */\n    int shutdown;\n};\n\n/* POOL_thread() :\n * Work thread for the thread pool.\n * Waits for jobs and executes them.\n * @returns : NULL on failure else non-null.\n */\nstatic void* POOL_thread(void* opaque) {\n    POOL_ctx* const ctx = (POOL_ctx*)opaque;\n    if (!ctx) { return NULL; }\n    for (;;) {\n        /* Lock the mutex and wait for a non-empty queue or until shutdown */\n        ZSTD_pthread_mutex_lock(&ctx->queueMutex);\n\n        while ( ctx->queueEmpty\n            || (ctx->numThreadsBusy >= ctx->threadLimit) ) {\n            if (ctx->shutdown) {\n                /* even if !queueEmpty, (possible if numThreadsBusy >= threadLimit),\n                 * a few threads will be shutdown while !queueEmpty,\n                 * but enough threads will remain active to finish the queue */\n                ZSTD_pthread_mutex_unlock(&ctx->queueMutex);\n                return opaque;\n            }\n            ZSTD_pthread_cond_wait(&ctx->queuePopCond, &ctx->queueMutex);\n        }\n        /* Pop a job off the queue */\n        {   POOL_job const job = ctx->queue[ctx->queueHead];\n            ctx->queueHead = (ctx->queueHead + 1) % ctx->queueSize;\n            ctx->numThreadsBusy++;\n            ctx->queueEmpty = (ctx->queueHead == ctx->queueTail);\n            /* Unlock the mutex, signal a pusher, and run the job */\n            ZSTD_pthread_cond_signal(&ctx->queuePushCond);\n            ZSTD_pthread_mutex_unlock(&ctx->queueMutex);\n\n            job.function(job.opaque);\n\n            /* If the intended queue size was 0, signal after finishing job */\n            ZSTD_pthread_mutex_lock(&ctx->queueMutex);\n            ctx->numThreadsBusy--;\n            ZSTD_pthread_cond_signal(&ctx->queuePushCond);\n            ZSTD_pthread_mutex_unlock(&ctx->queueMutex);\n        }\n    }  /* for (;;) */\n    assert(0);  /* Unreachable */\n}\n\n/* ZSTD_createThreadPool() : public access point */\nPOOL_ctx* ZSTD_createThreadPool(size_t numThreads) {\n    return POOL_create (numThreads, 0);\n}\n\nPOOL_ctx* POOL_create(size_t numThreads, size_t queueSize) {\n    return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem);\n}\n\nPOOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize,\n                               ZSTD_customMem customMem)\n{\n    POOL_ctx* ctx;\n    /* Check parameters */\n    if (!numThreads) { return NULL; }\n    /* Allocate the context and zero initialize */\n    ctx = (POOL_ctx*)ZSTD_customCalloc(sizeof(POOL_ctx), customMem);\n    if (!ctx) { return NULL; }\n    /* Initialize the job queue.\n     * It needs one extra space since one space is wasted to differentiate\n     * empty and full queues.\n     */\n    ctx->queueSize = queueSize + 1;\n    ctx->queue = (POOL_job*)ZSTD_customCalloc(ctx->queueSize * sizeof(POOL_job), customMem);\n    ctx->queueHead = 0;\n    ctx->queueTail = 0;\n    ctx->numThreadsBusy = 0;\n    ctx->queueEmpty = 1;\n    {\n        int error = 0;\n        error |= ZSTD_pthread_mutex_init(&ctx->queueMutex, NULL);\n        error |= ZSTD_pthread_cond_init(&ctx->queuePushCond, NULL);\n        error |= ZSTD_pthread_cond_init(&ctx->queuePopCond, NULL);\n        if (error) { POOL_free(ctx); return NULL; }\n    }\n    ctx->shutdown = 0;\n    /* Allocate space for the thread handles */\n    ctx->threads = (ZSTD_pthread_t*)ZSTD_customCalloc(numThreads * sizeof(ZSTD_pthread_t), customMem);\n    ctx->threadCapacity = 0;\n    ctx->threadLimit = numThreads;\n    ctx->customMem = customMem;\n    /* Check for errors */\n    if (!ctx->threads || !ctx->queue) { POOL_free(ctx); return NULL; }\n    /* Initialize the threads */\n    while (ctx->threadCapacity < numThreads) {\n        if (ZSTD_pthread_create(&ctx->threads[ctx->threadCapacity++], NULL, &POOL_thread, ctx)) {\n            --ctx->threadCapacity;\n            POOL_free(ctx);\n            return NULL;\n        }\n    }\n    return ctx;\n}\n\n/*! POOL_join() :\n    Shutdown the queue, wake any sleeping threads, and join all of the threads.\n*/\nstatic void POOL_join(POOL_ctx* ctx) {\n    /* Shut down the queue */\n    ZSTD_pthread_mutex_lock(&ctx->queueMutex);\n    ctx->shutdown = 1;\n    ZSTD_pthread_mutex_unlock(&ctx->queueMutex);\n    /* Wake up sleeping threads */\n    ZSTD_pthread_cond_broadcast(&ctx->queuePushCond);\n    ZSTD_pthread_cond_broadcast(&ctx->queuePopCond);\n    /* Join all of the threads */\n    {   size_t i;\n        for (i = 0; i < ctx->threadCapacity; ++i) {\n            ZSTD_pthread_join(ctx->threads[i]);  /* note : could fail */\n    }   }\n}\n\nvoid POOL_free(POOL_ctx *ctx) {\n    if (!ctx) { return; }\n    POOL_join(ctx);\n    ZSTD_pthread_mutex_destroy(&ctx->queueMutex);\n    ZSTD_pthread_cond_destroy(&ctx->queuePushCond);\n    ZSTD_pthread_cond_destroy(&ctx->queuePopCond);\n    ZSTD_customFree(ctx->queue, ctx->customMem);\n    ZSTD_customFree(ctx->threads, ctx->customMem);\n    ZSTD_customFree(ctx, ctx->customMem);\n}\n\n/*! POOL_joinJobs() :\n *  Waits for all queued jobs to finish executing.\n */\nvoid POOL_joinJobs(POOL_ctx* ctx) {\n    ZSTD_pthread_mutex_lock(&ctx->queueMutex);\n    while(!ctx->queueEmpty || ctx->numThreadsBusy > 0) {\n        ZSTD_pthread_cond_wait(&ctx->queuePushCond, &ctx->queueMutex);\n    }\n    ZSTD_pthread_mutex_unlock(&ctx->queueMutex);\n}\n\nvoid ZSTD_freeThreadPool (ZSTD_threadPool* pool) {\n  POOL_free (pool);\n}\n\nsize_t POOL_sizeof(const POOL_ctx* ctx) {\n    if (ctx==NULL) return 0;  /* supports sizeof NULL */\n    return sizeof(*ctx)\n        + ctx->queueSize * sizeof(POOL_job)\n        + ctx->threadCapacity * sizeof(ZSTD_pthread_t);\n}\n\n\n/* @return : 0 on success, 1 on error */\nstatic int POOL_resize_internal(POOL_ctx* ctx, size_t numThreads)\n{\n    if (numThreads <= ctx->threadCapacity) {\n        if (!numThreads) return 1;\n        ctx->threadLimit = numThreads;\n        return 0;\n    }\n    /* numThreads > threadCapacity */\n    ctx->threadLimit = numThreads;\n    {   ZSTD_pthread_t* const threadPool = (ZSTD_pthread_t*)ZSTD_customCalloc(numThreads * sizeof(ZSTD_pthread_t), ctx->customMem);\n        if (!threadPool) return 1;\n        /* extend existing thread pool */\n        ZSTD_memcpy(threadPool, ctx->threads, ctx->threadCapacity * sizeof(ZSTD_pthread_t));\n        ZSTD_customFree(ctx->threads, ctx->customMem);\n        ctx->threads = threadPool;\n        /* Initialize additional threads */\n        while (ctx->threadCapacity < numThreads) {\n            if (ZSTD_pthread_create(&threadPool[ctx->threadCapacity++], NULL, &POOL_thread, ctx)) {\n                --ctx->threadCapacity;\n                return 1;\n            }\n        }\n    }\n    /* successfully expanded */\n    return 0;\n}\n\n/* @return : 0 on success, 1 on error */\nint POOL_resize(POOL_ctx* ctx, size_t numThreads)\n{\n    int result;\n    if (ctx==NULL) return 1;\n    ZSTD_pthread_mutex_lock(&ctx->queueMutex);\n    result = POOL_resize_internal(ctx, numThreads);\n    ZSTD_pthread_cond_broadcast(&ctx->queuePopCond);\n    ZSTD_pthread_mutex_unlock(&ctx->queueMutex);\n    return result;\n}\n\n/**\n * Returns 1 if the queue is full and 0 otherwise.\n *\n * When queueSize is 1 (pool was created with an intended queueSize of 0),\n * then a queue is empty if there is a thread free _and_ no job is waiting.\n */\nstatic int isQueueFull(POOL_ctx const* ctx) {\n    if (ctx->queueSize > 1) {\n        return ctx->queueHead == ((ctx->queueTail + 1) % ctx->queueSize);\n    } else {\n        return (ctx->numThreadsBusy == ctx->threadLimit) ||\n               !ctx->queueEmpty;\n    }\n}\n\n\nstatic void\nPOOL_add_internal(POOL_ctx* ctx, POOL_function function, void *opaque)\n{\n    POOL_job job;\n    job.function = function;\n    job.opaque = opaque;\n    assert(ctx != NULL);\n    if (ctx->shutdown) return;\n\n    ctx->queueEmpty = 0;\n    ctx->queue[ctx->queueTail] = job;\n    ctx->queueTail = (ctx->queueTail + 1) % ctx->queueSize;\n    ZSTD_pthread_cond_signal(&ctx->queuePopCond);\n}\n\nvoid POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque)\n{\n    assert(ctx != NULL);\n    ZSTD_pthread_mutex_lock(&ctx->queueMutex);\n    /* Wait until there is space in the queue for the new job */\n    while (isQueueFull(ctx) && (!ctx->shutdown)) {\n        ZSTD_pthread_cond_wait(&ctx->queuePushCond, &ctx->queueMutex);\n    }\n    POOL_add_internal(ctx, function, opaque);\n    ZSTD_pthread_mutex_unlock(&ctx->queueMutex);\n}\n\n\nint POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque)\n{\n    assert(ctx != NULL);\n    ZSTD_pthread_mutex_lock(&ctx->queueMutex);\n    if (isQueueFull(ctx)) {\n        ZSTD_pthread_mutex_unlock(&ctx->queueMutex);\n        return 0;\n    }\n    POOL_add_internal(ctx, function, opaque);\n    ZSTD_pthread_mutex_unlock(&ctx->queueMutex);\n    return 1;\n}\n\n\n#else  /* ZSTD_MULTITHREAD  not defined */\n\n/* ========================== */\n/* No multi-threading support */\n/* ========================== */\n\n\n/* We don't need any data, but if it is empty, malloc() might return NULL. */\nstruct POOL_ctx_s {\n    int dummy;\n};\nstatic POOL_ctx g_poolCtx;\n\nPOOL_ctx* POOL_create(size_t numThreads, size_t queueSize) {\n    return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem);\n}\n\nPOOL_ctx*\nPOOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customMem customMem)\n{\n    (void)numThreads;\n    (void)queueSize;\n    (void)customMem;\n    return &g_poolCtx;\n}\n\nvoid POOL_free(POOL_ctx* ctx) {\n    assert(!ctx || ctx == &g_poolCtx);\n    (void)ctx;\n}\n\nvoid POOL_joinJobs(POOL_ctx* ctx){\n    assert(!ctx || ctx == &g_poolCtx);\n    (void)ctx;\n}\n\nint POOL_resize(POOL_ctx* ctx, size_t numThreads) {\n    (void)ctx; (void)numThreads;\n    return 0;\n}\n\nvoid POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque) {\n    (void)ctx;\n    function(opaque);\n}\n\nint POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque) {\n    (void)ctx;\n    function(opaque);\n    return 1;\n}\n\nsize_t POOL_sizeof(const POOL_ctx* ctx) {\n    if (ctx==NULL) return 0;  /* supports sizeof NULL */\n    assert(ctx == &g_poolCtx);\n    return sizeof(*ctx);\n}\n\n#endif  /* ZSTD_MULTITHREAD */\n"
  },
  {
    "path": "lib/common/pool.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef POOL_H\n#define POOL_H\n\n\n#include \"zstd_deps.h\"\n#define ZSTD_STATIC_LINKING_ONLY   /* ZSTD_customMem */\n#include \"../zstd.h\"\n\ntypedef struct POOL_ctx_s POOL_ctx;\n\n/*! POOL_create() :\n *  Create a thread pool with at most `numThreads` threads.\n * `numThreads` must be at least 1.\n *  The maximum number of queued jobs before blocking is `queueSize`.\n * @return : POOL_ctx pointer on success, else NULL.\n*/\nPOOL_ctx* POOL_create(size_t numThreads, size_t queueSize);\n\nPOOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize,\n                               ZSTD_customMem customMem);\n\n/*! POOL_free() :\n *  Free a thread pool returned by POOL_create().\n */\nvoid POOL_free(POOL_ctx* ctx);\n\n\n/*! POOL_joinJobs() :\n *  Waits for all queued jobs to finish executing.\n */\nvoid POOL_joinJobs(POOL_ctx* ctx);\n\n/*! POOL_resize() :\n *  Expands or shrinks pool's number of threads.\n *  This is more efficient than releasing + creating a new context,\n *  since it tries to preserve and reuse existing threads.\n * `numThreads` must be at least 1.\n * @return : 0 when resize was successful,\n *           !0 (typically 1) if there is an error.\n *    note : only numThreads can be resized, queueSize remains unchanged.\n */\nint POOL_resize(POOL_ctx* ctx, size_t numThreads);\n\n/*! POOL_sizeof() :\n * @return threadpool memory usage\n *  note : compatible with NULL (returns 0 in this case)\n */\nsize_t POOL_sizeof(const POOL_ctx* ctx);\n\n/*! POOL_function :\n *  The function type that can be added to a thread pool.\n */\ntypedef void (*POOL_function)(void*);\n\n/*! POOL_add() :\n *  Add the job `function(opaque)` to the thread pool. `ctx` must be valid.\n *  Possibly blocks until there is room in the queue.\n *  Note : The function may be executed asynchronously,\n *         therefore, `opaque` must live until function has been completed.\n */\nvoid POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque);\n\n\n/*! POOL_tryAdd() :\n *  Add the job `function(opaque)` to thread pool _if_ a queue slot is available.\n *  Returns immediately even if not (does not block).\n * @return : 1 if successful, 0 if not.\n */\nint POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque);\n\n#endif\n"
  },
  {
    "path": "lib/common/portability_macros.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_PORTABILITY_MACROS_H\n#define ZSTD_PORTABILITY_MACROS_H\n\n/**\n * This header file contains macro definitions to support portability.\n * This header is shared between C and ASM code, so it MUST only\n * contain macro definitions. It MUST not contain any C code.\n *\n * This header ONLY defines macros to detect platforms/feature support.\n *\n */\n\n\n/* compat. with non-clang compilers */\n#ifndef __has_attribute\n  #define __has_attribute(x) 0\n#endif\n\n/* compat. with non-clang compilers */\n#ifndef __has_builtin\n#  define __has_builtin(x) 0\n#endif\n\n/* compat. with non-clang compilers */\n#ifndef __has_feature\n#  define __has_feature(x) 0\n#endif\n\n/* detects whether we are being compiled under msan */\n#ifndef ZSTD_MEMORY_SANITIZER\n#  if __has_feature(memory_sanitizer)\n#    define ZSTD_MEMORY_SANITIZER 1\n#  else\n#    define ZSTD_MEMORY_SANITIZER 0\n#  endif\n#endif\n\n/* detects whether we are being compiled under asan */\n#ifndef ZSTD_ADDRESS_SANITIZER\n#  if __has_feature(address_sanitizer)\n#    define ZSTD_ADDRESS_SANITIZER 1\n#  elif defined(__SANITIZE_ADDRESS__)\n#    define ZSTD_ADDRESS_SANITIZER 1\n#  else\n#    define ZSTD_ADDRESS_SANITIZER 0\n#  endif\n#endif\n\n/* detects whether we are being compiled under dfsan */\n#ifndef ZSTD_DATAFLOW_SANITIZER\n# if __has_feature(dataflow_sanitizer)\n#  define ZSTD_DATAFLOW_SANITIZER 1\n# else\n#  define ZSTD_DATAFLOW_SANITIZER 0\n# endif\n#endif\n\n/* Mark the internal assembly functions as hidden  */\n#ifdef __ELF__\n# define ZSTD_HIDE_ASM_FUNCTION(func) .hidden func\n#elif defined(__APPLE__)\n# define ZSTD_HIDE_ASM_FUNCTION(func) .private_extern func\n#else\n# define ZSTD_HIDE_ASM_FUNCTION(func)\n#endif\n\n/* Compile time determination of BMI2 support */\n#ifndef STATIC_BMI2\n#  if defined(__BMI2__)\n#    define STATIC_BMI2 1\n#  elif defined(_MSC_VER) && defined(__AVX2__)\n#    define STATIC_BMI2 1 /* MSVC does not have a BMI2 specific flag, but every CPU that supports AVX2 also supports BMI2 */\n#  endif\n#endif\n\n#ifndef STATIC_BMI2\n#  define STATIC_BMI2 0\n#endif\n\n/* Enable runtime BMI2 dispatch based on the CPU.\n * Enabled for clang & gcc >=4.8 on x86 when BMI2 isn't enabled by default.\n */\n#ifndef DYNAMIC_BMI2\n#  if ((defined(__clang__) && __has_attribute(__target__)) \\\n      || (defined(__GNUC__) \\\n          && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))) \\\n      && (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)) \\\n      && !defined(__BMI2__)\n#    define DYNAMIC_BMI2 1\n#  else\n#    define DYNAMIC_BMI2 0\n#  endif\n#endif\n\n/**\n * Only enable assembly for GNU C compatible compilers,\n * because other platforms may not support GAS assembly syntax.\n *\n * Only enable assembly for Linux / MacOS / Win32, other platforms may\n * work, but they haven't been tested. This could likely be\n * extended to BSD systems.\n *\n * Disable assembly when MSAN is enabled, because MSAN requires\n * 100% of code to be instrumented to work.\n */\n#if defined(__GNUC__)\n#  if defined(__linux__) || defined(__linux) || defined(__APPLE__) || defined(_WIN32)\n#    if ZSTD_MEMORY_SANITIZER\n#      define ZSTD_ASM_SUPPORTED 0\n#    elif ZSTD_DATAFLOW_SANITIZER\n#      define ZSTD_ASM_SUPPORTED 0\n#    else\n#      define ZSTD_ASM_SUPPORTED 1\n#    endif\n#  else\n#    define ZSTD_ASM_SUPPORTED 0\n#  endif\n#else\n#  define ZSTD_ASM_SUPPORTED 0\n#endif\n\n/**\n * Determines whether we should enable assembly for x86-64\n * with BMI2.\n *\n * Enable if all of the following conditions hold:\n * - ASM hasn't been explicitly disabled by defining ZSTD_DISABLE_ASM\n * - Assembly is supported\n * - We are compiling for x86-64 and either:\n *   - DYNAMIC_BMI2 is enabled\n *   - BMI2 is supported at compile time\n */\n#if !defined(ZSTD_DISABLE_ASM) &&                                 \\\n    ZSTD_ASM_SUPPORTED &&                                         \\\n    defined(__x86_64__) &&                                        \\\n    (DYNAMIC_BMI2 || defined(__BMI2__))\n# define ZSTD_ENABLE_ASM_X86_64_BMI2 1\n#else\n# define ZSTD_ENABLE_ASM_X86_64_BMI2 0\n#endif\n\n/*\n * For x86 ELF targets, add .note.gnu.property section for Intel CET in\n * assembly sources when CET is enabled.\n *\n * Additionally, any function that may be called indirectly must begin\n * with ZSTD_CET_ENDBRANCH.\n */\n#if defined(__ELF__) && (defined(__x86_64__) || defined(__i386__)) \\\n    && defined(__has_include)\n# if __has_include(<cet.h>)\n#  include <cet.h>\n#  define ZSTD_CET_ENDBRANCH _CET_ENDBR\n# endif\n#endif\n\n#ifndef ZSTD_CET_ENDBRANCH\n# define ZSTD_CET_ENDBRANCH\n#endif\n\n/**\n * ZSTD_IS_DETERMINISTIC_BUILD must be set to 0 if any compilation macro is\n * active that impacts the compressed output.\n *\n * NOTE: ZSTD_MULTITHREAD is allowed to be set or unset.\n */\n#if defined(ZSTD_CLEVEL_DEFAULT) \\\n    || defined(ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR) \\\n    || defined(ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR) \\\n    || defined(ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR) \\\n    || defined(ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR) \\\n    || defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR) \\\n    || defined(ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR) \\\n    || defined(ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR)\n# define ZSTD_IS_DETERMINISTIC_BUILD 0\n#else\n# define ZSTD_IS_DETERMINISTIC_BUILD 1\n#endif\n\n#endif /* ZSTD_PORTABILITY_MACROS_H */\n"
  },
  {
    "path": "lib/common/threading.c",
    "content": "/**\n * Copyright (c) 2016 Tino Reichardt\n * All rights reserved.\n *\n * You can contact the author at:\n * - zstdmt source repository: https://github.com/mcmilk/zstdmt\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/**\n * This file will hold wrapper for systems, which do not support pthreads\n */\n\n#include \"threading.h\"\n\n/* create fake symbol to avoid empty translation unit warning */\nint g_ZSTD_threading_useless_symbol;\n\n#if defined(ZSTD_MULTITHREAD) && defined(_WIN32)\n\n/**\n * Windows minimalist Pthread Wrapper\n */\n\n\n/* ===  Dependencies  === */\n#include <process.h>\n#include <errno.h>\n\n\n/* ===  Implementation  === */\n\ntypedef struct {\n    void* (*start_routine)(void*);\n    void* arg;\n    int initialized;\n    ZSTD_pthread_cond_t initialized_cond;\n    ZSTD_pthread_mutex_t initialized_mutex;\n} ZSTD_thread_params_t;\n\nstatic unsigned __stdcall worker(void *arg)\n{\n    void* (*start_routine)(void*);\n    void* thread_arg;\n\n    /* Initialized thread_arg and start_routine and signal main thread that we don't need it\n     * to wait any longer.\n     */\n    {\n        ZSTD_thread_params_t*  thread_param = (ZSTD_thread_params_t*)arg;\n        thread_arg = thread_param->arg;\n        start_routine = thread_param->start_routine;\n\n        /* Signal main thread that we are running and do not depend on its memory anymore */\n        ZSTD_pthread_mutex_lock(&thread_param->initialized_mutex);\n        thread_param->initialized = 1;\n        ZSTD_pthread_cond_signal(&thread_param->initialized_cond);\n        ZSTD_pthread_mutex_unlock(&thread_param->initialized_mutex);\n    }\n\n    start_routine(thread_arg);\n\n    return 0;\n}\n\nint ZSTD_pthread_create(ZSTD_pthread_t* thread, const void* unused,\n            void* (*start_routine) (void*), void* arg)\n{\n    ZSTD_thread_params_t thread_param;\n    (void)unused;\n\n    if (thread==NULL) return -1;\n    *thread = NULL;\n\n    thread_param.start_routine = start_routine;\n    thread_param.arg = arg;\n    thread_param.initialized = 0;\n\n    /* Setup thread initialization synchronization */\n    if(ZSTD_pthread_cond_init(&thread_param.initialized_cond, NULL)) {\n        /* Should never happen on Windows */\n        return -1;\n    }\n    if(ZSTD_pthread_mutex_init(&thread_param.initialized_mutex, NULL)) {\n        /* Should never happen on Windows */\n        ZSTD_pthread_cond_destroy(&thread_param.initialized_cond);\n        return -1;\n    }\n\n    /* Spawn thread */\n    *thread = (HANDLE)_beginthreadex(NULL, 0, worker, &thread_param, 0, NULL);\n    if (*thread==NULL) {\n        ZSTD_pthread_mutex_destroy(&thread_param.initialized_mutex);\n        ZSTD_pthread_cond_destroy(&thread_param.initialized_cond);\n        return errno;\n    }\n\n    /* Wait for thread to be initialized */\n    ZSTD_pthread_mutex_lock(&thread_param.initialized_mutex);\n    while(!thread_param.initialized) {\n        ZSTD_pthread_cond_wait(&thread_param.initialized_cond, &thread_param.initialized_mutex);\n    }\n    ZSTD_pthread_mutex_unlock(&thread_param.initialized_mutex);\n    ZSTD_pthread_mutex_destroy(&thread_param.initialized_mutex);\n    ZSTD_pthread_cond_destroy(&thread_param.initialized_cond);\n\n    return 0;\n}\n\nint ZSTD_pthread_join(ZSTD_pthread_t thread)\n{\n    DWORD result;\n\n    if (!thread) return 0;\n\n    result = WaitForSingleObject(thread, INFINITE);\n    CloseHandle(thread);\n\n    switch (result) {\n    case WAIT_OBJECT_0:\n        return 0;\n    case WAIT_ABANDONED:\n        return EINVAL;\n    default:\n        return GetLastError();\n    }\n}\n\n#endif   /* ZSTD_MULTITHREAD */\n\n#if defined(ZSTD_MULTITHREAD) && DEBUGLEVEL >= 1 && !defined(_WIN32)\n\n#define ZSTD_DEPS_NEED_MALLOC\n#include \"zstd_deps.h\"\n\nint ZSTD_pthread_mutex_init(ZSTD_pthread_mutex_t* mutex, pthread_mutexattr_t const* attr)\n{\n    assert(mutex != NULL);\n    *mutex = (pthread_mutex_t*)ZSTD_malloc(sizeof(pthread_mutex_t));\n    if (!*mutex)\n        return 1;\n    {\n        int const ret = pthread_mutex_init(*mutex, attr);\n        if (ret != 0) {\n            ZSTD_free(*mutex);\n            *mutex = NULL;\n        }\n        return ret;\n    }\n}\n\nint ZSTD_pthread_mutex_destroy(ZSTD_pthread_mutex_t* mutex)\n{\n    assert(mutex != NULL);\n    if (!*mutex)\n        return 0;\n    {\n        int const ret = pthread_mutex_destroy(*mutex);\n        ZSTD_free(*mutex);\n        return ret;\n    }\n}\n\nint ZSTD_pthread_cond_init(ZSTD_pthread_cond_t* cond, pthread_condattr_t const* attr)\n{\n    assert(cond != NULL);\n    *cond = (pthread_cond_t*)ZSTD_malloc(sizeof(pthread_cond_t));\n    if (!*cond)\n        return 1;\n    {\n        int const ret = pthread_cond_init(*cond, attr);\n        if (ret != 0) {\n            ZSTD_free(*cond);\n            *cond = NULL;\n        }\n        return ret;\n    }\n}\n\nint ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* cond)\n{\n    assert(cond != NULL);\n    if (!*cond)\n        return 0;\n    {\n        int const ret = pthread_cond_destroy(*cond);\n        ZSTD_free(*cond);\n        return ret;\n    }\n}\n\n#endif\n"
  },
  {
    "path": "lib/common/threading.h",
    "content": "/**\n * Copyright (c) 2016 Tino Reichardt\n * All rights reserved.\n *\n * You can contact the author at:\n * - zstdmt source repository: https://github.com/mcmilk/zstdmt\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef THREADING_H_938743\n#define THREADING_H_938743\n\n#include \"debug.h\"\n\n#if defined(ZSTD_MULTITHREAD) && defined(_WIN32)\n\n/**\n * Windows minimalist Pthread Wrapper\n */\n#ifdef WINVER\n#  undef WINVER\n#endif\n#define WINVER       0x0600\n\n#ifdef _WIN32_WINNT\n#  undef _WIN32_WINNT\n#endif\n#define _WIN32_WINNT 0x0600\n\n#ifndef WIN32_LEAN_AND_MEAN\n#  define WIN32_LEAN_AND_MEAN\n#endif\n\n#undef ERROR   /* reported already defined on VS 2015 (Rich Geldreich) */\n#include <windows.h>\n#undef ERROR\n#define ERROR(name) ZSTD_ERROR(name)\n\n\n/* mutex */\n#define ZSTD_pthread_mutex_t           CRITICAL_SECTION\n#define ZSTD_pthread_mutex_init(a, b)  ((void)(b), InitializeCriticalSection((a)), 0)\n#define ZSTD_pthread_mutex_destroy(a)  DeleteCriticalSection((a))\n#define ZSTD_pthread_mutex_lock(a)     EnterCriticalSection((a))\n#define ZSTD_pthread_mutex_unlock(a)   LeaveCriticalSection((a))\n\n/* condition variable */\n#define ZSTD_pthread_cond_t             CONDITION_VARIABLE\n#define ZSTD_pthread_cond_init(a, b)    ((void)(b), InitializeConditionVariable((a)), 0)\n#define ZSTD_pthread_cond_destroy(a)    ((void)(a))\n#define ZSTD_pthread_cond_wait(a, b)    SleepConditionVariableCS((a), (b), INFINITE)\n#define ZSTD_pthread_cond_signal(a)     WakeConditionVariable((a))\n#define ZSTD_pthread_cond_broadcast(a)  WakeAllConditionVariable((a))\n\n/* ZSTD_pthread_create() and ZSTD_pthread_join() */\ntypedef HANDLE ZSTD_pthread_t;\n\nint ZSTD_pthread_create(ZSTD_pthread_t* thread, const void* unused,\n                   void* (*start_routine) (void*), void* arg);\n\nint ZSTD_pthread_join(ZSTD_pthread_t thread);\n\n/**\n * add here more wrappers as required\n */\n\n#elif defined(ZSTD_MULTITHREAD)    /* posix assumed ; need a better detection method */\n/* ===   POSIX Systems   === */\n#  include <pthread.h>\n\n#if DEBUGLEVEL < 1\n\n#define ZSTD_pthread_mutex_t            pthread_mutex_t\n#define ZSTD_pthread_mutex_init(a, b)   pthread_mutex_init((a), (b))\n#define ZSTD_pthread_mutex_destroy(a)   pthread_mutex_destroy((a))\n#define ZSTD_pthread_mutex_lock(a)      pthread_mutex_lock((a))\n#define ZSTD_pthread_mutex_unlock(a)    pthread_mutex_unlock((a))\n\n#define ZSTD_pthread_cond_t             pthread_cond_t\n#define ZSTD_pthread_cond_init(a, b)    pthread_cond_init((a), (b))\n#define ZSTD_pthread_cond_destroy(a)    pthread_cond_destroy((a))\n#define ZSTD_pthread_cond_wait(a, b)    pthread_cond_wait((a), (b))\n#define ZSTD_pthread_cond_signal(a)     pthread_cond_signal((a))\n#define ZSTD_pthread_cond_broadcast(a)  pthread_cond_broadcast((a))\n\n#define ZSTD_pthread_t                  pthread_t\n#define ZSTD_pthread_create(a, b, c, d) pthread_create((a), (b), (c), (d))\n#define ZSTD_pthread_join(a)         pthread_join((a),NULL)\n\n#else /* DEBUGLEVEL >= 1 */\n\n/* Debug implementation of threading.\n * In this implementation we use pointers for mutexes and condition variables.\n * This way, if we forget to init/destroy them the program will crash or ASAN\n * will report leaks.\n */\n\n#define ZSTD_pthread_mutex_t            pthread_mutex_t*\nint ZSTD_pthread_mutex_init(ZSTD_pthread_mutex_t* mutex, pthread_mutexattr_t const* attr);\nint ZSTD_pthread_mutex_destroy(ZSTD_pthread_mutex_t* mutex);\n#define ZSTD_pthread_mutex_lock(a)      pthread_mutex_lock(*(a))\n#define ZSTD_pthread_mutex_unlock(a)    pthread_mutex_unlock(*(a))\n\n#define ZSTD_pthread_cond_t             pthread_cond_t*\nint ZSTD_pthread_cond_init(ZSTD_pthread_cond_t* cond, pthread_condattr_t const* attr);\nint ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* cond);\n#define ZSTD_pthread_cond_wait(a, b)    pthread_cond_wait(*(a), *(b))\n#define ZSTD_pthread_cond_signal(a)     pthread_cond_signal(*(a))\n#define ZSTD_pthread_cond_broadcast(a)  pthread_cond_broadcast(*(a))\n\n#define ZSTD_pthread_t                  pthread_t\n#define ZSTD_pthread_create(a, b, c, d) pthread_create((a), (b), (c), (d))\n#define ZSTD_pthread_join(a)         pthread_join((a),NULL)\n\n#endif\n\n#else  /* ZSTD_MULTITHREAD not defined */\n/* No multithreading support */\n\ntypedef int ZSTD_pthread_mutex_t;\n#define ZSTD_pthread_mutex_init(a, b)   ((void)(a), (void)(b), 0)\n#define ZSTD_pthread_mutex_destroy(a)   ((void)(a))\n#define ZSTD_pthread_mutex_lock(a)      ((void)(a))\n#define ZSTD_pthread_mutex_unlock(a)    ((void)(a))\n\ntypedef int ZSTD_pthread_cond_t;\n#define ZSTD_pthread_cond_init(a, b)    ((void)(a), (void)(b), 0)\n#define ZSTD_pthread_cond_destroy(a)    ((void)(a))\n#define ZSTD_pthread_cond_wait(a, b)    ((void)(a), (void)(b))\n#define ZSTD_pthread_cond_signal(a)     ((void)(a))\n#define ZSTD_pthread_cond_broadcast(a)  ((void)(a))\n\n/* do not use ZSTD_pthread_t */\n\n#endif /* ZSTD_MULTITHREAD */\n\n\n#endif /* THREADING_H_938743 */\n"
  },
  {
    "path": "lib/common/xxhash.c",
    "content": "/*\n * xxHash - Extremely Fast Hash algorithm\n * Copyright (c) Yann Collet - Meta Platforms, Inc\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/*\n * xxhash.c instantiates functions defined in xxhash.h\n */\n\n#define XXH_STATIC_LINKING_ONLY /* access advanced declarations */\n#define XXH_IMPLEMENTATION      /* access definitions */\n\n#include \"xxhash.h\"\n"
  },
  {
    "path": "lib/common/xxhash.h",
    "content": "/*\n * xxHash - Extremely Fast Hash algorithm\n * Header File\n * Copyright (c) Yann Collet - Meta Platforms, Inc\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* Local adaptations for Zstandard */\n\n#ifndef XXH_NO_XXH3\n# define XXH_NO_XXH3\n#endif\n\n#ifndef XXH_NAMESPACE\n# define XXH_NAMESPACE ZSTD_\n#endif\n\n/*!\n * @mainpage xxHash\n *\n * xxHash is an extremely fast non-cryptographic hash algorithm, working at RAM speed\n * limits.\n *\n * It is proposed in four flavors, in three families:\n * 1. @ref XXH32_family\n *   - Classic 32-bit hash function. Simple, compact, and runs on almost all\n *     32-bit and 64-bit systems.\n * 2. @ref XXH64_family\n *   - Classic 64-bit adaptation of XXH32. Just as simple, and runs well on most\n *     64-bit systems (but _not_ 32-bit systems).\n * 3. @ref XXH3_family\n *   - Modern 64-bit and 128-bit hash function family which features improved\n *     strength and performance across the board, especially on smaller data.\n *     It benefits greatly from SIMD and 64-bit without requiring it.\n *\n * Benchmarks\n * ---\n * The reference system uses an Intel i7-9700K CPU, and runs Ubuntu x64 20.04.\n * The open source benchmark program is compiled with clang v10.0 using -O3 flag.\n *\n * | Hash Name            | ISA ext | Width | Large Data Speed | Small Data Velocity |\n * | -------------------- | ------- | ----: | ---------------: | ------------------: |\n * | XXH3_64bits()        | @b AVX2 |    64 |        59.4 GB/s |               133.1 |\n * | MeowHash             | AES-NI  |   128 |        58.2 GB/s |                52.5 |\n * | XXH3_128bits()       | @b AVX2 |   128 |        57.9 GB/s |               118.1 |\n * | CLHash               | PCLMUL  |    64 |        37.1 GB/s |                58.1 |\n * | XXH3_64bits()        | @b SSE2 |    64 |        31.5 GB/s |               133.1 |\n * | XXH3_128bits()       | @b SSE2 |   128 |        29.6 GB/s |               118.1 |\n * | RAM sequential read  |         |   N/A |        28.0 GB/s |                 N/A |\n * | ahash                | AES-NI  |    64 |        22.5 GB/s |               107.2 |\n * | City64               |         |    64 |        22.0 GB/s |                76.6 |\n * | T1ha2                |         |    64 |        22.0 GB/s |                99.0 |\n * | City128              |         |   128 |        21.7 GB/s |                57.7 |\n * | FarmHash             | AES-NI  |    64 |        21.3 GB/s |                71.9 |\n * | XXH64()              |         |    64 |        19.4 GB/s |                71.0 |\n * | SpookyHash           |         |    64 |        19.3 GB/s |                53.2 |\n * | Mum                  |         |    64 |        18.0 GB/s |                67.0 |\n * | CRC32C               | SSE4.2  |    32 |        13.0 GB/s |                57.9 |\n * | XXH32()              |         |    32 |         9.7 GB/s |                71.9 |\n * | City32               |         |    32 |         9.1 GB/s |                66.0 |\n * | Blake3*              | @b AVX2 |   256 |         4.4 GB/s |                 8.1 |\n * | Murmur3              |         |    32 |         3.9 GB/s |                56.1 |\n * | SipHash*             |         |    64 |         3.0 GB/s |                43.2 |\n * | Blake3*              | @b SSE2 |   256 |         2.4 GB/s |                 8.1 |\n * | HighwayHash          |         |    64 |         1.4 GB/s |                 6.0 |\n * | FNV64                |         |    64 |         1.2 GB/s |                62.7 |\n * | Blake2*              |         |   256 |         1.1 GB/s |                 5.1 |\n * | SHA1*                |         |   160 |         0.8 GB/s |                 5.6 |\n * | MD5*                 |         |   128 |         0.6 GB/s |                 7.8 |\n * @note\n *   - Hashes which require a specific ISA extension are noted. SSE2 is also noted,\n *     even though it is mandatory on x64.\n *   - Hashes with an asterisk are cryptographic. Note that MD5 is non-cryptographic\n *     by modern standards.\n *   - Small data velocity is a rough average of algorithm's efficiency for small\n *     data. For more accurate information, see the wiki.\n *   - More benchmarks and strength tests are found on the wiki:\n *         https://github.com/Cyan4973/xxHash/wiki\n *\n * Usage\n * ------\n * All xxHash variants use a similar API. Changing the algorithm is a trivial\n * substitution.\n *\n * @pre\n *    For functions which take an input and length parameter, the following\n *    requirements are assumed:\n *    - The range from [`input`, `input + length`) is valid, readable memory.\n *      - The only exception is if the `length` is `0`, `input` may be `NULL`.\n *    - For C++, the objects must have the *TriviallyCopyable* property, as the\n *      functions access bytes directly as if it was an array of `unsigned char`.\n *\n * @anchor single_shot_example\n * **Single Shot**\n *\n * These functions are stateless functions which hash a contiguous block of memory,\n * immediately returning the result. They are the easiest and usually the fastest\n * option.\n *\n * XXH32(), XXH64(), XXH3_64bits(), XXH3_128bits()\n *\n * @code{.c}\n *   #include <string.h>\n *   #include \"xxhash.h\"\n *\n *   // Example for a function which hashes a null terminated string with XXH32().\n *   XXH32_hash_t hash_string(const char* string, XXH32_hash_t seed)\n *   {\n *       // NULL pointers are only valid if the length is zero\n *       size_t length = (string == NULL) ? 0 : strlen(string);\n *       return XXH32(string, length, seed);\n *   }\n * @endcode\n *\n *\n * @anchor streaming_example\n * **Streaming**\n *\n * These groups of functions allow incremental hashing of unknown size, even\n * more than what would fit in a size_t.\n *\n * XXH32_reset(), XXH64_reset(), XXH3_64bits_reset(), XXH3_128bits_reset()\n *\n * @code{.c}\n *   #include <stdio.h>\n *   #include <assert.h>\n *   #include \"xxhash.h\"\n *   // Example for a function which hashes a FILE incrementally with XXH3_64bits().\n *   XXH64_hash_t hashFile(FILE* f)\n *   {\n *       // Allocate a state struct. Do not just use malloc() or new.\n *       XXH3_state_t* state = XXH3_createState();\n *       assert(state != NULL && \"Out of memory!\");\n *       // Reset the state to start a new hashing session.\n *       XXH3_64bits_reset(state);\n *       char buffer[4096];\n *       size_t count;\n *       // Read the file in chunks\n *       while ((count = fread(buffer, 1, sizeof(buffer), f)) != 0) {\n *           // Run update() as many times as necessary to process the data\n *           XXH3_64bits_update(state, buffer, count);\n *       }\n *       // Retrieve the finalized hash. This will not change the state.\n *       XXH64_hash_t result = XXH3_64bits_digest(state);\n *       // Free the state. Do not use free().\n *       XXH3_freeState(state);\n *       return result;\n *   }\n * @endcode\n *\n * Streaming functions generate the xxHash value from an incremental input.\n * This method is slower than single-call functions, due to state management.\n * For small inputs, prefer `XXH32()` and `XXH64()`, which are better optimized.\n *\n * An XXH state must first be allocated using `XXH*_createState()`.\n *\n * Start a new hash by initializing the state with a seed using `XXH*_reset()`.\n *\n * Then, feed the hash state by calling `XXH*_update()` as many times as necessary.\n *\n * The function returns an error code, with 0 meaning OK, and any other value\n * meaning there is an error.\n *\n * Finally, a hash value can be produced anytime, by using `XXH*_digest()`.\n * This function returns the nn-bits hash as an int or long long.\n *\n * It's still possible to continue inserting input into the hash state after a\n * digest, and generate new hash values later on by invoking `XXH*_digest()`.\n *\n * When done, release the state using `XXH*_freeState()`.\n *\n *\n * @anchor canonical_representation_example\n * **Canonical Representation**\n *\n * The default return values from XXH functions are unsigned 32, 64 and 128 bit\n * integers.\n * This the simplest and fastest format for further post-processing.\n *\n * However, this leaves open the question of what is the order on the byte level,\n * since little and big endian conventions will store the same number differently.\n *\n * The canonical representation settles this issue by mandating big-endian\n * convention, the same convention as human-readable numbers (large digits first).\n *\n * When writing hash values to storage, sending them over a network, or printing\n * them, it's highly recommended to use the canonical representation to ensure\n * portability across a wider range of systems, present and future.\n *\n * The following functions allow transformation of hash values to and from\n * canonical format.\n *\n * XXH32_canonicalFromHash(), XXH32_hashFromCanonical(),\n * XXH64_canonicalFromHash(), XXH64_hashFromCanonical(),\n * XXH128_canonicalFromHash(), XXH128_hashFromCanonical(),\n *\n * @code{.c}\n *   #include <stdio.h>\n *   #include \"xxhash.h\"\n *\n *   // Example for a function which prints XXH32_hash_t in human readable format\n *   void printXxh32(XXH32_hash_t hash)\n *   {\n *       XXH32_canonical_t cano;\n *       XXH32_canonicalFromHash(&cano, hash);\n *       size_t i;\n *       for(i = 0; i < sizeof(cano.digest); ++i) {\n *           printf(\"%02x\", cano.digest[i]);\n *       }\n *       printf(\"\\n\");\n *   }\n *\n *   // Example for a function which converts XXH32_canonical_t to XXH32_hash_t\n *   XXH32_hash_t convertCanonicalToXxh32(XXH32_canonical_t cano)\n *   {\n *       XXH32_hash_t hash = XXH32_hashFromCanonical(&cano);\n *       return hash;\n *   }\n * @endcode\n *\n *\n * @file xxhash.h\n * xxHash prototypes and implementation\n */\n\n/* ****************************\n *  INLINE mode\n ******************************/\n/*!\n * @defgroup public Public API\n * Contains details on the public xxHash functions.\n * @{\n */\n#ifdef XXH_DOXYGEN\n/*!\n * @brief Gives access to internal state declaration, required for static allocation.\n *\n * Incompatible with dynamic linking, due to risks of ABI changes.\n *\n * Usage:\n * @code{.c}\n *     #define XXH_STATIC_LINKING_ONLY\n *     #include \"xxhash.h\"\n * @endcode\n */\n#  define XXH_STATIC_LINKING_ONLY\n/* Do not undef XXH_STATIC_LINKING_ONLY for Doxygen */\n\n/*!\n * @brief Gives access to internal definitions.\n *\n * Usage:\n * @code{.c}\n *     #define XXH_STATIC_LINKING_ONLY\n *     #define XXH_IMPLEMENTATION\n *     #include \"xxhash.h\"\n * @endcode\n */\n#  define XXH_IMPLEMENTATION\n/* Do not undef XXH_IMPLEMENTATION for Doxygen */\n\n/*!\n * @brief Exposes the implementation and marks all functions as `inline`.\n *\n * Use these build macros to inline xxhash into the target unit.\n * Inlining improves performance on small inputs, especially when the length is\n * expressed as a compile-time constant:\n *\n *  https://fastcompression.blogspot.com/2018/03/xxhash-for-small-keys-impressive-power.html\n *\n * It also keeps xxHash symbols private to the unit, so they are not exported.\n *\n * Usage:\n * @code{.c}\n *     #define XXH_INLINE_ALL\n *     #include \"xxhash.h\"\n * @endcode\n * Do not compile and link xxhash.o as a separate object, as it is not useful.\n */\n#  define XXH_INLINE_ALL\n#  undef XXH_INLINE_ALL\n/*!\n * @brief Exposes the implementation without marking functions as inline.\n */\n#  define XXH_PRIVATE_API\n#  undef XXH_PRIVATE_API\n/*!\n * @brief Emulate a namespace by transparently prefixing all symbols.\n *\n * If you want to include _and expose_ xxHash functions from within your own\n * library, but also want to avoid symbol collisions with other libraries which\n * may also include xxHash, you can use @ref XXH_NAMESPACE to automatically prefix\n * any public symbol from xxhash library with the value of @ref XXH_NAMESPACE\n * (therefore, avoid empty or numeric values).\n *\n * Note that no change is required within the calling program as long as it\n * includes `xxhash.h`: Regular symbol names will be automatically translated\n * by this header.\n */\n#  define XXH_NAMESPACE /* YOUR NAME HERE */\n#  undef XXH_NAMESPACE\n#endif\n\n#if (defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API)) \\\n    && !defined(XXH_INLINE_ALL_31684351384)\n   /* this section should be traversed only once */\n#  define XXH_INLINE_ALL_31684351384\n   /* give access to the advanced API, required to compile implementations */\n#  undef XXH_STATIC_LINKING_ONLY   /* avoid macro redef */\n#  define XXH_STATIC_LINKING_ONLY\n   /* make all functions private */\n#  undef XXH_PUBLIC_API\n#  if defined(__GNUC__)\n#    define XXH_PUBLIC_API static __inline __attribute__((unused))\n#  elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n#    define XXH_PUBLIC_API static inline\n#  elif defined(_MSC_VER)\n#    define XXH_PUBLIC_API static __inline\n#  else\n     /* note: this version may generate warnings for unused static functions */\n#    define XXH_PUBLIC_API static\n#  endif\n\n   /*\n    * This part deals with the special case where a unit wants to inline xxHash,\n    * but \"xxhash.h\" has previously been included without XXH_INLINE_ALL,\n    * such as part of some previously included *.h header file.\n    * Without further action, the new include would just be ignored,\n    * and functions would effectively _not_ be inlined (silent failure).\n    * The following macros solve this situation by prefixing all inlined names,\n    * avoiding naming collision with previous inclusions.\n    */\n   /* Before that, we unconditionally #undef all symbols,\n    * in case they were already defined with XXH_NAMESPACE.\n    * They will then be redefined for XXH_INLINE_ALL\n    */\n#  undef XXH_versionNumber\n    /* XXH32 */\n#  undef XXH32\n#  undef XXH32_createState\n#  undef XXH32_freeState\n#  undef XXH32_reset\n#  undef XXH32_update\n#  undef XXH32_digest\n#  undef XXH32_copyState\n#  undef XXH32_canonicalFromHash\n#  undef XXH32_hashFromCanonical\n    /* XXH64 */\n#  undef XXH64\n#  undef XXH64_createState\n#  undef XXH64_freeState\n#  undef XXH64_reset\n#  undef XXH64_update\n#  undef XXH64_digest\n#  undef XXH64_copyState\n#  undef XXH64_canonicalFromHash\n#  undef XXH64_hashFromCanonical\n    /* XXH3_64bits */\n#  undef XXH3_64bits\n#  undef XXH3_64bits_withSecret\n#  undef XXH3_64bits_withSeed\n#  undef XXH3_64bits_withSecretandSeed\n#  undef XXH3_createState\n#  undef XXH3_freeState\n#  undef XXH3_copyState\n#  undef XXH3_64bits_reset\n#  undef XXH3_64bits_reset_withSeed\n#  undef XXH3_64bits_reset_withSecret\n#  undef XXH3_64bits_update\n#  undef XXH3_64bits_digest\n#  undef XXH3_generateSecret\n    /* XXH3_128bits */\n#  undef XXH128\n#  undef XXH3_128bits\n#  undef XXH3_128bits_withSeed\n#  undef XXH3_128bits_withSecret\n#  undef XXH3_128bits_reset\n#  undef XXH3_128bits_reset_withSeed\n#  undef XXH3_128bits_reset_withSecret\n#  undef XXH3_128bits_reset_withSecretandSeed\n#  undef XXH3_128bits_update\n#  undef XXH3_128bits_digest\n#  undef XXH128_isEqual\n#  undef XXH128_cmp\n#  undef XXH128_canonicalFromHash\n#  undef XXH128_hashFromCanonical\n    /* Finally, free the namespace itself */\n#  undef XXH_NAMESPACE\n\n    /* employ the namespace for XXH_INLINE_ALL */\n#  define XXH_NAMESPACE XXH_INLINE_\n   /*\n    * Some identifiers (enums, type names) are not symbols,\n    * but they must nonetheless be renamed to avoid redeclaration.\n    * Alternative solution: do not redeclare them.\n    * However, this requires some #ifdefs, and has a more dispersed impact.\n    * Meanwhile, renaming can be achieved in a single place.\n    */\n#  define XXH_IPREF(Id)   XXH_NAMESPACE ## Id\n#  define XXH_OK XXH_IPREF(XXH_OK)\n#  define XXH_ERROR XXH_IPREF(XXH_ERROR)\n#  define XXH_errorcode XXH_IPREF(XXH_errorcode)\n#  define XXH32_canonical_t  XXH_IPREF(XXH32_canonical_t)\n#  define XXH64_canonical_t  XXH_IPREF(XXH64_canonical_t)\n#  define XXH128_canonical_t XXH_IPREF(XXH128_canonical_t)\n#  define XXH32_state_s XXH_IPREF(XXH32_state_s)\n#  define XXH32_state_t XXH_IPREF(XXH32_state_t)\n#  define XXH64_state_s XXH_IPREF(XXH64_state_s)\n#  define XXH64_state_t XXH_IPREF(XXH64_state_t)\n#  define XXH3_state_s  XXH_IPREF(XXH3_state_s)\n#  define XXH3_state_t  XXH_IPREF(XXH3_state_t)\n#  define XXH128_hash_t XXH_IPREF(XXH128_hash_t)\n   /* Ensure the header is parsed again, even if it was previously included */\n#  undef XXHASH_H_5627135585666179\n#  undef XXHASH_H_STATIC_13879238742\n#endif /* XXH_INLINE_ALL || XXH_PRIVATE_API */\n\n/* ****************************************************************\n *  Stable API\n *****************************************************************/\n#ifndef XXHASH_H_5627135585666179\n#define XXHASH_H_5627135585666179 1\n\n/*! @brief Marks a global symbol. */\n#if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API)\n#  if defined(WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT))\n#    ifdef XXH_EXPORT\n#      define XXH_PUBLIC_API __declspec(dllexport)\n#    elif XXH_IMPORT\n#      define XXH_PUBLIC_API __declspec(dllimport)\n#    endif\n#  else\n#    define XXH_PUBLIC_API   /* do nothing */\n#  endif\n#endif\n\n#ifdef XXH_NAMESPACE\n#  define XXH_CAT(A,B) A##B\n#  define XXH_NAME2(A,B) XXH_CAT(A,B)\n#  define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber)\n/* XXH32 */\n#  define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32)\n#  define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState)\n#  define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState)\n#  define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset)\n#  define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update)\n#  define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest)\n#  define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState)\n#  define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash)\n#  define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical)\n/* XXH64 */\n#  define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64)\n#  define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState)\n#  define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState)\n#  define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset)\n#  define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update)\n#  define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest)\n#  define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState)\n#  define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash)\n#  define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical)\n/* XXH3_64bits */\n#  define XXH3_64bits XXH_NAME2(XXH_NAMESPACE, XXH3_64bits)\n#  define XXH3_64bits_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSecret)\n#  define XXH3_64bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSeed)\n#  define XXH3_64bits_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSecretandSeed)\n#  define XXH3_createState XXH_NAME2(XXH_NAMESPACE, XXH3_createState)\n#  define XXH3_freeState XXH_NAME2(XXH_NAMESPACE, XXH3_freeState)\n#  define XXH3_copyState XXH_NAME2(XXH_NAMESPACE, XXH3_copyState)\n#  define XXH3_64bits_reset XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset)\n#  define XXH3_64bits_reset_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSeed)\n#  define XXH3_64bits_reset_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSecret)\n#  define XXH3_64bits_reset_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSecretandSeed)\n#  define XXH3_64bits_update XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_update)\n#  define XXH3_64bits_digest XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_digest)\n#  define XXH3_generateSecret XXH_NAME2(XXH_NAMESPACE, XXH3_generateSecret)\n#  define XXH3_generateSecret_fromSeed XXH_NAME2(XXH_NAMESPACE, XXH3_generateSecret_fromSeed)\n/* XXH3_128bits */\n#  define XXH128 XXH_NAME2(XXH_NAMESPACE, XXH128)\n#  define XXH3_128bits XXH_NAME2(XXH_NAMESPACE, XXH3_128bits)\n#  define XXH3_128bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSeed)\n#  define XXH3_128bits_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSecret)\n#  define XXH3_128bits_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSecretandSeed)\n#  define XXH3_128bits_reset XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset)\n#  define XXH3_128bits_reset_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSeed)\n#  define XXH3_128bits_reset_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSecret)\n#  define XXH3_128bits_reset_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSecretandSeed)\n#  define XXH3_128bits_update XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_update)\n#  define XXH3_128bits_digest XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_digest)\n#  define XXH128_isEqual XXH_NAME2(XXH_NAMESPACE, XXH128_isEqual)\n#  define XXH128_cmp     XXH_NAME2(XXH_NAMESPACE, XXH128_cmp)\n#  define XXH128_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH128_canonicalFromHash)\n#  define XXH128_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH128_hashFromCanonical)\n#endif\n\n\n/* *************************************\n*  Compiler specifics\n***************************************/\n\n/* specific declaration modes for Windows */\n#if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API)\n#  if defined(WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT))\n#    ifdef XXH_EXPORT\n#      define XXH_PUBLIC_API __declspec(dllexport)\n#    elif XXH_IMPORT\n#      define XXH_PUBLIC_API __declspec(dllimport)\n#    endif\n#  else\n#    define XXH_PUBLIC_API   /* do nothing */\n#  endif\n#endif\n\n#if defined (__GNUC__)\n# define XXH_CONSTF  __attribute__((const))\n# define XXH_PUREF   __attribute__((pure))\n# define XXH_MALLOCF __attribute__((malloc))\n#else\n# define XXH_CONSTF  /* disable */\n# define XXH_PUREF\n# define XXH_MALLOCF\n#endif\n\n/* *************************************\n*  Version\n***************************************/\n#define XXH_VERSION_MAJOR    0\n#define XXH_VERSION_MINOR    8\n#define XXH_VERSION_RELEASE  2\n/*! @brief Version number, encoded as two digits each */\n#define XXH_VERSION_NUMBER  (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE)\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n/*!\n * @brief Obtains the xxHash version.\n *\n * This is mostly useful when xxHash is compiled as a shared library,\n * since the returned value comes from the library, as opposed to header file.\n *\n * @return @ref XXH_VERSION_NUMBER of the invoked library.\n */\nXXH_PUBLIC_API XXH_CONSTF unsigned XXH_versionNumber (void);\n\n#if defined (__cplusplus)\n}\n#endif\n\n/* ****************************\n*  Common basic types\n******************************/\n#include <stddef.h>   /* size_t */\n/*!\n * @brief Exit code for the streaming API.\n */\ntypedef enum {\n    XXH_OK = 0, /*!< OK */\n    XXH_ERROR   /*!< Error */\n} XXH_errorcode;\n\n\n/*-**********************************************************************\n*  32-bit hash\n************************************************************************/\n#if defined(XXH_DOXYGEN) /* Don't show <stdint.h> include */\n/*!\n * @brief An unsigned 32-bit integer.\n *\n * Not necessarily defined to `uint32_t` but functionally equivalent.\n */\ntypedef uint32_t XXH32_hash_t;\n\n#elif !defined (__VMS) \\\n  && (defined (__cplusplus) \\\n  || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )\n#   ifdef _AIX\n#     include <inttypes.h>\n#   else\n#     include <stdint.h>\n#   endif\n    typedef uint32_t XXH32_hash_t;\n\n#else\n#   include <limits.h>\n#   if UINT_MAX == 0xFFFFFFFFUL\n      typedef unsigned int XXH32_hash_t;\n#   elif ULONG_MAX == 0xFFFFFFFFUL\n      typedef unsigned long XXH32_hash_t;\n#   else\n#     error \"unsupported platform: need a 32-bit type\"\n#   endif\n#endif\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/*!\n * @}\n *\n * @defgroup XXH32_family XXH32 family\n * @ingroup public\n * Contains functions used in the classic 32-bit xxHash algorithm.\n *\n * @note\n *   XXH32 is useful for older platforms, with no or poor 64-bit performance.\n *   Note that the @ref XXH3_family provides competitive speed for both 32-bit\n *   and 64-bit systems, and offers true 64/128 bit hash results.\n *\n * @see @ref XXH64_family, @ref XXH3_family : Other xxHash families\n * @see @ref XXH32_impl for implementation details\n * @{\n */\n\n/*!\n * @brief Calculates the 32-bit hash of @p input using xxHash32.\n *\n * @param input The block of data to be hashed, at least @p length bytes in size.\n * @param length The length of @p input, in bytes.\n * @param seed The 32-bit seed to alter the hash's output predictably.\n *\n * @pre\n *   The memory between @p input and @p input + @p length must be valid,\n *   readable, contiguous memory. However, if @p length is `0`, @p input may be\n *   `NULL`. In C++, this also must be *TriviallyCopyable*.\n *\n * @return The calculated 32-bit xxHash32 value.\n *\n * @see @ref single_shot_example \"Single Shot Example\" for an example.\n */\nXXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32 (const void* input, size_t length, XXH32_hash_t seed);\n\n#ifndef XXH_NO_STREAM\n/*!\n * @typedef struct XXH32_state_s XXH32_state_t\n * @brief The opaque state struct for the XXH32 streaming API.\n *\n * @see XXH32_state_s for details.\n */\ntypedef struct XXH32_state_s XXH32_state_t;\n\n/*!\n * @brief Allocates an @ref XXH32_state_t.\n *\n * @return An allocated pointer of @ref XXH32_state_t on success.\n * @return `NULL` on failure.\n *\n * @note Must be freed with XXH32_freeState().\n */\nXXH_PUBLIC_API XXH_MALLOCF XXH32_state_t* XXH32_createState(void);\n/*!\n * @brief Frees an @ref XXH32_state_t.\n *\n * @param statePtr A pointer to an @ref XXH32_state_t allocated with @ref XXH32_createState().\n *\n * @return @ref XXH_OK.\n *\n * @note @p statePtr must be allocated with XXH32_createState().\n *\n */\nXXH_PUBLIC_API XXH_errorcode  XXH32_freeState(XXH32_state_t* statePtr);\n/*!\n * @brief Copies one @ref XXH32_state_t to another.\n *\n * @param dst_state The state to copy to.\n * @param src_state The state to copy from.\n * @pre\n *   @p dst_state and @p src_state must not be `NULL` and must not overlap.\n */\nXXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dst_state, const XXH32_state_t* src_state);\n\n/*!\n * @brief Resets an @ref XXH32_state_t to begin a new hash.\n *\n * @param statePtr The state struct to reset.\n * @param seed The 32-bit seed to alter the hash result predictably.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @note This function resets and seeds a state. Call it before @ref XXH32_update().\n */\nXXH_PUBLIC_API XXH_errorcode XXH32_reset  (XXH32_state_t* statePtr, XXH32_hash_t seed);\n\n/*!\n * @brief Consumes a block of @p input to an @ref XXH32_state_t.\n *\n * @param statePtr The state struct to update.\n * @param input The block of data to be hashed, at least @p length bytes in size.\n * @param length The length of @p input, in bytes.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n * @pre\n *   The memory between @p input and @p input + @p length must be valid,\n *   readable, contiguous memory. However, if @p length is `0`, @p input may be\n *   `NULL`. In C++, this also must be *TriviallyCopyable*.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @note Call this to incrementally consume blocks of data.\n */\nXXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length);\n\n/*!\n * @brief Returns the calculated hash value from an @ref XXH32_state_t.\n *\n * @param statePtr The state struct to calculate the hash from.\n *\n * @pre\n *  @p statePtr must not be `NULL`.\n *\n * @return The calculated 32-bit xxHash32 value from that state.\n *\n * @note\n *   Calling XXH32_digest() will not affect @p statePtr, so you can update,\n *   digest, and update again.\n */\nXXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr);\n#endif /* !XXH_NO_STREAM */\n\n/*******   Canonical representation   *******/\n\n/*!\n * @brief Canonical (big endian) representation of @ref XXH32_hash_t.\n */\ntypedef struct {\n    unsigned char digest[4]; /*!< Hash bytes, big endian */\n} XXH32_canonical_t;\n\n/*!\n * @brief Converts an @ref XXH32_hash_t to a big endian @ref XXH32_canonical_t.\n *\n * @param dst  The @ref XXH32_canonical_t pointer to be stored to.\n * @param hash The @ref XXH32_hash_t to be converted.\n *\n * @pre\n *   @p dst must not be `NULL`.\n *\n * @see @ref canonical_representation_example \"Canonical Representation Example\"\n */\nXXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash);\n\n/*!\n * @brief Converts an @ref XXH32_canonical_t to a native @ref XXH32_hash_t.\n *\n * @param src The @ref XXH32_canonical_t to convert.\n *\n * @pre\n *   @p src must not be `NULL`.\n *\n * @return The converted hash.\n *\n * @see @ref canonical_representation_example \"Canonical Representation Example\"\n */\nXXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src);\n\n\n/*! @cond Doxygen ignores this part */\n#ifdef __has_attribute\n# define XXH_HAS_ATTRIBUTE(x) __has_attribute(x)\n#else\n# define XXH_HAS_ATTRIBUTE(x) 0\n#endif\n/*! @endcond */\n\n/*! @cond Doxygen ignores this part */\n/*\n * C23 __STDC_VERSION__ number hasn't been specified yet. For now\n * leave as `201711L` (C17 + 1).\n * TODO: Update to correct value when its been specified.\n */\n#define XXH_C23_VN 201711L\n/*! @endcond */\n\n/*! @cond Doxygen ignores this part */\n/* C-language Attributes are added in C23. */\n#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= XXH_C23_VN) && defined(__has_c_attribute)\n# define XXH_HAS_C_ATTRIBUTE(x) __has_c_attribute(x)\n#else\n# define XXH_HAS_C_ATTRIBUTE(x) 0\n#endif\n/*! @endcond */\n\n/*! @cond Doxygen ignores this part */\n#if defined(__cplusplus) && defined(__has_cpp_attribute)\n# define XXH_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)\n#else\n# define XXH_HAS_CPP_ATTRIBUTE(x) 0\n#endif\n/*! @endcond */\n\n/*! @cond Doxygen ignores this part */\n/*\n * Define XXH_FALLTHROUGH macro for annotating switch case with the 'fallthrough' attribute\n * introduced in CPP17 and C23.\n * CPP17 : https://en.cppreference.com/w/cpp/language/attributes/fallthrough\n * C23   : https://en.cppreference.com/w/c/language/attributes/fallthrough\n */\n#if XXH_HAS_C_ATTRIBUTE(fallthrough) || XXH_HAS_CPP_ATTRIBUTE(fallthrough)\n# define XXH_FALLTHROUGH [[fallthrough]]\n#elif XXH_HAS_ATTRIBUTE(__fallthrough__)\n# define XXH_FALLTHROUGH __attribute__ ((__fallthrough__))\n#else\n# define XXH_FALLTHROUGH /* fallthrough */\n#endif\n/*! @endcond */\n\n/*! @cond Doxygen ignores this part */\n/*\n * Define XXH_NOESCAPE for annotated pointers in public API.\n * https://clang.llvm.org/docs/AttributeReference.html#noescape\n * As of writing this, only supported by clang.\n */\n#if XXH_HAS_ATTRIBUTE(noescape)\n# define XXH_NOESCAPE __attribute__((noescape))\n#else\n# define XXH_NOESCAPE\n#endif\n/*! @endcond */\n\n#if defined (__cplusplus)\n} /* end of extern \"C\" */\n#endif\n\n/*!\n * @}\n * @ingroup public\n * @{\n */\n\n#ifndef XXH_NO_LONG_LONG\n/*-**********************************************************************\n*  64-bit hash\n************************************************************************/\n#if defined(XXH_DOXYGEN) /* don't include <stdint.h> */\n/*!\n * @brief An unsigned 64-bit integer.\n *\n * Not necessarily defined to `uint64_t` but functionally equivalent.\n */\ntypedef uint64_t XXH64_hash_t;\n#elif !defined (__VMS) \\\n  && (defined (__cplusplus) \\\n  || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )\n#   ifdef _AIX\n#     include <inttypes.h>\n#   else\n#     include <stdint.h>\n#   endif\n   typedef uint64_t XXH64_hash_t;\n#else\n#  include <limits.h>\n#  if defined(__LP64__) && ULONG_MAX == 0xFFFFFFFFFFFFFFFFULL\n     /* LP64 ABI says uint64_t is unsigned long */\n     typedef unsigned long XXH64_hash_t;\n#  else\n     /* the following type must have a width of 64-bit */\n     typedef unsigned long long XXH64_hash_t;\n#  endif\n#endif\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n/*!\n * @}\n *\n * @defgroup XXH64_family XXH64 family\n * @ingroup public\n * @{\n * Contains functions used in the classic 64-bit xxHash algorithm.\n *\n * @note\n *   XXH3 provides competitive speed for both 32-bit and 64-bit systems,\n *   and offers true 64/128 bit hash results.\n *   It provides better speed for systems with vector processing capabilities.\n */\n\n/*!\n * @brief Calculates the 64-bit hash of @p input using xxHash64.\n *\n * @param input The block of data to be hashed, at least @p length bytes in size.\n * @param length The length of @p input, in bytes.\n * @param seed The 64-bit seed to alter the hash's output predictably.\n *\n * @pre\n *   The memory between @p input and @p input + @p length must be valid,\n *   readable, contiguous memory. However, if @p length is `0`, @p input may be\n *   `NULL`. In C++, this also must be *TriviallyCopyable*.\n *\n * @return The calculated 64-bit xxHash64 value.\n *\n * @see @ref single_shot_example \"Single Shot Example\" for an example.\n */\nXXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed);\n\n/*******   Streaming   *******/\n#ifndef XXH_NO_STREAM\n/*!\n * @brief The opaque state struct for the XXH64 streaming API.\n *\n * @see XXH64_state_s for details.\n */\ntypedef struct XXH64_state_s XXH64_state_t;   /* incomplete type */\n\n/*!\n * @brief Allocates an @ref XXH64_state_t.\n *\n * @return An allocated pointer of @ref XXH64_state_t on success.\n * @return `NULL` on failure.\n *\n * @note Must be freed with XXH64_freeState().\n */\nXXH_PUBLIC_API XXH_MALLOCF XXH64_state_t* XXH64_createState(void);\n\n/*!\n * @brief Frees an @ref XXH64_state_t.\n *\n * @param statePtr A pointer to an @ref XXH64_state_t allocated with @ref XXH64_createState().\n *\n * @return @ref XXH_OK.\n *\n * @note @p statePtr must be allocated with XXH64_createState().\n */\nXXH_PUBLIC_API XXH_errorcode  XXH64_freeState(XXH64_state_t* statePtr);\n\n/*!\n * @brief Copies one @ref XXH64_state_t to another.\n *\n * @param dst_state The state to copy to.\n * @param src_state The state to copy from.\n * @pre\n *   @p dst_state and @p src_state must not be `NULL` and must not overlap.\n */\nXXH_PUBLIC_API void XXH64_copyState(XXH_NOESCAPE XXH64_state_t* dst_state, const XXH64_state_t* src_state);\n\n/*!\n * @brief Resets an @ref XXH64_state_t to begin a new hash.\n *\n * @param statePtr The state struct to reset.\n * @param seed The 64-bit seed to alter the hash result predictably.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @note This function resets and seeds a state. Call it before @ref XXH64_update().\n */\nXXH_PUBLIC_API XXH_errorcode XXH64_reset  (XXH_NOESCAPE XXH64_state_t* statePtr, XXH64_hash_t seed);\n\n/*!\n * @brief Consumes a block of @p input to an @ref XXH64_state_t.\n *\n * @param statePtr The state struct to update.\n * @param input The block of data to be hashed, at least @p length bytes in size.\n * @param length The length of @p input, in bytes.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n * @pre\n *   The memory between @p input and @p input + @p length must be valid,\n *   readable, contiguous memory. However, if @p length is `0`, @p input may be\n *   `NULL`. In C++, this also must be *TriviallyCopyable*.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @note Call this to incrementally consume blocks of data.\n */\nXXH_PUBLIC_API XXH_errorcode XXH64_update (XXH_NOESCAPE XXH64_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length);\n\n/*!\n * @brief Returns the calculated hash value from an @ref XXH64_state_t.\n *\n * @param statePtr The state struct to calculate the hash from.\n *\n * @pre\n *  @p statePtr must not be `NULL`.\n *\n * @return The calculated 64-bit xxHash64 value from that state.\n *\n * @note\n *   Calling XXH64_digest() will not affect @p statePtr, so you can update,\n *   digest, and update again.\n */\nXXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_digest (XXH_NOESCAPE const XXH64_state_t* statePtr);\n#endif /* !XXH_NO_STREAM */\n/*******   Canonical representation   *******/\n\n/*!\n * @brief Canonical (big endian) representation of @ref XXH64_hash_t.\n */\ntypedef struct { unsigned char digest[sizeof(XXH64_hash_t)]; } XXH64_canonical_t;\n\n/*!\n * @brief Converts an @ref XXH64_hash_t to a big endian @ref XXH64_canonical_t.\n *\n * @param dst The @ref XXH64_canonical_t pointer to be stored to.\n * @param hash The @ref XXH64_hash_t to be converted.\n *\n * @pre\n *   @p dst must not be `NULL`.\n *\n * @see @ref canonical_representation_example \"Canonical Representation Example\"\n */\nXXH_PUBLIC_API void XXH64_canonicalFromHash(XXH_NOESCAPE XXH64_canonical_t* dst, XXH64_hash_t hash);\n\n/*!\n * @brief Converts an @ref XXH64_canonical_t to a native @ref XXH64_hash_t.\n *\n * @param src The @ref XXH64_canonical_t to convert.\n *\n * @pre\n *   @p src must not be `NULL`.\n *\n * @return The converted hash.\n *\n * @see @ref canonical_representation_example \"Canonical Representation Example\"\n */\nXXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_canonical_t* src);\n\n#ifndef XXH_NO_XXH3\n\n/*!\n * @}\n * ************************************************************************\n * @defgroup XXH3_family XXH3 family\n * @ingroup public\n * @{\n *\n * XXH3 is a more recent hash algorithm featuring:\n *  - Improved speed for both small and large inputs\n *  - True 64-bit and 128-bit outputs\n *  - SIMD acceleration\n *  - Improved 32-bit viability\n *\n * Speed analysis methodology is explained here:\n *\n *    https://fastcompression.blogspot.com/2019/03/presenting-xxh3.html\n *\n * Compared to XXH64, expect XXH3 to run approximately\n * ~2x faster on large inputs and >3x faster on small ones,\n * exact differences vary depending on platform.\n *\n * XXH3's speed benefits greatly from SIMD and 64-bit arithmetic,\n * but does not require it.\n * Most 32-bit and 64-bit targets that can run XXH32 smoothly can run XXH3\n * at competitive speeds, even without vector support. Further details are\n * explained in the implementation.\n *\n * XXH3 has a fast scalar implementation, but it also includes accelerated SIMD\n * implementations for many common platforms:\n *   - AVX512\n *   - AVX2\n *   - SSE2\n *   - ARM NEON\n *   - WebAssembly SIMD128\n *   - POWER8 VSX\n *   - s390x ZVector\n * This can be controlled via the @ref XXH_VECTOR macro, but it automatically\n * selects the best version according to predefined macros. For the x86 family, an\n * automatic runtime dispatcher is included separately in @ref xxh_x86dispatch.c.\n *\n * XXH3 implementation is portable:\n * it has a generic C90 formulation that can be compiled on any platform,\n * all implementations generate exactly the same hash value on all platforms.\n * Starting from v0.8.0, it's also labelled \"stable\", meaning that\n * any future version will also generate the same hash value.\n *\n * XXH3 offers 2 variants, _64bits and _128bits.\n *\n * When only 64 bits are needed, prefer invoking the _64bits variant, as it\n * reduces the amount of mixing, resulting in faster speed on small inputs.\n * It's also generally simpler to manipulate a scalar return type than a struct.\n *\n * The API supports one-shot hashing, streaming mode, and custom secrets.\n */\n/*-**********************************************************************\n*  XXH3 64-bit variant\n************************************************************************/\n\n/*!\n * @brief Calculates 64-bit unseeded variant of XXH3 hash of @p input.\n *\n * @param input  The block of data to be hashed, at least @p length bytes in size.\n * @param length The length of @p input, in bytes.\n *\n * @pre\n *   The memory between @p input and @p input + @p length must be valid,\n *   readable, contiguous memory. However, if @p length is `0`, @p input may be\n *   `NULL`. In C++, this also must be *TriviallyCopyable*.\n *\n * @return The calculated 64-bit XXH3 hash value.\n *\n * @note\n *   This is equivalent to @ref XXH3_64bits_withSeed() with a seed of `0`, however\n *   it may have slightly better performance due to constant propagation of the\n *   defaults.\n *\n * @see\n *    XXH3_64bits_withSeed(), XXH3_64bits_withSecret(): other seeding variants\n * @see @ref single_shot_example \"Single Shot Example\" for an example.\n */\nXXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits(XXH_NOESCAPE const void* input, size_t length);\n\n/*!\n * @brief Calculates 64-bit seeded variant of XXH3 hash of @p input.\n *\n * @param input  The block of data to be hashed, at least @p length bytes in size.\n * @param length The length of @p input, in bytes.\n * @param seed   The 64-bit seed to alter the hash result predictably.\n *\n * @pre\n *   The memory between @p input and @p input + @p length must be valid,\n *   readable, contiguous memory. However, if @p length is `0`, @p input may be\n *   `NULL`. In C++, this also must be *TriviallyCopyable*.\n *\n * @return The calculated 64-bit XXH3 hash value.\n *\n * @note\n *    seed == 0 produces the same results as @ref XXH3_64bits().\n *\n * This variant generates a custom secret on the fly based on default secret\n * altered using the @p seed value.\n *\n * While this operation is decently fast, note that it's not completely free.\n *\n * @see @ref single_shot_example \"Single Shot Example\" for an example.\n */\nXXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSeed(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed);\n\n/*!\n * The bare minimum size for a custom secret.\n *\n * @see\n *  XXH3_64bits_withSecret(), XXH3_64bits_reset_withSecret(),\n *  XXH3_128bits_withSecret(), XXH3_128bits_reset_withSecret().\n */\n#define XXH3_SECRET_SIZE_MIN 136\n\n/*!\n * @brief Calculates 64-bit variant of XXH3 with a custom \"secret\".\n *\n * @param data       The block of data to be hashed, at least @p len bytes in size.\n * @param len        The length of @p data, in bytes.\n * @param secret     The secret data.\n * @param secretSize The length of @p secret, in bytes.\n *\n * @return The calculated 64-bit XXH3 hash value.\n *\n * @pre\n *   The memory between @p data and @p data + @p len must be valid,\n *   readable, contiguous memory. However, if @p length is `0`, @p data may be\n *   `NULL`. In C++, this also must be *TriviallyCopyable*.\n *\n * It's possible to provide any blob of bytes as a \"secret\" to generate the hash.\n * This makes it more difficult for an external actor to prepare an intentional collision.\n * The main condition is that @p secretSize *must* be large enough (>= @ref XXH3_SECRET_SIZE_MIN).\n * However, the quality of the secret impacts the dispersion of the hash algorithm.\n * Therefore, the secret _must_ look like a bunch of random bytes.\n * Avoid \"trivial\" or structured data such as repeated sequences or a text document.\n * Whenever in doubt about the \"randomness\" of the blob of bytes,\n * consider employing @ref XXH3_generateSecret() instead (see below).\n * It will generate a proper high entropy secret derived from the blob of bytes.\n * Another advantage of using XXH3_generateSecret() is that\n * it guarantees that all bits within the initial blob of bytes\n * will impact every bit of the output.\n * This is not necessarily the case when using the blob of bytes directly\n * because, when hashing _small_ inputs, only a portion of the secret is employed.\n *\n * @see @ref single_shot_example \"Single Shot Example\" for an example.\n */\nXXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSecret(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize);\n\n\n/*******   Streaming   *******/\n#ifndef XXH_NO_STREAM\n/*\n * Streaming requires state maintenance.\n * This operation costs memory and CPU.\n * As a consequence, streaming is slower than one-shot hashing.\n * For better performance, prefer one-shot functions whenever applicable.\n */\n\n/*!\n * @brief The opaque state struct for the XXH3 streaming API.\n *\n * @see XXH3_state_s for details.\n */\ntypedef struct XXH3_state_s XXH3_state_t;\nXXH_PUBLIC_API XXH_MALLOCF XXH3_state_t* XXH3_createState(void);\nXXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr);\n\n/*!\n * @brief Copies one @ref XXH3_state_t to another.\n *\n * @param dst_state The state to copy to.\n * @param src_state The state to copy from.\n * @pre\n *   @p dst_state and @p src_state must not be `NULL` and must not overlap.\n */\nXXH_PUBLIC_API void XXH3_copyState(XXH_NOESCAPE XXH3_state_t* dst_state, XXH_NOESCAPE const XXH3_state_t* src_state);\n\n/*!\n * @brief Resets an @ref XXH3_state_t to begin a new hash.\n *\n * @param statePtr The state struct to reset.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @note\n *   - This function resets `statePtr` and generate a secret with default parameters.\n *   - Call this function before @ref XXH3_64bits_update().\n *   - Digest will be equivalent to `XXH3_64bits()`.\n *\n */\nXXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr);\n\n/*!\n * @brief Resets an @ref XXH3_state_t with 64-bit seed to begin a new hash.\n *\n * @param statePtr The state struct to reset.\n * @param seed     The 64-bit seed to alter the hash result predictably.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @note\n *   - This function resets `statePtr` and generate a secret from `seed`.\n *   - Call this function before @ref XXH3_64bits_update().\n *   - Digest will be equivalent to `XXH3_64bits_withSeed()`.\n *\n */\nXXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed);\n\n/*!\n * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash.\n *\n * @param statePtr The state struct to reset.\n * @param secret     The secret data.\n * @param secretSize The length of @p secret, in bytes.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @note\n *   `secret` is referenced, it _must outlive_ the hash streaming session.\n *\n * Similar to one-shot API, `secretSize` must be >= @ref XXH3_SECRET_SIZE_MIN,\n * and the quality of produced hash values depends on secret's entropy\n * (secret's content should look like a bunch of random bytes).\n * When in doubt about the randomness of a candidate `secret`,\n * consider employing `XXH3_generateSecret()` instead (see below).\n */\nXXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize);\n\n/*!\n * @brief Consumes a block of @p input to an @ref XXH3_state_t.\n *\n * @param statePtr The state struct to update.\n * @param input The block of data to be hashed, at least @p length bytes in size.\n * @param length The length of @p input, in bytes.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n * @pre\n *   The memory between @p input and @p input + @p length must be valid,\n *   readable, contiguous memory. However, if @p length is `0`, @p input may be\n *   `NULL`. In C++, this also must be *TriviallyCopyable*.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @note Call this to incrementally consume blocks of data.\n */\nXXH_PUBLIC_API XXH_errorcode XXH3_64bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length);\n\n/*!\n * @brief Returns the calculated XXH3 64-bit hash value from an @ref XXH3_state_t.\n *\n * @param statePtr The state struct to calculate the hash from.\n *\n * @pre\n *  @p statePtr must not be `NULL`.\n *\n * @return The calculated XXH3 64-bit hash value from that state.\n *\n * @note\n *   Calling XXH3_64bits_digest() will not affect @p statePtr, so you can update,\n *   digest, and update again.\n */\nXXH_PUBLIC_API XXH_PUREF XXH64_hash_t  XXH3_64bits_digest (XXH_NOESCAPE const XXH3_state_t* statePtr);\n#endif /* !XXH_NO_STREAM */\n\n/* note : canonical representation of XXH3 is the same as XXH64\n * since they both produce XXH64_hash_t values */\n\n\n/*-**********************************************************************\n*  XXH3 128-bit variant\n************************************************************************/\n\n/*!\n * @brief The return value from 128-bit hashes.\n *\n * Stored in little endian order, although the fields themselves are in native\n * endianness.\n */\ntypedef struct {\n    XXH64_hash_t low64;   /*!< `value & 0xFFFFFFFFFFFFFFFF` */\n    XXH64_hash_t high64;  /*!< `value >> 64` */\n} XXH128_hash_t;\n\n/*!\n * @brief Calculates 128-bit unseeded variant of XXH3 of @p data.\n *\n * @param data The block of data to be hashed, at least @p length bytes in size.\n * @param len  The length of @p data, in bytes.\n *\n * @return The calculated 128-bit variant of XXH3 value.\n *\n * The 128-bit variant of XXH3 has more strength, but it has a bit of overhead\n * for shorter inputs.\n *\n * This is equivalent to @ref XXH3_128bits_withSeed() with a seed of `0`, however\n * it may have slightly better performance due to constant propagation of the\n * defaults.\n *\n * @see XXH3_128bits_withSeed(), XXH3_128bits_withSecret(): other seeding variants\n * @see @ref single_shot_example \"Single Shot Example\" for an example.\n */\nXXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits(XXH_NOESCAPE const void* data, size_t len);\n/*! @brief Calculates 128-bit seeded variant of XXH3 hash of @p data.\n *\n * @param data The block of data to be hashed, at least @p length bytes in size.\n * @param len  The length of @p data, in bytes.\n * @param seed The 64-bit seed to alter the hash result predictably.\n *\n * @return The calculated 128-bit variant of XXH3 value.\n *\n * @note\n *    seed == 0 produces the same results as @ref XXH3_64bits().\n *\n * This variant generates a custom secret on the fly based on default secret\n * altered using the @p seed value.\n *\n * While this operation is decently fast, note that it's not completely free.\n *\n * @see XXH3_128bits(), XXH3_128bits_withSecret(): other seeding variants\n * @see @ref single_shot_example \"Single Shot Example\" for an example.\n */\nXXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSeed(XXH_NOESCAPE const void* data, size_t len, XXH64_hash_t seed);\n/*!\n * @brief Calculates 128-bit variant of XXH3 with a custom \"secret\".\n *\n * @param data       The block of data to be hashed, at least @p len bytes in size.\n * @param len        The length of @p data, in bytes.\n * @param secret     The secret data.\n * @param secretSize The length of @p secret, in bytes.\n *\n * @return The calculated 128-bit variant of XXH3 value.\n *\n * It's possible to provide any blob of bytes as a \"secret\" to generate the hash.\n * This makes it more difficult for an external actor to prepare an intentional collision.\n * The main condition is that @p secretSize *must* be large enough (>= @ref XXH3_SECRET_SIZE_MIN).\n * However, the quality of the secret impacts the dispersion of the hash algorithm.\n * Therefore, the secret _must_ look like a bunch of random bytes.\n * Avoid \"trivial\" or structured data such as repeated sequences or a text document.\n * Whenever in doubt about the \"randomness\" of the blob of bytes,\n * consider employing @ref XXH3_generateSecret() instead (see below).\n * It will generate a proper high entropy secret derived from the blob of bytes.\n * Another advantage of using XXH3_generateSecret() is that\n * it guarantees that all bits within the initial blob of bytes\n * will impact every bit of the output.\n * This is not necessarily the case when using the blob of bytes directly\n * because, when hashing _small_ inputs, only a portion of the secret is employed.\n *\n * @see @ref single_shot_example \"Single Shot Example\" for an example.\n */\nXXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSecret(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize);\n\n/*******   Streaming   *******/\n#ifndef XXH_NO_STREAM\n/*\n * Streaming requires state maintenance.\n * This operation costs memory and CPU.\n * As a consequence, streaming is slower than one-shot hashing.\n * For better performance, prefer one-shot functions whenever applicable.\n *\n * XXH3_128bits uses the same XXH3_state_t as XXH3_64bits().\n * Use already declared XXH3_createState() and XXH3_freeState().\n *\n * All reset and streaming functions have same meaning as their 64-bit counterpart.\n */\n\n/*!\n * @brief Resets an @ref XXH3_state_t to begin a new hash.\n *\n * @param statePtr The state struct to reset.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @note\n *   - This function resets `statePtr` and generate a secret with default parameters.\n *   - Call it before @ref XXH3_128bits_update().\n *   - Digest will be equivalent to `XXH3_128bits()`.\n */\nXXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr);\n\n/*!\n * @brief Resets an @ref XXH3_state_t with 64-bit seed to begin a new hash.\n *\n * @param statePtr The state struct to reset.\n * @param seed     The 64-bit seed to alter the hash result predictably.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @note\n *   - This function resets `statePtr` and generate a secret from `seed`.\n *   - Call it before @ref XXH3_128bits_update().\n *   - Digest will be equivalent to `XXH3_128bits_withSeed()`.\n */\nXXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed);\n/*!\n * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash.\n *\n * @param statePtr   The state struct to reset.\n * @param secret     The secret data.\n * @param secretSize The length of @p secret, in bytes.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * `secret` is referenced, it _must outlive_ the hash streaming session.\n * Similar to one-shot API, `secretSize` must be >= @ref XXH3_SECRET_SIZE_MIN,\n * and the quality of produced hash values depends on secret's entropy\n * (secret's content should look like a bunch of random bytes).\n * When in doubt about the randomness of a candidate `secret`,\n * consider employing `XXH3_generateSecret()` instead (see below).\n */\nXXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize);\n\n/*!\n * @brief Consumes a block of @p input to an @ref XXH3_state_t.\n *\n * Call this to incrementally consume blocks of data.\n *\n * @param statePtr The state struct to update.\n * @param input The block of data to be hashed, at least @p length bytes in size.\n * @param length The length of @p input, in bytes.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @note\n *   The memory between @p input and @p input + @p length must be valid,\n *   readable, contiguous memory. However, if @p length is `0`, @p input may be\n *   `NULL`. In C++, this also must be *TriviallyCopyable*.\n *\n */\nXXH_PUBLIC_API XXH_errorcode XXH3_128bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length);\n\n/*!\n * @brief Returns the calculated XXH3 128-bit hash value from an @ref XXH3_state_t.\n *\n * @param statePtr The state struct to calculate the hash from.\n *\n * @pre\n *  @p statePtr must not be `NULL`.\n *\n * @return The calculated XXH3 128-bit hash value from that state.\n *\n * @note\n *   Calling XXH3_128bits_digest() will not affect @p statePtr, so you can update,\n *   digest, and update again.\n *\n */\nXXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_digest (XXH_NOESCAPE const XXH3_state_t* statePtr);\n#endif /* !XXH_NO_STREAM */\n\n/* Following helper functions make it possible to compare XXH128_hast_t values.\n * Since XXH128_hash_t is a structure, this capability is not offered by the language.\n * Note: For better performance, these functions can be inlined using XXH_INLINE_ALL */\n\n/*!\n * @brief Check equality of two XXH128_hash_t values\n *\n * @param h1 The 128-bit hash value.\n * @param h2 Another 128-bit hash value.\n *\n * @return `1` if `h1` and `h2` are equal.\n * @return `0` if they are not.\n */\nXXH_PUBLIC_API XXH_PUREF int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2);\n\n/*!\n * @brief Compares two @ref XXH128_hash_t\n *\n * This comparator is compatible with stdlib's `qsort()`/`bsearch()`.\n *\n * @param h128_1 Left-hand side value\n * @param h128_2 Right-hand side value\n *\n * @return >0 if @p h128_1  > @p h128_2\n * @return =0 if @p h128_1 == @p h128_2\n * @return <0 if @p h128_1  < @p h128_2\n */\nXXH_PUBLIC_API XXH_PUREF int XXH128_cmp(XXH_NOESCAPE const void* h128_1, XXH_NOESCAPE const void* h128_2);\n\n\n/*******   Canonical representation   *******/\ntypedef struct { unsigned char digest[sizeof(XXH128_hash_t)]; } XXH128_canonical_t;\n\n\n/*!\n * @brief Converts an @ref XXH128_hash_t to a big endian @ref XXH128_canonical_t.\n *\n * @param dst  The @ref XXH128_canonical_t pointer to be stored to.\n * @param hash The @ref XXH128_hash_t to be converted.\n *\n * @pre\n *   @p dst must not be `NULL`.\n * @see @ref canonical_representation_example \"Canonical Representation Example\"\n */\nXXH_PUBLIC_API void XXH128_canonicalFromHash(XXH_NOESCAPE XXH128_canonical_t* dst, XXH128_hash_t hash);\n\n/*!\n * @brief Converts an @ref XXH128_canonical_t to a native @ref XXH128_hash_t.\n *\n * @param src The @ref XXH128_canonical_t to convert.\n *\n * @pre\n *   @p src must not be `NULL`.\n *\n * @return The converted hash.\n * @see @ref canonical_representation_example \"Canonical Representation Example\"\n */\nXXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t* src);\n\n\n#endif  /* !XXH_NO_XXH3 */\n\n#if defined (__cplusplus)\n} /* extern \"C\" */\n#endif\n\n#endif  /* XXH_NO_LONG_LONG */\n\n/*!\n * @}\n */\n#endif /* XXHASH_H_5627135585666179 */\n\n\n\n#if defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742)\n#define XXHASH_H_STATIC_13879238742\n/* ****************************************************************************\n * This section contains declarations which are not guaranteed to remain stable.\n * They may change in future versions, becoming incompatible with a different\n * version of the library.\n * These declarations should only be used with static linking.\n * Never use them in association with dynamic linking!\n ***************************************************************************** */\n\n/*\n * These definitions are only present to allow static allocation\n * of XXH states, on stack or in a struct, for example.\n * Never **ever** access their members directly.\n */\n\n/*!\n * @internal\n * @brief Structure for XXH32 streaming API.\n *\n * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY,\n * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. Otherwise it is\n * an opaque type. This allows fields to safely be changed.\n *\n * Typedef'd to @ref XXH32_state_t.\n * Do not access the members of this struct directly.\n * @see XXH64_state_s, XXH3_state_s\n */\nstruct XXH32_state_s {\n   XXH32_hash_t total_len_32; /*!< Total length hashed, modulo 2^32 */\n   XXH32_hash_t large_len;    /*!< Whether the hash is >= 16 (handles @ref total_len_32 overflow) */\n   XXH32_hash_t v[4];         /*!< Accumulator lanes */\n   XXH32_hash_t mem32[4];     /*!< Internal buffer for partial reads. Treated as unsigned char[16]. */\n   XXH32_hash_t memsize;      /*!< Amount of data in @ref mem32 */\n   XXH32_hash_t reserved;     /*!< Reserved field. Do not read nor write to it. */\n};   /* typedef'd to XXH32_state_t */\n\n\n#ifndef XXH_NO_LONG_LONG  /* defined when there is no 64-bit support */\n\n/*!\n * @internal\n * @brief Structure for XXH64 streaming API.\n *\n * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY,\n * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. Otherwise it is\n * an opaque type. This allows fields to safely be changed.\n *\n * Typedef'd to @ref XXH64_state_t.\n * Do not access the members of this struct directly.\n * @see XXH32_state_s, XXH3_state_s\n */\nstruct XXH64_state_s {\n   XXH64_hash_t total_len;    /*!< Total length hashed. This is always 64-bit. */\n   XXH64_hash_t v[4];         /*!< Accumulator lanes */\n   XXH64_hash_t mem64[4];     /*!< Internal buffer for partial reads. Treated as unsigned char[32]. */\n   XXH32_hash_t memsize;      /*!< Amount of data in @ref mem64 */\n   XXH32_hash_t reserved32;   /*!< Reserved field, needed for padding anyways*/\n   XXH64_hash_t reserved64;   /*!< Reserved field. Do not read or write to it. */\n};   /* typedef'd to XXH64_state_t */\n\n#ifndef XXH_NO_XXH3\n\n#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* >= C11 */\n#  include <stdalign.h>\n#  define XXH_ALIGN(n)      alignas(n)\n#elif defined(__cplusplus) && (__cplusplus >= 201103L) /* >= C++11 */\n/* In C++ alignas() is a keyword */\n#  define XXH_ALIGN(n)      alignas(n)\n#elif defined(__GNUC__)\n#  define XXH_ALIGN(n)      __attribute__ ((aligned(n)))\n#elif defined(_MSC_VER)\n#  define XXH_ALIGN(n)      __declspec(align(n))\n#else\n#  define XXH_ALIGN(n)   /* disabled */\n#endif\n\n/* Old GCC versions only accept the attribute after the type in structures. */\n#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L))   /* C11+ */ \\\n    && ! (defined(__cplusplus) && (__cplusplus >= 201103L)) /* >= C++11 */ \\\n    && defined(__GNUC__)\n#   define XXH_ALIGN_MEMBER(align, type) type XXH_ALIGN(align)\n#else\n#   define XXH_ALIGN_MEMBER(align, type) XXH_ALIGN(align) type\n#endif\n\n/*!\n * @brief The size of the internal XXH3 buffer.\n *\n * This is the optimal update size for incremental hashing.\n *\n * @see XXH3_64b_update(), XXH3_128b_update().\n */\n#define XXH3_INTERNALBUFFER_SIZE 256\n\n/*!\n * @internal\n * @brief Default size of the secret buffer (and @ref XXH3_kSecret).\n *\n * This is the size used in @ref XXH3_kSecret and the seeded functions.\n *\n * Not to be confused with @ref XXH3_SECRET_SIZE_MIN.\n */\n#define XXH3_SECRET_DEFAULT_SIZE 192\n\n/*!\n * @internal\n * @brief Structure for XXH3 streaming API.\n *\n * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY,\n * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined.\n * Otherwise it is an opaque type.\n * Never use this definition in combination with dynamic library.\n * This allows fields to safely be changed in the future.\n *\n * @note ** This structure has a strict alignment requirement of 64 bytes!! **\n * Do not allocate this with `malloc()` or `new`,\n * it will not be sufficiently aligned.\n * Use @ref XXH3_createState() and @ref XXH3_freeState(), or stack allocation.\n *\n * Typedef'd to @ref XXH3_state_t.\n * Do never access the members of this struct directly.\n *\n * @see XXH3_INITSTATE() for stack initialization.\n * @see XXH3_createState(), XXH3_freeState().\n * @see XXH32_state_s, XXH64_state_s\n */\nstruct XXH3_state_s {\n   XXH_ALIGN_MEMBER(64, XXH64_hash_t acc[8]);\n       /*!< The 8 accumulators. See @ref XXH32_state_s::v and @ref XXH64_state_s::v */\n   XXH_ALIGN_MEMBER(64, unsigned char customSecret[XXH3_SECRET_DEFAULT_SIZE]);\n       /*!< Used to store a custom secret generated from a seed. */\n   XXH_ALIGN_MEMBER(64, unsigned char buffer[XXH3_INTERNALBUFFER_SIZE]);\n       /*!< The internal buffer. @see XXH32_state_s::mem32 */\n   XXH32_hash_t bufferedSize;\n       /*!< The amount of memory in @ref buffer, @see XXH32_state_s::memsize */\n   XXH32_hash_t useSeed;\n       /*!< Reserved field. Needed for padding on 64-bit. */\n   size_t nbStripesSoFar;\n       /*!< Number or stripes processed. */\n   XXH64_hash_t totalLen;\n       /*!< Total length hashed. 64-bit even on 32-bit targets. */\n   size_t nbStripesPerBlock;\n       /*!< Number of stripes per block. */\n   size_t secretLimit;\n       /*!< Size of @ref customSecret or @ref extSecret */\n   XXH64_hash_t seed;\n       /*!< Seed for _withSeed variants. Must be zero otherwise, @see XXH3_INITSTATE() */\n   XXH64_hash_t reserved64;\n       /*!< Reserved field. */\n   const unsigned char* extSecret;\n       /*!< Reference to an external secret for the _withSecret variants, NULL\n        *   for other variants. */\n   /* note: there may be some padding at the end due to alignment on 64 bytes */\n}; /* typedef'd to XXH3_state_t */\n\n#undef XXH_ALIGN_MEMBER\n\n/*!\n * @brief Initializes a stack-allocated `XXH3_state_s`.\n *\n * When the @ref XXH3_state_t structure is merely emplaced on stack,\n * it should be initialized with XXH3_INITSTATE() or a memset()\n * in case its first reset uses XXH3_NNbits_reset_withSeed().\n * This init can be omitted if the first reset uses default or _withSecret mode.\n * This operation isn't necessary when the state is created with XXH3_createState().\n * Note that this doesn't prepare the state for a streaming operation,\n * it's still necessary to use XXH3_NNbits_reset*() afterwards.\n */\n#define XXH3_INITSTATE(XXH3_state_ptr)                       \\\n    do {                                                     \\\n        XXH3_state_t* tmp_xxh3_state_ptr = (XXH3_state_ptr); \\\n        tmp_xxh3_state_ptr->seed = 0;                        \\\n        tmp_xxh3_state_ptr->extSecret = NULL;                \\\n    } while(0)\n\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/*!\n * @brief Calculates the 128-bit hash of @p data using XXH3.\n *\n * @param data The block of data to be hashed, at least @p len bytes in size.\n * @param len  The length of @p data, in bytes.\n * @param seed The 64-bit seed to alter the hash's output predictably.\n *\n * @pre\n *   The memory between @p data and @p data + @p len must be valid,\n *   readable, contiguous memory. However, if @p len is `0`, @p data may be\n *   `NULL`. In C++, this also must be *TriviallyCopyable*.\n *\n * @return The calculated 128-bit XXH3 value.\n *\n * @see @ref single_shot_example \"Single Shot Example\" for an example.\n */\nXXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128(XXH_NOESCAPE const void* data, size_t len, XXH64_hash_t seed);\n\n\n/* ===   Experimental API   === */\n/* Symbols defined below must be considered tied to a specific library version. */\n\n/*!\n * @brief Derive a high-entropy secret from any user-defined content, named customSeed.\n *\n * @param secretBuffer    A writable buffer for derived high-entropy secret data.\n * @param secretSize      Size of secretBuffer, in bytes.  Must be >= XXH3_SECRET_DEFAULT_SIZE.\n * @param customSeed      A user-defined content.\n * @param customSeedSize  Size of customSeed, in bytes.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * The generated secret can be used in combination with `*_withSecret()` functions.\n * The `_withSecret()` variants are useful to provide a higher level of protection\n * than 64-bit seed, as it becomes much more difficult for an external actor to\n * guess how to impact the calculation logic.\n *\n * The function accepts as input a custom seed of any length and any content,\n * and derives from it a high-entropy secret of length @p secretSize into an\n * already allocated buffer @p secretBuffer.\n *\n * The generated secret can then be used with any `*_withSecret()` variant.\n * The functions @ref XXH3_128bits_withSecret(), @ref XXH3_64bits_withSecret(),\n * @ref XXH3_128bits_reset_withSecret() and @ref XXH3_64bits_reset_withSecret()\n * are part of this list. They all accept a `secret` parameter\n * which must be large enough for implementation reasons (>= @ref XXH3_SECRET_SIZE_MIN)\n * _and_ feature very high entropy (consist of random-looking bytes).\n * These conditions can be a high bar to meet, so @ref XXH3_generateSecret() can\n * be employed to ensure proper quality.\n *\n * @p customSeed can be anything. It can have any size, even small ones,\n * and its content can be anything, even \"poor entropy\" sources such as a bunch\n * of zeroes. The resulting `secret` will nonetheless provide all required qualities.\n *\n * @pre\n *   - @p secretSize must be >= @ref XXH3_SECRET_SIZE_MIN\n *   - When @p customSeedSize > 0, supplying NULL as customSeed is undefined behavior.\n *\n * Example code:\n * @code{.c}\n *    #include <stdio.h>\n *    #include <stdlib.h>\n *    #include <string.h>\n *    #define XXH_STATIC_LINKING_ONLY // expose unstable API\n *    #include \"xxhash.h\"\n *    // Hashes argv[2] using the entropy from argv[1].\n *    int main(int argc, char* argv[])\n *    {\n *        char secret[XXH3_SECRET_SIZE_MIN];\n *        if (argv != 3) { return 1; }\n *        XXH3_generateSecret(secret, sizeof(secret), argv[1], strlen(argv[1]));\n *        XXH64_hash_t h = XXH3_64bits_withSecret(\n *             argv[2], strlen(argv[2]),\n *             secret, sizeof(secret)\n *        );\n *        printf(\"%016llx\\n\", (unsigned long long) h);\n *    }\n * @endcode\n */\nXXH_PUBLIC_API XXH_errorcode XXH3_generateSecret(XXH_NOESCAPE void* secretBuffer, size_t secretSize, XXH_NOESCAPE const void* customSeed, size_t customSeedSize);\n\n/*!\n * @brief Generate the same secret as the _withSeed() variants.\n *\n * @param secretBuffer A writable buffer of @ref XXH3_SECRET_SIZE_MIN bytes\n * @param seed         The 64-bit seed to alter the hash result predictably.\n *\n * The generated secret can be used in combination with\n *`*_withSecret()` and `_withSecretandSeed()` variants.\n *\n * Example C++ `std::string` hash class:\n * @code{.cpp}\n *    #include <string>\n *    #define XXH_STATIC_LINKING_ONLY // expose unstable API\n *    #include \"xxhash.h\"\n *    // Slow, seeds each time\n *    class HashSlow {\n *        XXH64_hash_t seed;\n *    public:\n *        HashSlow(XXH64_hash_t s) : seed{s} {}\n *        size_t operator()(const std::string& x) const {\n *            return size_t{XXH3_64bits_withSeed(x.c_str(), x.length(), seed)};\n *        }\n *    };\n *    // Fast, caches the seeded secret for future uses.\n *    class HashFast {\n *        unsigned char secret[XXH3_SECRET_SIZE_MIN];\n *    public:\n *        HashFast(XXH64_hash_t s) {\n *            XXH3_generateSecret_fromSeed(secret, seed);\n *        }\n *        size_t operator()(const std::string& x) const {\n *            return size_t{\n *                XXH3_64bits_withSecret(x.c_str(), x.length(), secret, sizeof(secret))\n *            };\n *        }\n *    };\n * @endcode\n */\nXXH_PUBLIC_API void XXH3_generateSecret_fromSeed(XXH_NOESCAPE void* secretBuffer, XXH64_hash_t seed);\n\n/*!\n * @brief Calculates 64/128-bit seeded variant of XXH3 hash of @p data.\n *\n * @param data       The block of data to be hashed, at least @p len bytes in size.\n * @param len        The length of @p data, in bytes.\n * @param secret     The secret data.\n * @param secretSize The length of @p secret, in bytes.\n * @param seed       The 64-bit seed to alter the hash result predictably.\n *\n * These variants generate hash values using either\n * @p seed for \"short\" keys (< @ref XXH3_MIDSIZE_MAX = 240 bytes)\n * or @p secret for \"large\" keys (>= @ref XXH3_MIDSIZE_MAX).\n *\n * This generally benefits speed, compared to `_withSeed()` or `_withSecret()`.\n * `_withSeed()` has to generate the secret on the fly for \"large\" keys.\n * It's fast, but can be perceptible for \"not so large\" keys (< 1 KB).\n * `_withSecret()` has to generate the masks on the fly for \"small\" keys,\n * which requires more instructions than _withSeed() variants.\n * Therefore, _withSecretandSeed variant combines the best of both worlds.\n *\n * When @p secret has been generated by XXH3_generateSecret_fromSeed(),\n * this variant produces *exactly* the same results as `_withSeed()` variant,\n * hence offering only a pure speed benefit on \"large\" input,\n * by skipping the need to regenerate the secret for every large input.\n *\n * Another usage scenario is to hash the secret to a 64-bit hash value,\n * for example with XXH3_64bits(), which then becomes the seed,\n * and then employ both the seed and the secret in _withSecretandSeed().\n * On top of speed, an added benefit is that each bit in the secret\n * has a 50% chance to swap each bit in the output, via its impact to the seed.\n *\n * This is not guaranteed when using the secret directly in \"small data\" scenarios,\n * because only portions of the secret are employed for small data.\n */\nXXH_PUBLIC_API XXH_PUREF XXH64_hash_t\nXXH3_64bits_withSecretandSeed(XXH_NOESCAPE const void* data, size_t len,\n                              XXH_NOESCAPE const void* secret, size_t secretSize,\n                              XXH64_hash_t seed);\n/*!\n * @brief Calculates 128-bit seeded variant of XXH3 hash of @p data.\n *\n * @param input      The block of data to be hashed, at least @p len bytes in size.\n * @param length     The length of @p data, in bytes.\n * @param secret     The secret data.\n * @param secretSize The length of @p secret, in bytes.\n * @param seed64     The 64-bit seed to alter the hash result predictably.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @see XXH3_64bits_withSecretandSeed()\n */\nXXH_PUBLIC_API XXH_PUREF XXH128_hash_t\nXXH3_128bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t length,\n                               XXH_NOESCAPE const void* secret, size_t secretSize,\n                               XXH64_hash_t seed64);\n#ifndef XXH_NO_STREAM\n/*!\n * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash.\n *\n * @param statePtr   A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState().\n * @param secret     The secret data.\n * @param secretSize The length of @p secret, in bytes.\n * @param seed64     The 64-bit seed to alter the hash result predictably.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @see XXH3_64bits_withSecretandSeed()\n */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_64bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr,\n                                    XXH_NOESCAPE const void* secret, size_t secretSize,\n                                    XXH64_hash_t seed64);\n/*!\n * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash.\n *\n * @param statePtr   A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState().\n * @param secret     The secret data.\n * @param secretSize The length of @p secret, in bytes.\n * @param seed64     The 64-bit seed to alter the hash result predictably.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @see XXH3_64bits_withSecretandSeed()\n */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr,\n                                     XXH_NOESCAPE const void* secret, size_t secretSize,\n                                     XXH64_hash_t seed64);\n#endif /* !XXH_NO_STREAM */\n\n#if defined (__cplusplus)\n} /* extern \"C\" */\n#endif\n\n#endif  /* !XXH_NO_XXH3 */\n#endif  /* XXH_NO_LONG_LONG */\n\n#if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API)\n#  define XXH_IMPLEMENTATION\n#endif\n\n#endif  /* defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742) */\n\n\n/* ======================================================================== */\n/* ======================================================================== */\n/* ======================================================================== */\n\n\n/*-**********************************************************************\n * xxHash implementation\n *-**********************************************************************\n * xxHash's implementation used to be hosted inside xxhash.c.\n *\n * However, inlining requires implementation to be visible to the compiler,\n * hence be included alongside the header.\n * Previously, implementation was hosted inside xxhash.c,\n * which was then #included when inlining was activated.\n * This construction created issues with a few build and install systems,\n * as it required xxhash.c to be stored in /include directory.\n *\n * xxHash implementation is now directly integrated within xxhash.h.\n * As a consequence, xxhash.c is no longer needed in /include.\n *\n * xxhash.c is still available and is still useful.\n * In a \"normal\" setup, when xxhash is not inlined,\n * xxhash.h only exposes the prototypes and public symbols,\n * while xxhash.c can be built into an object file xxhash.o\n * which can then be linked into the final binary.\n ************************************************************************/\n\n#if ( defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) \\\n   || defined(XXH_IMPLEMENTATION) ) && !defined(XXH_IMPLEM_13a8737387)\n#  define XXH_IMPLEM_13a8737387\n\n/* *************************************\n*  Tuning parameters\n***************************************/\n\n/*!\n * @defgroup tuning Tuning parameters\n * @{\n *\n * Various macros to control xxHash's behavior.\n */\n#ifdef XXH_DOXYGEN\n/*!\n * @brief Define this to disable 64-bit code.\n *\n * Useful if only using the @ref XXH32_family and you have a strict C90 compiler.\n */\n#  define XXH_NO_LONG_LONG\n#  undef XXH_NO_LONG_LONG /* don't actually */\n/*!\n * @brief Controls how unaligned memory is accessed.\n *\n * By default, access to unaligned memory is controlled by `memcpy()`, which is\n * safe and portable.\n *\n * Unfortunately, on some target/compiler combinations, the generated assembly\n * is sub-optimal.\n *\n * The below switch allow selection of a different access method\n * in the search for improved performance.\n *\n * @par Possible options:\n *\n *  - `XXH_FORCE_MEMORY_ACCESS=0` (default): `memcpy`\n *   @par\n *     Use `memcpy()`. Safe and portable. Note that most modern compilers will\n *     eliminate the function call and treat it as an unaligned access.\n *\n *  - `XXH_FORCE_MEMORY_ACCESS=1`: `__attribute__((aligned(1)))`\n *   @par\n *     Depends on compiler extensions and is therefore not portable.\n *     This method is safe _if_ your compiler supports it,\n *     and *generally* as fast or faster than `memcpy`.\n *\n *  - `XXH_FORCE_MEMORY_ACCESS=2`: Direct cast\n *  @par\n *     Casts directly and dereferences. This method doesn't depend on the\n *     compiler, but it violates the C standard as it directly dereferences an\n *     unaligned pointer. It can generate buggy code on targets which do not\n *     support unaligned memory accesses, but in some circumstances, it's the\n *     only known way to get the most performance.\n *\n *  - `XXH_FORCE_MEMORY_ACCESS=3`: Byteshift\n *  @par\n *     Also portable. This can generate the best code on old compilers which don't\n *     inline small `memcpy()` calls, and it might also be faster on big-endian\n *     systems which lack a native byteswap instruction. However, some compilers\n *     will emit literal byteshifts even if the target supports unaligned access.\n *\n *\n * @warning\n *   Methods 1 and 2 rely on implementation-defined behavior. Use these with\n *   care, as what works on one compiler/platform/optimization level may cause\n *   another to read garbage data or even crash.\n *\n * See https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html for details.\n *\n * Prefer these methods in priority order (0 > 3 > 1 > 2)\n */\n#  define XXH_FORCE_MEMORY_ACCESS 0\n\n/*!\n * @def XXH_SIZE_OPT\n * @brief Controls how much xxHash optimizes for size.\n *\n * xxHash, when compiled, tends to result in a rather large binary size. This\n * is mostly due to heavy usage to forced inlining and constant folding of the\n * @ref XXH3_family to increase performance.\n *\n * However, some developers prefer size over speed. This option can\n * significantly reduce the size of the generated code. When using the `-Os`\n * or `-Oz` options on GCC or Clang, this is defined to 1 by default,\n * otherwise it is defined to 0.\n *\n * Most of these size optimizations can be controlled manually.\n *\n * This is a number from 0-2.\n *  - `XXH_SIZE_OPT` == 0: Default. xxHash makes no size optimizations. Speed\n *    comes first.\n *  - `XXH_SIZE_OPT` == 1: Default for `-Os` and `-Oz`. xxHash is more\n *    conservative and disables hacks that increase code size. It implies the\n *    options @ref XXH_NO_INLINE_HINTS == 1, @ref XXH_FORCE_ALIGN_CHECK == 0,\n *    and @ref XXH3_NEON_LANES == 8 if they are not already defined.\n *  - `XXH_SIZE_OPT` == 2: xxHash tries to make itself as small as possible.\n *    Performance may cry. For example, the single shot functions just use the\n *    streaming API.\n */\n#  define XXH_SIZE_OPT 0\n\n/*!\n * @def XXH_FORCE_ALIGN_CHECK\n * @brief If defined to non-zero, adds a special path for aligned inputs (XXH32()\n * and XXH64() only).\n *\n * This is an important performance trick for architectures without decent\n * unaligned memory access performance.\n *\n * It checks for input alignment, and when conditions are met, uses a \"fast\n * path\" employing direct 32-bit/64-bit reads, resulting in _dramatically\n * faster_ read speed.\n *\n * The check costs one initial branch per hash, which is generally negligible,\n * but not zero.\n *\n * Moreover, it's not useful to generate an additional code path if memory\n * access uses the same instruction for both aligned and unaligned\n * addresses (e.g. x86 and aarch64).\n *\n * In these cases, the alignment check can be removed by setting this macro to 0.\n * Then the code will always use unaligned memory access.\n * Align check is automatically disabled on x86, x64, ARM64, and some ARM chips\n * which are platforms known to offer good unaligned memory accesses performance.\n *\n * It is also disabled by default when @ref XXH_SIZE_OPT >= 1.\n *\n * This option does not affect XXH3 (only XXH32 and XXH64).\n */\n#  define XXH_FORCE_ALIGN_CHECK 0\n\n/*!\n * @def XXH_NO_INLINE_HINTS\n * @brief When non-zero, sets all functions to `static`.\n *\n * By default, xxHash tries to force the compiler to inline almost all internal\n * functions.\n *\n * This can usually improve performance due to reduced jumping and improved\n * constant folding, but significantly increases the size of the binary which\n * might not be favorable.\n *\n * Additionally, sometimes the forced inlining can be detrimental to performance,\n * depending on the architecture.\n *\n * XXH_NO_INLINE_HINTS marks all internal functions as static, giving the\n * compiler full control on whether to inline or not.\n *\n * When not optimizing (-O0), using `-fno-inline` with GCC or Clang, or if\n * @ref XXH_SIZE_OPT >= 1, this will automatically be defined.\n */\n#  define XXH_NO_INLINE_HINTS 0\n\n/*!\n * @def XXH3_INLINE_SECRET\n * @brief Determines whether to inline the XXH3 withSecret code.\n *\n * When the secret size is known, the compiler can improve the performance\n * of XXH3_64bits_withSecret() and XXH3_128bits_withSecret().\n *\n * However, if the secret size is not known, it doesn't have any benefit. This\n * happens when xxHash is compiled into a global symbol. Therefore, if\n * @ref XXH_INLINE_ALL is *not* defined, this will be defined to 0.\n *\n * Additionally, this defaults to 0 on GCC 12+, which has an issue with function pointers\n * that are *sometimes* force inline on -Og, and it is impossible to automatically\n * detect this optimization level.\n */\n#  define XXH3_INLINE_SECRET 0\n\n/*!\n * @def XXH32_ENDJMP\n * @brief Whether to use a jump for `XXH32_finalize`.\n *\n * For performance, `XXH32_finalize` uses multiple branches in the finalizer.\n * This is generally preferable for performance,\n * but depending on exact architecture, a jmp may be preferable.\n *\n * This setting is only possibly making a difference for very small inputs.\n */\n#  define XXH32_ENDJMP 0\n\n/*!\n * @internal\n * @brief Redefines old internal names.\n *\n * For compatibility with code that uses xxHash's internals before the names\n * were changed to improve namespacing. There is no other reason to use this.\n */\n#  define XXH_OLD_NAMES\n#  undef XXH_OLD_NAMES /* don't actually use, it is ugly. */\n\n/*!\n * @def XXH_NO_STREAM\n * @brief Disables the streaming API.\n *\n * When xxHash is not inlined and the streaming functions are not used, disabling\n * the streaming functions can improve code size significantly, especially with\n * the @ref XXH3_family which tends to make constant folded copies of itself.\n */\n#  define XXH_NO_STREAM\n#  undef XXH_NO_STREAM /* don't actually */\n#endif /* XXH_DOXYGEN */\n/*!\n * @}\n */\n\n#ifndef XXH_FORCE_MEMORY_ACCESS   /* can be defined externally, on command line for example */\n   /* prefer __packed__ structures (method 1) for GCC\n    * < ARMv7 with unaligned access (e.g. Raspbian armhf) still uses byte shifting, so we use memcpy\n    * which for some reason does unaligned loads. */\n#  if defined(__GNUC__) && !(defined(__ARM_ARCH) && __ARM_ARCH < 7 && defined(__ARM_FEATURE_UNALIGNED))\n#    define XXH_FORCE_MEMORY_ACCESS 1\n#  endif\n#endif\n\n#ifndef XXH_SIZE_OPT\n   /* default to 1 for -Os or -Oz */\n#  if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE_SIZE__)\n#    define XXH_SIZE_OPT 1\n#  else\n#    define XXH_SIZE_OPT 0\n#  endif\n#endif\n\n#ifndef XXH_FORCE_ALIGN_CHECK  /* can be defined externally */\n   /* don't check on sizeopt, x86, aarch64, or arm when unaligned access is available */\n#  if XXH_SIZE_OPT >= 1 || \\\n      defined(__i386)  || defined(__x86_64__) || defined(__aarch64__) || defined(__ARM_FEATURE_UNALIGNED) \\\n   || defined(_M_IX86) || defined(_M_X64)     || defined(_M_ARM64)    || defined(_M_ARM) /* visual */\n#    define XXH_FORCE_ALIGN_CHECK 0\n#  else\n#    define XXH_FORCE_ALIGN_CHECK 1\n#  endif\n#endif\n\n#ifndef XXH_NO_INLINE_HINTS\n#  if XXH_SIZE_OPT >= 1 || defined(__NO_INLINE__)  /* -O0, -fno-inline */\n#    define XXH_NO_INLINE_HINTS 1\n#  else\n#    define XXH_NO_INLINE_HINTS 0\n#  endif\n#endif\n\n#ifndef XXH3_INLINE_SECRET\n#  if (defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 12) \\\n     || !defined(XXH_INLINE_ALL)\n#    define XXH3_INLINE_SECRET 0\n#  else\n#    define XXH3_INLINE_SECRET 1\n#  endif\n#endif\n\n#ifndef XXH32_ENDJMP\n/* generally preferable for performance */\n#  define XXH32_ENDJMP 0\n#endif\n\n/*!\n * @defgroup impl Implementation\n * @{\n */\n\n/* *************************************\n*  Includes & Memory related functions\n***************************************/\n#include <string.h>   /* memcmp, memcpy */\n#include <limits.h>   /* ULLONG_MAX */\n\n#if defined(XXH_NO_STREAM)\n/* nothing */\n#elif defined(XXH_NO_STDLIB)\n\n/* When requesting to disable any mention of stdlib,\n * the library loses the ability to invoked malloc / free.\n * In practice, it means that functions like `XXH*_createState()`\n * will always fail, and return NULL.\n * This flag is useful in situations where\n * xxhash.h is integrated into some kernel, embedded or limited environment\n * without access to dynamic allocation.\n */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nstatic XXH_CONSTF void* XXH_malloc(size_t s) { (void)s; return NULL; }\nstatic void XXH_free(void* p) { (void)p; }\n\n#if defined (__cplusplus)\n} /* extern \"C\" */\n#endif\n\n#else\n\n/*\n * Modify the local functions below should you wish to use\n * different memory routines for malloc() and free()\n */\n#include <stdlib.h>\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n/*!\n * @internal\n * @brief Modify this function to use a different routine than malloc().\n */\nstatic XXH_MALLOCF void* XXH_malloc(size_t s) { return malloc(s); }\n\n/*!\n * @internal\n * @brief Modify this function to use a different routine than free().\n */\nstatic void XXH_free(void* p) { free(p); }\n\n#if defined (__cplusplus)\n} /* extern \"C\" */\n#endif\n\n#endif  /* XXH_NO_STDLIB */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n/*!\n * @internal\n * @brief Modify this function to use a different routine than memcpy().\n */\nstatic void* XXH_memcpy(void* dest, const void* src, size_t size)\n{\n    return memcpy(dest,src,size);\n}\n\n#if defined (__cplusplus)\n} /* extern \"C\" */\n#endif\n\n/* *************************************\n*  Compiler Specific Options\n***************************************/\n#ifdef _MSC_VER /* Visual Studio warning fix */\n#  pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */\n#endif\n\n#if XXH_NO_INLINE_HINTS  /* disable inlining hints */\n#  if defined(__GNUC__) || defined(__clang__)\n#    define XXH_FORCE_INLINE static __attribute__((unused))\n#  else\n#    define XXH_FORCE_INLINE static\n#  endif\n#  define XXH_NO_INLINE static\n/* enable inlining hints */\n#elif defined(__GNUC__) || defined(__clang__)\n#  define XXH_FORCE_INLINE static __inline__ __attribute__((always_inline, unused))\n#  define XXH_NO_INLINE static __attribute__((noinline))\n#elif defined(_MSC_VER)  /* Visual Studio */\n#  define XXH_FORCE_INLINE static __forceinline\n#  define XXH_NO_INLINE static __declspec(noinline)\n#elif defined (__cplusplus) \\\n  || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L))   /* C99 */\n#  define XXH_FORCE_INLINE static inline\n#  define XXH_NO_INLINE static\n#else\n#  define XXH_FORCE_INLINE static\n#  define XXH_NO_INLINE static\n#endif\n\n#if XXH3_INLINE_SECRET\n#  define XXH3_WITH_SECRET_INLINE XXH_FORCE_INLINE\n#else\n#  define XXH3_WITH_SECRET_INLINE XXH_NO_INLINE\n#endif\n\n\n/* *************************************\n*  Debug\n***************************************/\n/*!\n * @ingroup tuning\n * @def XXH_DEBUGLEVEL\n * @brief Sets the debugging level.\n *\n * XXH_DEBUGLEVEL is expected to be defined externally, typically via the\n * compiler's command line options. The value must be a number.\n */\n#ifndef XXH_DEBUGLEVEL\n#  ifdef DEBUGLEVEL /* backwards compat */\n#    define XXH_DEBUGLEVEL DEBUGLEVEL\n#  else\n#    define XXH_DEBUGLEVEL 0\n#  endif\n#endif\n\n#if (XXH_DEBUGLEVEL>=1)\n#  include <assert.h>   /* note: can still be disabled with NDEBUG */\n#  define XXH_ASSERT(c)   assert(c)\n#else\n#  if defined(__INTEL_COMPILER)\n#    define XXH_ASSERT(c)   XXH_ASSUME((unsigned char) (c))\n#  else\n#    define XXH_ASSERT(c)   XXH_ASSUME(c)\n#  endif\n#endif\n\n/* note: use after variable declarations */\n#ifndef XXH_STATIC_ASSERT\n#  if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)    /* C11 */\n#    define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { _Static_assert((c),m); } while(0)\n#  elif defined(__cplusplus) && (__cplusplus >= 201103L)            /* C++11 */\n#    define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { static_assert((c),m); } while(0)\n#  else\n#    define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { struct xxh_sa { char x[(c) ? 1 : -1]; }; } while(0)\n#  endif\n#  define XXH_STATIC_ASSERT(c) XXH_STATIC_ASSERT_WITH_MESSAGE((c),#c)\n#endif\n\n/*!\n * @internal\n * @def XXH_COMPILER_GUARD(var)\n * @brief Used to prevent unwanted optimizations for @p var.\n *\n * It uses an empty GCC inline assembly statement with a register constraint\n * which forces @p var into a general purpose register (eg eax, ebx, ecx\n * on x86) and marks it as modified.\n *\n * This is used in a few places to avoid unwanted autovectorization (e.g.\n * XXH32_round()). All vectorization we want is explicit via intrinsics,\n * and _usually_ isn't wanted elsewhere.\n *\n * We also use it to prevent unwanted constant folding for AArch64 in\n * XXH3_initCustomSecret_scalar().\n */\n#if defined(__GNUC__) || defined(__clang__)\n#  define XXH_COMPILER_GUARD(var) __asm__(\"\" : \"+r\" (var))\n#else\n#  define XXH_COMPILER_GUARD(var) ((void)0)\n#endif\n\n/* Specifically for NEON vectors which use the \"w\" constraint, on\n * Clang. */\n#if defined(__clang__) && defined(__ARM_ARCH) && !defined(__wasm__)\n#  define XXH_COMPILER_GUARD_CLANG_NEON(var) __asm__(\"\" : \"+w\" (var))\n#else\n#  define XXH_COMPILER_GUARD_CLANG_NEON(var) ((void)0)\n#endif\n\n/* *************************************\n*  Basic Types\n***************************************/\n#if !defined (__VMS) \\\n && (defined (__cplusplus) \\\n || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )\n# ifdef _AIX\n#   include <inttypes.h>\n# else\n#   include <stdint.h>\n# endif\n  typedef uint8_t xxh_u8;\n#else\n  typedef unsigned char xxh_u8;\n#endif\ntypedef XXH32_hash_t xxh_u32;\n\n#ifdef XXH_OLD_NAMES\n#  warning \"XXH_OLD_NAMES is planned to be removed starting v0.9. If the program depends on it, consider moving away from it by employing newer type names directly\"\n#  define BYTE xxh_u8\n#  define U8   xxh_u8\n#  define U32  xxh_u32\n#endif\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* ***   Memory access   *** */\n\n/*!\n * @internal\n * @fn xxh_u32 XXH_read32(const void* ptr)\n * @brief Reads an unaligned 32-bit integer from @p ptr in native endianness.\n *\n * Affected by @ref XXH_FORCE_MEMORY_ACCESS.\n *\n * @param ptr The pointer to read from.\n * @return The 32-bit native endian integer from the bytes at @p ptr.\n */\n\n/*!\n * @internal\n * @fn xxh_u32 XXH_readLE32(const void* ptr)\n * @brief Reads an unaligned 32-bit little endian integer from @p ptr.\n *\n * Affected by @ref XXH_FORCE_MEMORY_ACCESS.\n *\n * @param ptr The pointer to read from.\n * @return The 32-bit little endian integer from the bytes at @p ptr.\n */\n\n/*!\n * @internal\n * @fn xxh_u32 XXH_readBE32(const void* ptr)\n * @brief Reads an unaligned 32-bit big endian integer from @p ptr.\n *\n * Affected by @ref XXH_FORCE_MEMORY_ACCESS.\n *\n * @param ptr The pointer to read from.\n * @return The 32-bit big endian integer from the bytes at @p ptr.\n */\n\n/*!\n * @internal\n * @fn xxh_u32 XXH_readLE32_align(const void* ptr, XXH_alignment align)\n * @brief Like @ref XXH_readLE32(), but has an option for aligned reads.\n *\n * Affected by @ref XXH_FORCE_MEMORY_ACCESS.\n * Note that when @ref XXH_FORCE_ALIGN_CHECK == 0, the @p align parameter is\n * always @ref XXH_alignment::XXH_unaligned.\n *\n * @param ptr The pointer to read from.\n * @param align Whether @p ptr is aligned.\n * @pre\n *   If @p align == @ref XXH_alignment::XXH_aligned, @p ptr must be 4 byte\n *   aligned.\n * @return The 32-bit little endian integer from the bytes at @p ptr.\n */\n\n#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3))\n/*\n * Manual byteshift. Best for old compilers which don't inline memcpy.\n * We actually directly use XXH_readLE32 and XXH_readBE32.\n */\n#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))\n\n/*\n * Force direct memory access. Only works on CPU which support unaligned memory\n * access in hardware.\n */\nstatic xxh_u32 XXH_read32(const void* memPtr) { return *(const xxh_u32*) memPtr; }\n\n#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))\n\n/*\n * __attribute__((aligned(1))) is supported by gcc and clang. Originally the\n * documentation claimed that it only increased the alignment, but actually it\n * can decrease it on gcc, clang, and icc:\n * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69502,\n * https://gcc.godbolt.org/z/xYez1j67Y.\n */\n#ifdef XXH_OLD_NAMES\ntypedef union { xxh_u32 u32; } __attribute__((packed)) unalign;\n#endif\nstatic xxh_u32 XXH_read32(const void* ptr)\n{\n    typedef __attribute__((aligned(1))) xxh_u32 xxh_unalign32;\n    return *((const xxh_unalign32*)ptr);\n}\n\n#else\n\n/*\n * Portable and safe solution. Generally efficient.\n * see: https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html\n */\nstatic xxh_u32 XXH_read32(const void* memPtr)\n{\n    xxh_u32 val;\n    XXH_memcpy(&val, memPtr, sizeof(val));\n    return val;\n}\n\n#endif   /* XXH_FORCE_DIRECT_MEMORY_ACCESS */\n\n\n/* ***   Endianness   *** */\n\n/*!\n * @ingroup tuning\n * @def XXH_CPU_LITTLE_ENDIAN\n * @brief Whether the target is little endian.\n *\n * Defined to 1 if the target is little endian, or 0 if it is big endian.\n * It can be defined externally, for example on the compiler command line.\n *\n * If it is not defined,\n * a runtime check (which is usually constant folded) is used instead.\n *\n * @note\n *   This is not necessarily defined to an integer constant.\n *\n * @see XXH_isLittleEndian() for the runtime check.\n */\n#ifndef XXH_CPU_LITTLE_ENDIAN\n/*\n * Try to detect endianness automatically, to avoid the nonstandard behavior\n * in `XXH_isLittleEndian()`\n */\n#  if defined(_WIN32) /* Windows is always little endian */ \\\n     || defined(__LITTLE_ENDIAN__) \\\n     || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)\n#    define XXH_CPU_LITTLE_ENDIAN 1\n#  elif defined(__BIG_ENDIAN__) \\\n     || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)\n#    define XXH_CPU_LITTLE_ENDIAN 0\n#  else\n/*!\n * @internal\n * @brief Runtime check for @ref XXH_CPU_LITTLE_ENDIAN.\n *\n * Most compilers will constant fold this.\n */\nstatic int XXH_isLittleEndian(void)\n{\n    /*\n     * Portable and well-defined behavior.\n     * Don't use static: it is detrimental to performance.\n     */\n    const union { xxh_u32 u; xxh_u8 c[4]; } one = { 1 };\n    return one.c[0];\n}\n#   define XXH_CPU_LITTLE_ENDIAN   XXH_isLittleEndian()\n#  endif\n#endif\n\n\n\n\n/* ****************************************\n*  Compiler-specific Functions and Macros\n******************************************/\n#define XXH_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)\n\n#ifdef __has_builtin\n#  define XXH_HAS_BUILTIN(x) __has_builtin(x)\n#else\n#  define XXH_HAS_BUILTIN(x) 0\n#endif\n\n\n\n/*\n * C23 and future versions have standard \"unreachable()\".\n * Once it has been implemented reliably we can add it as an\n * additional case:\n *\n * ```\n * #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= XXH_C23_VN)\n * #  include <stddef.h>\n * #  ifdef unreachable\n * #    define XXH_UNREACHABLE() unreachable()\n * #  endif\n * #endif\n * ```\n *\n * Note C++23 also has std::unreachable() which can be detected\n * as follows:\n * ```\n * #if defined(__cpp_lib_unreachable) && (__cpp_lib_unreachable >= 202202L)\n * #  include <utility>\n * #  define XXH_UNREACHABLE() std::unreachable()\n * #endif\n * ```\n * NB: `__cpp_lib_unreachable` is defined in the `<version>` header.\n * We don't use that as including `<utility>` in `extern \"C\"` blocks\n * doesn't work on GCC12\n */\n\n#if XXH_HAS_BUILTIN(__builtin_unreachable)\n#  define XXH_UNREACHABLE() __builtin_unreachable()\n\n#elif defined(_MSC_VER)\n#  define XXH_UNREACHABLE() __assume(0)\n\n#else\n#  define XXH_UNREACHABLE()\n#endif\n\n#if XXH_HAS_BUILTIN(__builtin_assume)\n#  define XXH_ASSUME(c) __builtin_assume(c)\n#else\n#  define XXH_ASSUME(c) if (!(c)) { XXH_UNREACHABLE(); }\n#endif\n\n/*!\n * @internal\n * @def XXH_rotl32(x,r)\n * @brief 32-bit rotate left.\n *\n * @param x The 32-bit integer to be rotated.\n * @param r The number of bits to rotate.\n * @pre\n *   @p r > 0 && @p r < 32\n * @note\n *   @p x and @p r may be evaluated multiple times.\n * @return The rotated result.\n */\n#if !defined(NO_CLANG_BUILTIN) && XXH_HAS_BUILTIN(__builtin_rotateleft32) \\\n                               && XXH_HAS_BUILTIN(__builtin_rotateleft64)\n#  define XXH_rotl32 __builtin_rotateleft32\n#  define XXH_rotl64 __builtin_rotateleft64\n/* Note: although _rotl exists for minGW (GCC under windows), performance seems poor */\n#elif defined(_MSC_VER)\n#  define XXH_rotl32(x,r) _rotl(x,r)\n#  define XXH_rotl64(x,r) _rotl64(x,r)\n#else\n#  define XXH_rotl32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))\n#  define XXH_rotl64(x,r) (((x) << (r)) | ((x) >> (64 - (r))))\n#endif\n\n/*!\n * @internal\n * @fn xxh_u32 XXH_swap32(xxh_u32 x)\n * @brief A 32-bit byteswap.\n *\n * @param x The 32-bit integer to byteswap.\n * @return @p x, byteswapped.\n */\n#if defined(_MSC_VER)     /* Visual Studio */\n#  define XXH_swap32 _byteswap_ulong\n#elif XXH_GCC_VERSION >= 403\n#  define XXH_swap32 __builtin_bswap32\n#else\nstatic xxh_u32 XXH_swap32 (xxh_u32 x)\n{\n    return  ((x << 24) & 0xff000000 ) |\n            ((x <<  8) & 0x00ff0000 ) |\n            ((x >>  8) & 0x0000ff00 ) |\n            ((x >> 24) & 0x000000ff );\n}\n#endif\n\n\n/* ***************************\n*  Memory reads\n*****************************/\n\n/*!\n * @internal\n * @brief Enum to indicate whether a pointer is aligned.\n */\ntypedef enum {\n    XXH_aligned,  /*!< Aligned */\n    XXH_unaligned /*!< Possibly unaligned */\n} XXH_alignment;\n\n/*\n * XXH_FORCE_MEMORY_ACCESS==3 is an endian-independent byteshift load.\n *\n * This is ideal for older compilers which don't inline memcpy.\n */\n#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3))\n\nXXH_FORCE_INLINE xxh_u32 XXH_readLE32(const void* memPtr)\n{\n    const xxh_u8* bytePtr = (const xxh_u8 *)memPtr;\n    return bytePtr[0]\n         | ((xxh_u32)bytePtr[1] << 8)\n         | ((xxh_u32)bytePtr[2] << 16)\n         | ((xxh_u32)bytePtr[3] << 24);\n}\n\nXXH_FORCE_INLINE xxh_u32 XXH_readBE32(const void* memPtr)\n{\n    const xxh_u8* bytePtr = (const xxh_u8 *)memPtr;\n    return bytePtr[3]\n         | ((xxh_u32)bytePtr[2] << 8)\n         | ((xxh_u32)bytePtr[1] << 16)\n         | ((xxh_u32)bytePtr[0] << 24);\n}\n\n#else\nXXH_FORCE_INLINE xxh_u32 XXH_readLE32(const void* ptr)\n{\n    return XXH_CPU_LITTLE_ENDIAN ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr));\n}\n\nstatic xxh_u32 XXH_readBE32(const void* ptr)\n{\n    return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr);\n}\n#endif\n\nXXH_FORCE_INLINE xxh_u32\nXXH_readLE32_align(const void* ptr, XXH_alignment align)\n{\n    if (align==XXH_unaligned) {\n        return XXH_readLE32(ptr);\n    } else {\n        return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u32*)ptr : XXH_swap32(*(const xxh_u32*)ptr);\n    }\n}\n\n\n/* *************************************\n*  Misc\n***************************************/\n/*! @ingroup public */\nXXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; }\n\n\n/* *******************************************************************\n*  32-bit hash functions\n*********************************************************************/\n/*!\n * @}\n * @defgroup XXH32_impl XXH32 implementation\n * @ingroup impl\n *\n * Details on the XXH32 implementation.\n * @{\n */\n /* #define instead of static const, to be used as initializers */\n#define XXH_PRIME32_1  0x9E3779B1U  /*!< 0b10011110001101110111100110110001 */\n#define XXH_PRIME32_2  0x85EBCA77U  /*!< 0b10000101111010111100101001110111 */\n#define XXH_PRIME32_3  0xC2B2AE3DU  /*!< 0b11000010101100101010111000111101 */\n#define XXH_PRIME32_4  0x27D4EB2FU  /*!< 0b00100111110101001110101100101111 */\n#define XXH_PRIME32_5  0x165667B1U  /*!< 0b00010110010101100110011110110001 */\n\n#ifdef XXH_OLD_NAMES\n#  define PRIME32_1 XXH_PRIME32_1\n#  define PRIME32_2 XXH_PRIME32_2\n#  define PRIME32_3 XXH_PRIME32_3\n#  define PRIME32_4 XXH_PRIME32_4\n#  define PRIME32_5 XXH_PRIME32_5\n#endif\n\n/*!\n * @internal\n * @brief Normal stripe processing routine.\n *\n * This shuffles the bits so that any bit from @p input impacts several bits in\n * @p acc.\n *\n * @param acc The accumulator lane.\n * @param input The stripe of input to mix.\n * @return The mixed accumulator lane.\n */\nstatic xxh_u32 XXH32_round(xxh_u32 acc, xxh_u32 input)\n{\n    acc += input * XXH_PRIME32_2;\n    acc  = XXH_rotl32(acc, 13);\n    acc *= XXH_PRIME32_1;\n#if (defined(__SSE4_1__) || defined(__aarch64__) || defined(__wasm_simd128__)) && !defined(XXH_ENABLE_AUTOVECTORIZE)\n    /*\n     * UGLY HACK:\n     * A compiler fence is the only thing that prevents GCC and Clang from\n     * autovectorizing the XXH32 loop (pragmas and attributes don't work for some\n     * reason) without globally disabling SSE4.1.\n     *\n     * The reason we want to avoid vectorization is because despite working on\n     * 4 integers at a time, there are multiple factors slowing XXH32 down on\n     * SSE4:\n     * - There's a ridiculous amount of lag from pmulld (10 cycles of latency on\n     *   newer chips!) making it slightly slower to multiply four integers at\n     *   once compared to four integers independently. Even when pmulld was\n     *   fastest, Sandy/Ivy Bridge, it is still not worth it to go into SSE\n     *   just to multiply unless doing a long operation.\n     *\n     * - Four instructions are required to rotate,\n     *      movqda tmp,  v // not required with VEX encoding\n     *      pslld  tmp, 13 // tmp <<= 13\n     *      psrld  v,   19 // x >>= 19\n     *      por    v,  tmp // x |= tmp\n     *   compared to one for scalar:\n     *      roll   v, 13    // reliably fast across the board\n     *      shldl  v, v, 13 // Sandy Bridge and later prefer this for some reason\n     *\n     * - Instruction level parallelism is actually more beneficial here because\n     *   the SIMD actually serializes this operation: While v1 is rotating, v2\n     *   can load data, while v3 can multiply. SSE forces them to operate\n     *   together.\n     *\n     * This is also enabled on AArch64, as Clang is *very aggressive* in vectorizing\n     * the loop. NEON is only faster on the A53, and with the newer cores, it is less\n     * than half the speed.\n     *\n     * Additionally, this is used on WASM SIMD128 because it JITs to the same\n     * SIMD instructions and has the same issue.\n     */\n    XXH_COMPILER_GUARD(acc);\n#endif\n    return acc;\n}\n\n/*!\n * @internal\n * @brief Mixes all bits to finalize the hash.\n *\n * The final mix ensures that all input bits have a chance to impact any bit in\n * the output digest, resulting in an unbiased distribution.\n *\n * @param hash The hash to avalanche.\n * @return The avalanched hash.\n */\nstatic xxh_u32 XXH32_avalanche(xxh_u32 hash)\n{\n    hash ^= hash >> 15;\n    hash *= XXH_PRIME32_2;\n    hash ^= hash >> 13;\n    hash *= XXH_PRIME32_3;\n    hash ^= hash >> 16;\n    return hash;\n}\n\n#define XXH_get32bits(p) XXH_readLE32_align(p, align)\n\n/*!\n * @internal\n * @brief Processes the last 0-15 bytes of @p ptr.\n *\n * There may be up to 15 bytes remaining to consume from the input.\n * This final stage will digest them to ensure that all input bytes are present\n * in the final mix.\n *\n * @param hash The hash to finalize.\n * @param ptr The pointer to the remaining input.\n * @param len The remaining length, modulo 16.\n * @param align Whether @p ptr is aligned.\n * @return The finalized hash.\n * @see XXH64_finalize().\n */\nstatic XXH_PUREF xxh_u32\nXXH32_finalize(xxh_u32 hash, const xxh_u8* ptr, size_t len, XXH_alignment align)\n{\n#define XXH_PROCESS1 do {                             \\\n    hash += (*ptr++) * XXH_PRIME32_5;                 \\\n    hash = XXH_rotl32(hash, 11) * XXH_PRIME32_1;      \\\n} while (0)\n\n#define XXH_PROCESS4 do {                             \\\n    hash += XXH_get32bits(ptr) * XXH_PRIME32_3;       \\\n    ptr += 4;                                         \\\n    hash  = XXH_rotl32(hash, 17) * XXH_PRIME32_4;     \\\n} while (0)\n\n    if (ptr==NULL) XXH_ASSERT(len == 0);\n\n    /* Compact rerolled version; generally faster */\n    if (!XXH32_ENDJMP) {\n        len &= 15;\n        while (len >= 4) {\n            XXH_PROCESS4;\n            len -= 4;\n        }\n        while (len > 0) {\n            XXH_PROCESS1;\n            --len;\n        }\n        return XXH32_avalanche(hash);\n    } else {\n         switch(len&15) /* or switch(bEnd - p) */ {\n           case 12:      XXH_PROCESS4;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 8:       XXH_PROCESS4;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 4:       XXH_PROCESS4;\n                         return XXH32_avalanche(hash);\n\n           case 13:      XXH_PROCESS4;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 9:       XXH_PROCESS4;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 5:       XXH_PROCESS4;\n                         XXH_PROCESS1;\n                         return XXH32_avalanche(hash);\n\n           case 14:      XXH_PROCESS4;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 10:      XXH_PROCESS4;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 6:       XXH_PROCESS4;\n                         XXH_PROCESS1;\n                         XXH_PROCESS1;\n                         return XXH32_avalanche(hash);\n\n           case 15:      XXH_PROCESS4;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 11:      XXH_PROCESS4;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 7:       XXH_PROCESS4;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 3:       XXH_PROCESS1;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 2:       XXH_PROCESS1;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 1:       XXH_PROCESS1;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 0:       return XXH32_avalanche(hash);\n        }\n        XXH_ASSERT(0);\n        return hash;   /* reaching this point is deemed impossible */\n    }\n}\n\n#ifdef XXH_OLD_NAMES\n#  define PROCESS1 XXH_PROCESS1\n#  define PROCESS4 XXH_PROCESS4\n#else\n#  undef XXH_PROCESS1\n#  undef XXH_PROCESS4\n#endif\n\n/*!\n * @internal\n * @brief The implementation for @ref XXH32().\n *\n * @param input , len , seed Directly passed from @ref XXH32().\n * @param align Whether @p input is aligned.\n * @return The calculated hash.\n */\nXXH_FORCE_INLINE XXH_PUREF xxh_u32\nXXH32_endian_align(const xxh_u8* input, size_t len, xxh_u32 seed, XXH_alignment align)\n{\n    xxh_u32 h32;\n\n    if (input==NULL) XXH_ASSERT(len == 0);\n\n    if (len>=16) {\n        const xxh_u8* const bEnd = input + len;\n        const xxh_u8* const limit = bEnd - 15;\n        xxh_u32 v1 = seed + XXH_PRIME32_1 + XXH_PRIME32_2;\n        xxh_u32 v2 = seed + XXH_PRIME32_2;\n        xxh_u32 v3 = seed + 0;\n        xxh_u32 v4 = seed - XXH_PRIME32_1;\n\n        do {\n            v1 = XXH32_round(v1, XXH_get32bits(input)); input += 4;\n            v2 = XXH32_round(v2, XXH_get32bits(input)); input += 4;\n            v3 = XXH32_round(v3, XXH_get32bits(input)); input += 4;\n            v4 = XXH32_round(v4, XXH_get32bits(input)); input += 4;\n        } while (input < limit);\n\n        h32 = XXH_rotl32(v1, 1)  + XXH_rotl32(v2, 7)\n            + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);\n    } else {\n        h32  = seed + XXH_PRIME32_5;\n    }\n\n    h32 += (xxh_u32)len;\n\n    return XXH32_finalize(h32, input, len&15, align);\n}\n\n/*! @ingroup XXH32_family */\nXXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t len, XXH32_hash_t seed)\n{\n#if !defined(XXH_NO_STREAM) && XXH_SIZE_OPT >= 2\n    /* Simple version, good for code maintenance, but unfortunately slow for small inputs */\n    XXH32_state_t state;\n    XXH32_reset(&state, seed);\n    XXH32_update(&state, (const xxh_u8*)input, len);\n    return XXH32_digest(&state);\n#else\n    if (XXH_FORCE_ALIGN_CHECK) {\n        if ((((size_t)input) & 3) == 0) {   /* Input is 4-bytes aligned, leverage the speed benefit */\n            return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_aligned);\n    }   }\n\n    return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned);\n#endif\n}\n\n\n\n/*******   Hash streaming   *******/\n#ifndef XXH_NO_STREAM\n/*! @ingroup XXH32_family */\nXXH_PUBLIC_API XXH32_state_t* XXH32_createState(void)\n{\n    return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t));\n}\n/*! @ingroup XXH32_family */\nXXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr)\n{\n    XXH_free(statePtr);\n    return XXH_OK;\n}\n\n/*! @ingroup XXH32_family */\nXXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dstState, const XXH32_state_t* srcState)\n{\n    XXH_memcpy(dstState, srcState, sizeof(*dstState));\n}\n\n/*! @ingroup XXH32_family */\nXXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, XXH32_hash_t seed)\n{\n    XXH_ASSERT(statePtr != NULL);\n    memset(statePtr, 0, sizeof(*statePtr));\n    statePtr->v[0] = seed + XXH_PRIME32_1 + XXH_PRIME32_2;\n    statePtr->v[1] = seed + XXH_PRIME32_2;\n    statePtr->v[2] = seed + 0;\n    statePtr->v[3] = seed - XXH_PRIME32_1;\n    return XXH_OK;\n}\n\n\n/*! @ingroup XXH32_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH32_update(XXH32_state_t* state, const void* input, size_t len)\n{\n    if (input==NULL) {\n        XXH_ASSERT(len == 0);\n        return XXH_OK;\n    }\n\n    {   const xxh_u8* p = (const xxh_u8*)input;\n        const xxh_u8* const bEnd = p + len;\n\n        state->total_len_32 += (XXH32_hash_t)len;\n        state->large_len |= (XXH32_hash_t)((len>=16) | (state->total_len_32>=16));\n\n        if (state->memsize + len < 16)  {   /* fill in tmp buffer */\n            XXH_memcpy((xxh_u8*)(state->mem32) + state->memsize, input, len);\n            state->memsize += (XXH32_hash_t)len;\n            return XXH_OK;\n        }\n\n        if (state->memsize) {   /* some data left from previous update */\n            XXH_memcpy((xxh_u8*)(state->mem32) + state->memsize, input, 16-state->memsize);\n            {   const xxh_u32* p32 = state->mem32;\n                state->v[0] = XXH32_round(state->v[0], XXH_readLE32(p32)); p32++;\n                state->v[1] = XXH32_round(state->v[1], XXH_readLE32(p32)); p32++;\n                state->v[2] = XXH32_round(state->v[2], XXH_readLE32(p32)); p32++;\n                state->v[3] = XXH32_round(state->v[3], XXH_readLE32(p32));\n            }\n            p += 16-state->memsize;\n            state->memsize = 0;\n        }\n\n        if (p <= bEnd-16) {\n            const xxh_u8* const limit = bEnd - 16;\n\n            do {\n                state->v[0] = XXH32_round(state->v[0], XXH_readLE32(p)); p+=4;\n                state->v[1] = XXH32_round(state->v[1], XXH_readLE32(p)); p+=4;\n                state->v[2] = XXH32_round(state->v[2], XXH_readLE32(p)); p+=4;\n                state->v[3] = XXH32_round(state->v[3], XXH_readLE32(p)); p+=4;\n            } while (p<=limit);\n\n        }\n\n        if (p < bEnd) {\n            XXH_memcpy(state->mem32, p, (size_t)(bEnd-p));\n            state->memsize = (unsigned)(bEnd-p);\n        }\n    }\n\n    return XXH_OK;\n}\n\n\n/*! @ingroup XXH32_family */\nXXH_PUBLIC_API XXH32_hash_t XXH32_digest(const XXH32_state_t* state)\n{\n    xxh_u32 h32;\n\n    if (state->large_len) {\n        h32 = XXH_rotl32(state->v[0], 1)\n            + XXH_rotl32(state->v[1], 7)\n            + XXH_rotl32(state->v[2], 12)\n            + XXH_rotl32(state->v[3], 18);\n    } else {\n        h32 = state->v[2] /* == seed */ + XXH_PRIME32_5;\n    }\n\n    h32 += state->total_len_32;\n\n    return XXH32_finalize(h32, (const xxh_u8*)state->mem32, state->memsize, XXH_aligned);\n}\n#endif /* !XXH_NO_STREAM */\n\n/*******   Canonical representation   *******/\n\n/*! @ingroup XXH32_family */\nXXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash)\n{\n    XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t));\n    if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash);\n    XXH_memcpy(dst, &hash, sizeof(*dst));\n}\n/*! @ingroup XXH32_family */\nXXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src)\n{\n    return XXH_readBE32(src);\n}\n\n\n#ifndef XXH_NO_LONG_LONG\n\n/* *******************************************************************\n*  64-bit hash functions\n*********************************************************************/\n/*!\n * @}\n * @ingroup impl\n * @{\n */\n/*******   Memory access   *******/\n\ntypedef XXH64_hash_t xxh_u64;\n\n#ifdef XXH_OLD_NAMES\n#  define U64 xxh_u64\n#endif\n\n#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3))\n/*\n * Manual byteshift. Best for old compilers which don't inline memcpy.\n * We actually directly use XXH_readLE64 and XXH_readBE64.\n */\n#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))\n\n/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */\nstatic xxh_u64 XXH_read64(const void* memPtr)\n{\n    return *(const xxh_u64*) memPtr;\n}\n\n#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))\n\n/*\n * __attribute__((aligned(1))) is supported by gcc and clang. Originally the\n * documentation claimed that it only increased the alignment, but actually it\n * can decrease it on gcc, clang, and icc:\n * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69502,\n * https://gcc.godbolt.org/z/xYez1j67Y.\n */\n#ifdef XXH_OLD_NAMES\ntypedef union { xxh_u32 u32; xxh_u64 u64; } __attribute__((packed)) unalign64;\n#endif\nstatic xxh_u64 XXH_read64(const void* ptr)\n{\n    typedef __attribute__((aligned(1))) xxh_u64 xxh_unalign64;\n    return *((const xxh_unalign64*)ptr);\n}\n\n#else\n\n/*\n * Portable and safe solution. Generally efficient.\n * see: https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html\n */\nstatic xxh_u64 XXH_read64(const void* memPtr)\n{\n    xxh_u64 val;\n    XXH_memcpy(&val, memPtr, sizeof(val));\n    return val;\n}\n\n#endif   /* XXH_FORCE_DIRECT_MEMORY_ACCESS */\n\n#if defined(_MSC_VER)     /* Visual Studio */\n#  define XXH_swap64 _byteswap_uint64\n#elif XXH_GCC_VERSION >= 403\n#  define XXH_swap64 __builtin_bswap64\n#else\nstatic xxh_u64 XXH_swap64(xxh_u64 x)\n{\n    return  ((x << 56) & 0xff00000000000000ULL) |\n            ((x << 40) & 0x00ff000000000000ULL) |\n            ((x << 24) & 0x0000ff0000000000ULL) |\n            ((x << 8)  & 0x000000ff00000000ULL) |\n            ((x >> 8)  & 0x00000000ff000000ULL) |\n            ((x >> 24) & 0x0000000000ff0000ULL) |\n            ((x >> 40) & 0x000000000000ff00ULL) |\n            ((x >> 56) & 0x00000000000000ffULL);\n}\n#endif\n\n\n/* XXH_FORCE_MEMORY_ACCESS==3 is an endian-independent byteshift load. */\n#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3))\n\nXXH_FORCE_INLINE xxh_u64 XXH_readLE64(const void* memPtr)\n{\n    const xxh_u8* bytePtr = (const xxh_u8 *)memPtr;\n    return bytePtr[0]\n         | ((xxh_u64)bytePtr[1] << 8)\n         | ((xxh_u64)bytePtr[2] << 16)\n         | ((xxh_u64)bytePtr[3] << 24)\n         | ((xxh_u64)bytePtr[4] << 32)\n         | ((xxh_u64)bytePtr[5] << 40)\n         | ((xxh_u64)bytePtr[6] << 48)\n         | ((xxh_u64)bytePtr[7] << 56);\n}\n\nXXH_FORCE_INLINE xxh_u64 XXH_readBE64(const void* memPtr)\n{\n    const xxh_u8* bytePtr = (const xxh_u8 *)memPtr;\n    return bytePtr[7]\n         | ((xxh_u64)bytePtr[6] << 8)\n         | ((xxh_u64)bytePtr[5] << 16)\n         | ((xxh_u64)bytePtr[4] << 24)\n         | ((xxh_u64)bytePtr[3] << 32)\n         | ((xxh_u64)bytePtr[2] << 40)\n         | ((xxh_u64)bytePtr[1] << 48)\n         | ((xxh_u64)bytePtr[0] << 56);\n}\n\n#else\nXXH_FORCE_INLINE xxh_u64 XXH_readLE64(const void* ptr)\n{\n    return XXH_CPU_LITTLE_ENDIAN ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr));\n}\n\nstatic xxh_u64 XXH_readBE64(const void* ptr)\n{\n    return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr);\n}\n#endif\n\nXXH_FORCE_INLINE xxh_u64\nXXH_readLE64_align(const void* ptr, XXH_alignment align)\n{\n    if (align==XXH_unaligned)\n        return XXH_readLE64(ptr);\n    else\n        return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u64*)ptr : XXH_swap64(*(const xxh_u64*)ptr);\n}\n\n\n/*******   xxh64   *******/\n/*!\n * @}\n * @defgroup XXH64_impl XXH64 implementation\n * @ingroup impl\n *\n * Details on the XXH64 implementation.\n * @{\n */\n/* #define rather that static const, to be used as initializers */\n#define XXH_PRIME64_1  0x9E3779B185EBCA87ULL  /*!< 0b1001111000110111011110011011000110000101111010111100101010000111 */\n#define XXH_PRIME64_2  0xC2B2AE3D27D4EB4FULL  /*!< 0b1100001010110010101011100011110100100111110101001110101101001111 */\n#define XXH_PRIME64_3  0x165667B19E3779F9ULL  /*!< 0b0001011001010110011001111011000110011110001101110111100111111001 */\n#define XXH_PRIME64_4  0x85EBCA77C2B2AE63ULL  /*!< 0b1000010111101011110010100111011111000010101100101010111001100011 */\n#define XXH_PRIME64_5  0x27D4EB2F165667C5ULL  /*!< 0b0010011111010100111010110010111100010110010101100110011111000101 */\n\n#ifdef XXH_OLD_NAMES\n#  define PRIME64_1 XXH_PRIME64_1\n#  define PRIME64_2 XXH_PRIME64_2\n#  define PRIME64_3 XXH_PRIME64_3\n#  define PRIME64_4 XXH_PRIME64_4\n#  define PRIME64_5 XXH_PRIME64_5\n#endif\n\n/*! @copydoc XXH32_round */\nstatic xxh_u64 XXH64_round(xxh_u64 acc, xxh_u64 input)\n{\n    acc += input * XXH_PRIME64_2;\n    acc  = XXH_rotl64(acc, 31);\n    acc *= XXH_PRIME64_1;\n#if (defined(__AVX512F__)) && !defined(XXH_ENABLE_AUTOVECTORIZE)\n    /*\n     * DISABLE AUTOVECTORIZATION:\n     * A compiler fence is used to prevent GCC and Clang from\n     * autovectorizing the XXH64 loop (pragmas and attributes don't work for some\n     * reason) without globally disabling AVX512.\n     *\n     * Autovectorization of XXH64 tends to be detrimental,\n     * though the exact outcome may change depending on exact cpu and compiler version.\n     * For information, it has been reported as detrimental for Skylake-X,\n     * but possibly beneficial for Zen4.\n     *\n     * The default is to disable auto-vectorization,\n     * but you can select to enable it instead using `XXH_ENABLE_AUTOVECTORIZE` build variable.\n     */\n    XXH_COMPILER_GUARD(acc);\n#endif\n    return acc;\n}\n\nstatic xxh_u64 XXH64_mergeRound(xxh_u64 acc, xxh_u64 val)\n{\n    val  = XXH64_round(0, val);\n    acc ^= val;\n    acc  = acc * XXH_PRIME64_1 + XXH_PRIME64_4;\n    return acc;\n}\n\n/*! @copydoc XXH32_avalanche */\nstatic xxh_u64 XXH64_avalanche(xxh_u64 hash)\n{\n    hash ^= hash >> 33;\n    hash *= XXH_PRIME64_2;\n    hash ^= hash >> 29;\n    hash *= XXH_PRIME64_3;\n    hash ^= hash >> 32;\n    return hash;\n}\n\n\n#define XXH_get64bits(p) XXH_readLE64_align(p, align)\n\n/*!\n * @internal\n * @brief Processes the last 0-31 bytes of @p ptr.\n *\n * There may be up to 31 bytes remaining to consume from the input.\n * This final stage will digest them to ensure that all input bytes are present\n * in the final mix.\n *\n * @param hash The hash to finalize.\n * @param ptr The pointer to the remaining input.\n * @param len The remaining length, modulo 32.\n * @param align Whether @p ptr is aligned.\n * @return The finalized hash\n * @see XXH32_finalize().\n */\nstatic XXH_PUREF xxh_u64\nXXH64_finalize(xxh_u64 hash, const xxh_u8* ptr, size_t len, XXH_alignment align)\n{\n    if (ptr==NULL) XXH_ASSERT(len == 0);\n    len &= 31;\n    while (len >= 8) {\n        xxh_u64 const k1 = XXH64_round(0, XXH_get64bits(ptr));\n        ptr += 8;\n        hash ^= k1;\n        hash  = XXH_rotl64(hash,27) * XXH_PRIME64_1 + XXH_PRIME64_4;\n        len -= 8;\n    }\n    if (len >= 4) {\n        hash ^= (xxh_u64)(XXH_get32bits(ptr)) * XXH_PRIME64_1;\n        ptr += 4;\n        hash = XXH_rotl64(hash, 23) * XXH_PRIME64_2 + XXH_PRIME64_3;\n        len -= 4;\n    }\n    while (len > 0) {\n        hash ^= (*ptr++) * XXH_PRIME64_5;\n        hash = XXH_rotl64(hash, 11) * XXH_PRIME64_1;\n        --len;\n    }\n    return  XXH64_avalanche(hash);\n}\n\n#ifdef XXH_OLD_NAMES\n#  define PROCESS1_64 XXH_PROCESS1_64\n#  define PROCESS4_64 XXH_PROCESS4_64\n#  define PROCESS8_64 XXH_PROCESS8_64\n#else\n#  undef XXH_PROCESS1_64\n#  undef XXH_PROCESS4_64\n#  undef XXH_PROCESS8_64\n#endif\n\n/*!\n * @internal\n * @brief The implementation for @ref XXH64().\n *\n * @param input , len , seed Directly passed from @ref XXH64().\n * @param align Whether @p input is aligned.\n * @return The calculated hash.\n */\nXXH_FORCE_INLINE XXH_PUREF xxh_u64\nXXH64_endian_align(const xxh_u8* input, size_t len, xxh_u64 seed, XXH_alignment align)\n{\n    xxh_u64 h64;\n    if (input==NULL) XXH_ASSERT(len == 0);\n\n    if (len>=32) {\n        const xxh_u8* const bEnd = input + len;\n        const xxh_u8* const limit = bEnd - 31;\n        xxh_u64 v1 = seed + XXH_PRIME64_1 + XXH_PRIME64_2;\n        xxh_u64 v2 = seed + XXH_PRIME64_2;\n        xxh_u64 v3 = seed + 0;\n        xxh_u64 v4 = seed - XXH_PRIME64_1;\n\n        do {\n            v1 = XXH64_round(v1, XXH_get64bits(input)); input+=8;\n            v2 = XXH64_round(v2, XXH_get64bits(input)); input+=8;\n            v3 = XXH64_round(v3, XXH_get64bits(input)); input+=8;\n            v4 = XXH64_round(v4, XXH_get64bits(input)); input+=8;\n        } while (input<limit);\n\n        h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);\n        h64 = XXH64_mergeRound(h64, v1);\n        h64 = XXH64_mergeRound(h64, v2);\n        h64 = XXH64_mergeRound(h64, v3);\n        h64 = XXH64_mergeRound(h64, v4);\n\n    } else {\n        h64  = seed + XXH_PRIME64_5;\n    }\n\n    h64 += (xxh_u64) len;\n\n    return XXH64_finalize(h64, input, len, align);\n}\n\n\n/*! @ingroup XXH64_family */\nXXH_PUBLIC_API XXH64_hash_t XXH64 (XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed)\n{\n#if !defined(XXH_NO_STREAM) && XXH_SIZE_OPT >= 2\n    /* Simple version, good for code maintenance, but unfortunately slow for small inputs */\n    XXH64_state_t state;\n    XXH64_reset(&state, seed);\n    XXH64_update(&state, (const xxh_u8*)input, len);\n    return XXH64_digest(&state);\n#else\n    if (XXH_FORCE_ALIGN_CHECK) {\n        if ((((size_t)input) & 7)==0) {  /* Input is aligned, let's leverage the speed advantage */\n            return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_aligned);\n    }   }\n\n    return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned);\n\n#endif\n}\n\n/*******   Hash Streaming   *******/\n#ifndef XXH_NO_STREAM\n/*! @ingroup XXH64_family*/\nXXH_PUBLIC_API XXH64_state_t* XXH64_createState(void)\n{\n    return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t));\n}\n/*! @ingroup XXH64_family */\nXXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr)\n{\n    XXH_free(statePtr);\n    return XXH_OK;\n}\n\n/*! @ingroup XXH64_family */\nXXH_PUBLIC_API void XXH64_copyState(XXH_NOESCAPE XXH64_state_t* dstState, const XXH64_state_t* srcState)\n{\n    XXH_memcpy(dstState, srcState, sizeof(*dstState));\n}\n\n/*! @ingroup XXH64_family */\nXXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH_NOESCAPE XXH64_state_t* statePtr, XXH64_hash_t seed)\n{\n    XXH_ASSERT(statePtr != NULL);\n    memset(statePtr, 0, sizeof(*statePtr));\n    statePtr->v[0] = seed + XXH_PRIME64_1 + XXH_PRIME64_2;\n    statePtr->v[1] = seed + XXH_PRIME64_2;\n    statePtr->v[2] = seed + 0;\n    statePtr->v[3] = seed - XXH_PRIME64_1;\n    return XXH_OK;\n}\n\n/*! @ingroup XXH64_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH64_update (XXH_NOESCAPE XXH64_state_t* state, XXH_NOESCAPE const void* input, size_t len)\n{\n    if (input==NULL) {\n        XXH_ASSERT(len == 0);\n        return XXH_OK;\n    }\n\n    {   const xxh_u8* p = (const xxh_u8*)input;\n        const xxh_u8* const bEnd = p + len;\n\n        state->total_len += len;\n\n        if (state->memsize + len < 32) {  /* fill in tmp buffer */\n            XXH_memcpy(((xxh_u8*)state->mem64) + state->memsize, input, len);\n            state->memsize += (xxh_u32)len;\n            return XXH_OK;\n        }\n\n        if (state->memsize) {   /* tmp buffer is full */\n            XXH_memcpy(((xxh_u8*)state->mem64) + state->memsize, input, 32-state->memsize);\n            state->v[0] = XXH64_round(state->v[0], XXH_readLE64(state->mem64+0));\n            state->v[1] = XXH64_round(state->v[1], XXH_readLE64(state->mem64+1));\n            state->v[2] = XXH64_round(state->v[2], XXH_readLE64(state->mem64+2));\n            state->v[3] = XXH64_round(state->v[3], XXH_readLE64(state->mem64+3));\n            p += 32 - state->memsize;\n            state->memsize = 0;\n        }\n\n        if (p+32 <= bEnd) {\n            const xxh_u8* const limit = bEnd - 32;\n\n            do {\n                state->v[0] = XXH64_round(state->v[0], XXH_readLE64(p)); p+=8;\n                state->v[1] = XXH64_round(state->v[1], XXH_readLE64(p)); p+=8;\n                state->v[2] = XXH64_round(state->v[2], XXH_readLE64(p)); p+=8;\n                state->v[3] = XXH64_round(state->v[3], XXH_readLE64(p)); p+=8;\n            } while (p<=limit);\n\n        }\n\n        if (p < bEnd) {\n            XXH_memcpy(state->mem64, p, (size_t)(bEnd-p));\n            state->memsize = (unsigned)(bEnd-p);\n        }\n    }\n\n    return XXH_OK;\n}\n\n\n/*! @ingroup XXH64_family */\nXXH_PUBLIC_API XXH64_hash_t XXH64_digest(XXH_NOESCAPE const XXH64_state_t* state)\n{\n    xxh_u64 h64;\n\n    if (state->total_len >= 32) {\n        h64 = XXH_rotl64(state->v[0], 1) + XXH_rotl64(state->v[1], 7) + XXH_rotl64(state->v[2], 12) + XXH_rotl64(state->v[3], 18);\n        h64 = XXH64_mergeRound(h64, state->v[0]);\n        h64 = XXH64_mergeRound(h64, state->v[1]);\n        h64 = XXH64_mergeRound(h64, state->v[2]);\n        h64 = XXH64_mergeRound(h64, state->v[3]);\n    } else {\n        h64  = state->v[2] /*seed*/ + XXH_PRIME64_5;\n    }\n\n    h64 += (xxh_u64) state->total_len;\n\n    return XXH64_finalize(h64, (const xxh_u8*)state->mem64, (size_t)state->total_len, XXH_aligned);\n}\n#endif /* !XXH_NO_STREAM */\n\n/******* Canonical representation   *******/\n\n/*! @ingroup XXH64_family */\nXXH_PUBLIC_API void XXH64_canonicalFromHash(XXH_NOESCAPE XXH64_canonical_t* dst, XXH64_hash_t hash)\n{\n    XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t));\n    if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash);\n    XXH_memcpy(dst, &hash, sizeof(*dst));\n}\n\n/*! @ingroup XXH64_family */\nXXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_canonical_t* src)\n{\n    return XXH_readBE64(src);\n}\n\n#if defined (__cplusplus)\n}\n#endif\n\n#ifndef XXH_NO_XXH3\n\n/* *********************************************************************\n*  XXH3\n*  New generation hash designed for speed on small keys and vectorization\n************************************************************************ */\n/*!\n * @}\n * @defgroup XXH3_impl XXH3 implementation\n * @ingroup impl\n * @{\n */\n\n/* ===   Compiler specifics   === */\n\n#if ((defined(sun) || defined(__sun)) && __cplusplus) /* Solaris includes __STDC_VERSION__ with C++. Tested with GCC 5.5 */\n#  define XXH_RESTRICT   /* disable */\n#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* >= C99 */\n#  define XXH_RESTRICT   restrict\n#elif (defined (__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) \\\n   || (defined (__clang__)) \\\n   || (defined (_MSC_VER) && (_MSC_VER >= 1400)) \\\n   || (defined (__INTEL_COMPILER) && (__INTEL_COMPILER >= 1300))\n/*\n * There are a LOT more compilers that recognize __restrict but this\n * covers the major ones.\n */\n#  define XXH_RESTRICT   __restrict\n#else\n#  define XXH_RESTRICT   /* disable */\n#endif\n\n#if (defined(__GNUC__) && (__GNUC__ >= 3))  \\\n  || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) \\\n  || defined(__clang__)\n#    define XXH_likely(x) __builtin_expect(x, 1)\n#    define XXH_unlikely(x) __builtin_expect(x, 0)\n#else\n#    define XXH_likely(x) (x)\n#    define XXH_unlikely(x) (x)\n#endif\n\n#ifndef XXH_HAS_INCLUDE\n#  ifdef __has_include\n/*\n * Not defined as XXH_HAS_INCLUDE(x) (function-like) because\n * this causes segfaults in Apple Clang 4.2 (on Mac OS X 10.7 Lion)\n */\n#    define XXH_HAS_INCLUDE __has_include\n#  else\n#    define XXH_HAS_INCLUDE(x) 0\n#  endif\n#endif\n\n#if defined(__GNUC__) || defined(__clang__)\n#  if defined(__ARM_FEATURE_SVE)\n#    include <arm_sve.h>\n#  endif\n#  if defined(__ARM_NEON__) || defined(__ARM_NEON) \\\n   || (defined(_M_ARM) && _M_ARM >= 7) \\\n   || defined(_M_ARM64) || defined(_M_ARM64EC) \\\n   || (defined(__wasm_simd128__) && XXH_HAS_INCLUDE(<arm_neon.h>)) /* WASM SIMD128 via SIMDe */\n#    define inline __inline__  /* circumvent a clang bug */\n#    include <arm_neon.h>\n#    undef inline\n#  elif defined(__AVX2__)\n#    include <immintrin.h>\n#  elif defined(__SSE2__)\n#    include <emmintrin.h>\n#  endif\n#endif\n\n#if defined(_MSC_VER)\n#  include <intrin.h>\n#endif\n\n/*\n * One goal of XXH3 is to make it fast on both 32-bit and 64-bit, while\n * remaining a true 64-bit/128-bit hash function.\n *\n * This is done by prioritizing a subset of 64-bit operations that can be\n * emulated without too many steps on the average 32-bit machine.\n *\n * For example, these two lines seem similar, and run equally fast on 64-bit:\n *\n *   xxh_u64 x;\n *   x ^= (x >> 47); // good\n *   x ^= (x >> 13); // bad\n *\n * However, to a 32-bit machine, there is a major difference.\n *\n * x ^= (x >> 47) looks like this:\n *\n *   x.lo ^= (x.hi >> (47 - 32));\n *\n * while x ^= (x >> 13) looks like this:\n *\n *   // note: funnel shifts are not usually cheap.\n *   x.lo ^= (x.lo >> 13) | (x.hi << (32 - 13));\n *   x.hi ^= (x.hi >> 13);\n *\n * The first one is significantly faster than the second, simply because the\n * shift is larger than 32. This means:\n *  - All the bits we need are in the upper 32 bits, so we can ignore the lower\n *    32 bits in the shift.\n *  - The shift result will always fit in the lower 32 bits, and therefore,\n *    we can ignore the upper 32 bits in the xor.\n *\n * Thanks to this optimization, XXH3 only requires these features to be efficient:\n *\n *  - Usable unaligned access\n *  - A 32-bit or 64-bit ALU\n *      - If 32-bit, a decent ADC instruction\n *  - A 32 or 64-bit multiply with a 64-bit result\n *  - For the 128-bit variant, a decent byteswap helps short inputs.\n *\n * The first two are already required by XXH32, and almost all 32-bit and 64-bit\n * platforms which can run XXH32 can run XXH3 efficiently.\n *\n * Thumb-1, the classic 16-bit only subset of ARM's instruction set, is one\n * notable exception.\n *\n * First of all, Thumb-1 lacks support for the UMULL instruction which\n * performs the important long multiply. This means numerous __aeabi_lmul\n * calls.\n *\n * Second of all, the 8 functional registers are just not enough.\n * Setup for __aeabi_lmul, byteshift loads, pointers, and all arithmetic need\n * Lo registers, and this shuffling results in thousands more MOVs than A32.\n *\n * A32 and T32 don't have this limitation. They can access all 14 registers,\n * do a 32->64 multiply with UMULL, and the flexible operand allowing free\n * shifts is helpful, too.\n *\n * Therefore, we do a quick sanity check.\n *\n * If compiling Thumb-1 for a target which supports ARM instructions, we will\n * emit a warning, as it is not a \"sane\" platform to compile for.\n *\n * Usually, if this happens, it is because of an accident and you probably need\n * to specify -march, as you likely meant to compile for a newer architecture.\n *\n * Credit: large sections of the vectorial and asm source code paths\n *         have been contributed by @easyaspi314\n */\n#if defined(__thumb__) && !defined(__thumb2__) && defined(__ARM_ARCH_ISA_ARM)\n#   warning \"XXH3 is highly inefficient without ARM or Thumb-2.\"\n#endif\n\n/* ==========================================\n * Vectorization detection\n * ========================================== */\n\n#ifdef XXH_DOXYGEN\n/*!\n * @ingroup tuning\n * @brief Overrides the vectorization implementation chosen for XXH3.\n *\n * Can be defined to 0 to disable SIMD or any of the values mentioned in\n * @ref XXH_VECTOR_TYPE.\n *\n * If this is not defined, it uses predefined macros to determine the best\n * implementation.\n */\n#  define XXH_VECTOR XXH_SCALAR\n/*!\n * @ingroup tuning\n * @brief Possible values for @ref XXH_VECTOR.\n *\n * Note that these are actually implemented as macros.\n *\n * If this is not defined, it is detected automatically.\n * internal macro XXH_X86DISPATCH overrides this.\n */\nenum XXH_VECTOR_TYPE /* fake enum */ {\n    XXH_SCALAR = 0,  /*!< Portable scalar version */\n    XXH_SSE2   = 1,  /*!<\n                      * SSE2 for Pentium 4, Opteron, all x86_64.\n                      *\n                      * @note SSE2 is also guaranteed on Windows 10, macOS, and\n                      * Android x86.\n                      */\n    XXH_AVX2   = 2,  /*!< AVX2 for Haswell and Bulldozer */\n    XXH_AVX512 = 3,  /*!< AVX512 for Skylake and Icelake */\n    XXH_NEON   = 4,  /*!<\n                       * NEON for most ARMv7-A, all AArch64, and WASM SIMD128\n                       * via the SIMDeverywhere polyfill provided with the\n                       * Emscripten SDK.\n                       */\n    XXH_VSX    = 5,  /*!< VSX and ZVector for POWER8/z13 (64-bit) */\n    XXH_SVE    = 6,  /*!< SVE for some ARMv8-A and ARMv9-A */\n};\n/*!\n * @ingroup tuning\n * @brief Selects the minimum alignment for XXH3's accumulators.\n *\n * When using SIMD, this should match the alignment required for said vector\n * type, so, for example, 32 for AVX2.\n *\n * Default: Auto detected.\n */\n#  define XXH_ACC_ALIGN 8\n#endif\n\n/* Actual definition */\n#ifndef XXH_DOXYGEN\n#  define XXH_SCALAR 0\n#  define XXH_SSE2   1\n#  define XXH_AVX2   2\n#  define XXH_AVX512 3\n#  define XXH_NEON   4\n#  define XXH_VSX    5\n#  define XXH_SVE    6\n#endif\n\n#ifndef XXH_VECTOR    /* can be defined on command line */\n#  if defined(__ARM_FEATURE_SVE)\n#    define XXH_VECTOR XXH_SVE\n#  elif ( \\\n        defined(__ARM_NEON__) || defined(__ARM_NEON) /* gcc */ \\\n     || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC) /* msvc */ \\\n     || (defined(__wasm_simd128__) && XXH_HAS_INCLUDE(<arm_neon.h>)) /* wasm simd128 via SIMDe */ \\\n   ) && ( \\\n        defined(_WIN32) || defined(__LITTLE_ENDIAN__) /* little endian only */ \\\n    || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) \\\n   )\n#    define XXH_VECTOR XXH_NEON\n#  elif defined(__AVX512F__)\n#    define XXH_VECTOR XXH_AVX512\n#  elif defined(__AVX2__)\n#    define XXH_VECTOR XXH_AVX2\n#  elif defined(__SSE2__) || defined(_M_X64) || (defined(_M_IX86_FP) && (_M_IX86_FP == 2))\n#    define XXH_VECTOR XXH_SSE2\n#  elif (defined(__PPC64__) && defined(__POWER8_VECTOR__)) \\\n     || (defined(__s390x__) && defined(__VEC__)) \\\n     && defined(__GNUC__) /* TODO: IBM XL */\n#    define XXH_VECTOR XXH_VSX\n#  else\n#    define XXH_VECTOR XXH_SCALAR\n#  endif\n#endif\n\n/* __ARM_FEATURE_SVE is only supported by GCC & Clang. */\n#if (XXH_VECTOR == XXH_SVE) && !defined(__ARM_FEATURE_SVE)\n#  ifdef _MSC_VER\n#    pragma warning(once : 4606)\n#  else\n#    warning \"__ARM_FEATURE_SVE isn't supported. Use SCALAR instead.\"\n#  endif\n#  undef XXH_VECTOR\n#  define XXH_VECTOR XXH_SCALAR\n#endif\n\n/*\n * Controls the alignment of the accumulator,\n * for compatibility with aligned vector loads, which are usually faster.\n */\n#ifndef XXH_ACC_ALIGN\n#  if defined(XXH_X86DISPATCH)\n#     define XXH_ACC_ALIGN 64  /* for compatibility with avx512 */\n#  elif XXH_VECTOR == XXH_SCALAR  /* scalar */\n#     define XXH_ACC_ALIGN 8\n#  elif XXH_VECTOR == XXH_SSE2  /* sse2 */\n#     define XXH_ACC_ALIGN 16\n#  elif XXH_VECTOR == XXH_AVX2  /* avx2 */\n#     define XXH_ACC_ALIGN 32\n#  elif XXH_VECTOR == XXH_NEON  /* neon */\n#     define XXH_ACC_ALIGN 16\n#  elif XXH_VECTOR == XXH_VSX   /* vsx */\n#     define XXH_ACC_ALIGN 16\n#  elif XXH_VECTOR == XXH_AVX512  /* avx512 */\n#     define XXH_ACC_ALIGN 64\n#  elif XXH_VECTOR == XXH_SVE   /* sve */\n#     define XXH_ACC_ALIGN 64\n#  endif\n#endif\n\n#if defined(XXH_X86DISPATCH) || XXH_VECTOR == XXH_SSE2 \\\n    || XXH_VECTOR == XXH_AVX2 || XXH_VECTOR == XXH_AVX512\n#  define XXH_SEC_ALIGN XXH_ACC_ALIGN\n#elif XXH_VECTOR == XXH_SVE\n#  define XXH_SEC_ALIGN XXH_ACC_ALIGN\n#else\n#  define XXH_SEC_ALIGN 8\n#endif\n\n#if defined(__GNUC__) || defined(__clang__)\n#  define XXH_ALIASING __attribute__((may_alias))\n#else\n#  define XXH_ALIASING /* nothing */\n#endif\n\n/*\n * UGLY HACK:\n * GCC usually generates the best code with -O3 for xxHash.\n *\n * However, when targeting AVX2, it is overzealous in its unrolling resulting\n * in code roughly 3/4 the speed of Clang.\n *\n * There are other issues, such as GCC splitting _mm256_loadu_si256 into\n * _mm_loadu_si128 + _mm256_inserti128_si256. This is an optimization which\n * only applies to Sandy and Ivy Bridge... which don't even support AVX2.\n *\n * That is why when compiling the AVX2 version, it is recommended to use either\n *   -O2 -mavx2 -march=haswell\n * or\n *   -O2 -mavx2 -mno-avx256-split-unaligned-load\n * for decent performance, or to use Clang instead.\n *\n * Fortunately, we can control the first one with a pragma that forces GCC into\n * -O2, but the other one we can't control without \"failed to inline always\n * inline function due to target mismatch\" warnings.\n */\n#if XXH_VECTOR == XXH_AVX2 /* AVX2 */ \\\n  && defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \\\n  && defined(__OPTIMIZE__) && XXH_SIZE_OPT <= 0 /* respect -O0 and -Os */\n#  pragma GCC push_options\n#  pragma GCC optimize(\"-O2\")\n#endif\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n#if XXH_VECTOR == XXH_NEON\n\n/*\n * UGLY HACK: While AArch64 GCC on Linux does not seem to care, on macOS, GCC -O3\n * optimizes out the entire hashLong loop because of the aliasing violation.\n *\n * However, GCC is also inefficient at load-store optimization with vld1q/vst1q,\n * so the only option is to mark it as aliasing.\n */\ntypedef uint64x2_t xxh_aliasing_uint64x2_t XXH_ALIASING;\n\n/*!\n * @internal\n * @brief `vld1q_u64` but faster and alignment-safe.\n *\n * On AArch64, unaligned access is always safe, but on ARMv7-a, it is only\n * *conditionally* safe (`vld1` has an alignment bit like `movdq[ua]` in x86).\n *\n * GCC for AArch64 sees `vld1q_u8` as an intrinsic instead of a load, so it\n * prohibits load-store optimizations. Therefore, a direct dereference is used.\n *\n * Otherwise, `vld1q_u8` is used with `vreinterpretq_u8_u64` to do a safe\n * unaligned load.\n */\n#if defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__)\nXXH_FORCE_INLINE uint64x2_t XXH_vld1q_u64(void const* ptr) /* silence -Wcast-align */\n{\n    return *(xxh_aliasing_uint64x2_t const *)ptr;\n}\n#else\nXXH_FORCE_INLINE uint64x2_t XXH_vld1q_u64(void const* ptr)\n{\n    return vreinterpretq_u64_u8(vld1q_u8((uint8_t const*)ptr));\n}\n#endif\n\n/*!\n * @internal\n * @brief `vmlal_u32` on low and high halves of a vector.\n *\n * This is a workaround for AArch64 GCC < 11 which implemented arm_neon.h with\n * inline assembly and were therefore incapable of merging the `vget_{low, high}_u32`\n * with `vmlal_u32`.\n */\n#if defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 11\nXXH_FORCE_INLINE uint64x2_t\nXXH_vmlal_low_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs)\n{\n    /* Inline assembly is the only way */\n    __asm__(\"umlal   %0.2d, %1.2s, %2.2s\" : \"+w\" (acc) : \"w\" (lhs), \"w\" (rhs));\n    return acc;\n}\nXXH_FORCE_INLINE uint64x2_t\nXXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs)\n{\n    /* This intrinsic works as expected */\n    return vmlal_high_u32(acc, lhs, rhs);\n}\n#else\n/* Portable intrinsic versions */\nXXH_FORCE_INLINE uint64x2_t\nXXH_vmlal_low_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs)\n{\n    return vmlal_u32(acc, vget_low_u32(lhs), vget_low_u32(rhs));\n}\n/*! @copydoc XXH_vmlal_low_u32\n * Assume the compiler converts this to vmlal_high_u32 on aarch64 */\nXXH_FORCE_INLINE uint64x2_t\nXXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs)\n{\n    return vmlal_u32(acc, vget_high_u32(lhs), vget_high_u32(rhs));\n}\n#endif\n\n/*!\n * @ingroup tuning\n * @brief Controls the NEON to scalar ratio for XXH3\n *\n * This can be set to 2, 4, 6, or 8.\n *\n * ARM Cortex CPUs are _very_ sensitive to how their pipelines are used.\n *\n * For example, the Cortex-A73 can dispatch 3 micro-ops per cycle, but only 2 of those\n * can be NEON. If you are only using NEON instructions, you are only using 2/3 of the CPU\n * bandwidth.\n *\n * This is even more noticeable on the more advanced cores like the Cortex-A76 which\n * can dispatch 8 micro-ops per cycle, but still only 2 NEON micro-ops at once.\n *\n * Therefore, to make the most out of the pipeline, it is beneficial to run 6 NEON lanes\n * and 2 scalar lanes, which is chosen by default.\n *\n * This does not apply to Apple processors or 32-bit processors, which run better with\n * full NEON. These will default to 8. Additionally, size-optimized builds run 8 lanes.\n *\n * This change benefits CPUs with large micro-op buffers without negatively affecting\n * most other CPUs:\n *\n *  | Chipset               | Dispatch type       | NEON only | 6:2 hybrid | Diff. |\n *  |:----------------------|:--------------------|----------:|-----------:|------:|\n *  | Snapdragon 730 (A76)  | 2 NEON/8 micro-ops  |  8.8 GB/s |  10.1 GB/s |  ~16% |\n *  | Snapdragon 835 (A73)  | 2 NEON/3 micro-ops  |  5.1 GB/s |   5.3 GB/s |   ~5% |\n *  | Marvell PXA1928 (A53) | In-order dual-issue |  1.9 GB/s |   1.9 GB/s |    0% |\n *  | Apple M1              | 4 NEON/8 micro-ops  | 37.3 GB/s |  36.1 GB/s |  ~-3% |\n *\n * It also seems to fix some bad codegen on GCC, making it almost as fast as clang.\n *\n * When using WASM SIMD128, if this is 2 or 6, SIMDe will scalarize 2 of the lanes meaning\n * it effectively becomes worse 4.\n *\n * @see XXH3_accumulate_512_neon()\n */\n# ifndef XXH3_NEON_LANES\n#  if (defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) || defined(_M_ARM64EC)) \\\n   && !defined(__APPLE__) && XXH_SIZE_OPT <= 0\n#   define XXH3_NEON_LANES 6\n#  else\n#   define XXH3_NEON_LANES XXH_ACC_NB\n#  endif\n# endif\n#endif  /* XXH_VECTOR == XXH_NEON */\n\n#if defined (__cplusplus)\n} /* extern \"C\" */\n#endif\n\n/*\n * VSX and Z Vector helpers.\n *\n * This is very messy, and any pull requests to clean this up are welcome.\n *\n * There are a lot of problems with supporting VSX and s390x, due to\n * inconsistent intrinsics, spotty coverage, and multiple endiannesses.\n */\n#if XXH_VECTOR == XXH_VSX\n/* Annoyingly, these headers _may_ define three macros: `bool`, `vector`,\n * and `pixel`. This is a problem for obvious reasons.\n *\n * These keywords are unnecessary; the spec literally says they are\n * equivalent to `__bool`, `__vector`, and `__pixel` and may be undef'd\n * after including the header.\n *\n * We use pragma push_macro/pop_macro to keep the namespace clean. */\n#  pragma push_macro(\"bool\")\n#  pragma push_macro(\"vector\")\n#  pragma push_macro(\"pixel\")\n/* silence potential macro redefined warnings */\n#  undef bool\n#  undef vector\n#  undef pixel\n\n#  if defined(__s390x__)\n#    include <s390intrin.h>\n#  else\n#    include <altivec.h>\n#  endif\n\n/* Restore the original macro values, if applicable. */\n#  pragma pop_macro(\"pixel\")\n#  pragma pop_macro(\"vector\")\n#  pragma pop_macro(\"bool\")\n\ntypedef __vector unsigned long long xxh_u64x2;\ntypedef __vector unsigned char xxh_u8x16;\ntypedef __vector unsigned xxh_u32x4;\n\n/*\n * UGLY HACK: Similar to aarch64 macOS GCC, s390x GCC has the same aliasing issue.\n */\ntypedef xxh_u64x2 xxh_aliasing_u64x2 XXH_ALIASING;\n\n# ifndef XXH_VSX_BE\n#  if defined(__BIG_ENDIAN__) \\\n  || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)\n#    define XXH_VSX_BE 1\n#  elif defined(__VEC_ELEMENT_REG_ORDER__) && __VEC_ELEMENT_REG_ORDER__ == __ORDER_BIG_ENDIAN__\n#    warning \"-maltivec=be is not recommended. Please use native endianness.\"\n#    define XXH_VSX_BE 1\n#  else\n#    define XXH_VSX_BE 0\n#  endif\n# endif /* !defined(XXH_VSX_BE) */\n\n# if XXH_VSX_BE\n#  if defined(__POWER9_VECTOR__) || (defined(__clang__) && defined(__s390x__))\n#    define XXH_vec_revb vec_revb\n#  else\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n/*!\n * A polyfill for POWER9's vec_revb().\n */\nXXH_FORCE_INLINE xxh_u64x2 XXH_vec_revb(xxh_u64x2 val)\n{\n    xxh_u8x16 const vByteSwap = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,\n                                  0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 };\n    return vec_perm(val, val, vByteSwap);\n}\n#if defined (__cplusplus)\n} /* extern \"C\" */\n#endif\n#  endif\n# endif /* XXH_VSX_BE */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n/*!\n * Performs an unaligned vector load and byte swaps it on big endian.\n */\nXXH_FORCE_INLINE xxh_u64x2 XXH_vec_loadu(const void *ptr)\n{\n    xxh_u64x2 ret;\n    XXH_memcpy(&ret, ptr, sizeof(xxh_u64x2));\n# if XXH_VSX_BE\n    ret = XXH_vec_revb(ret);\n# endif\n    return ret;\n}\n\n/*\n * vec_mulo and vec_mule are very problematic intrinsics on PowerPC\n *\n * These intrinsics weren't added until GCC 8, despite existing for a while,\n * and they are endian dependent. Also, their meaning swap depending on version.\n * */\n# if defined(__s390x__)\n /* s390x is always big endian, no issue on this platform */\n#  define XXH_vec_mulo vec_mulo\n#  define XXH_vec_mule vec_mule\n# elif defined(__clang__) && XXH_HAS_BUILTIN(__builtin_altivec_vmuleuw) && !defined(__ibmxl__)\n/* Clang has a better way to control this, we can just use the builtin which doesn't swap. */\n /* The IBM XL Compiler (which defined __clang__) only implements the vec_* operations */\n#  define XXH_vec_mulo __builtin_altivec_vmulouw\n#  define XXH_vec_mule __builtin_altivec_vmuleuw\n# else\n/* gcc needs inline assembly */\n/* Adapted from https://github.com/google/highwayhash/blob/master/highwayhash/hh_vsx.h. */\nXXH_FORCE_INLINE xxh_u64x2 XXH_vec_mulo(xxh_u32x4 a, xxh_u32x4 b)\n{\n    xxh_u64x2 result;\n    __asm__(\"vmulouw %0, %1, %2\" : \"=v\" (result) : \"v\" (a), \"v\" (b));\n    return result;\n}\nXXH_FORCE_INLINE xxh_u64x2 XXH_vec_mule(xxh_u32x4 a, xxh_u32x4 b)\n{\n    xxh_u64x2 result;\n    __asm__(\"vmuleuw %0, %1, %2\" : \"=v\" (result) : \"v\" (a), \"v\" (b));\n    return result;\n}\n# endif /* XXH_vec_mulo, XXH_vec_mule */\n\n#if defined (__cplusplus)\n} /* extern \"C\" */\n#endif\n\n#endif /* XXH_VECTOR == XXH_VSX */\n\n#if XXH_VECTOR == XXH_SVE\n#define ACCRND(acc, offset) \\\ndo { \\\n    svuint64_t input_vec = svld1_u64(mask, xinput + offset);         \\\n    svuint64_t secret_vec = svld1_u64(mask, xsecret + offset);       \\\n    svuint64_t mixed = sveor_u64_x(mask, secret_vec, input_vec);     \\\n    svuint64_t swapped = svtbl_u64(input_vec, kSwap);                \\\n    svuint64_t mixed_lo = svextw_u64_x(mask, mixed);                 \\\n    svuint64_t mixed_hi = svlsr_n_u64_x(mask, mixed, 32);            \\\n    svuint64_t mul = svmad_u64_x(mask, mixed_lo, mixed_hi, swapped); \\\n    acc = svadd_u64_x(mask, acc, mul);                               \\\n} while (0)\n#endif /* XXH_VECTOR == XXH_SVE */\n\n/* prefetch\n * can be disabled, by declaring XXH_NO_PREFETCH build macro */\n#if defined(XXH_NO_PREFETCH)\n#  define XXH_PREFETCH(ptr)  (void)(ptr)  /* disabled */\n#else\n#  if XXH_SIZE_OPT >= 1\n#    define XXH_PREFETCH(ptr) (void)(ptr)\n#  elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))  /* _mm_prefetch() not defined outside of x86/x64 */\n#    include <mmintrin.h>   /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */\n#    define XXH_PREFETCH(ptr)  _mm_prefetch((const char*)(ptr), _MM_HINT_T0)\n#  elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) )\n#    define XXH_PREFETCH(ptr)  __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */)\n#  else\n#    define XXH_PREFETCH(ptr) (void)(ptr)  /* disabled */\n#  endif\n#endif  /* XXH_NO_PREFETCH */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n/* ==========================================\n * XXH3 default settings\n * ========================================== */\n\n#define XXH_SECRET_DEFAULT_SIZE 192   /* minimum XXH3_SECRET_SIZE_MIN */\n\n#if (XXH_SECRET_DEFAULT_SIZE < XXH3_SECRET_SIZE_MIN)\n#  error \"default keyset is not large enough\"\n#endif\n\n/*! Pseudorandom secret taken directly from FARSH. */\nXXH_ALIGN(64) static const xxh_u8 XXH3_kSecret[XXH_SECRET_DEFAULT_SIZE] = {\n    0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c,\n    0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f,\n    0xcb, 0x79, 0xe6, 0x4e, 0xcc, 0xc0, 0xe5, 0x78, 0x82, 0x5a, 0xd0, 0x7d, 0xcc, 0xff, 0x72, 0x21,\n    0xb8, 0x08, 0x46, 0x74, 0xf7, 0x43, 0x24, 0x8e, 0xe0, 0x35, 0x90, 0xe6, 0x81, 0x3a, 0x26, 0x4c,\n    0x3c, 0x28, 0x52, 0xbb, 0x91, 0xc3, 0x00, 0xcb, 0x88, 0xd0, 0x65, 0x8b, 0x1b, 0x53, 0x2e, 0xa3,\n    0x71, 0x64, 0x48, 0x97, 0xa2, 0x0d, 0xf9, 0x4e, 0x38, 0x19, 0xef, 0x46, 0xa9, 0xde, 0xac, 0xd8,\n    0xa8, 0xfa, 0x76, 0x3f, 0xe3, 0x9c, 0x34, 0x3f, 0xf9, 0xdc, 0xbb, 0xc7, 0xc7, 0x0b, 0x4f, 0x1d,\n    0x8a, 0x51, 0xe0, 0x4b, 0xcd, 0xb4, 0x59, 0x31, 0xc8, 0x9f, 0x7e, 0xc9, 0xd9, 0x78, 0x73, 0x64,\n    0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb,\n    0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e,\n    0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce,\n    0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e,\n};\n\nstatic const xxh_u64 PRIME_MX1 = 0x165667919E3779F9ULL;  /*!< 0b0001011001010110011001111001000110011110001101110111100111111001 */\nstatic const xxh_u64 PRIME_MX2 = 0x9FB21C651E98DF25ULL;  /*!< 0b1001111110110010000111000110010100011110100110001101111100100101 */\n\n#ifdef XXH_OLD_NAMES\n#  define kSecret XXH3_kSecret\n#endif\n\n#ifdef XXH_DOXYGEN\n/*!\n * @brief Calculates a 32-bit to 64-bit long multiply.\n *\n * Implemented as a macro.\n *\n * Wraps `__emulu` on MSVC x86 because it tends to call `__allmul` when it doesn't\n * need to (but it shouldn't need to anyways, it is about 7 instructions to do\n * a 64x64 multiply...). Since we know that this will _always_ emit `MULL`, we\n * use that instead of the normal method.\n *\n * If you are compiling for platforms like Thumb-1 and don't have a better option,\n * you may also want to write your own long multiply routine here.\n *\n * @param x, y Numbers to be multiplied\n * @return 64-bit product of the low 32 bits of @p x and @p y.\n */\nXXH_FORCE_INLINE xxh_u64\nXXH_mult32to64(xxh_u64 x, xxh_u64 y)\n{\n   return (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF);\n}\n#elif defined(_MSC_VER) && defined(_M_IX86)\n#    define XXH_mult32to64(x, y) __emulu((unsigned)(x), (unsigned)(y))\n#else\n/*\n * Downcast + upcast is usually better than masking on older compilers like\n * GCC 4.2 (especially 32-bit ones), all without affecting newer compilers.\n *\n * The other method, (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF), will AND both operands\n * and perform a full 64x64 multiply -- entirely redundant on 32-bit.\n */\n#    define XXH_mult32to64(x, y) ((xxh_u64)(xxh_u32)(x) * (xxh_u64)(xxh_u32)(y))\n#endif\n\n/*!\n * @brief Calculates a 64->128-bit long multiply.\n *\n * Uses `__uint128_t` and `_umul128` if available, otherwise uses a scalar\n * version.\n *\n * @param lhs , rhs The 64-bit integers to be multiplied\n * @return The 128-bit result represented in an @ref XXH128_hash_t.\n */\nstatic XXH128_hash_t\nXXH_mult64to128(xxh_u64 lhs, xxh_u64 rhs)\n{\n    /*\n     * GCC/Clang __uint128_t method.\n     *\n     * On most 64-bit targets, GCC and Clang define a __uint128_t type.\n     * This is usually the best way as it usually uses a native long 64-bit\n     * multiply, such as MULQ on x86_64 or MUL + UMULH on aarch64.\n     *\n     * Usually.\n     *\n     * Despite being a 32-bit platform, Clang (and emscripten) define this type\n     * despite not having the arithmetic for it. This results in a laggy\n     * compiler builtin call which calculates a full 128-bit multiply.\n     * In that case it is best to use the portable one.\n     * https://github.com/Cyan4973/xxHash/issues/211#issuecomment-515575677\n     */\n#if (defined(__GNUC__) || defined(__clang__)) && !defined(__wasm__) \\\n    && defined(__SIZEOF_INT128__) \\\n    || (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 128)\n\n    __uint128_t const product = (__uint128_t)lhs * (__uint128_t)rhs;\n    XXH128_hash_t r128;\n    r128.low64  = (xxh_u64)(product);\n    r128.high64 = (xxh_u64)(product >> 64);\n    return r128;\n\n    /*\n     * MSVC for x64's _umul128 method.\n     *\n     * xxh_u64 _umul128(xxh_u64 Multiplier, xxh_u64 Multiplicand, xxh_u64 *HighProduct);\n     *\n     * This compiles to single operand MUL on x64.\n     */\n#elif (defined(_M_X64) || defined(_M_IA64)) && !defined(_M_ARM64EC)\n\n#ifndef _MSC_VER\n#   pragma intrinsic(_umul128)\n#endif\n    xxh_u64 product_high;\n    xxh_u64 const product_low = _umul128(lhs, rhs, &product_high);\n    XXH128_hash_t r128;\n    r128.low64  = product_low;\n    r128.high64 = product_high;\n    return r128;\n\n    /*\n     * MSVC for ARM64's __umulh method.\n     *\n     * This compiles to the same MUL + UMULH as GCC/Clang's __uint128_t method.\n     */\n#elif defined(_M_ARM64) || defined(_M_ARM64EC)\n\n#ifndef _MSC_VER\n#   pragma intrinsic(__umulh)\n#endif\n    XXH128_hash_t r128;\n    r128.low64  = lhs * rhs;\n    r128.high64 = __umulh(lhs, rhs);\n    return r128;\n\n#else\n    /*\n     * Portable scalar method. Optimized for 32-bit and 64-bit ALUs.\n     *\n     * This is a fast and simple grade school multiply, which is shown below\n     * with base 10 arithmetic instead of base 0x100000000.\n     *\n     *           9 3 // D2 lhs = 93\n     *         x 7 5 // D2 rhs = 75\n     *     ----------\n     *           1 5 // D2 lo_lo = (93 % 10) * (75 % 10) = 15\n     *         4 5 | // D2 hi_lo = (93 / 10) * (75 % 10) = 45\n     *         2 1 | // D2 lo_hi = (93 % 10) * (75 / 10) = 21\n     *     + 6 3 | | // D2 hi_hi = (93 / 10) * (75 / 10) = 63\n     *     ---------\n     *         2 7 | // D2 cross = (15 / 10) + (45 % 10) + 21 = 27\n     *     + 6 7 | | // D2 upper = (27 / 10) + (45 / 10) + 63 = 67\n     *     ---------\n     *       6 9 7 5 // D4 res = (27 * 10) + (15 % 10) + (67 * 100) = 6975\n     *\n     * The reasons for adding the products like this are:\n     *  1. It avoids manual carry tracking. Just like how\n     *     (9 * 9) + 9 + 9 = 99, the same applies with this for UINT64_MAX.\n     *     This avoids a lot of complexity.\n     *\n     *  2. It hints for, and on Clang, compiles to, the powerful UMAAL\n     *     instruction available in ARM's Digital Signal Processing extension\n     *     in 32-bit ARMv6 and later, which is shown below:\n     *\n     *         void UMAAL(xxh_u32 *RdLo, xxh_u32 *RdHi, xxh_u32 Rn, xxh_u32 Rm)\n     *         {\n     *             xxh_u64 product = (xxh_u64)*RdLo * (xxh_u64)*RdHi + Rn + Rm;\n     *             *RdLo = (xxh_u32)(product & 0xFFFFFFFF);\n     *             *RdHi = (xxh_u32)(product >> 32);\n     *         }\n     *\n     *     This instruction was designed for efficient long multiplication, and\n     *     allows this to be calculated in only 4 instructions at speeds\n     *     comparable to some 64-bit ALUs.\n     *\n     *  3. It isn't terrible on other platforms. Usually this will be a couple\n     *     of 32-bit ADD/ADCs.\n     */\n\n    /* First calculate all of the cross products. */\n    xxh_u64 const lo_lo = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs & 0xFFFFFFFF);\n    xxh_u64 const hi_lo = XXH_mult32to64(lhs >> 32,        rhs & 0xFFFFFFFF);\n    xxh_u64 const lo_hi = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs >> 32);\n    xxh_u64 const hi_hi = XXH_mult32to64(lhs >> 32,        rhs >> 32);\n\n    /* Now add the products together. These will never overflow. */\n    xxh_u64 const cross = (lo_lo >> 32) + (hi_lo & 0xFFFFFFFF) + lo_hi;\n    xxh_u64 const upper = (hi_lo >> 32) + (cross >> 32)        + hi_hi;\n    xxh_u64 const lower = (cross << 32) | (lo_lo & 0xFFFFFFFF);\n\n    XXH128_hash_t r128;\n    r128.low64  = lower;\n    r128.high64 = upper;\n    return r128;\n#endif\n}\n\n/*!\n * @brief Calculates a 64-bit to 128-bit multiply, then XOR folds it.\n *\n * The reason for the separate function is to prevent passing too many structs\n * around by value. This will hopefully inline the multiply, but we don't force it.\n *\n * @param lhs , rhs The 64-bit integers to multiply\n * @return The low 64 bits of the product XOR'd by the high 64 bits.\n * @see XXH_mult64to128()\n */\nstatic xxh_u64\nXXH3_mul128_fold64(xxh_u64 lhs, xxh_u64 rhs)\n{\n    XXH128_hash_t product = XXH_mult64to128(lhs, rhs);\n    return product.low64 ^ product.high64;\n}\n\n/*! Seems to produce slightly better code on GCC for some reason. */\nXXH_FORCE_INLINE XXH_CONSTF xxh_u64 XXH_xorshift64(xxh_u64 v64, int shift)\n{\n    XXH_ASSERT(0 <= shift && shift < 64);\n    return v64 ^ (v64 >> shift);\n}\n\n/*\n * This is a fast avalanche stage,\n * suitable when input bits are already partially mixed\n */\nstatic XXH64_hash_t XXH3_avalanche(xxh_u64 h64)\n{\n    h64 = XXH_xorshift64(h64, 37);\n    h64 *= PRIME_MX1;\n    h64 = XXH_xorshift64(h64, 32);\n    return h64;\n}\n\n/*\n * This is a stronger avalanche,\n * inspired by Pelle Evensen's rrmxmx\n * preferable when input has not been previously mixed\n */\nstatic XXH64_hash_t XXH3_rrmxmx(xxh_u64 h64, xxh_u64 len)\n{\n    /* this mix is inspired by Pelle Evensen's rrmxmx */\n    h64 ^= XXH_rotl64(h64, 49) ^ XXH_rotl64(h64, 24);\n    h64 *= PRIME_MX2;\n    h64 ^= (h64 >> 35) + len ;\n    h64 *= PRIME_MX2;\n    return XXH_xorshift64(h64, 28);\n}\n\n\n/* ==========================================\n * Short keys\n * ==========================================\n * One of the shortcomings of XXH32 and XXH64 was that their performance was\n * sub-optimal on short lengths. It used an iterative algorithm which strongly\n * favored lengths that were a multiple of 4 or 8.\n *\n * Instead of iterating over individual inputs, we use a set of single shot\n * functions which piece together a range of lengths and operate in constant time.\n *\n * Additionally, the number of multiplies has been significantly reduced. This\n * reduces latency, especially when emulating 64-bit multiplies on 32-bit.\n *\n * Depending on the platform, this may or may not be faster than XXH32, but it\n * is almost guaranteed to be faster than XXH64.\n */\n\n/*\n * At very short lengths, there isn't enough input to fully hide secrets, or use\n * the entire secret.\n *\n * There is also only a limited amount of mixing we can do before significantly\n * impacting performance.\n *\n * Therefore, we use different sections of the secret and always mix two secret\n * samples with an XOR. This should have no effect on performance on the\n * seedless or withSeed variants because everything _should_ be constant folded\n * by modern compilers.\n *\n * The XOR mixing hides individual parts of the secret and increases entropy.\n *\n * This adds an extra layer of strength for custom secrets.\n */\nXXH_FORCE_INLINE XXH_PUREF XXH64_hash_t\nXXH3_len_1to3_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)\n{\n    XXH_ASSERT(input != NULL);\n    XXH_ASSERT(1 <= len && len <= 3);\n    XXH_ASSERT(secret != NULL);\n    /*\n     * len = 1: combined = { input[0], 0x01, input[0], input[0] }\n     * len = 2: combined = { input[1], 0x02, input[0], input[1] }\n     * len = 3: combined = { input[2], 0x03, input[0], input[1] }\n     */\n    {   xxh_u8  const c1 = input[0];\n        xxh_u8  const c2 = input[len >> 1];\n        xxh_u8  const c3 = input[len - 1];\n        xxh_u32 const combined = ((xxh_u32)c1 << 16) | ((xxh_u32)c2  << 24)\n                               | ((xxh_u32)c3 <<  0) | ((xxh_u32)len << 8);\n        xxh_u64 const bitflip = (XXH_readLE32(secret) ^ XXH_readLE32(secret+4)) + seed;\n        xxh_u64 const keyed = (xxh_u64)combined ^ bitflip;\n        return XXH64_avalanche(keyed);\n    }\n}\n\nXXH_FORCE_INLINE XXH_PUREF XXH64_hash_t\nXXH3_len_4to8_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)\n{\n    XXH_ASSERT(input != NULL);\n    XXH_ASSERT(secret != NULL);\n    XXH_ASSERT(4 <= len && len <= 8);\n    seed ^= (xxh_u64)XXH_swap32((xxh_u32)seed) << 32;\n    {   xxh_u32 const input1 = XXH_readLE32(input);\n        xxh_u32 const input2 = XXH_readLE32(input + len - 4);\n        xxh_u64 const bitflip = (XXH_readLE64(secret+8) ^ XXH_readLE64(secret+16)) - seed;\n        xxh_u64 const input64 = input2 + (((xxh_u64)input1) << 32);\n        xxh_u64 const keyed = input64 ^ bitflip;\n        return XXH3_rrmxmx(keyed, len);\n    }\n}\n\nXXH_FORCE_INLINE XXH_PUREF XXH64_hash_t\nXXH3_len_9to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)\n{\n    XXH_ASSERT(input != NULL);\n    XXH_ASSERT(secret != NULL);\n    XXH_ASSERT(9 <= len && len <= 16);\n    {   xxh_u64 const bitflip1 = (XXH_readLE64(secret+24) ^ XXH_readLE64(secret+32)) + seed;\n        xxh_u64 const bitflip2 = (XXH_readLE64(secret+40) ^ XXH_readLE64(secret+48)) - seed;\n        xxh_u64 const input_lo = XXH_readLE64(input)           ^ bitflip1;\n        xxh_u64 const input_hi = XXH_readLE64(input + len - 8) ^ bitflip2;\n        xxh_u64 const acc = len\n                          + XXH_swap64(input_lo) + input_hi\n                          + XXH3_mul128_fold64(input_lo, input_hi);\n        return XXH3_avalanche(acc);\n    }\n}\n\nXXH_FORCE_INLINE XXH_PUREF XXH64_hash_t\nXXH3_len_0to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)\n{\n    XXH_ASSERT(len <= 16);\n    {   if (XXH_likely(len >  8)) return XXH3_len_9to16_64b(input, len, secret, seed);\n        if (XXH_likely(len >= 4)) return XXH3_len_4to8_64b(input, len, secret, seed);\n        if (len) return XXH3_len_1to3_64b(input, len, secret, seed);\n        return XXH64_avalanche(seed ^ (XXH_readLE64(secret+56) ^ XXH_readLE64(secret+64)));\n    }\n}\n\n/*\n * DISCLAIMER: There are known *seed-dependent* multicollisions here due to\n * multiplication by zero, affecting hashes of lengths 17 to 240.\n *\n * However, they are very unlikely.\n *\n * Keep this in mind when using the unseeded XXH3_64bits() variant: As with all\n * unseeded non-cryptographic hashes, it does not attempt to defend itself\n * against specially crafted inputs, only random inputs.\n *\n * Compared to classic UMAC where a 1 in 2^31 chance of 4 consecutive bytes\n * cancelling out the secret is taken an arbitrary number of times (addressed\n * in XXH3_accumulate_512), this collision is very unlikely with random inputs\n * and/or proper seeding:\n *\n * This only has a 1 in 2^63 chance of 8 consecutive bytes cancelling out, in a\n * function that is only called up to 16 times per hash with up to 240 bytes of\n * input.\n *\n * This is not too bad for a non-cryptographic hash function, especially with\n * only 64 bit outputs.\n *\n * The 128-bit variant (which trades some speed for strength) is NOT affected\n * by this, although it is always a good idea to use a proper seed if you care\n * about strength.\n */\nXXH_FORCE_INLINE xxh_u64 XXH3_mix16B(const xxh_u8* XXH_RESTRICT input,\n                                     const xxh_u8* XXH_RESTRICT secret, xxh_u64 seed64)\n{\n#if defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \\\n  && defined(__i386__) && defined(__SSE2__)  /* x86 + SSE2 */ \\\n  && !defined(XXH_ENABLE_AUTOVECTORIZE)      /* Define to disable like XXH32 hack */\n    /*\n     * UGLY HACK:\n     * GCC for x86 tends to autovectorize the 128-bit multiply, resulting in\n     * slower code.\n     *\n     * By forcing seed64 into a register, we disrupt the cost model and\n     * cause it to scalarize. See `XXH32_round()`\n     *\n     * FIXME: Clang's output is still _much_ faster -- On an AMD Ryzen 3600,\n     * XXH3_64bits @ len=240 runs at 4.6 GB/s with Clang 9, but 3.3 GB/s on\n     * GCC 9.2, despite both emitting scalar code.\n     *\n     * GCC generates much better scalar code than Clang for the rest of XXH3,\n     * which is why finding a more optimal codepath is an interest.\n     */\n    XXH_COMPILER_GUARD(seed64);\n#endif\n    {   xxh_u64 const input_lo = XXH_readLE64(input);\n        xxh_u64 const input_hi = XXH_readLE64(input+8);\n        return XXH3_mul128_fold64(\n            input_lo ^ (XXH_readLE64(secret)   + seed64),\n            input_hi ^ (XXH_readLE64(secret+8) - seed64)\n        );\n    }\n}\n\n/* For mid range keys, XXH3 uses a Mum-hash variant. */\nXXH_FORCE_INLINE XXH_PUREF XXH64_hash_t\nXXH3_len_17to128_64b(const xxh_u8* XXH_RESTRICT input, size_t len,\n                     const xxh_u8* XXH_RESTRICT secret, size_t secretSize,\n                     XXH64_hash_t seed)\n{\n    XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize;\n    XXH_ASSERT(16 < len && len <= 128);\n\n    {   xxh_u64 acc = len * XXH_PRIME64_1;\n#if XXH_SIZE_OPT >= 1\n        /* Smaller and cleaner, but slightly slower. */\n        unsigned int i = (unsigned int)(len - 1) / 32;\n        do {\n            acc += XXH3_mix16B(input+16 * i, secret+32*i, seed);\n            acc += XXH3_mix16B(input+len-16*(i+1), secret+32*i+16, seed);\n        } while (i-- != 0);\n#else\n        if (len > 32) {\n            if (len > 64) {\n                if (len > 96) {\n                    acc += XXH3_mix16B(input+48, secret+96, seed);\n                    acc += XXH3_mix16B(input+len-64, secret+112, seed);\n                }\n                acc += XXH3_mix16B(input+32, secret+64, seed);\n                acc += XXH3_mix16B(input+len-48, secret+80, seed);\n            }\n            acc += XXH3_mix16B(input+16, secret+32, seed);\n            acc += XXH3_mix16B(input+len-32, secret+48, seed);\n        }\n        acc += XXH3_mix16B(input+0, secret+0, seed);\n        acc += XXH3_mix16B(input+len-16, secret+16, seed);\n#endif\n        return XXH3_avalanche(acc);\n    }\n}\n\n/*!\n * @brief Maximum size of \"short\" key in bytes.\n */\n#define XXH3_MIDSIZE_MAX 240\n\nXXH_NO_INLINE XXH_PUREF XXH64_hash_t\nXXH3_len_129to240_64b(const xxh_u8* XXH_RESTRICT input, size_t len,\n                      const xxh_u8* XXH_RESTRICT secret, size_t secretSize,\n                      XXH64_hash_t seed)\n{\n    XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize;\n    XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX);\n\n    #define XXH3_MIDSIZE_STARTOFFSET 3\n    #define XXH3_MIDSIZE_LASTOFFSET  17\n\n    {   xxh_u64 acc = len * XXH_PRIME64_1;\n        xxh_u64 acc_end;\n        unsigned int const nbRounds = (unsigned int)len / 16;\n        unsigned int i;\n        XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX);\n        for (i=0; i<8; i++) {\n            acc += XXH3_mix16B(input+(16*i), secret+(16*i), seed);\n        }\n        /* last bytes */\n        acc_end = XXH3_mix16B(input + len - 16, secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET, seed);\n        XXH_ASSERT(nbRounds >= 8);\n        acc = XXH3_avalanche(acc);\n#if defined(__clang__)                                /* Clang */ \\\n    && (defined(__ARM_NEON) || defined(__ARM_NEON__)) /* NEON */ \\\n    && !defined(XXH_ENABLE_AUTOVECTORIZE)             /* Define to disable */\n        /*\n         * UGLY HACK:\n         * Clang for ARMv7-A tries to vectorize this loop, similar to GCC x86.\n         * In everywhere else, it uses scalar code.\n         *\n         * For 64->128-bit multiplies, even if the NEON was 100% optimal, it\n         * would still be slower than UMAAL (see XXH_mult64to128).\n         *\n         * Unfortunately, Clang doesn't handle the long multiplies properly and\n         * converts them to the nonexistent \"vmulq_u64\" intrinsic, which is then\n         * scalarized into an ugly mess of VMOV.32 instructions.\n         *\n         * This mess is difficult to avoid without turning autovectorization\n         * off completely, but they are usually relatively minor and/or not\n         * worth it to fix.\n         *\n         * This loop is the easiest to fix, as unlike XXH32, this pragma\n         * _actually works_ because it is a loop vectorization instead of an\n         * SLP vectorization.\n         */\n        #pragma clang loop vectorize(disable)\n#endif\n        for (i=8 ; i < nbRounds; i++) {\n            /*\n             * Prevents clang for unrolling the acc loop and interleaving with this one.\n             */\n            XXH_COMPILER_GUARD(acc);\n            acc_end += XXH3_mix16B(input+(16*i), secret+(16*(i-8)) + XXH3_MIDSIZE_STARTOFFSET, seed);\n        }\n        return XXH3_avalanche(acc + acc_end);\n    }\n}\n\n\n/* =======     Long Keys     ======= */\n\n#define XXH_STRIPE_LEN 64\n#define XXH_SECRET_CONSUME_RATE 8   /* nb of secret bytes consumed at each accumulation */\n#define XXH_ACC_NB (XXH_STRIPE_LEN / sizeof(xxh_u64))\n\n#ifdef XXH_OLD_NAMES\n#  define STRIPE_LEN XXH_STRIPE_LEN\n#  define ACC_NB XXH_ACC_NB\n#endif\n\n#ifndef XXH_PREFETCH_DIST\n#  ifdef __clang__\n#    define XXH_PREFETCH_DIST 320\n#  else\n#    if (XXH_VECTOR == XXH_AVX512)\n#      define XXH_PREFETCH_DIST 512\n#    else\n#      define XXH_PREFETCH_DIST 384\n#    endif\n#  endif  /* __clang__ */\n#endif  /* XXH_PREFETCH_DIST */\n\n/*\n * These macros are to generate an XXH3_accumulate() function.\n * The two arguments select the name suffix and target attribute.\n *\n * The name of this symbol is XXH3_accumulate_<name>() and it calls\n * XXH3_accumulate_512_<name>().\n *\n * It may be useful to hand implement this function if the compiler fails to\n * optimize the inline function.\n */\n#define XXH3_ACCUMULATE_TEMPLATE(name)                      \\\nvoid                                                        \\\nXXH3_accumulate_##name(xxh_u64* XXH_RESTRICT acc,           \\\n                       const xxh_u8* XXH_RESTRICT input,    \\\n                       const xxh_u8* XXH_RESTRICT secret,   \\\n                       size_t nbStripes)                    \\\n{                                                           \\\n    size_t n;                                               \\\n    for (n = 0; n < nbStripes; n++ ) {                      \\\n        const xxh_u8* const in = input + n*XXH_STRIPE_LEN;  \\\n        XXH_PREFETCH(in + XXH_PREFETCH_DIST);               \\\n        XXH3_accumulate_512_##name(                         \\\n                 acc,                                       \\\n                 in,                                        \\\n                 secret + n*XXH_SECRET_CONSUME_RATE);       \\\n    }                                                       \\\n}\n\n\nXXH_FORCE_INLINE void XXH_writeLE64(void* dst, xxh_u64 v64)\n{\n    if (!XXH_CPU_LITTLE_ENDIAN) v64 = XXH_swap64(v64);\n    XXH_memcpy(dst, &v64, sizeof(v64));\n}\n\n/* Several intrinsic functions below are supposed to accept __int64 as argument,\n * as documented in https://software.intel.com/sites/landingpage/IntrinsicsGuide/ .\n * However, several environments do not define __int64 type,\n * requiring a workaround.\n */\n#if !defined (__VMS) \\\n  && (defined (__cplusplus) \\\n  || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )\n    typedef int64_t xxh_i64;\n#else\n    /* the following type must have a width of 64-bit */\n    typedef long long xxh_i64;\n#endif\n\n\n/*\n * XXH3_accumulate_512 is the tightest loop for long inputs, and it is the most optimized.\n *\n * It is a hardened version of UMAC, based off of FARSH's implementation.\n *\n * This was chosen because it adapts quite well to 32-bit, 64-bit, and SIMD\n * implementations, and it is ridiculously fast.\n *\n * We harden it by mixing the original input to the accumulators as well as the product.\n *\n * This means that in the (relatively likely) case of a multiply by zero, the\n * original input is preserved.\n *\n * On 128-bit inputs, we swap 64-bit pairs when we add the input to improve\n * cross-pollination, as otherwise the upper and lower halves would be\n * essentially independent.\n *\n * This doesn't matter on 64-bit hashes since they all get merged together in\n * the end, so we skip the extra step.\n *\n * Both XXH3_64bits and XXH3_128bits use this subroutine.\n */\n\n#if (XXH_VECTOR == XXH_AVX512) \\\n     || (defined(XXH_DISPATCH_AVX512) && XXH_DISPATCH_AVX512 != 0)\n\n#ifndef XXH_TARGET_AVX512\n# define XXH_TARGET_AVX512  /* disable attribute target */\n#endif\n\nXXH_FORCE_INLINE XXH_TARGET_AVX512 void\nXXH3_accumulate_512_avx512(void* XXH_RESTRICT acc,\n                     const void* XXH_RESTRICT input,\n                     const void* XXH_RESTRICT secret)\n{\n    __m512i* const xacc = (__m512i *) acc;\n    XXH_ASSERT((((size_t)acc) & 63) == 0);\n    XXH_STATIC_ASSERT(XXH_STRIPE_LEN == sizeof(__m512i));\n\n    {\n        /* data_vec    = input[0]; */\n        __m512i const data_vec    = _mm512_loadu_si512   (input);\n        /* key_vec     = secret[0]; */\n        __m512i const key_vec     = _mm512_loadu_si512   (secret);\n        /* data_key    = data_vec ^ key_vec; */\n        __m512i const data_key    = _mm512_xor_si512     (data_vec, key_vec);\n        /* data_key_lo = data_key >> 32; */\n        __m512i const data_key_lo = _mm512_srli_epi64 (data_key, 32);\n        /* product     = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */\n        __m512i const product     = _mm512_mul_epu32     (data_key, data_key_lo);\n        /* xacc[0] += swap(data_vec); */\n        __m512i const data_swap = _mm512_shuffle_epi32(data_vec, (_MM_PERM_ENUM)_MM_SHUFFLE(1, 0, 3, 2));\n        __m512i const sum       = _mm512_add_epi64(*xacc, data_swap);\n        /* xacc[0] += product; */\n        *xacc = _mm512_add_epi64(product, sum);\n    }\n}\nXXH_FORCE_INLINE XXH_TARGET_AVX512 XXH3_ACCUMULATE_TEMPLATE(avx512)\n\n/*\n * XXH3_scrambleAcc: Scrambles the accumulators to improve mixing.\n *\n * Multiplication isn't perfect, as explained by Google in HighwayHash:\n *\n *  // Multiplication mixes/scrambles bytes 0-7 of the 64-bit result to\n *  // varying degrees. In descending order of goodness, bytes\n *  // 3 4 2 5 1 6 0 7 have quality 228 224 164 160 100 96 36 32.\n *  // As expected, the upper and lower bytes are much worse.\n *\n * Source: https://github.com/google/highwayhash/blob/0aaf66b/highwayhash/hh_avx2.h#L291\n *\n * Since our algorithm uses a pseudorandom secret to add some variance into the\n * mix, we don't need to (or want to) mix as often or as much as HighwayHash does.\n *\n * This isn't as tight as XXH3_accumulate, but still written in SIMD to avoid\n * extraction.\n *\n * Both XXH3_64bits and XXH3_128bits use this subroutine.\n */\n\nXXH_FORCE_INLINE XXH_TARGET_AVX512 void\nXXH3_scrambleAcc_avx512(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)\n{\n    XXH_ASSERT((((size_t)acc) & 63) == 0);\n    XXH_STATIC_ASSERT(XXH_STRIPE_LEN == sizeof(__m512i));\n    {   __m512i* const xacc = (__m512i*) acc;\n        const __m512i prime32 = _mm512_set1_epi32((int)XXH_PRIME32_1);\n\n        /* xacc[0] ^= (xacc[0] >> 47) */\n        __m512i const acc_vec     = *xacc;\n        __m512i const shifted     = _mm512_srli_epi64    (acc_vec, 47);\n        /* xacc[0] ^= secret; */\n        __m512i const key_vec     = _mm512_loadu_si512   (secret);\n        __m512i const data_key    = _mm512_ternarylogic_epi32(key_vec, acc_vec, shifted, 0x96 /* key_vec ^ acc_vec ^ shifted */);\n\n        /* xacc[0] *= XXH_PRIME32_1; */\n        __m512i const data_key_hi = _mm512_srli_epi64 (data_key, 32);\n        __m512i const prod_lo     = _mm512_mul_epu32     (data_key, prime32);\n        __m512i const prod_hi     = _mm512_mul_epu32     (data_key_hi, prime32);\n        *xacc = _mm512_add_epi64(prod_lo, _mm512_slli_epi64(prod_hi, 32));\n    }\n}\n\nXXH_FORCE_INLINE XXH_TARGET_AVX512 void\nXXH3_initCustomSecret_avx512(void* XXH_RESTRICT customSecret, xxh_u64 seed64)\n{\n    XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 63) == 0);\n    XXH_STATIC_ASSERT(XXH_SEC_ALIGN == 64);\n    XXH_ASSERT(((size_t)customSecret & 63) == 0);\n    (void)(&XXH_writeLE64);\n    {   int const nbRounds = XXH_SECRET_DEFAULT_SIZE / sizeof(__m512i);\n        __m512i const seed_pos = _mm512_set1_epi64((xxh_i64)seed64);\n        __m512i const seed     = _mm512_mask_sub_epi64(seed_pos, 0xAA, _mm512_set1_epi8(0), seed_pos);\n\n        const __m512i* const src  = (const __m512i*) ((const void*) XXH3_kSecret);\n              __m512i* const dest = (      __m512i*) customSecret;\n        int i;\n        XXH_ASSERT(((size_t)src & 63) == 0); /* control alignment */\n        XXH_ASSERT(((size_t)dest & 63) == 0);\n        for (i=0; i < nbRounds; ++i) {\n            dest[i] = _mm512_add_epi64(_mm512_load_si512(src + i), seed);\n    }   }\n}\n\n#endif\n\n#if (XXH_VECTOR == XXH_AVX2) \\\n    || (defined(XXH_DISPATCH_AVX2) && XXH_DISPATCH_AVX2 != 0)\n\n#ifndef XXH_TARGET_AVX2\n# define XXH_TARGET_AVX2  /* disable attribute target */\n#endif\n\nXXH_FORCE_INLINE XXH_TARGET_AVX2 void\nXXH3_accumulate_512_avx2( void* XXH_RESTRICT acc,\n                    const void* XXH_RESTRICT input,\n                    const void* XXH_RESTRICT secret)\n{\n    XXH_ASSERT((((size_t)acc) & 31) == 0);\n    {   __m256i* const xacc    =       (__m256i *) acc;\n        /* Unaligned. This is mainly for pointer arithmetic, and because\n         * _mm256_loadu_si256 requires  a const __m256i * pointer for some reason. */\n        const         __m256i* const xinput  = (const __m256i *) input;\n        /* Unaligned. This is mainly for pointer arithmetic, and because\n         * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */\n        const         __m256i* const xsecret = (const __m256i *) secret;\n\n        size_t i;\n        for (i=0; i < XXH_STRIPE_LEN/sizeof(__m256i); i++) {\n            /* data_vec    = xinput[i]; */\n            __m256i const data_vec    = _mm256_loadu_si256    (xinput+i);\n            /* key_vec     = xsecret[i]; */\n            __m256i const key_vec     = _mm256_loadu_si256   (xsecret+i);\n            /* data_key    = data_vec ^ key_vec; */\n            __m256i const data_key    = _mm256_xor_si256     (data_vec, key_vec);\n            /* data_key_lo = data_key >> 32; */\n            __m256i const data_key_lo = _mm256_srli_epi64 (data_key, 32);\n            /* product     = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */\n            __m256i const product     = _mm256_mul_epu32     (data_key, data_key_lo);\n            /* xacc[i] += swap(data_vec); */\n            __m256i const data_swap = _mm256_shuffle_epi32(data_vec, _MM_SHUFFLE(1, 0, 3, 2));\n            __m256i const sum       = _mm256_add_epi64(xacc[i], data_swap);\n            /* xacc[i] += product; */\n            xacc[i] = _mm256_add_epi64(product, sum);\n    }   }\n}\nXXH_FORCE_INLINE XXH_TARGET_AVX2 XXH3_ACCUMULATE_TEMPLATE(avx2)\n\nXXH_FORCE_INLINE XXH_TARGET_AVX2 void\nXXH3_scrambleAcc_avx2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)\n{\n    XXH_ASSERT((((size_t)acc) & 31) == 0);\n    {   __m256i* const xacc = (__m256i*) acc;\n        /* Unaligned. This is mainly for pointer arithmetic, and because\n         * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */\n        const         __m256i* const xsecret = (const __m256i *) secret;\n        const __m256i prime32 = _mm256_set1_epi32((int)XXH_PRIME32_1);\n\n        size_t i;\n        for (i=0; i < XXH_STRIPE_LEN/sizeof(__m256i); i++) {\n            /* xacc[i] ^= (xacc[i] >> 47) */\n            __m256i const acc_vec     = xacc[i];\n            __m256i const shifted     = _mm256_srli_epi64    (acc_vec, 47);\n            __m256i const data_vec    = _mm256_xor_si256     (acc_vec, shifted);\n            /* xacc[i] ^= xsecret; */\n            __m256i const key_vec     = _mm256_loadu_si256   (xsecret+i);\n            __m256i const data_key    = _mm256_xor_si256     (data_vec, key_vec);\n\n            /* xacc[i] *= XXH_PRIME32_1; */\n            __m256i const data_key_hi = _mm256_srli_epi64 (data_key, 32);\n            __m256i const prod_lo     = _mm256_mul_epu32     (data_key, prime32);\n            __m256i const prod_hi     = _mm256_mul_epu32     (data_key_hi, prime32);\n            xacc[i] = _mm256_add_epi64(prod_lo, _mm256_slli_epi64(prod_hi, 32));\n        }\n    }\n}\n\nXXH_FORCE_INLINE XXH_TARGET_AVX2 void XXH3_initCustomSecret_avx2(void* XXH_RESTRICT customSecret, xxh_u64 seed64)\n{\n    XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 31) == 0);\n    XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE / sizeof(__m256i)) == 6);\n    XXH_STATIC_ASSERT(XXH_SEC_ALIGN <= 64);\n    (void)(&XXH_writeLE64);\n    XXH_PREFETCH(customSecret);\n    {   __m256i const seed = _mm256_set_epi64x((xxh_i64)(0U - seed64), (xxh_i64)seed64, (xxh_i64)(0U - seed64), (xxh_i64)seed64);\n\n        const __m256i* const src  = (const __m256i*) ((const void*) XXH3_kSecret);\n              __m256i*       dest = (      __m256i*) customSecret;\n\n#       if defined(__GNUC__) || defined(__clang__)\n        /*\n         * On GCC & Clang, marking 'dest' as modified will cause the compiler:\n         *   - do not extract the secret from sse registers in the internal loop\n         *   - use less common registers, and avoid pushing these reg into stack\n         */\n        XXH_COMPILER_GUARD(dest);\n#       endif\n        XXH_ASSERT(((size_t)src & 31) == 0); /* control alignment */\n        XXH_ASSERT(((size_t)dest & 31) == 0);\n\n        /* GCC -O2 need unroll loop manually */\n        dest[0] = _mm256_add_epi64(_mm256_load_si256(src+0), seed);\n        dest[1] = _mm256_add_epi64(_mm256_load_si256(src+1), seed);\n        dest[2] = _mm256_add_epi64(_mm256_load_si256(src+2), seed);\n        dest[3] = _mm256_add_epi64(_mm256_load_si256(src+3), seed);\n        dest[4] = _mm256_add_epi64(_mm256_load_si256(src+4), seed);\n        dest[5] = _mm256_add_epi64(_mm256_load_si256(src+5), seed);\n    }\n}\n\n#endif\n\n/* x86dispatch always generates SSE2 */\n#if (XXH_VECTOR == XXH_SSE2) || defined(XXH_X86DISPATCH)\n\n#ifndef XXH_TARGET_SSE2\n# define XXH_TARGET_SSE2  /* disable attribute target */\n#endif\n\nXXH_FORCE_INLINE XXH_TARGET_SSE2 void\nXXH3_accumulate_512_sse2( void* XXH_RESTRICT acc,\n                    const void* XXH_RESTRICT input,\n                    const void* XXH_RESTRICT secret)\n{\n    /* SSE2 is just a half-scale version of the AVX2 version. */\n    XXH_ASSERT((((size_t)acc) & 15) == 0);\n    {   __m128i* const xacc    =       (__m128i *) acc;\n        /* Unaligned. This is mainly for pointer arithmetic, and because\n         * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */\n        const         __m128i* const xinput  = (const __m128i *) input;\n        /* Unaligned. This is mainly for pointer arithmetic, and because\n         * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */\n        const         __m128i* const xsecret = (const __m128i *) secret;\n\n        size_t i;\n        for (i=0; i < XXH_STRIPE_LEN/sizeof(__m128i); i++) {\n            /* data_vec    = xinput[i]; */\n            __m128i const data_vec    = _mm_loadu_si128   (xinput+i);\n            /* key_vec     = xsecret[i]; */\n            __m128i const key_vec     = _mm_loadu_si128   (xsecret+i);\n            /* data_key    = data_vec ^ key_vec; */\n            __m128i const data_key    = _mm_xor_si128     (data_vec, key_vec);\n            /* data_key_lo = data_key >> 32; */\n            __m128i const data_key_lo = _mm_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1));\n            /* product     = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */\n            __m128i const product     = _mm_mul_epu32     (data_key, data_key_lo);\n            /* xacc[i] += swap(data_vec); */\n            __m128i const data_swap = _mm_shuffle_epi32(data_vec, _MM_SHUFFLE(1,0,3,2));\n            __m128i const sum       = _mm_add_epi64(xacc[i], data_swap);\n            /* xacc[i] += product; */\n            xacc[i] = _mm_add_epi64(product, sum);\n    }   }\n}\nXXH_FORCE_INLINE XXH_TARGET_SSE2 XXH3_ACCUMULATE_TEMPLATE(sse2)\n\nXXH_FORCE_INLINE XXH_TARGET_SSE2 void\nXXH3_scrambleAcc_sse2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)\n{\n    XXH_ASSERT((((size_t)acc) & 15) == 0);\n    {   __m128i* const xacc = (__m128i*) acc;\n        /* Unaligned. This is mainly for pointer arithmetic, and because\n         * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */\n        const         __m128i* const xsecret = (const __m128i *) secret;\n        const __m128i prime32 = _mm_set1_epi32((int)XXH_PRIME32_1);\n\n        size_t i;\n        for (i=0; i < XXH_STRIPE_LEN/sizeof(__m128i); i++) {\n            /* xacc[i] ^= (xacc[i] >> 47) */\n            __m128i const acc_vec     = xacc[i];\n            __m128i const shifted     = _mm_srli_epi64    (acc_vec, 47);\n            __m128i const data_vec    = _mm_xor_si128     (acc_vec, shifted);\n            /* xacc[i] ^= xsecret[i]; */\n            __m128i const key_vec     = _mm_loadu_si128   (xsecret+i);\n            __m128i const data_key    = _mm_xor_si128     (data_vec, key_vec);\n\n            /* xacc[i] *= XXH_PRIME32_1; */\n            __m128i const data_key_hi = _mm_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1));\n            __m128i const prod_lo     = _mm_mul_epu32     (data_key, prime32);\n            __m128i const prod_hi     = _mm_mul_epu32     (data_key_hi, prime32);\n            xacc[i] = _mm_add_epi64(prod_lo, _mm_slli_epi64(prod_hi, 32));\n        }\n    }\n}\n\nXXH_FORCE_INLINE XXH_TARGET_SSE2 void XXH3_initCustomSecret_sse2(void* XXH_RESTRICT customSecret, xxh_u64 seed64)\n{\n    XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 15) == 0);\n    (void)(&XXH_writeLE64);\n    {   int const nbRounds = XXH_SECRET_DEFAULT_SIZE / sizeof(__m128i);\n\n#       if defined(_MSC_VER) && defined(_M_IX86) && _MSC_VER < 1900\n        /* MSVC 32bit mode does not support _mm_set_epi64x before 2015 */\n        XXH_ALIGN(16) const xxh_i64 seed64x2[2] = { (xxh_i64)seed64, (xxh_i64)(0U - seed64) };\n        __m128i const seed = _mm_load_si128((__m128i const*)seed64x2);\n#       else\n        __m128i const seed = _mm_set_epi64x((xxh_i64)(0U - seed64), (xxh_i64)seed64);\n#       endif\n        int i;\n\n        const void* const src16 = XXH3_kSecret;\n        __m128i* dst16 = (__m128i*) customSecret;\n#       if defined(__GNUC__) || defined(__clang__)\n        /*\n         * On GCC & Clang, marking 'dest' as modified will cause the compiler:\n         *   - do not extract the secret from sse registers in the internal loop\n         *   - use less common registers, and avoid pushing these reg into stack\n         */\n        XXH_COMPILER_GUARD(dst16);\n#       endif\n        XXH_ASSERT(((size_t)src16 & 15) == 0); /* control alignment */\n        XXH_ASSERT(((size_t)dst16 & 15) == 0);\n\n        for (i=0; i < nbRounds; ++i) {\n            dst16[i] = _mm_add_epi64(_mm_load_si128((const __m128i *)src16+i), seed);\n    }   }\n}\n\n#endif\n\n#if (XXH_VECTOR == XXH_NEON)\n\n/* forward declarations for the scalar routines */\nXXH_FORCE_INLINE void\nXXH3_scalarRound(void* XXH_RESTRICT acc, void const* XXH_RESTRICT input,\n                 void const* XXH_RESTRICT secret, size_t lane);\n\nXXH_FORCE_INLINE void\nXXH3_scalarScrambleRound(void* XXH_RESTRICT acc,\n                         void const* XXH_RESTRICT secret, size_t lane);\n\n/*!\n * @internal\n * @brief The bulk processing loop for NEON and WASM SIMD128.\n *\n * The NEON code path is actually partially scalar when running on AArch64. This\n * is to optimize the pipelining and can have up to 15% speedup depending on the\n * CPU, and it also mitigates some GCC codegen issues.\n *\n * @see XXH3_NEON_LANES for configuring this and details about this optimization.\n *\n * NEON's 32-bit to 64-bit long multiply takes a half vector of 32-bit\n * integers instead of the other platforms which mask full 64-bit vectors,\n * so the setup is more complicated than just shifting right.\n *\n * Additionally, there is an optimization for 4 lanes at once noted below.\n *\n * Since, as stated, the most optimal amount of lanes for Cortexes is 6,\n * there needs to be *three* versions of the accumulate operation used\n * for the remaining 2 lanes.\n *\n * WASM's SIMD128 uses SIMDe's arm_neon.h polyfill because the intrinsics overlap\n * nearly perfectly.\n */\n\nXXH_FORCE_INLINE void\nXXH3_accumulate_512_neon( void* XXH_RESTRICT acc,\n                    const void* XXH_RESTRICT input,\n                    const void* XXH_RESTRICT secret)\n{\n    XXH_ASSERT((((size_t)acc) & 15) == 0);\n    XXH_STATIC_ASSERT(XXH3_NEON_LANES > 0 && XXH3_NEON_LANES <= XXH_ACC_NB && XXH3_NEON_LANES % 2 == 0);\n    {   /* GCC for darwin arm64 does not like aliasing here */\n        xxh_aliasing_uint64x2_t* const xacc = (xxh_aliasing_uint64x2_t*) acc;\n        /* We don't use a uint32x4_t pointer because it causes bus errors on ARMv7. */\n        uint8_t const* xinput = (const uint8_t *) input;\n        uint8_t const* xsecret  = (const uint8_t *) secret;\n\n        size_t i;\n#ifdef __wasm_simd128__\n        /*\n         * On WASM SIMD128, Clang emits direct address loads when XXH3_kSecret\n         * is constant propagated, which results in it converting it to this\n         * inside the loop:\n         *\n         *    a = v128.load(XXH3_kSecret +  0 + $secret_offset, offset = 0)\n         *    b = v128.load(XXH3_kSecret + 16 + $secret_offset, offset = 0)\n         *    ...\n         *\n         * This requires a full 32-bit address immediate (and therefore a 6 byte\n         * instruction) as well as an add for each offset.\n         *\n         * Putting an asm guard prevents it from folding (at the cost of losing\n         * the alignment hint), and uses the free offset in `v128.load` instead\n         * of adding secret_offset each time which overall reduces code size by\n         * about a kilobyte and improves performance.\n         */\n        XXH_COMPILER_GUARD(xsecret);\n#endif\n        /* Scalar lanes use the normal scalarRound routine */\n        for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) {\n            XXH3_scalarRound(acc, input, secret, i);\n        }\n        i = 0;\n        /* 4 NEON lanes at a time. */\n        for (; i+1 < XXH3_NEON_LANES / 2; i+=2) {\n            /* data_vec = xinput[i]; */\n            uint64x2_t data_vec_1 = XXH_vld1q_u64(xinput  + (i * 16));\n            uint64x2_t data_vec_2 = XXH_vld1q_u64(xinput  + ((i+1) * 16));\n            /* key_vec  = xsecret[i];  */\n            uint64x2_t key_vec_1  = XXH_vld1q_u64(xsecret + (i * 16));\n            uint64x2_t key_vec_2  = XXH_vld1q_u64(xsecret + ((i+1) * 16));\n            /* data_swap = swap(data_vec) */\n            uint64x2_t data_swap_1 = vextq_u64(data_vec_1, data_vec_1, 1);\n            uint64x2_t data_swap_2 = vextq_u64(data_vec_2, data_vec_2, 1);\n            /* data_key = data_vec ^ key_vec; */\n            uint64x2_t data_key_1 = veorq_u64(data_vec_1, key_vec_1);\n            uint64x2_t data_key_2 = veorq_u64(data_vec_2, key_vec_2);\n\n            /*\n             * If we reinterpret the 64x2 vectors as 32x4 vectors, we can use a\n             * de-interleave operation for 4 lanes in 1 step with `vuzpq_u32` to\n             * get one vector with the low 32 bits of each lane, and one vector\n             * with the high 32 bits of each lane.\n             *\n             * The intrinsic returns a double vector because the original ARMv7-a\n             * instruction modified both arguments in place. AArch64 and SIMD128 emit\n             * two instructions from this intrinsic.\n             *\n             *  [ dk11L | dk11H | dk12L | dk12H ] -> [ dk11L | dk12L | dk21L | dk22L ]\n             *  [ dk21L | dk21H | dk22L | dk22H ] -> [ dk11H | dk12H | dk21H | dk22H ]\n             */\n            uint32x4x2_t unzipped = vuzpq_u32(\n                vreinterpretq_u32_u64(data_key_1),\n                vreinterpretq_u32_u64(data_key_2)\n            );\n            /* data_key_lo = data_key & 0xFFFFFFFF */\n            uint32x4_t data_key_lo = unzipped.val[0];\n            /* data_key_hi = data_key >> 32 */\n            uint32x4_t data_key_hi = unzipped.val[1];\n            /*\n             * Then, we can split the vectors horizontally and multiply which, as for most\n             * widening intrinsics, have a variant that works on both high half vectors\n             * for free on AArch64. A similar instruction is available on SIMD128.\n             *\n             * sum = data_swap + (u64x2) data_key_lo * (u64x2) data_key_hi\n             */\n            uint64x2_t sum_1 = XXH_vmlal_low_u32(data_swap_1, data_key_lo, data_key_hi);\n            uint64x2_t sum_2 = XXH_vmlal_high_u32(data_swap_2, data_key_lo, data_key_hi);\n            /*\n             * Clang reorders\n             *    a += b * c;     // umlal   swap.2d, dkl.2s, dkh.2s\n             *    c += a;         // add     acc.2d, acc.2d, swap.2d\n             * to\n             *    c += a;         // add     acc.2d, acc.2d, swap.2d\n             *    c += b * c;     // umlal   acc.2d, dkl.2s, dkh.2s\n             *\n             * While it would make sense in theory since the addition is faster,\n             * for reasons likely related to umlal being limited to certain NEON\n             * pipelines, this is worse. A compiler guard fixes this.\n             */\n            XXH_COMPILER_GUARD_CLANG_NEON(sum_1);\n            XXH_COMPILER_GUARD_CLANG_NEON(sum_2);\n            /* xacc[i] = acc_vec + sum; */\n            xacc[i]   = vaddq_u64(xacc[i], sum_1);\n            xacc[i+1] = vaddq_u64(xacc[i+1], sum_2);\n        }\n        /* Operate on the remaining NEON lanes 2 at a time. */\n        for (; i < XXH3_NEON_LANES / 2; i++) {\n            /* data_vec = xinput[i]; */\n            uint64x2_t data_vec = XXH_vld1q_u64(xinput  + (i * 16));\n            /* key_vec  = xsecret[i];  */\n            uint64x2_t key_vec  = XXH_vld1q_u64(xsecret + (i * 16));\n            /* acc_vec_2 = swap(data_vec) */\n            uint64x2_t data_swap = vextq_u64(data_vec, data_vec, 1);\n            /* data_key = data_vec ^ key_vec; */\n            uint64x2_t data_key = veorq_u64(data_vec, key_vec);\n            /* For two lanes, just use VMOVN and VSHRN. */\n            /* data_key_lo = data_key & 0xFFFFFFFF; */\n            uint32x2_t data_key_lo = vmovn_u64(data_key);\n            /* data_key_hi = data_key >> 32; */\n            uint32x2_t data_key_hi = vshrn_n_u64(data_key, 32);\n            /* sum = data_swap + (u64x2) data_key_lo * (u64x2) data_key_hi; */\n            uint64x2_t sum = vmlal_u32(data_swap, data_key_lo, data_key_hi);\n            /* Same Clang workaround as before */\n            XXH_COMPILER_GUARD_CLANG_NEON(sum);\n            /* xacc[i] = acc_vec + sum; */\n            xacc[i] = vaddq_u64 (xacc[i], sum);\n        }\n    }\n}\nXXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(neon)\n\nXXH_FORCE_INLINE void\nXXH3_scrambleAcc_neon(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)\n{\n    XXH_ASSERT((((size_t)acc) & 15) == 0);\n\n    {   xxh_aliasing_uint64x2_t* xacc       = (xxh_aliasing_uint64x2_t*) acc;\n        uint8_t const* xsecret = (uint8_t const*) secret;\n\n        size_t i;\n        /* WASM uses operator overloads and doesn't need these. */\n#ifndef __wasm_simd128__\n        /* { prime32_1, prime32_1 } */\n        uint32x2_t const kPrimeLo = vdup_n_u32(XXH_PRIME32_1);\n        /* { 0, prime32_1, 0, prime32_1 } */\n        uint32x4_t const kPrimeHi = vreinterpretq_u32_u64(vdupq_n_u64((xxh_u64)XXH_PRIME32_1 << 32));\n#endif\n\n        /* AArch64 uses both scalar and neon at the same time */\n        for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) {\n            XXH3_scalarScrambleRound(acc, secret, i);\n        }\n        for (i=0; i < XXH3_NEON_LANES / 2; i++) {\n            /* xacc[i] ^= (xacc[i] >> 47); */\n            uint64x2_t acc_vec  = xacc[i];\n            uint64x2_t shifted  = vshrq_n_u64(acc_vec, 47);\n            uint64x2_t data_vec = veorq_u64(acc_vec, shifted);\n\n            /* xacc[i] ^= xsecret[i]; */\n            uint64x2_t key_vec  = XXH_vld1q_u64(xsecret + (i * 16));\n            uint64x2_t data_key = veorq_u64(data_vec, key_vec);\n            /* xacc[i] *= XXH_PRIME32_1 */\n#ifdef __wasm_simd128__\n            /* SIMD128 has multiply by u64x2, use it instead of expanding and scalarizing */\n            xacc[i] = data_key * XXH_PRIME32_1;\n#else\n            /*\n             * Expanded version with portable NEON intrinsics\n             *\n             *    lo(x) * lo(y) + (hi(x) * lo(y) << 32)\n             *\n             * prod_hi = hi(data_key) * lo(prime) << 32\n             *\n             * Since we only need 32 bits of this multiply a trick can be used, reinterpreting the vector\n             * as a uint32x4_t and multiplying by { 0, prime, 0, prime } to cancel out the unwanted bits\n             * and avoid the shift.\n             */\n            uint32x4_t prod_hi = vmulq_u32 (vreinterpretq_u32_u64(data_key), kPrimeHi);\n            /* Extract low bits for vmlal_u32  */\n            uint32x2_t data_key_lo = vmovn_u64(data_key);\n            /* xacc[i] = prod_hi + lo(data_key) * XXH_PRIME32_1; */\n            xacc[i] = vmlal_u32(vreinterpretq_u64_u32(prod_hi), data_key_lo, kPrimeLo);\n#endif\n        }\n    }\n}\n#endif\n\n#if (XXH_VECTOR == XXH_VSX)\n\nXXH_FORCE_INLINE void\nXXH3_accumulate_512_vsx(  void* XXH_RESTRICT acc,\n                    const void* XXH_RESTRICT input,\n                    const void* XXH_RESTRICT secret)\n{\n    /* presumed aligned */\n    xxh_aliasing_u64x2* const xacc = (xxh_aliasing_u64x2*) acc;\n    xxh_u8 const* const xinput   = (xxh_u8 const*) input;   /* no alignment restriction */\n    xxh_u8 const* const xsecret  = (xxh_u8 const*) secret;    /* no alignment restriction */\n    xxh_u64x2 const v32 = { 32, 32 };\n    size_t i;\n    for (i = 0; i < XXH_STRIPE_LEN / sizeof(xxh_u64x2); i++) {\n        /* data_vec = xinput[i]; */\n        xxh_u64x2 const data_vec = XXH_vec_loadu(xinput + 16*i);\n        /* key_vec = xsecret[i]; */\n        xxh_u64x2 const key_vec  = XXH_vec_loadu(xsecret + 16*i);\n        xxh_u64x2 const data_key = data_vec ^ key_vec;\n        /* shuffled = (data_key << 32) | (data_key >> 32); */\n        xxh_u32x4 const shuffled = (xxh_u32x4)vec_rl(data_key, v32);\n        /* product = ((xxh_u64x2)data_key & 0xFFFFFFFF) * ((xxh_u64x2)shuffled & 0xFFFFFFFF); */\n        xxh_u64x2 const product  = XXH_vec_mulo((xxh_u32x4)data_key, shuffled);\n        /* acc_vec = xacc[i]; */\n        xxh_u64x2 acc_vec        = xacc[i];\n        acc_vec += product;\n\n        /* swap high and low halves */\n#ifdef __s390x__\n        acc_vec += vec_permi(data_vec, data_vec, 2);\n#else\n        acc_vec += vec_xxpermdi(data_vec, data_vec, 2);\n#endif\n        xacc[i] = acc_vec;\n    }\n}\nXXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(vsx)\n\nXXH_FORCE_INLINE void\nXXH3_scrambleAcc_vsx(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)\n{\n    XXH_ASSERT((((size_t)acc) & 15) == 0);\n\n    {   xxh_aliasing_u64x2* const xacc = (xxh_aliasing_u64x2*) acc;\n        const xxh_u8* const xsecret = (const xxh_u8*) secret;\n        /* constants */\n        xxh_u64x2 const v32  = { 32, 32 };\n        xxh_u64x2 const v47 = { 47, 47 };\n        xxh_u32x4 const prime = { XXH_PRIME32_1, XXH_PRIME32_1, XXH_PRIME32_1, XXH_PRIME32_1 };\n        size_t i;\n        for (i = 0; i < XXH_STRIPE_LEN / sizeof(xxh_u64x2); i++) {\n            /* xacc[i] ^= (xacc[i] >> 47); */\n            xxh_u64x2 const acc_vec  = xacc[i];\n            xxh_u64x2 const data_vec = acc_vec ^ (acc_vec >> v47);\n\n            /* xacc[i] ^= xsecret[i]; */\n            xxh_u64x2 const key_vec  = XXH_vec_loadu(xsecret + 16*i);\n            xxh_u64x2 const data_key = data_vec ^ key_vec;\n\n            /* xacc[i] *= XXH_PRIME32_1 */\n            /* prod_lo = ((xxh_u64x2)data_key & 0xFFFFFFFF) * ((xxh_u64x2)prime & 0xFFFFFFFF);  */\n            xxh_u64x2 const prod_even  = XXH_vec_mule((xxh_u32x4)data_key, prime);\n            /* prod_hi = ((xxh_u64x2)data_key >> 32) * ((xxh_u64x2)prime >> 32);  */\n            xxh_u64x2 const prod_odd  = XXH_vec_mulo((xxh_u32x4)data_key, prime);\n            xacc[i] = prod_odd + (prod_even << v32);\n    }   }\n}\n\n#endif\n\n#if (XXH_VECTOR == XXH_SVE)\n\nXXH_FORCE_INLINE void\nXXH3_accumulate_512_sve( void* XXH_RESTRICT acc,\n                   const void* XXH_RESTRICT input,\n                   const void* XXH_RESTRICT secret)\n{\n    uint64_t *xacc = (uint64_t *)acc;\n    const uint64_t *xinput = (const uint64_t *)(const void *)input;\n    const uint64_t *xsecret = (const uint64_t *)(const void *)secret;\n    svuint64_t kSwap = sveor_n_u64_z(svptrue_b64(), svindex_u64(0, 1), 1);\n    uint64_t element_count = svcntd();\n    if (element_count >= 8) {\n        svbool_t mask = svptrue_pat_b64(SV_VL8);\n        svuint64_t vacc = svld1_u64(mask, xacc);\n        ACCRND(vacc, 0);\n        svst1_u64(mask, xacc, vacc);\n    } else if (element_count == 2) {   /* sve128 */\n        svbool_t mask = svptrue_pat_b64(SV_VL2);\n        svuint64_t acc0 = svld1_u64(mask, xacc + 0);\n        svuint64_t acc1 = svld1_u64(mask, xacc + 2);\n        svuint64_t acc2 = svld1_u64(mask, xacc + 4);\n        svuint64_t acc3 = svld1_u64(mask, xacc + 6);\n        ACCRND(acc0, 0);\n        ACCRND(acc1, 2);\n        ACCRND(acc2, 4);\n        ACCRND(acc3, 6);\n        svst1_u64(mask, xacc + 0, acc0);\n        svst1_u64(mask, xacc + 2, acc1);\n        svst1_u64(mask, xacc + 4, acc2);\n        svst1_u64(mask, xacc + 6, acc3);\n    } else {\n        svbool_t mask = svptrue_pat_b64(SV_VL4);\n        svuint64_t acc0 = svld1_u64(mask, xacc + 0);\n        svuint64_t acc1 = svld1_u64(mask, xacc + 4);\n        ACCRND(acc0, 0);\n        ACCRND(acc1, 4);\n        svst1_u64(mask, xacc + 0, acc0);\n        svst1_u64(mask, xacc + 4, acc1);\n    }\n}\n\nXXH_FORCE_INLINE void\nXXH3_accumulate_sve(xxh_u64* XXH_RESTRICT acc,\n               const xxh_u8* XXH_RESTRICT input,\n               const xxh_u8* XXH_RESTRICT secret,\n               size_t nbStripes)\n{\n    if (nbStripes != 0) {\n        uint64_t *xacc = (uint64_t *)acc;\n        const uint64_t *xinput = (const uint64_t *)(const void *)input;\n        const uint64_t *xsecret = (const uint64_t *)(const void *)secret;\n        svuint64_t kSwap = sveor_n_u64_z(svptrue_b64(), svindex_u64(0, 1), 1);\n        uint64_t element_count = svcntd();\n        if (element_count >= 8) {\n            svbool_t mask = svptrue_pat_b64(SV_VL8);\n            svuint64_t vacc = svld1_u64(mask, xacc + 0);\n            do {\n                /* svprfd(svbool_t, void *, enum svfprop); */\n                svprfd(mask, xinput + 128, SV_PLDL1STRM);\n                ACCRND(vacc, 0);\n                xinput += 8;\n                xsecret += 1;\n                nbStripes--;\n           } while (nbStripes != 0);\n\n           svst1_u64(mask, xacc + 0, vacc);\n        } else if (element_count == 2) { /* sve128 */\n            svbool_t mask = svptrue_pat_b64(SV_VL2);\n            svuint64_t acc0 = svld1_u64(mask, xacc + 0);\n            svuint64_t acc1 = svld1_u64(mask, xacc + 2);\n            svuint64_t acc2 = svld1_u64(mask, xacc + 4);\n            svuint64_t acc3 = svld1_u64(mask, xacc + 6);\n            do {\n                svprfd(mask, xinput + 128, SV_PLDL1STRM);\n                ACCRND(acc0, 0);\n                ACCRND(acc1, 2);\n                ACCRND(acc2, 4);\n                ACCRND(acc3, 6);\n                xinput += 8;\n                xsecret += 1;\n                nbStripes--;\n           } while (nbStripes != 0);\n\n           svst1_u64(mask, xacc + 0, acc0);\n           svst1_u64(mask, xacc + 2, acc1);\n           svst1_u64(mask, xacc + 4, acc2);\n           svst1_u64(mask, xacc + 6, acc3);\n        } else {\n            svbool_t mask = svptrue_pat_b64(SV_VL4);\n            svuint64_t acc0 = svld1_u64(mask, xacc + 0);\n            svuint64_t acc1 = svld1_u64(mask, xacc + 4);\n            do {\n                svprfd(mask, xinput + 128, SV_PLDL1STRM);\n                ACCRND(acc0, 0);\n                ACCRND(acc1, 4);\n                xinput += 8;\n                xsecret += 1;\n                nbStripes--;\n           } while (nbStripes != 0);\n\n           svst1_u64(mask, xacc + 0, acc0);\n           svst1_u64(mask, xacc + 4, acc1);\n       }\n    }\n}\n\n#endif\n\n/* scalar variants - universal */\n\n#if defined(__aarch64__) && (defined(__GNUC__) || defined(__clang__))\n/*\n * In XXH3_scalarRound(), GCC and Clang have a similar codegen issue, where they\n * emit an excess mask and a full 64-bit multiply-add (MADD X-form).\n *\n * While this might not seem like much, as AArch64 is a 64-bit architecture, only\n * big Cortex designs have a full 64-bit multiplier.\n *\n * On the little cores, the smaller 32-bit multiplier is used, and full 64-bit\n * multiplies expand to 2-3 multiplies in microcode. This has a major penalty\n * of up to 4 latency cycles and 2 stall cycles in the multiply pipeline.\n *\n * Thankfully, AArch64 still provides the 32-bit long multiply-add (UMADDL) which does\n * not have this penalty and does the mask automatically.\n */\nXXH_FORCE_INLINE xxh_u64\nXXH_mult32to64_add64(xxh_u64 lhs, xxh_u64 rhs, xxh_u64 acc)\n{\n    xxh_u64 ret;\n    /* note: %x = 64-bit register, %w = 32-bit register */\n    __asm__(\"umaddl %x0, %w1, %w2, %x3\" : \"=r\" (ret) : \"r\" (lhs), \"r\" (rhs), \"r\" (acc));\n    return ret;\n}\n#else\nXXH_FORCE_INLINE xxh_u64\nXXH_mult32to64_add64(xxh_u64 lhs, xxh_u64 rhs, xxh_u64 acc)\n{\n    return XXH_mult32to64((xxh_u32)lhs, (xxh_u32)rhs) + acc;\n}\n#endif\n\n/*!\n * @internal\n * @brief Scalar round for @ref XXH3_accumulate_512_scalar().\n *\n * This is extracted to its own function because the NEON path uses a combination\n * of NEON and scalar.\n */\nXXH_FORCE_INLINE void\nXXH3_scalarRound(void* XXH_RESTRICT acc,\n                 void const* XXH_RESTRICT input,\n                 void const* XXH_RESTRICT secret,\n                 size_t lane)\n{\n    xxh_u64* xacc = (xxh_u64*) acc;\n    xxh_u8 const* xinput  = (xxh_u8 const*) input;\n    xxh_u8 const* xsecret = (xxh_u8 const*) secret;\n    XXH_ASSERT(lane < XXH_ACC_NB);\n    XXH_ASSERT(((size_t)acc & (XXH_ACC_ALIGN-1)) == 0);\n    {\n        xxh_u64 const data_val = XXH_readLE64(xinput + lane * 8);\n        xxh_u64 const data_key = data_val ^ XXH_readLE64(xsecret + lane * 8);\n        xacc[lane ^ 1] += data_val; /* swap adjacent lanes */\n        xacc[lane] = XXH_mult32to64_add64(data_key /* & 0xFFFFFFFF */, data_key >> 32, xacc[lane]);\n    }\n}\n\n/*!\n * @internal\n * @brief Processes a 64 byte block of data using the scalar path.\n */\nXXH_FORCE_INLINE void\nXXH3_accumulate_512_scalar(void* XXH_RESTRICT acc,\n                     const void* XXH_RESTRICT input,\n                     const void* XXH_RESTRICT secret)\n{\n    size_t i;\n    /* ARM GCC refuses to unroll this loop, resulting in a 24% slowdown on ARMv6. */\n#if defined(__GNUC__) && !defined(__clang__) \\\n  && (defined(__arm__) || defined(__thumb2__)) \\\n  && defined(__ARM_FEATURE_UNALIGNED) /* no unaligned access just wastes bytes */ \\\n  && XXH_SIZE_OPT <= 0\n#  pragma GCC unroll 8\n#endif\n    for (i=0; i < XXH_ACC_NB; i++) {\n        XXH3_scalarRound(acc, input, secret, i);\n    }\n}\nXXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(scalar)\n\n/*!\n * @internal\n * @brief Scalar scramble step for @ref XXH3_scrambleAcc_scalar().\n *\n * This is extracted to its own function because the NEON path uses a combination\n * of NEON and scalar.\n */\nXXH_FORCE_INLINE void\nXXH3_scalarScrambleRound(void* XXH_RESTRICT acc,\n                         void const* XXH_RESTRICT secret,\n                         size_t lane)\n{\n    xxh_u64* const xacc = (xxh_u64*) acc;   /* presumed aligned */\n    const xxh_u8* const xsecret = (const xxh_u8*) secret;   /* no alignment restriction */\n    XXH_ASSERT((((size_t)acc) & (XXH_ACC_ALIGN-1)) == 0);\n    XXH_ASSERT(lane < XXH_ACC_NB);\n    {\n        xxh_u64 const key64 = XXH_readLE64(xsecret + lane * 8);\n        xxh_u64 acc64 = xacc[lane];\n        acc64 = XXH_xorshift64(acc64, 47);\n        acc64 ^= key64;\n        acc64 *= XXH_PRIME32_1;\n        xacc[lane] = acc64;\n    }\n}\n\n/*!\n * @internal\n * @brief Scrambles the accumulators after a large chunk has been read\n */\nXXH_FORCE_INLINE void\nXXH3_scrambleAcc_scalar(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)\n{\n    size_t i;\n    for (i=0; i < XXH_ACC_NB; i++) {\n        XXH3_scalarScrambleRound(acc, secret, i);\n    }\n}\n\nXXH_FORCE_INLINE void\nXXH3_initCustomSecret_scalar(void* XXH_RESTRICT customSecret, xxh_u64 seed64)\n{\n    /*\n     * We need a separate pointer for the hack below,\n     * which requires a non-const pointer.\n     * Any decent compiler will optimize this out otherwise.\n     */\n    const xxh_u8* kSecretPtr = XXH3_kSecret;\n    XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 15) == 0);\n\n#if defined(__GNUC__) && defined(__aarch64__)\n    /*\n     * UGLY HACK:\n     * GCC and Clang generate a bunch of MOV/MOVK pairs for aarch64, and they are\n     * placed sequentially, in order, at the top of the unrolled loop.\n     *\n     * While MOVK is great for generating constants (2 cycles for a 64-bit\n     * constant compared to 4 cycles for LDR), it fights for bandwidth with\n     * the arithmetic instructions.\n     *\n     *   I   L   S\n     * MOVK\n     * MOVK\n     * MOVK\n     * MOVK\n     * ADD\n     * SUB      STR\n     *          STR\n     * By forcing loads from memory (as the asm line causes the compiler to assume\n     * that XXH3_kSecretPtr has been changed), the pipelines are used more\n     * efficiently:\n     *   I   L   S\n     *      LDR\n     *  ADD LDR\n     *  SUB     STR\n     *          STR\n     *\n     * See XXH3_NEON_LANES for details on the pipsline.\n     *\n     * XXH3_64bits_withSeed, len == 256, Snapdragon 835\n     *   without hack: 2654.4 MB/s\n     *   with hack:    3202.9 MB/s\n     */\n    XXH_COMPILER_GUARD(kSecretPtr);\n#endif\n    {   int const nbRounds = XXH_SECRET_DEFAULT_SIZE / 16;\n        int i;\n        for (i=0; i < nbRounds; i++) {\n            /*\n             * The asm hack causes the compiler to assume that kSecretPtr aliases with\n             * customSecret, and on aarch64, this prevented LDP from merging two\n             * loads together for free. Putting the loads together before the stores\n             * properly generates LDP.\n             */\n            xxh_u64 lo = XXH_readLE64(kSecretPtr + 16*i)     + seed64;\n            xxh_u64 hi = XXH_readLE64(kSecretPtr + 16*i + 8) - seed64;\n            XXH_writeLE64((xxh_u8*)customSecret + 16*i,     lo);\n            XXH_writeLE64((xxh_u8*)customSecret + 16*i + 8, hi);\n    }   }\n}\n\n\ntypedef void (*XXH3_f_accumulate)(xxh_u64* XXH_RESTRICT, const xxh_u8* XXH_RESTRICT, const xxh_u8* XXH_RESTRICT, size_t);\ntypedef void (*XXH3_f_scrambleAcc)(void* XXH_RESTRICT, const void*);\ntypedef void (*XXH3_f_initCustomSecret)(void* XXH_RESTRICT, xxh_u64);\n\n\n#if (XXH_VECTOR == XXH_AVX512)\n\n#define XXH3_accumulate_512 XXH3_accumulate_512_avx512\n#define XXH3_accumulate     XXH3_accumulate_avx512\n#define XXH3_scrambleAcc    XXH3_scrambleAcc_avx512\n#define XXH3_initCustomSecret XXH3_initCustomSecret_avx512\n\n#elif (XXH_VECTOR == XXH_AVX2)\n\n#define XXH3_accumulate_512 XXH3_accumulate_512_avx2\n#define XXH3_accumulate     XXH3_accumulate_avx2\n#define XXH3_scrambleAcc    XXH3_scrambleAcc_avx2\n#define XXH3_initCustomSecret XXH3_initCustomSecret_avx2\n\n#elif (XXH_VECTOR == XXH_SSE2)\n\n#define XXH3_accumulate_512 XXH3_accumulate_512_sse2\n#define XXH3_accumulate     XXH3_accumulate_sse2\n#define XXH3_scrambleAcc    XXH3_scrambleAcc_sse2\n#define XXH3_initCustomSecret XXH3_initCustomSecret_sse2\n\n#elif (XXH_VECTOR == XXH_NEON)\n\n#define XXH3_accumulate_512 XXH3_accumulate_512_neon\n#define XXH3_accumulate     XXH3_accumulate_neon\n#define XXH3_scrambleAcc    XXH3_scrambleAcc_neon\n#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar\n\n#elif (XXH_VECTOR == XXH_VSX)\n\n#define XXH3_accumulate_512 XXH3_accumulate_512_vsx\n#define XXH3_accumulate     XXH3_accumulate_vsx\n#define XXH3_scrambleAcc    XXH3_scrambleAcc_vsx\n#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar\n\n#elif (XXH_VECTOR == XXH_SVE)\n#define XXH3_accumulate_512 XXH3_accumulate_512_sve\n#define XXH3_accumulate     XXH3_accumulate_sve\n#define XXH3_scrambleAcc    XXH3_scrambleAcc_scalar\n#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar\n\n#else /* scalar */\n\n#define XXH3_accumulate_512 XXH3_accumulate_512_scalar\n#define XXH3_accumulate     XXH3_accumulate_scalar\n#define XXH3_scrambleAcc    XXH3_scrambleAcc_scalar\n#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar\n\n#endif\n\n#if XXH_SIZE_OPT >= 1 /* don't do SIMD for initialization */\n#  undef XXH3_initCustomSecret\n#  define XXH3_initCustomSecret XXH3_initCustomSecret_scalar\n#endif\n\nXXH_FORCE_INLINE void\nXXH3_hashLong_internal_loop(xxh_u64* XXH_RESTRICT acc,\n                      const xxh_u8* XXH_RESTRICT input, size_t len,\n                      const xxh_u8* XXH_RESTRICT secret, size_t secretSize,\n                            XXH3_f_accumulate f_acc,\n                            XXH3_f_scrambleAcc f_scramble)\n{\n    size_t const nbStripesPerBlock = (secretSize - XXH_STRIPE_LEN) / XXH_SECRET_CONSUME_RATE;\n    size_t const block_len = XXH_STRIPE_LEN * nbStripesPerBlock;\n    size_t const nb_blocks = (len - 1) / block_len;\n\n    size_t n;\n\n    XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN);\n\n    for (n = 0; n < nb_blocks; n++) {\n        f_acc(acc, input + n*block_len, secret, nbStripesPerBlock);\n        f_scramble(acc, secret + secretSize - XXH_STRIPE_LEN);\n    }\n\n    /* last partial block */\n    XXH_ASSERT(len > XXH_STRIPE_LEN);\n    {   size_t const nbStripes = ((len - 1) - (block_len * nb_blocks)) / XXH_STRIPE_LEN;\n        XXH_ASSERT(nbStripes <= (secretSize / XXH_SECRET_CONSUME_RATE));\n        f_acc(acc, input + nb_blocks*block_len, secret, nbStripes);\n\n        /* last stripe */\n        {   const xxh_u8* const p = input + len - XXH_STRIPE_LEN;\n#define XXH_SECRET_LASTACC_START 7  /* not aligned on 8, last secret is different from acc & scrambler */\n            XXH3_accumulate_512(acc, p, secret + secretSize - XXH_STRIPE_LEN - XXH_SECRET_LASTACC_START);\n    }   }\n}\n\nXXH_FORCE_INLINE xxh_u64\nXXH3_mix2Accs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret)\n{\n    return XXH3_mul128_fold64(\n               acc[0] ^ XXH_readLE64(secret),\n               acc[1] ^ XXH_readLE64(secret+8) );\n}\n\nstatic XXH64_hash_t\nXXH3_mergeAccs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret, xxh_u64 start)\n{\n    xxh_u64 result64 = start;\n    size_t i = 0;\n\n    for (i = 0; i < 4; i++) {\n        result64 += XXH3_mix2Accs(acc+2*i, secret + 16*i);\n#if defined(__clang__)                                /* Clang */ \\\n    && (defined(__arm__) || defined(__thumb__))       /* ARMv7 */ \\\n    && (defined(__ARM_NEON) || defined(__ARM_NEON__)) /* NEON */  \\\n    && !defined(XXH_ENABLE_AUTOVECTORIZE)             /* Define to disable */\n        /*\n         * UGLY HACK:\n         * Prevent autovectorization on Clang ARMv7-a. Exact same problem as\n         * the one in XXH3_len_129to240_64b. Speeds up shorter keys > 240b.\n         * XXH3_64bits, len == 256, Snapdragon 835:\n         *   without hack: 2063.7 MB/s\n         *   with hack:    2560.7 MB/s\n         */\n        XXH_COMPILER_GUARD(result64);\n#endif\n    }\n\n    return XXH3_avalanche(result64);\n}\n\n#define XXH3_INIT_ACC { XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, XXH_PRIME64_3, \\\n                        XXH_PRIME64_4, XXH_PRIME32_2, XXH_PRIME64_5, XXH_PRIME32_1 }\n\nXXH_FORCE_INLINE XXH64_hash_t\nXXH3_hashLong_64b_internal(const void* XXH_RESTRICT input, size_t len,\n                           const void* XXH_RESTRICT secret, size_t secretSize,\n                           XXH3_f_accumulate f_acc,\n                           XXH3_f_scrambleAcc f_scramble)\n{\n    XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC;\n\n    XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, (const xxh_u8*)secret, secretSize, f_acc, f_scramble);\n\n    /* converge into final hash */\n    XXH_STATIC_ASSERT(sizeof(acc) == 64);\n    /* do not align on 8, so that the secret is different from the accumulator */\n#define XXH_SECRET_MERGEACCS_START 11\n    XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START);\n    return XXH3_mergeAccs(acc, (const xxh_u8*)secret + XXH_SECRET_MERGEACCS_START, (xxh_u64)len * XXH_PRIME64_1);\n}\n\n/*\n * It's important for performance to transmit secret's size (when it's static)\n * so that the compiler can properly optimize the vectorized loop.\n * This makes a big performance difference for \"medium\" keys (<1 KB) when using AVX instruction set.\n * When the secret size is unknown, or on GCC 12 where the mix of NO_INLINE and FORCE_INLINE\n * breaks -Og, this is XXH_NO_INLINE.\n */\nXXH3_WITH_SECRET_INLINE XXH64_hash_t\nXXH3_hashLong_64b_withSecret(const void* XXH_RESTRICT input, size_t len,\n                             XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen)\n{\n    (void)seed64;\n    return XXH3_hashLong_64b_internal(input, len, secret, secretLen, XXH3_accumulate, XXH3_scrambleAcc);\n}\n\n/*\n * It's preferable for performance that XXH3_hashLong is not inlined,\n * as it results in a smaller function for small data, easier to the instruction cache.\n * Note that inside this no_inline function, we do inline the internal loop,\n * and provide a statically defined secret size to allow optimization of vector loop.\n */\nXXH_NO_INLINE XXH_PUREF XXH64_hash_t\nXXH3_hashLong_64b_default(const void* XXH_RESTRICT input, size_t len,\n                          XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen)\n{\n    (void)seed64; (void)secret; (void)secretLen;\n    return XXH3_hashLong_64b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_accumulate, XXH3_scrambleAcc);\n}\n\n/*\n * XXH3_hashLong_64b_withSeed():\n * Generate a custom key based on alteration of default XXH3_kSecret with the seed,\n * and then use this key for long mode hashing.\n *\n * This operation is decently fast but nonetheless costs a little bit of time.\n * Try to avoid it whenever possible (typically when seed==0).\n *\n * It's important for performance that XXH3_hashLong is not inlined. Not sure\n * why (uop cache maybe?), but the difference is large and easily measurable.\n */\nXXH_FORCE_INLINE XXH64_hash_t\nXXH3_hashLong_64b_withSeed_internal(const void* input, size_t len,\n                                    XXH64_hash_t seed,\n                                    XXH3_f_accumulate f_acc,\n                                    XXH3_f_scrambleAcc f_scramble,\n                                    XXH3_f_initCustomSecret f_initSec)\n{\n#if XXH_SIZE_OPT <= 0\n    if (seed == 0)\n        return XXH3_hashLong_64b_internal(input, len,\n                                          XXH3_kSecret, sizeof(XXH3_kSecret),\n                                          f_acc, f_scramble);\n#endif\n    {   XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE];\n        f_initSec(secret, seed);\n        return XXH3_hashLong_64b_internal(input, len, secret, sizeof(secret),\n                                          f_acc, f_scramble);\n    }\n}\n\n/*\n * It's important for performance that XXH3_hashLong is not inlined.\n */\nXXH_NO_INLINE XXH64_hash_t\nXXH3_hashLong_64b_withSeed(const void* XXH_RESTRICT input, size_t len,\n                           XXH64_hash_t seed, const xxh_u8* XXH_RESTRICT secret, size_t secretLen)\n{\n    (void)secret; (void)secretLen;\n    return XXH3_hashLong_64b_withSeed_internal(input, len, seed,\n                XXH3_accumulate, XXH3_scrambleAcc, XXH3_initCustomSecret);\n}\n\n\ntypedef XXH64_hash_t (*XXH3_hashLong64_f)(const void* XXH_RESTRICT, size_t,\n                                          XXH64_hash_t, const xxh_u8* XXH_RESTRICT, size_t);\n\nXXH_FORCE_INLINE XXH64_hash_t\nXXH3_64bits_internal(const void* XXH_RESTRICT input, size_t len,\n                     XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen,\n                     XXH3_hashLong64_f f_hashLong)\n{\n    XXH_ASSERT(secretLen >= XXH3_SECRET_SIZE_MIN);\n    /*\n     * If an action is to be taken if `secretLen` condition is not respected,\n     * it should be done here.\n     * For now, it's a contract pre-condition.\n     * Adding a check and a branch here would cost performance at every hash.\n     * Also, note that function signature doesn't offer room to return an error.\n     */\n    if (len <= 16)\n        return XXH3_len_0to16_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, seed64);\n    if (len <= 128)\n        return XXH3_len_17to128_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64);\n    if (len <= XXH3_MIDSIZE_MAX)\n        return XXH3_len_129to240_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64);\n    return f_hashLong(input, len, seed64, (const xxh_u8*)secret, secretLen);\n}\n\n\n/* ===   Public entry point   === */\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH64_hash_t XXH3_64bits(XXH_NOESCAPE const void* input, size_t length)\n{\n    return XXH3_64bits_internal(input, length, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_default);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH64_hash_t\nXXH3_64bits_withSecret(XXH_NOESCAPE const void* input, size_t length, XXH_NOESCAPE const void* secret, size_t secretSize)\n{\n    return XXH3_64bits_internal(input, length, 0, secret, secretSize, XXH3_hashLong_64b_withSecret);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH64_hash_t\nXXH3_64bits_withSeed(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed)\n{\n    return XXH3_64bits_internal(input, length, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_withSeed);\n}\n\nXXH_PUBLIC_API XXH64_hash_t\nXXH3_64bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t length, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed)\n{\n    if (length <= XXH3_MIDSIZE_MAX)\n        return XXH3_64bits_internal(input, length, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL);\n    return XXH3_hashLong_64b_withSecret(input, length, seed, (const xxh_u8*)secret, secretSize);\n}\n\n\n/* ===   XXH3 streaming   === */\n#ifndef XXH_NO_STREAM\n/*\n * Malloc's a pointer that is always aligned to align.\n *\n * This must be freed with `XXH_alignedFree()`.\n *\n * malloc typically guarantees 16 byte alignment on 64-bit systems and 8 byte\n * alignment on 32-bit. This isn't enough for the 32 byte aligned loads in AVX2\n * or on 32-bit, the 16 byte aligned loads in SSE2 and NEON.\n *\n * This underalignment previously caused a rather obvious crash which went\n * completely unnoticed due to XXH3_createState() not actually being tested.\n * Credit to RedSpah for noticing this bug.\n *\n * The alignment is done manually: Functions like posix_memalign or _mm_malloc\n * are avoided: To maintain portability, we would have to write a fallback\n * like this anyways, and besides, testing for the existence of library\n * functions without relying on external build tools is impossible.\n *\n * The method is simple: Overallocate, manually align, and store the offset\n * to the original behind the returned pointer.\n *\n * Align must be a power of 2 and 8 <= align <= 128.\n */\nstatic XXH_MALLOCF void* XXH_alignedMalloc(size_t s, size_t align)\n{\n    XXH_ASSERT(align <= 128 && align >= 8); /* range check */\n    XXH_ASSERT((align & (align-1)) == 0);   /* power of 2 */\n    XXH_ASSERT(s != 0 && s < (s + align));  /* empty/overflow */\n    {   /* Overallocate to make room for manual realignment and an offset byte */\n        xxh_u8* base = (xxh_u8*)XXH_malloc(s + align);\n        if (base != NULL) {\n            /*\n             * Get the offset needed to align this pointer.\n             *\n             * Even if the returned pointer is aligned, there will always be\n             * at least one byte to store the offset to the original pointer.\n             */\n            size_t offset = align - ((size_t)base & (align - 1)); /* base % align */\n            /* Add the offset for the now-aligned pointer */\n            xxh_u8* ptr = base + offset;\n\n            XXH_ASSERT((size_t)ptr % align == 0);\n\n            /* Store the offset immediately before the returned pointer. */\n            ptr[-1] = (xxh_u8)offset;\n            return ptr;\n        }\n        return NULL;\n    }\n}\n/*\n * Frees an aligned pointer allocated by XXH_alignedMalloc(). Don't pass\n * normal malloc'd pointers, XXH_alignedMalloc has a specific data layout.\n */\nstatic void XXH_alignedFree(void* p)\n{\n    if (p != NULL) {\n        xxh_u8* ptr = (xxh_u8*)p;\n        /* Get the offset byte we added in XXH_malloc. */\n        xxh_u8 offset = ptr[-1];\n        /* Free the original malloc'd pointer */\n        xxh_u8* base = ptr - offset;\n        XXH_free(base);\n    }\n}\n/*! @ingroup XXH3_family */\n/*!\n * @brief Allocate an @ref XXH3_state_t.\n *\n * @return An allocated pointer of @ref XXH3_state_t on success.\n * @return `NULL` on failure.\n *\n * @note Must be freed with XXH3_freeState().\n */\nXXH_PUBLIC_API XXH3_state_t* XXH3_createState(void)\n{\n    XXH3_state_t* const state = (XXH3_state_t*)XXH_alignedMalloc(sizeof(XXH3_state_t), 64);\n    if (state==NULL) return NULL;\n    XXH3_INITSTATE(state);\n    return state;\n}\n\n/*! @ingroup XXH3_family */\n/*!\n * @brief Frees an @ref XXH3_state_t.\n *\n * @param statePtr A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState().\n *\n * @return @ref XXH_OK.\n *\n * @note Must be allocated with XXH3_createState().\n */\nXXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr)\n{\n    XXH_alignedFree(statePtr);\n    return XXH_OK;\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API void\nXXH3_copyState(XXH_NOESCAPE XXH3_state_t* dst_state, XXH_NOESCAPE const XXH3_state_t* src_state)\n{\n    XXH_memcpy(dst_state, src_state, sizeof(*dst_state));\n}\n\nstatic void\nXXH3_reset_internal(XXH3_state_t* statePtr,\n                    XXH64_hash_t seed,\n                    const void* secret, size_t secretSize)\n{\n    size_t const initStart = offsetof(XXH3_state_t, bufferedSize);\n    size_t const initLength = offsetof(XXH3_state_t, nbStripesPerBlock) - initStart;\n    XXH_ASSERT(offsetof(XXH3_state_t, nbStripesPerBlock) > initStart);\n    XXH_ASSERT(statePtr != NULL);\n    /* set members from bufferedSize to nbStripesPerBlock (excluded) to 0 */\n    memset((char*)statePtr + initStart, 0, initLength);\n    statePtr->acc[0] = XXH_PRIME32_3;\n    statePtr->acc[1] = XXH_PRIME64_1;\n    statePtr->acc[2] = XXH_PRIME64_2;\n    statePtr->acc[3] = XXH_PRIME64_3;\n    statePtr->acc[4] = XXH_PRIME64_4;\n    statePtr->acc[5] = XXH_PRIME32_2;\n    statePtr->acc[6] = XXH_PRIME64_5;\n    statePtr->acc[7] = XXH_PRIME32_1;\n    statePtr->seed = seed;\n    statePtr->useSeed = (seed != 0);\n    statePtr->extSecret = (const unsigned char*)secret;\n    XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN);\n    statePtr->secretLimit = secretSize - XXH_STRIPE_LEN;\n    statePtr->nbStripesPerBlock = statePtr->secretLimit / XXH_SECRET_CONSUME_RATE;\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_64bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr)\n{\n    if (statePtr == NULL) return XXH_ERROR;\n    XXH3_reset_internal(statePtr, 0, XXH3_kSecret, XXH_SECRET_DEFAULT_SIZE);\n    return XXH_OK;\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_64bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize)\n{\n    if (statePtr == NULL) return XXH_ERROR;\n    XXH3_reset_internal(statePtr, 0, secret, secretSize);\n    if (secret == NULL) return XXH_ERROR;\n    if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR;\n    return XXH_OK;\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_64bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed)\n{\n    if (statePtr == NULL) return XXH_ERROR;\n    if (seed==0) return XXH3_64bits_reset(statePtr);\n    if ((seed != statePtr->seed) || (statePtr->extSecret != NULL))\n        XXH3_initCustomSecret(statePtr->customSecret, seed);\n    XXH3_reset_internal(statePtr, seed, NULL, XXH_SECRET_DEFAULT_SIZE);\n    return XXH_OK;\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_64bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed64)\n{\n    if (statePtr == NULL) return XXH_ERROR;\n    if (secret == NULL) return XXH_ERROR;\n    if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR;\n    XXH3_reset_internal(statePtr, seed64, secret, secretSize);\n    statePtr->useSeed = 1; /* always, even if seed64==0 */\n    return XXH_OK;\n}\n\n/*!\n * @internal\n * @brief Processes a large input for XXH3_update() and XXH3_digest_long().\n *\n * Unlike XXH3_hashLong_internal_loop(), this can process data that overlaps a block.\n *\n * @param acc                Pointer to the 8 accumulator lanes\n * @param nbStripesSoFarPtr  In/out pointer to the number of leftover stripes in the block*\n * @param nbStripesPerBlock  Number of stripes in a block\n * @param input              Input pointer\n * @param nbStripes          Number of stripes to process\n * @param secret             Secret pointer\n * @param secretLimit        Offset of the last block in @p secret\n * @param f_acc              Pointer to an XXH3_accumulate implementation\n * @param f_scramble         Pointer to an XXH3_scrambleAcc implementation\n * @return                   Pointer past the end of @p input after processing\n */\nXXH_FORCE_INLINE const xxh_u8 *\nXXH3_consumeStripes(xxh_u64* XXH_RESTRICT acc,\n                    size_t* XXH_RESTRICT nbStripesSoFarPtr, size_t nbStripesPerBlock,\n                    const xxh_u8* XXH_RESTRICT input, size_t nbStripes,\n                    const xxh_u8* XXH_RESTRICT secret, size_t secretLimit,\n                    XXH3_f_accumulate f_acc,\n                    XXH3_f_scrambleAcc f_scramble)\n{\n    const xxh_u8* initialSecret = secret + *nbStripesSoFarPtr * XXH_SECRET_CONSUME_RATE;\n    /* Process full blocks */\n    if (nbStripes >= (nbStripesPerBlock - *nbStripesSoFarPtr)) {\n        /* Process the initial partial block... */\n        size_t nbStripesThisIter = nbStripesPerBlock - *nbStripesSoFarPtr;\n\n        do {\n            /* Accumulate and scramble */\n            f_acc(acc, input, initialSecret, nbStripesThisIter);\n            f_scramble(acc, secret + secretLimit);\n            input += nbStripesThisIter * XXH_STRIPE_LEN;\n            nbStripes -= nbStripesThisIter;\n            /* Then continue the loop with the full block size */\n            nbStripesThisIter = nbStripesPerBlock;\n            initialSecret = secret;\n        } while (nbStripes >= nbStripesPerBlock);\n        *nbStripesSoFarPtr = 0;\n    }\n    /* Process a partial block */\n    if (nbStripes > 0) {\n        f_acc(acc, input, initialSecret, nbStripes);\n        input += nbStripes * XXH_STRIPE_LEN;\n        *nbStripesSoFarPtr += nbStripes;\n    }\n    /* Return end pointer */\n    return input;\n}\n\n#ifndef XXH3_STREAM_USE_STACK\n# if XXH_SIZE_OPT <= 0 && !defined(__clang__) /* clang doesn't need additional stack space */\n#   define XXH3_STREAM_USE_STACK 1\n# endif\n#endif\n/*\n * Both XXH3_64bits_update and XXH3_128bits_update use this routine.\n */\nXXH_FORCE_INLINE XXH_errorcode\nXXH3_update(XXH3_state_t* XXH_RESTRICT const state,\n            const xxh_u8* XXH_RESTRICT input, size_t len,\n            XXH3_f_accumulate f_acc,\n            XXH3_f_scrambleAcc f_scramble)\n{\n    if (input==NULL) {\n        XXH_ASSERT(len == 0);\n        return XXH_OK;\n    }\n\n    XXH_ASSERT(state != NULL);\n    {   const xxh_u8* const bEnd = input + len;\n        const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret;\n#if defined(XXH3_STREAM_USE_STACK) && XXH3_STREAM_USE_STACK >= 1\n        /* For some reason, gcc and MSVC seem to suffer greatly\n         * when operating accumulators directly into state.\n         * Operating into stack space seems to enable proper optimization.\n         * clang, on the other hand, doesn't seem to need this trick */\n        XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[8];\n        XXH_memcpy(acc, state->acc, sizeof(acc));\n#else\n        xxh_u64* XXH_RESTRICT const acc = state->acc;\n#endif\n        state->totalLen += len;\n        XXH_ASSERT(state->bufferedSize <= XXH3_INTERNALBUFFER_SIZE);\n\n        /* small input : just fill in tmp buffer */\n        if (len <= XXH3_INTERNALBUFFER_SIZE - state->bufferedSize) {\n            XXH_memcpy(state->buffer + state->bufferedSize, input, len);\n            state->bufferedSize += (XXH32_hash_t)len;\n            return XXH_OK;\n        }\n\n        /* total input is now > XXH3_INTERNALBUFFER_SIZE */\n        #define XXH3_INTERNALBUFFER_STRIPES (XXH3_INTERNALBUFFER_SIZE / XXH_STRIPE_LEN)\n        XXH_STATIC_ASSERT(XXH3_INTERNALBUFFER_SIZE % XXH_STRIPE_LEN == 0);   /* clean multiple */\n\n        /*\n         * Internal buffer is partially filled (always, except at beginning)\n         * Complete it, then consume it.\n         */\n        if (state->bufferedSize) {\n            size_t const loadSize = XXH3_INTERNALBUFFER_SIZE - state->bufferedSize;\n            XXH_memcpy(state->buffer + state->bufferedSize, input, loadSize);\n            input += loadSize;\n            XXH3_consumeStripes(acc,\n                               &state->nbStripesSoFar, state->nbStripesPerBlock,\n                                state->buffer, XXH3_INTERNALBUFFER_STRIPES,\n                                secret, state->secretLimit,\n                                f_acc, f_scramble);\n            state->bufferedSize = 0;\n        }\n        XXH_ASSERT(input < bEnd);\n        if (bEnd - input > XXH3_INTERNALBUFFER_SIZE) {\n            size_t nbStripes = (size_t)(bEnd - 1 - input) / XXH_STRIPE_LEN;\n            input = XXH3_consumeStripes(acc,\n                                       &state->nbStripesSoFar, state->nbStripesPerBlock,\n                                       input, nbStripes,\n                                       secret, state->secretLimit,\n                                       f_acc, f_scramble);\n            XXH_memcpy(state->buffer + sizeof(state->buffer) - XXH_STRIPE_LEN, input - XXH_STRIPE_LEN, XXH_STRIPE_LEN);\n\n        }\n        /* Some remaining input (always) : buffer it */\n        XXH_ASSERT(input < bEnd);\n        XXH_ASSERT(bEnd - input <= XXH3_INTERNALBUFFER_SIZE);\n        XXH_ASSERT(state->bufferedSize == 0);\n        XXH_memcpy(state->buffer, input, (size_t)(bEnd-input));\n        state->bufferedSize = (XXH32_hash_t)(bEnd-input);\n#if defined(XXH3_STREAM_USE_STACK) && XXH3_STREAM_USE_STACK >= 1\n        /* save stack accumulators into state */\n        XXH_memcpy(state->acc, acc, sizeof(acc));\n#endif\n    }\n\n    return XXH_OK;\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_64bits_update(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len)\n{\n    return XXH3_update(state, (const xxh_u8*)input, len,\n                       XXH3_accumulate, XXH3_scrambleAcc);\n}\n\n\nXXH_FORCE_INLINE void\nXXH3_digest_long (XXH64_hash_t* acc,\n                  const XXH3_state_t* state,\n                  const unsigned char* secret)\n{\n    xxh_u8 lastStripe[XXH_STRIPE_LEN];\n    const xxh_u8* lastStripePtr;\n\n    /*\n     * Digest on a local copy. This way, the state remains unaltered, and it can\n     * continue ingesting more input afterwards.\n     */\n    XXH_memcpy(acc, state->acc, sizeof(state->acc));\n    if (state->bufferedSize >= XXH_STRIPE_LEN) {\n        /* Consume remaining stripes then point to remaining data in buffer */\n        size_t const nbStripes = (state->bufferedSize - 1) / XXH_STRIPE_LEN;\n        size_t nbStripesSoFar = state->nbStripesSoFar;\n        XXH3_consumeStripes(acc,\n                           &nbStripesSoFar, state->nbStripesPerBlock,\n                            state->buffer, nbStripes,\n                            secret, state->secretLimit,\n                            XXH3_accumulate, XXH3_scrambleAcc);\n        lastStripePtr = state->buffer + state->bufferedSize - XXH_STRIPE_LEN;\n    } else {  /* bufferedSize < XXH_STRIPE_LEN */\n        /* Copy to temp buffer */\n        size_t const catchupSize = XXH_STRIPE_LEN - state->bufferedSize;\n        XXH_ASSERT(state->bufferedSize > 0);  /* there is always some input buffered */\n        XXH_memcpy(lastStripe, state->buffer + sizeof(state->buffer) - catchupSize, catchupSize);\n        XXH_memcpy(lastStripe + catchupSize, state->buffer, state->bufferedSize);\n        lastStripePtr = lastStripe;\n    }\n    /* Last stripe */\n    XXH3_accumulate_512(acc,\n                        lastStripePtr,\n                        secret + state->secretLimit - XXH_SECRET_LASTACC_START);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH64_hash_t XXH3_64bits_digest (XXH_NOESCAPE const XXH3_state_t* state)\n{\n    const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret;\n    if (state->totalLen > XXH3_MIDSIZE_MAX) {\n        XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB];\n        XXH3_digest_long(acc, state, secret);\n        return XXH3_mergeAccs(acc,\n                              secret + XXH_SECRET_MERGEACCS_START,\n                              (xxh_u64)state->totalLen * XXH_PRIME64_1);\n    }\n    /* totalLen <= XXH3_MIDSIZE_MAX: digesting a short input */\n    if (state->useSeed)\n        return XXH3_64bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed);\n    return XXH3_64bits_withSecret(state->buffer, (size_t)(state->totalLen),\n                                  secret, state->secretLimit + XXH_STRIPE_LEN);\n}\n#endif /* !XXH_NO_STREAM */\n\n\n/* ==========================================\n * XXH3 128 bits (a.k.a XXH128)\n * ==========================================\n * XXH3's 128-bit variant has better mixing and strength than the 64-bit variant,\n * even without counting the significantly larger output size.\n *\n * For example, extra steps are taken to avoid the seed-dependent collisions\n * in 17-240 byte inputs (See XXH3_mix16B and XXH128_mix32B).\n *\n * This strength naturally comes at the cost of some speed, especially on short\n * lengths. Note that longer hashes are about as fast as the 64-bit version\n * due to it using only a slight modification of the 64-bit loop.\n *\n * XXH128 is also more oriented towards 64-bit machines. It is still extremely\n * fast for a _128-bit_ hash on 32-bit (it usually clears XXH64).\n */\n\nXXH_FORCE_INLINE XXH_PUREF XXH128_hash_t\nXXH3_len_1to3_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)\n{\n    /* A doubled version of 1to3_64b with different constants. */\n    XXH_ASSERT(input != NULL);\n    XXH_ASSERT(1 <= len && len <= 3);\n    XXH_ASSERT(secret != NULL);\n    /*\n     * len = 1: combinedl = { input[0], 0x01, input[0], input[0] }\n     * len = 2: combinedl = { input[1], 0x02, input[0], input[1] }\n     * len = 3: combinedl = { input[2], 0x03, input[0], input[1] }\n     */\n    {   xxh_u8 const c1 = input[0];\n        xxh_u8 const c2 = input[len >> 1];\n        xxh_u8 const c3 = input[len - 1];\n        xxh_u32 const combinedl = ((xxh_u32)c1 <<16) | ((xxh_u32)c2 << 24)\n                                | ((xxh_u32)c3 << 0) | ((xxh_u32)len << 8);\n        xxh_u32 const combinedh = XXH_rotl32(XXH_swap32(combinedl), 13);\n        xxh_u64 const bitflipl = (XXH_readLE32(secret) ^ XXH_readLE32(secret+4)) + seed;\n        xxh_u64 const bitfliph = (XXH_readLE32(secret+8) ^ XXH_readLE32(secret+12)) - seed;\n        xxh_u64 const keyed_lo = (xxh_u64)combinedl ^ bitflipl;\n        xxh_u64 const keyed_hi = (xxh_u64)combinedh ^ bitfliph;\n        XXH128_hash_t h128;\n        h128.low64  = XXH64_avalanche(keyed_lo);\n        h128.high64 = XXH64_avalanche(keyed_hi);\n        return h128;\n    }\n}\n\nXXH_FORCE_INLINE XXH_PUREF XXH128_hash_t\nXXH3_len_4to8_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)\n{\n    XXH_ASSERT(input != NULL);\n    XXH_ASSERT(secret != NULL);\n    XXH_ASSERT(4 <= len && len <= 8);\n    seed ^= (xxh_u64)XXH_swap32((xxh_u32)seed) << 32;\n    {   xxh_u32 const input_lo = XXH_readLE32(input);\n        xxh_u32 const input_hi = XXH_readLE32(input + len - 4);\n        xxh_u64 const input_64 = input_lo + ((xxh_u64)input_hi << 32);\n        xxh_u64 const bitflip = (XXH_readLE64(secret+16) ^ XXH_readLE64(secret+24)) + seed;\n        xxh_u64 const keyed = input_64 ^ bitflip;\n\n        /* Shift len to the left to ensure it is even, this avoids even multiplies. */\n        XXH128_hash_t m128 = XXH_mult64to128(keyed, XXH_PRIME64_1 + (len << 2));\n\n        m128.high64 += (m128.low64 << 1);\n        m128.low64  ^= (m128.high64 >> 3);\n\n        m128.low64   = XXH_xorshift64(m128.low64, 35);\n        m128.low64  *= PRIME_MX2;\n        m128.low64   = XXH_xorshift64(m128.low64, 28);\n        m128.high64  = XXH3_avalanche(m128.high64);\n        return m128;\n    }\n}\n\nXXH_FORCE_INLINE XXH_PUREF XXH128_hash_t\nXXH3_len_9to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)\n{\n    XXH_ASSERT(input != NULL);\n    XXH_ASSERT(secret != NULL);\n    XXH_ASSERT(9 <= len && len <= 16);\n    {   xxh_u64 const bitflipl = (XXH_readLE64(secret+32) ^ XXH_readLE64(secret+40)) - seed;\n        xxh_u64 const bitfliph = (XXH_readLE64(secret+48) ^ XXH_readLE64(secret+56)) + seed;\n        xxh_u64 const input_lo = XXH_readLE64(input);\n        xxh_u64       input_hi = XXH_readLE64(input + len - 8);\n        XXH128_hash_t m128 = XXH_mult64to128(input_lo ^ input_hi ^ bitflipl, XXH_PRIME64_1);\n        /*\n         * Put len in the middle of m128 to ensure that the length gets mixed to\n         * both the low and high bits in the 128x64 multiply below.\n         */\n        m128.low64 += (xxh_u64)(len - 1) << 54;\n        input_hi   ^= bitfliph;\n        /*\n         * Add the high 32 bits of input_hi to the high 32 bits of m128, then\n         * add the long product of the low 32 bits of input_hi and XXH_PRIME32_2 to\n         * the high 64 bits of m128.\n         *\n         * The best approach to this operation is different on 32-bit and 64-bit.\n         */\n        if (sizeof(void *) < sizeof(xxh_u64)) { /* 32-bit */\n            /*\n             * 32-bit optimized version, which is more readable.\n             *\n             * On 32-bit, it removes an ADC and delays a dependency between the two\n             * halves of m128.high64, but it generates an extra mask on 64-bit.\n             */\n            m128.high64 += (input_hi & 0xFFFFFFFF00000000ULL) + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2);\n        } else {\n            /*\n             * 64-bit optimized (albeit more confusing) version.\n             *\n             * Uses some properties of addition and multiplication to remove the mask:\n             *\n             * Let:\n             *    a = input_hi.lo = (input_hi & 0x00000000FFFFFFFF)\n             *    b = input_hi.hi = (input_hi & 0xFFFFFFFF00000000)\n             *    c = XXH_PRIME32_2\n             *\n             *    a + (b * c)\n             * Inverse Property: x + y - x == y\n             *    a + (b * (1 + c - 1))\n             * Distributive Property: x * (y + z) == (x * y) + (x * z)\n             *    a + (b * 1) + (b * (c - 1))\n             * Identity Property: x * 1 == x\n             *    a + b + (b * (c - 1))\n             *\n             * Substitute a, b, and c:\n             *    input_hi.hi + input_hi.lo + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1))\n             *\n             * Since input_hi.hi + input_hi.lo == input_hi, we get this:\n             *    input_hi + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1))\n             */\n            m128.high64 += input_hi + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2 - 1);\n        }\n        /* m128 ^= XXH_swap64(m128 >> 64); */\n        m128.low64  ^= XXH_swap64(m128.high64);\n\n        {   /* 128x64 multiply: h128 = m128 * XXH_PRIME64_2; */\n            XXH128_hash_t h128 = XXH_mult64to128(m128.low64, XXH_PRIME64_2);\n            h128.high64 += m128.high64 * XXH_PRIME64_2;\n\n            h128.low64   = XXH3_avalanche(h128.low64);\n            h128.high64  = XXH3_avalanche(h128.high64);\n            return h128;\n    }   }\n}\n\n/*\n * Assumption: `secret` size is >= XXH3_SECRET_SIZE_MIN\n */\nXXH_FORCE_INLINE XXH_PUREF XXH128_hash_t\nXXH3_len_0to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)\n{\n    XXH_ASSERT(len <= 16);\n    {   if (len > 8) return XXH3_len_9to16_128b(input, len, secret, seed);\n        if (len >= 4) return XXH3_len_4to8_128b(input, len, secret, seed);\n        if (len) return XXH3_len_1to3_128b(input, len, secret, seed);\n        {   XXH128_hash_t h128;\n            xxh_u64 const bitflipl = XXH_readLE64(secret+64) ^ XXH_readLE64(secret+72);\n            xxh_u64 const bitfliph = XXH_readLE64(secret+80) ^ XXH_readLE64(secret+88);\n            h128.low64 = XXH64_avalanche(seed ^ bitflipl);\n            h128.high64 = XXH64_avalanche( seed ^ bitfliph);\n            return h128;\n    }   }\n}\n\n/*\n * A bit slower than XXH3_mix16B, but handles multiply by zero better.\n */\nXXH_FORCE_INLINE XXH128_hash_t\nXXH128_mix32B(XXH128_hash_t acc, const xxh_u8* input_1, const xxh_u8* input_2,\n              const xxh_u8* secret, XXH64_hash_t seed)\n{\n    acc.low64  += XXH3_mix16B (input_1, secret+0, seed);\n    acc.low64  ^= XXH_readLE64(input_2) + XXH_readLE64(input_2 + 8);\n    acc.high64 += XXH3_mix16B (input_2, secret+16, seed);\n    acc.high64 ^= XXH_readLE64(input_1) + XXH_readLE64(input_1 + 8);\n    return acc;\n}\n\n\nXXH_FORCE_INLINE XXH_PUREF XXH128_hash_t\nXXH3_len_17to128_128b(const xxh_u8* XXH_RESTRICT input, size_t len,\n                      const xxh_u8* XXH_RESTRICT secret, size_t secretSize,\n                      XXH64_hash_t seed)\n{\n    XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize;\n    XXH_ASSERT(16 < len && len <= 128);\n\n    {   XXH128_hash_t acc;\n        acc.low64 = len * XXH_PRIME64_1;\n        acc.high64 = 0;\n\n#if XXH_SIZE_OPT >= 1\n        {\n            /* Smaller, but slightly slower. */\n            unsigned int i = (unsigned int)(len - 1) / 32;\n            do {\n                acc = XXH128_mix32B(acc, input+16*i, input+len-16*(i+1), secret+32*i, seed);\n            } while (i-- != 0);\n        }\n#else\n        if (len > 32) {\n            if (len > 64) {\n                if (len > 96) {\n                    acc = XXH128_mix32B(acc, input+48, input+len-64, secret+96, seed);\n                }\n                acc = XXH128_mix32B(acc, input+32, input+len-48, secret+64, seed);\n            }\n            acc = XXH128_mix32B(acc, input+16, input+len-32, secret+32, seed);\n        }\n        acc = XXH128_mix32B(acc, input, input+len-16, secret, seed);\n#endif\n        {   XXH128_hash_t h128;\n            h128.low64  = acc.low64 + acc.high64;\n            h128.high64 = (acc.low64    * XXH_PRIME64_1)\n                        + (acc.high64   * XXH_PRIME64_4)\n                        + ((len - seed) * XXH_PRIME64_2);\n            h128.low64  = XXH3_avalanche(h128.low64);\n            h128.high64 = (XXH64_hash_t)0 - XXH3_avalanche(h128.high64);\n            return h128;\n        }\n    }\n}\n\nXXH_NO_INLINE XXH_PUREF XXH128_hash_t\nXXH3_len_129to240_128b(const xxh_u8* XXH_RESTRICT input, size_t len,\n                       const xxh_u8* XXH_RESTRICT secret, size_t secretSize,\n                       XXH64_hash_t seed)\n{\n    XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize;\n    XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX);\n\n    {   XXH128_hash_t acc;\n        unsigned i;\n        acc.low64 = len * XXH_PRIME64_1;\n        acc.high64 = 0;\n        /*\n         *  We set as `i` as offset + 32. We do this so that unchanged\n         * `len` can be used as upper bound. This reaches a sweet spot\n         * where both x86 and aarch64 get simple agen and good codegen\n         * for the loop.\n         */\n        for (i = 32; i < 160; i += 32) {\n            acc = XXH128_mix32B(acc,\n                                input  + i - 32,\n                                input  + i - 16,\n                                secret + i - 32,\n                                seed);\n        }\n        acc.low64 = XXH3_avalanche(acc.low64);\n        acc.high64 = XXH3_avalanche(acc.high64);\n        /*\n         * NB: `i <= len` will duplicate the last 32-bytes if\n         * len % 32 was zero. This is an unfortunate necessity to keep\n         * the hash result stable.\n         */\n        for (i=160; i <= len; i += 32) {\n            acc = XXH128_mix32B(acc,\n                                input + i - 32,\n                                input + i - 16,\n                                secret + XXH3_MIDSIZE_STARTOFFSET + i - 160,\n                                seed);\n        }\n        /* last bytes */\n        acc = XXH128_mix32B(acc,\n                            input + len - 16,\n                            input + len - 32,\n                            secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET - 16,\n                            (XXH64_hash_t)0 - seed);\n\n        {   XXH128_hash_t h128;\n            h128.low64  = acc.low64 + acc.high64;\n            h128.high64 = (acc.low64    * XXH_PRIME64_1)\n                        + (acc.high64   * XXH_PRIME64_4)\n                        + ((len - seed) * XXH_PRIME64_2);\n            h128.low64  = XXH3_avalanche(h128.low64);\n            h128.high64 = (XXH64_hash_t)0 - XXH3_avalanche(h128.high64);\n            return h128;\n        }\n    }\n}\n\nXXH_FORCE_INLINE XXH128_hash_t\nXXH3_hashLong_128b_internal(const void* XXH_RESTRICT input, size_t len,\n                            const xxh_u8* XXH_RESTRICT secret, size_t secretSize,\n                            XXH3_f_accumulate f_acc,\n                            XXH3_f_scrambleAcc f_scramble)\n{\n    XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC;\n\n    XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, secret, secretSize, f_acc, f_scramble);\n\n    /* converge into final hash */\n    XXH_STATIC_ASSERT(sizeof(acc) == 64);\n    XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START);\n    {   XXH128_hash_t h128;\n        h128.low64  = XXH3_mergeAccs(acc,\n                                     secret + XXH_SECRET_MERGEACCS_START,\n                                     (xxh_u64)len * XXH_PRIME64_1);\n        h128.high64 = XXH3_mergeAccs(acc,\n                                     secret + secretSize\n                                            - sizeof(acc) - XXH_SECRET_MERGEACCS_START,\n                                     ~((xxh_u64)len * XXH_PRIME64_2));\n        return h128;\n    }\n}\n\n/*\n * It's important for performance that XXH3_hashLong() is not inlined.\n */\nXXH_NO_INLINE XXH_PUREF XXH128_hash_t\nXXH3_hashLong_128b_default(const void* XXH_RESTRICT input, size_t len,\n                           XXH64_hash_t seed64,\n                           const void* XXH_RESTRICT secret, size_t secretLen)\n{\n    (void)seed64; (void)secret; (void)secretLen;\n    return XXH3_hashLong_128b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret),\n                                       XXH3_accumulate, XXH3_scrambleAcc);\n}\n\n/*\n * It's important for performance to pass @p secretLen (when it's static)\n * to the compiler, so that it can properly optimize the vectorized loop.\n *\n * When the secret size is unknown, or on GCC 12 where the mix of NO_INLINE and FORCE_INLINE\n * breaks -Og, this is XXH_NO_INLINE.\n */\nXXH3_WITH_SECRET_INLINE XXH128_hash_t\nXXH3_hashLong_128b_withSecret(const void* XXH_RESTRICT input, size_t len,\n                              XXH64_hash_t seed64,\n                              const void* XXH_RESTRICT secret, size_t secretLen)\n{\n    (void)seed64;\n    return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, secretLen,\n                                       XXH3_accumulate, XXH3_scrambleAcc);\n}\n\nXXH_FORCE_INLINE XXH128_hash_t\nXXH3_hashLong_128b_withSeed_internal(const void* XXH_RESTRICT input, size_t len,\n                                XXH64_hash_t seed64,\n                                XXH3_f_accumulate f_acc,\n                                XXH3_f_scrambleAcc f_scramble,\n                                XXH3_f_initCustomSecret f_initSec)\n{\n    if (seed64 == 0)\n        return XXH3_hashLong_128b_internal(input, len,\n                                           XXH3_kSecret, sizeof(XXH3_kSecret),\n                                           f_acc, f_scramble);\n    {   XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE];\n        f_initSec(secret, seed64);\n        return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, sizeof(secret),\n                                           f_acc, f_scramble);\n    }\n}\n\n/*\n * It's important for performance that XXH3_hashLong is not inlined.\n */\nXXH_NO_INLINE XXH128_hash_t\nXXH3_hashLong_128b_withSeed(const void* input, size_t len,\n                            XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen)\n{\n    (void)secret; (void)secretLen;\n    return XXH3_hashLong_128b_withSeed_internal(input, len, seed64,\n                XXH3_accumulate, XXH3_scrambleAcc, XXH3_initCustomSecret);\n}\n\ntypedef XXH128_hash_t (*XXH3_hashLong128_f)(const void* XXH_RESTRICT, size_t,\n                                            XXH64_hash_t, const void* XXH_RESTRICT, size_t);\n\nXXH_FORCE_INLINE XXH128_hash_t\nXXH3_128bits_internal(const void* input, size_t len,\n                      XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen,\n                      XXH3_hashLong128_f f_hl128)\n{\n    XXH_ASSERT(secretLen >= XXH3_SECRET_SIZE_MIN);\n    /*\n     * If an action is to be taken if `secret` conditions are not respected,\n     * it should be done here.\n     * For now, it's a contract pre-condition.\n     * Adding a check and a branch here would cost performance at every hash.\n     */\n    if (len <= 16)\n        return XXH3_len_0to16_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, seed64);\n    if (len <= 128)\n        return XXH3_len_17to128_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64);\n    if (len <= XXH3_MIDSIZE_MAX)\n        return XXH3_len_129to240_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64);\n    return f_hl128(input, len, seed64, secret, secretLen);\n}\n\n\n/* ===   Public XXH128 API   === */\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH128_hash_t XXH3_128bits(XXH_NOESCAPE const void* input, size_t len)\n{\n    return XXH3_128bits_internal(input, len, 0,\n                                 XXH3_kSecret, sizeof(XXH3_kSecret),\n                                 XXH3_hashLong_128b_default);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH128_hash_t\nXXH3_128bits_withSecret(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize)\n{\n    return XXH3_128bits_internal(input, len, 0,\n                                 (const xxh_u8*)secret, secretSize,\n                                 XXH3_hashLong_128b_withSecret);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH128_hash_t\nXXH3_128bits_withSeed(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed)\n{\n    return XXH3_128bits_internal(input, len, seed,\n                                 XXH3_kSecret, sizeof(XXH3_kSecret),\n                                 XXH3_hashLong_128b_withSeed);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH128_hash_t\nXXH3_128bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed)\n{\n    if (len <= XXH3_MIDSIZE_MAX)\n        return XXH3_128bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL);\n    return XXH3_hashLong_128b_withSecret(input, len, seed, secret, secretSize);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH128_hash_t\nXXH128(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed)\n{\n    return XXH3_128bits_withSeed(input, len, seed);\n}\n\n\n/* ===   XXH3 128-bit streaming   === */\n#ifndef XXH_NO_STREAM\n/*\n * All initialization and update functions are identical to 64-bit streaming variant.\n * The only difference is the finalization routine.\n */\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_128bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr)\n{\n    return XXH3_64bits_reset(statePtr);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize)\n{\n    return XXH3_64bits_reset_withSecret(statePtr, secret, secretSize);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_128bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed)\n{\n    return XXH3_64bits_reset_withSeed(statePtr, seed);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed)\n{\n    return XXH3_64bits_reset_withSecretandSeed(statePtr, secret, secretSize, seed);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_128bits_update(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len)\n{\n    return XXH3_64bits_update(state, input, len);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH128_hash_t XXH3_128bits_digest (XXH_NOESCAPE const XXH3_state_t* state)\n{\n    const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret;\n    if (state->totalLen > XXH3_MIDSIZE_MAX) {\n        XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB];\n        XXH3_digest_long(acc, state, secret);\n        XXH_ASSERT(state->secretLimit + XXH_STRIPE_LEN >= sizeof(acc) + XXH_SECRET_MERGEACCS_START);\n        {   XXH128_hash_t h128;\n            h128.low64  = XXH3_mergeAccs(acc,\n                                         secret + XXH_SECRET_MERGEACCS_START,\n                                         (xxh_u64)state->totalLen * XXH_PRIME64_1);\n            h128.high64 = XXH3_mergeAccs(acc,\n                                         secret + state->secretLimit + XXH_STRIPE_LEN\n                                                - sizeof(acc) - XXH_SECRET_MERGEACCS_START,\n                                         ~((xxh_u64)state->totalLen * XXH_PRIME64_2));\n            return h128;\n        }\n    }\n    /* len <= XXH3_MIDSIZE_MAX : short code */\n    if (state->seed)\n        return XXH3_128bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed);\n    return XXH3_128bits_withSecret(state->buffer, (size_t)(state->totalLen),\n                                   secret, state->secretLimit + XXH_STRIPE_LEN);\n}\n#endif /* !XXH_NO_STREAM */\n/* 128-bit utility functions */\n\n/* return : 1 is equal, 0 if different */\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2)\n{\n    /* note : XXH128_hash_t is compact, it has no padding byte */\n    return !(memcmp(&h1, &h2, sizeof(h1)));\n}\n\n/* This prototype is compatible with stdlib's qsort().\n * @return : >0 if *h128_1  > *h128_2\n *           <0 if *h128_1  < *h128_2\n *           =0 if *h128_1 == *h128_2  */\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API int XXH128_cmp(XXH_NOESCAPE const void* h128_1, XXH_NOESCAPE const void* h128_2)\n{\n    XXH128_hash_t const h1 = *(const XXH128_hash_t*)h128_1;\n    XXH128_hash_t const h2 = *(const XXH128_hash_t*)h128_2;\n    int const hcmp = (h1.high64 > h2.high64) - (h2.high64 > h1.high64);\n    /* note : bets that, in most cases, hash values are different */\n    if (hcmp) return hcmp;\n    return (h1.low64 > h2.low64) - (h2.low64 > h1.low64);\n}\n\n\n/*======   Canonical representation   ======*/\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API void\nXXH128_canonicalFromHash(XXH_NOESCAPE XXH128_canonical_t* dst, XXH128_hash_t hash)\n{\n    XXH_STATIC_ASSERT(sizeof(XXH128_canonical_t) == sizeof(XXH128_hash_t));\n    if (XXH_CPU_LITTLE_ENDIAN) {\n        hash.high64 = XXH_swap64(hash.high64);\n        hash.low64  = XXH_swap64(hash.low64);\n    }\n    XXH_memcpy(dst, &hash.high64, sizeof(hash.high64));\n    XXH_memcpy((char*)dst + sizeof(hash.high64), &hash.low64, sizeof(hash.low64));\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH128_hash_t\nXXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t* src)\n{\n    XXH128_hash_t h;\n    h.high64 = XXH_readBE64(src);\n    h.low64  = XXH_readBE64(src->digest + 8);\n    return h;\n}\n\n\n\n/* ==========================================\n * Secret generators\n * ==========================================\n */\n#define XXH_MIN(x, y) (((x) > (y)) ? (y) : (x))\n\nXXH_FORCE_INLINE void XXH3_combine16(void* dst, XXH128_hash_t h128)\n{\n    XXH_writeLE64( dst, XXH_readLE64(dst) ^ h128.low64 );\n    XXH_writeLE64( (char*)dst+8, XXH_readLE64((char*)dst+8) ^ h128.high64 );\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_generateSecret(XXH_NOESCAPE void* secretBuffer, size_t secretSize, XXH_NOESCAPE const void* customSeed, size_t customSeedSize)\n{\n#if (XXH_DEBUGLEVEL >= 1)\n    XXH_ASSERT(secretBuffer != NULL);\n    XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN);\n#else\n    /* production mode, assert() are disabled */\n    if (secretBuffer == NULL) return XXH_ERROR;\n    if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR;\n#endif\n\n    if (customSeedSize == 0) {\n        customSeed = XXH3_kSecret;\n        customSeedSize = XXH_SECRET_DEFAULT_SIZE;\n    }\n#if (XXH_DEBUGLEVEL >= 1)\n    XXH_ASSERT(customSeed != NULL);\n#else\n    if (customSeed == NULL) return XXH_ERROR;\n#endif\n\n    /* Fill secretBuffer with a copy of customSeed - repeat as needed */\n    {   size_t pos = 0;\n        while (pos < secretSize) {\n            size_t const toCopy = XXH_MIN((secretSize - pos), customSeedSize);\n            memcpy((char*)secretBuffer + pos, customSeed, toCopy);\n            pos += toCopy;\n    }   }\n\n    {   size_t const nbSeg16 = secretSize / 16;\n        size_t n;\n        XXH128_canonical_t scrambler;\n        XXH128_canonicalFromHash(&scrambler, XXH128(customSeed, customSeedSize, 0));\n        for (n=0; n<nbSeg16; n++) {\n            XXH128_hash_t const h128 = XXH128(&scrambler, sizeof(scrambler), n);\n            XXH3_combine16((char*)secretBuffer + n*16, h128);\n        }\n        /* last segment */\n        XXH3_combine16((char*)secretBuffer + secretSize - 16, XXH128_hashFromCanonical(&scrambler));\n    }\n    return XXH_OK;\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API void\nXXH3_generateSecret_fromSeed(XXH_NOESCAPE void* secretBuffer, XXH64_hash_t seed)\n{\n    XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE];\n    XXH3_initCustomSecret(secret, seed);\n    XXH_ASSERT(secretBuffer != NULL);\n    memcpy(secretBuffer, secret, XXH_SECRET_DEFAULT_SIZE);\n}\n\n\n\n/* Pop our optimization override from above */\n#if XXH_VECTOR == XXH_AVX2 /* AVX2 */ \\\n  && defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \\\n  && defined(__OPTIMIZE__) && XXH_SIZE_OPT <= 0 /* respect -O0 and -Os */\n#  pragma GCC pop_options\n#endif\n\n\n#if defined (__cplusplus)\n} /* extern \"C\" */\n#endif\n\n#endif  /* XXH_NO_LONG_LONG */\n#endif  /* XXH_NO_XXH3 */\n\n/*!\n * @}\n */\n#endif  /* XXH_IMPLEMENTATION */\n"
  },
  {
    "path": "lib/common/zstd_common.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n\n/*-*************************************\n*  Dependencies\n***************************************/\n#define ZSTD_DEPS_NEED_MALLOC\n#include \"error_private.h\"\n#include \"zstd_internal.h\"\n\n\n/*-****************************************\n*  Version\n******************************************/\nunsigned ZSTD_versionNumber(void) { return ZSTD_VERSION_NUMBER; }\n\nconst char* ZSTD_versionString(void) { return ZSTD_VERSION_STRING; }\n\n\n/*-****************************************\n*  ZSTD Error Management\n******************************************/\n#undef ZSTD_isError   /* defined within zstd_internal.h */\n/*! ZSTD_isError() :\n *  tells if a return value is an error code\n *  symbol is required for external callers */\nunsigned ZSTD_isError(size_t code) { return ERR_isError(code); }\n\n/*! ZSTD_getErrorName() :\n *  provides error code string from function result (useful for debugging) */\nconst char* ZSTD_getErrorName(size_t code) { return ERR_getErrorName(code); }\n\n/*! ZSTD_getError() :\n *  convert a `size_t` function result into a proper ZSTD_errorCode enum */\nZSTD_ErrorCode ZSTD_getErrorCode(size_t code) { return ERR_getErrorCode(code); }\n\n/*! ZSTD_getErrorString() :\n *  provides error code string from enum */\nconst char* ZSTD_getErrorString(ZSTD_ErrorCode code) { return ERR_getErrorString(code); }\n\nint ZSTD_isDeterministicBuild(void)\n{\n#if ZSTD_IS_DETERMINISTIC_BUILD\n    return 1;\n#else\n    return 0;\n#endif\n}\n"
  },
  {
    "path": "lib/common/zstd_deps.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* This file provides common libc dependencies that zstd requires.\n * The purpose is to allow replacing this file with a custom implementation\n * to compile zstd without libc support.\n */\n\n/* Need:\n * NULL\n * INT_MAX\n * UINT_MAX\n * ZSTD_memcpy()\n * ZSTD_memset()\n * ZSTD_memmove()\n */\n#ifndef ZSTD_DEPS_COMMON\n#define ZSTD_DEPS_COMMON\n\n/* Even though we use qsort_r only for the dictionary builder, the macro\n * _GNU_SOURCE has to be declared *before* the inclusion of any standard\n * header and the script 'combine.sh' combines the whole zstd source code\n * in a single file.\n */\n#if defined(__linux) || defined(__linux__) || defined(linux) || defined(__gnu_linux__) || \\\n    defined(__CYGWIN__) || defined(__MSYS__)\n#if !defined(_GNU_SOURCE) && !defined(__ANDROID__) /* NDK doesn't ship qsort_r(). */\n#define _GNU_SOURCE\n#endif\n#endif\n\n#include <limits.h>\n#include <stddef.h>\n#include <string.h>\n\n#if defined(__GNUC__) && __GNUC__ >= 4\n# define ZSTD_memcpy(d,s,l) __builtin_memcpy((d),(s),(l))\n# define ZSTD_memmove(d,s,l) __builtin_memmove((d),(s),(l))\n# define ZSTD_memset(p,v,l) __builtin_memset((p),(v),(l))\n#else\n# define ZSTD_memcpy(d,s,l) memcpy((d),(s),(l))\n# define ZSTD_memmove(d,s,l) memmove((d),(s),(l))\n# define ZSTD_memset(p,v,l) memset((p),(v),(l))\n#endif\n\n#endif /* ZSTD_DEPS_COMMON */\n\n/* Need:\n * ZSTD_malloc()\n * ZSTD_free()\n * ZSTD_calloc()\n */\n#ifdef ZSTD_DEPS_NEED_MALLOC\n#ifndef ZSTD_DEPS_MALLOC\n#define ZSTD_DEPS_MALLOC\n\n#include <stdlib.h>\n\n#define ZSTD_malloc(s) malloc(s)\n#define ZSTD_calloc(n,s) calloc((n), (s))\n#define ZSTD_free(p) free((p))\n\n#endif /* ZSTD_DEPS_MALLOC */\n#endif /* ZSTD_DEPS_NEED_MALLOC */\n\n/*\n * Provides 64-bit math support.\n * Need:\n * U64 ZSTD_div64(U64 dividend, U32 divisor)\n */\n#ifdef ZSTD_DEPS_NEED_MATH64\n#ifndef ZSTD_DEPS_MATH64\n#define ZSTD_DEPS_MATH64\n\n#define ZSTD_div64(dividend, divisor) ((dividend) / (divisor))\n\n#endif /* ZSTD_DEPS_MATH64 */\n#endif /* ZSTD_DEPS_NEED_MATH64 */\n\n/* Need:\n * assert()\n */\n#ifdef ZSTD_DEPS_NEED_ASSERT\n#ifndef ZSTD_DEPS_ASSERT\n#define ZSTD_DEPS_ASSERT\n\n#include <assert.h>\n\n#endif /* ZSTD_DEPS_ASSERT */\n#endif /* ZSTD_DEPS_NEED_ASSERT */\n\n/* Need:\n * ZSTD_DEBUG_PRINT()\n */\n#ifdef ZSTD_DEPS_NEED_IO\n#ifndef ZSTD_DEPS_IO\n#define ZSTD_DEPS_IO\n\n#include <stdio.h>\n#define ZSTD_DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__)\n\n#endif /* ZSTD_DEPS_IO */\n#endif /* ZSTD_DEPS_NEED_IO */\n\n/* Only requested when <stdint.h> is known to be present.\n * Need:\n * intptr_t\n */\n#ifdef ZSTD_DEPS_NEED_STDINT\n#ifndef ZSTD_DEPS_STDINT\n#define ZSTD_DEPS_STDINT\n\n#include <stdint.h>\n\n#endif /* ZSTD_DEPS_STDINT */\n#endif /* ZSTD_DEPS_NEED_STDINT */\n"
  },
  {
    "path": "lib/common/zstd_internal.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_CCOMMON_H_MODULE\n#define ZSTD_CCOMMON_H_MODULE\n\n/* this module contains definitions which must be identical\n * across compression, decompression and dictBuilder.\n * It also contains a few functions useful to at least 2 of them\n * and which benefit from being inlined */\n\n/*-*************************************\n*  Dependencies\n***************************************/\n#include \"compiler.h\"\n#include \"cpu.h\"\n#include \"mem.h\"\n#include \"debug.h\"                 /* assert, DEBUGLOG, RAWLOG, g_debuglevel */\n#include \"error_private.h\"\n#define ZSTD_STATIC_LINKING_ONLY\n#include \"../zstd.h\"\n#define FSE_STATIC_LINKING_ONLY\n#include \"fse.h\"\n#include \"huf.h\"\n#ifndef XXH_STATIC_LINKING_ONLY\n#  define XXH_STATIC_LINKING_ONLY  /* XXH64_state_t */\n#endif\n#include \"xxhash.h\"                /* XXH_reset, update, digest */\n#ifndef ZSTD_NO_TRACE\n#  include \"zstd_trace.h\"\n#else\n#  define ZSTD_TRACE 0\n#endif\n\n/* ---- static assert (debug) --- */\n#define ZSTD_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c)\n#define ZSTD_isError ERR_isError   /* for inlining */\n#define FSE_isError  ERR_isError\n#define HUF_isError  ERR_isError\n\n\n/*-*************************************\n*  shared macros\n***************************************/\n#undef MIN\n#undef MAX\n#define MIN(a,b) ((a)<(b) ? (a) : (b))\n#define MAX(a,b) ((a)>(b) ? (a) : (b))\n#define BOUNDED(min,val,max) (MAX(min,MIN(val,max)))\n\n\n/*-*************************************\n*  Common constants\n***************************************/\n#define ZSTD_OPT_NUM    (1<<12)\n\n#define ZSTD_REP_NUM      3                 /* number of repcodes */\nstatic UNUSED_ATTR const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 };\n\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\n#define BIT7 128\n#define BIT6  64\n#define BIT5  32\n#define BIT4  16\n#define BIT1   2\n#define BIT0   1\n\n#define ZSTD_WINDOWLOG_ABSOLUTEMIN 10\nstatic UNUSED_ATTR const size_t ZSTD_fcs_fieldSize[4] = { 0, 2, 4, 8 };\nstatic UNUSED_ATTR const size_t ZSTD_did_fieldSize[4] = { 0, 1, 2, 4 };\n\n#define ZSTD_FRAMEIDSIZE 4   /* magic number size */\n\n#define ZSTD_BLOCKHEADERSIZE 3   /* C standard doesn't allow `static const` variable to be init using another `static const` variable */\nstatic UNUSED_ATTR const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE;\ntypedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e;\n\n#define ZSTD_FRAMECHECKSUMSIZE 4\n\n#define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */\n#define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */)   /* for a non-null block */\n#define MIN_LITERALS_FOR_4_STREAMS 6\n\ntypedef enum { set_basic, set_rle, set_compressed, set_repeat } SymbolEncodingType_e;\n\n#define LONGNBSEQ 0x7F00\n\n#define MINMATCH 3\n\n#define Litbits  8\n#define LitHufLog 11\n#define MaxLit ((1<<Litbits) - 1)\n#define MaxML   52\n#define MaxLL   35\n#define DefaultMaxOff 28\n#define MaxOff  31\n#define MaxSeq MAX(MaxLL, MaxML)   /* Assumption : MaxOff < MaxLL,MaxML */\n#define MLFSELog    9\n#define LLFSELog    9\n#define OffFSELog   8\n#define MaxFSELog  MAX(MAX(MLFSELog, LLFSELog), OffFSELog)\n#define MaxMLBits 16\n#define MaxLLBits 16\n\n#define ZSTD_MAX_HUF_HEADER_SIZE 128 /* header + <= 127 byte tree description */\n/* Each table cannot take more than #symbols * FSELog bits */\n#define ZSTD_MAX_FSE_HEADERS_SIZE (((MaxML + 1) * MLFSELog + (MaxLL + 1) * LLFSELog + (MaxOff + 1) * OffFSELog + 7) / 8)\n\nstatic UNUSED_ATTR const U8 LL_bits[MaxLL+1] = {\n     0, 0, 0, 0, 0, 0, 0, 0,\n     0, 0, 0, 0, 0, 0, 0, 0,\n     1, 1, 1, 1, 2, 2, 3, 3,\n     4, 6, 7, 8, 9,10,11,12,\n    13,14,15,16\n};\nstatic UNUSED_ATTR const S16 LL_defaultNorm[MaxLL+1] = {\n     4, 3, 2, 2, 2, 2, 2, 2,\n     2, 2, 2, 2, 2, 1, 1, 1,\n     2, 2, 2, 2, 2, 2, 2, 2,\n     2, 3, 2, 1, 1, 1, 1, 1,\n    -1,-1,-1,-1\n};\n#define LL_DEFAULTNORMLOG 6  /* for static allocation */\nstatic UNUSED_ATTR const U32 LL_defaultNormLog = LL_DEFAULTNORMLOG;\n\nstatic UNUSED_ATTR const U8 ML_bits[MaxML+1] = {\n     0, 0, 0, 0, 0, 0, 0, 0,\n     0, 0, 0, 0, 0, 0, 0, 0,\n     0, 0, 0, 0, 0, 0, 0, 0,\n     0, 0, 0, 0, 0, 0, 0, 0,\n     1, 1, 1, 1, 2, 2, 3, 3,\n     4, 4, 5, 7, 8, 9,10,11,\n    12,13,14,15,16\n};\nstatic UNUSED_ATTR const S16 ML_defaultNorm[MaxML+1] = {\n     1, 4, 3, 2, 2, 2, 2, 2,\n     2, 1, 1, 1, 1, 1, 1, 1,\n     1, 1, 1, 1, 1, 1, 1, 1,\n     1, 1, 1, 1, 1, 1, 1, 1,\n     1, 1, 1, 1, 1, 1, 1, 1,\n     1, 1, 1, 1, 1, 1,-1,-1,\n    -1,-1,-1,-1,-1\n};\n#define ML_DEFAULTNORMLOG 6  /* for static allocation */\nstatic UNUSED_ATTR const U32 ML_defaultNormLog = ML_DEFAULTNORMLOG;\n\nstatic UNUSED_ATTR const S16 OF_defaultNorm[DefaultMaxOff+1] = {\n     1, 1, 1, 1, 1, 1, 2, 2,\n     2, 1, 1, 1, 1, 1, 1, 1,\n     1, 1, 1, 1, 1, 1, 1, 1,\n    -1,-1,-1,-1,-1\n};\n#define OF_DEFAULTNORMLOG 5  /* for static allocation */\nstatic UNUSED_ATTR const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG;\n\n\n/*-*******************************************\n*  Shared functions to include for inlining\n*********************************************/\nstatic void ZSTD_copy8(void* dst, const void* src) {\n#if defined(ZSTD_ARCH_ARM_NEON) && !defined(__aarch64__)\n    vst1_u8((uint8_t*)dst, vld1_u8((const uint8_t*)src));\n#else\n    ZSTD_memcpy(dst, src, 8);\n#endif\n}\n#define COPY8(d,s) do { ZSTD_copy8(d,s); d+=8; s+=8; } while (0)\n\n/* Need to use memmove here since the literal buffer can now be located within\n   the dst buffer. In circumstances where the op \"catches up\" to where the\n   literal buffer is, there can be partial overlaps in this call on the final\n   copy if the literal is being shifted by less than 16 bytes. */\nstatic void ZSTD_copy16(void* dst, const void* src) {\n#if defined(ZSTD_ARCH_ARM_NEON)\n    vst1q_u8((uint8_t*)dst, vld1q_u8((const uint8_t*)src));\n#elif defined(ZSTD_ARCH_X86_SSE2)\n    _mm_storeu_si128((__m128i*)dst, _mm_loadu_si128((const __m128i*)src));\n#elif defined(ZSTD_ARCH_RISCV_RVV)\n    __riscv_vse8_v_u8m1((uint8_t*)dst, __riscv_vle8_v_u8m1((const uint8_t*)src, 16), 16);\n#elif defined(__clang__)\n    ZSTD_memmove(dst, src, 16);\n#else\n    /* ZSTD_memmove is not inlined properly by gcc */\n    BYTE copy16_buf[16];\n    ZSTD_memcpy(copy16_buf, src, 16);\n    ZSTD_memcpy(dst, copy16_buf, 16);\n#endif\n}\n#define COPY16(d,s) do { ZSTD_copy16(d,s); d+=16; s+=16; } while (0)\n\n#define WILDCOPY_OVERLENGTH 32\n#define WILDCOPY_VECLEN 16\n\ntypedef enum {\n    ZSTD_no_overlap,\n    ZSTD_overlap_src_before_dst\n    /*  ZSTD_overlap_dst_before_src, */\n} ZSTD_overlap_e;\n\n/*! ZSTD_wildcopy() :\n *  Custom version of ZSTD_memcpy(), can over read/write up to WILDCOPY_OVERLENGTH bytes (if length==0)\n *  @param ovtype controls the overlap detection\n *         - ZSTD_no_overlap: The source and destination are guaranteed to be at least WILDCOPY_VECLEN bytes apart.\n *         - ZSTD_overlap_src_before_dst: The src and dst may overlap, but they MUST be at least 8 bytes apart.\n *           The src buffer must be before the dst buffer.\n */\nMEM_STATIC FORCE_INLINE_ATTR\nvoid ZSTD_wildcopy(void* dst, const void* src, size_t length, ZSTD_overlap_e const ovtype)\n{\n    ptrdiff_t diff = (BYTE*)dst - (const BYTE*)src;\n    const BYTE* ip = (const BYTE*)src;\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + length;\n\n    if (ovtype == ZSTD_overlap_src_before_dst && diff < WILDCOPY_VECLEN) {\n        /* Handle short offset copies. */\n        do {\n            COPY8(op, ip);\n        } while (op < oend);\n    } else {\n        assert(diff >= WILDCOPY_VECLEN || diff <= -WILDCOPY_VECLEN);\n        /* Separate out the first COPY16() call because the copy length is\n         * almost certain to be short, so the branches have different\n         * probabilities. Since it is almost certain to be short, only do\n         * one COPY16() in the first call. Then, do two calls per loop since\n         * at that point it is more likely to have a high trip count.\n         */\n        ZSTD_copy16(op, ip);\n        if (16 >= length) return;\n        op += 16;\n        ip += 16;\n        do {\n            COPY16(op, ip);\n            COPY16(op, ip);\n        }\n        while (op < oend);\n    }\n}\n\nMEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    size_t const length = MIN(dstCapacity, srcSize);\n    if (length > 0) {\n        ZSTD_memcpy(dst, src, length);\n    }\n    return length;\n}\n\n/* define \"workspace is too large\" as this number of times larger than needed */\n#define ZSTD_WORKSPACETOOLARGE_FACTOR 3\n\n/* when workspace is continuously too large\n * during at least this number of times,\n * context's memory usage is considered wasteful,\n * because it's sized to handle a worst case scenario which rarely happens.\n * In which case, resize it down to free some memory */\n#define ZSTD_WORKSPACETOOLARGE_MAXDURATION 128\n\n/* Controls whether the input/output buffer is buffered or stable. */\ntypedef enum {\n    ZSTD_bm_buffered = 0,  /* Buffer the input/output */\n    ZSTD_bm_stable = 1     /* ZSTD_inBuffer/ZSTD_outBuffer is stable */\n} ZSTD_bufferMode_e;\n\n\n/*-*******************************************\n*  Private declarations\n*********************************************/\n\n/**\n * Contains the compressed frame size and an upper-bound for the decompressed frame size.\n * Note: before using `compressedSize`, check for errors using ZSTD_isError().\n *       similarly, before using `decompressedBound`, check for errors using:\n *          `decompressedBound != ZSTD_CONTENTSIZE_ERROR`\n */\ntypedef struct {\n    size_t nbBlocks;\n    size_t compressedSize;\n    unsigned long long decompressedBound;\n} ZSTD_frameSizeInfo;   /* decompress & legacy */\n\n/* ZSTD_invalidateRepCodes() :\n * ensures next compression will not use repcodes from previous block.\n * Note : only works with regular variant;\n *        do not use with extDict variant ! */\nvoid ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx);   /* zstdmt, adaptive_compression (shouldn't get this definition from here) */\n\n\ntypedef struct {\n    blockType_e blockType;\n    U32 lastBlock;\n    U32 origSize;\n} blockProperties_t;   /* declared here for decompress and fullbench */\n\n/*! ZSTD_getcBlockSize() :\n *  Provides the size of compressed block from block header `src` */\n/*  Used by: decompress, fullbench */\nsize_t ZSTD_getcBlockSize(const void* src, size_t srcSize,\n                          blockProperties_t* bpPtr);\n\n/*! ZSTD_decodeSeqHeaders() :\n *  decode sequence header from src */\n/*  Used by: zstd_decompress_block, fullbench */\nsize_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,\n                       const void* src, size_t srcSize);\n\n/**\n * @returns true iff the CPU supports dynamic BMI2 dispatch.\n */\nMEM_STATIC int ZSTD_cpuSupportsBmi2(void)\n{\n    ZSTD_cpuid_t cpuid = ZSTD_cpuid();\n    return ZSTD_cpuid_bmi1(cpuid) && ZSTD_cpuid_bmi2(cpuid);\n}\n\n#endif   /* ZSTD_CCOMMON_H_MODULE */\n"
  },
  {
    "path": "lib/common/zstd_trace.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_TRACE_H\n#define ZSTD_TRACE_H\n\n#include <stddef.h>\n\n/* weak symbol support\n * For now, enable conservatively:\n * - Only GNUC\n * - Only ELF\n * - Only x86-64, i386, aarch64 and risc-v.\n * Also, explicitly disable on platforms known not to work so they aren't\n * forgotten in the future.\n */\n#if !defined(ZSTD_HAVE_WEAK_SYMBOLS) && \\\n    defined(__GNUC__) && defined(__ELF__) && \\\n    (defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || \\\n     defined(_M_IX86) || defined(__aarch64__) || defined(__riscv)) && \\\n    !defined(__APPLE__) && !defined(_WIN32) && !defined(__MINGW32__) && \\\n    !defined(__CYGWIN__) && !defined(_AIX)\n#  define ZSTD_HAVE_WEAK_SYMBOLS 1\n#else\n#  define ZSTD_HAVE_WEAK_SYMBOLS 0\n#endif\n#if ZSTD_HAVE_WEAK_SYMBOLS\n#  define ZSTD_WEAK_ATTR __attribute__((__weak__))\n#else\n#  define ZSTD_WEAK_ATTR\n#endif\n\n/* Only enable tracing when weak symbols are available. */\n#ifndef ZSTD_TRACE\n#  define ZSTD_TRACE ZSTD_HAVE_WEAK_SYMBOLS\n#endif\n\n#if ZSTD_TRACE\n\nstruct ZSTD_CCtx_s;\nstruct ZSTD_DCtx_s;\nstruct ZSTD_CCtx_params_s;\n\ntypedef struct {\n    /**\n     * ZSTD_VERSION_NUMBER\n     *\n     * This is guaranteed to be the first member of ZSTD_trace.\n     * Otherwise, this struct is not stable between versions. If\n     * the version number does not match your expectation, you\n     * should not interpret the rest of the struct.\n     */\n    unsigned version;\n    /**\n     * Non-zero if streaming (de)compression is used.\n     */\n    int streaming;\n    /**\n     * The dictionary ID.\n     */\n    unsigned dictionaryID;\n    /**\n     * Is the dictionary cold?\n     * Only set on decompression.\n     */\n    int dictionaryIsCold;\n    /**\n     * The dictionary size or zero if no dictionary.\n     */\n    size_t dictionarySize;\n    /**\n     * The uncompressed size of the data.\n     */\n    size_t uncompressedSize;\n    /**\n     * The compressed size of the data.\n     */\n    size_t compressedSize;\n    /**\n     * The fully resolved CCtx parameters (NULL on decompression).\n     */\n    struct ZSTD_CCtx_params_s const* params;\n    /**\n     * The ZSTD_CCtx pointer (NULL on decompression).\n     */\n    struct ZSTD_CCtx_s const* cctx;\n    /**\n     * The ZSTD_DCtx pointer (NULL on compression).\n     */\n    struct ZSTD_DCtx_s const* dctx;\n} ZSTD_Trace;\n\n/**\n * A tracing context. It must be 0 when tracing is disabled.\n * Otherwise, any non-zero value returned by a tracing begin()\n * function is presented to any subsequent calls to end().\n *\n * Any non-zero value is treated as tracing is enabled and not\n * interpreted by the library.\n *\n * Two possible uses are:\n * * A timestamp for when the begin() function was called.\n * * A unique key identifying the (de)compression, like the\n *   address of the [dc]ctx pointer if you need to track\n *   more information than just a timestamp.\n */\ntypedef unsigned long long ZSTD_TraceCtx;\n\n/**\n * Trace the beginning of a compression call.\n * @param cctx The dctx pointer for the compression.\n *             It can be used as a key to map begin() to end().\n * @returns Non-zero if tracing is enabled. The return value is\n *          passed to ZSTD_trace_compress_end().\n */\nZSTD_WEAK_ATTR ZSTD_TraceCtx ZSTD_trace_compress_begin(\n    struct ZSTD_CCtx_s const* cctx);\n\n/**\n * Trace the end of a compression call.\n * @param ctx The return value of ZSTD_trace_compress_begin().\n * @param trace The zstd tracing info.\n */\nZSTD_WEAK_ATTR void ZSTD_trace_compress_end(\n    ZSTD_TraceCtx ctx,\n    ZSTD_Trace const* trace);\n\n/**\n * Trace the beginning of a decompression call.\n * @param dctx The dctx pointer for the decompression.\n *             It can be used as a key to map begin() to end().\n * @returns Non-zero if tracing is enabled. The return value is\n *          passed to ZSTD_trace_compress_end().\n */\nZSTD_WEAK_ATTR ZSTD_TraceCtx ZSTD_trace_decompress_begin(\n    struct ZSTD_DCtx_s const* dctx);\n\n/**\n * Trace the end of a decompression call.\n * @param ctx The return value of ZSTD_trace_decompress_begin().\n * @param trace The zstd tracing info.\n */\nZSTD_WEAK_ATTR void ZSTD_trace_decompress_end(\n    ZSTD_TraceCtx ctx,\n    ZSTD_Trace const* trace);\n\n#endif /* ZSTD_TRACE */\n\n#endif /* ZSTD_TRACE_H */\n"
  },
  {
    "path": "lib/compress/clevels.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_CLEVELS_H\n#define ZSTD_CLEVELS_H\n\n#define ZSTD_STATIC_LINKING_ONLY  /* ZSTD_compressionParameters  */\n#include \"../zstd.h\"\n\n/*-=====  Pre-defined compression levels  =====-*/\n\n#define ZSTD_MAX_CLEVEL     22\n\n#ifdef __GNUC__\n__attribute__((__unused__))\n#endif\n\nstatic const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {\n{   /* \"default\" - for any srcSize > 256 KB */\n    /* W,  C,  H,  S,  L, TL, strat */\n    { 19, 12, 13,  1,  6,  1, ZSTD_fast    },  /* base for negative levels */\n    { 19, 13, 14,  1,  7,  0, ZSTD_fast    },  /* level  1 */\n    { 20, 15, 16,  1,  6,  0, ZSTD_fast    },  /* level  2 */\n    { 21, 16, 17,  1,  5,  0, ZSTD_dfast   },  /* level  3 */\n    { 21, 18, 18,  1,  5,  0, ZSTD_dfast   },  /* level  4 */\n    { 21, 18, 19,  3,  5,  2, ZSTD_greedy  },  /* level  5 */\n    { 21, 18, 19,  3,  5,  4, ZSTD_lazy    },  /* level  6 */\n    { 21, 19, 20,  4,  5,  8, ZSTD_lazy    },  /* level  7 */\n    { 21, 19, 20,  4,  5, 16, ZSTD_lazy2   },  /* level  8 */\n    { 22, 20, 21,  4,  5, 16, ZSTD_lazy2   },  /* level  9 */\n    { 22, 21, 22,  5,  5, 16, ZSTD_lazy2   },  /* level 10 */\n    { 22, 21, 22,  6,  5, 16, ZSTD_lazy2   },  /* level 11 */\n    { 22, 22, 23,  6,  5, 32, ZSTD_lazy2   },  /* level 12 */\n    { 22, 22, 22,  4,  5, 32, ZSTD_btlazy2 },  /* level 13 */\n    { 22, 22, 23,  5,  5, 32, ZSTD_btlazy2 },  /* level 14 */\n    { 22, 23, 23,  6,  5, 32, ZSTD_btlazy2 },  /* level 15 */\n    { 22, 22, 22,  5,  5, 48, ZSTD_btopt   },  /* level 16 */\n    { 23, 23, 22,  5,  4, 64, ZSTD_btopt   },  /* level 17 */\n    { 23, 23, 22,  6,  3, 64, ZSTD_btultra },  /* level 18 */\n    { 23, 24, 22,  7,  3,256, ZSTD_btultra2},  /* level 19 */\n    { 25, 25, 23,  7,  3,256, ZSTD_btultra2},  /* level 20 */\n    { 26, 26, 24,  7,  3,512, ZSTD_btultra2},  /* level 21 */\n    { 27, 27, 25,  9,  3,999, ZSTD_btultra2},  /* level 22 */\n},\n{   /* for srcSize <= 256 KB */\n    /* W,  C,  H,  S,  L,  T, strat */\n    { 18, 12, 13,  1,  5,  1, ZSTD_fast    },  /* base for negative levels */\n    { 18, 13, 14,  1,  6,  0, ZSTD_fast    },  /* level  1 */\n    { 18, 14, 14,  1,  5,  0, ZSTD_dfast   },  /* level  2 */\n    { 18, 16, 16,  1,  4,  0, ZSTD_dfast   },  /* level  3 */\n    { 18, 16, 17,  3,  5,  2, ZSTD_greedy  },  /* level  4.*/\n    { 18, 17, 18,  5,  5,  2, ZSTD_greedy  },  /* level  5.*/\n    { 18, 18, 19,  3,  5,  4, ZSTD_lazy    },  /* level  6.*/\n    { 18, 18, 19,  4,  4,  4, ZSTD_lazy    },  /* level  7 */\n    { 18, 18, 19,  4,  4,  8, ZSTD_lazy2   },  /* level  8 */\n    { 18, 18, 19,  5,  4,  8, ZSTD_lazy2   },  /* level  9 */\n    { 18, 18, 19,  6,  4,  8, ZSTD_lazy2   },  /* level 10 */\n    { 18, 18, 19,  5,  4, 12, ZSTD_btlazy2 },  /* level 11.*/\n    { 18, 19, 19,  7,  4, 12, ZSTD_btlazy2 },  /* level 12.*/\n    { 18, 18, 19,  4,  4, 16, ZSTD_btopt   },  /* level 13 */\n    { 18, 18, 19,  4,  3, 32, ZSTD_btopt   },  /* level 14.*/\n    { 18, 18, 19,  6,  3,128, ZSTD_btopt   },  /* level 15.*/\n    { 18, 19, 19,  6,  3,128, ZSTD_btultra },  /* level 16.*/\n    { 18, 19, 19,  8,  3,256, ZSTD_btultra },  /* level 17.*/\n    { 18, 19, 19,  6,  3,128, ZSTD_btultra2},  /* level 18.*/\n    { 18, 19, 19,  8,  3,256, ZSTD_btultra2},  /* level 19.*/\n    { 18, 19, 19, 10,  3,512, ZSTD_btultra2},  /* level 20.*/\n    { 18, 19, 19, 12,  3,512, ZSTD_btultra2},  /* level 21.*/\n    { 18, 19, 19, 13,  3,999, ZSTD_btultra2},  /* level 22.*/\n},\n{   /* for srcSize <= 128 KB */\n    /* W,  C,  H,  S,  L,  T, strat */\n    { 17, 12, 12,  1,  5,  1, ZSTD_fast    },  /* base for negative levels */\n    { 17, 12, 13,  1,  6,  0, ZSTD_fast    },  /* level  1 */\n    { 17, 13, 15,  1,  5,  0, ZSTD_fast    },  /* level  2 */\n    { 17, 15, 16,  2,  5,  0, ZSTD_dfast   },  /* level  3 */\n    { 17, 17, 17,  2,  4,  0, ZSTD_dfast   },  /* level  4 */\n    { 17, 16, 17,  3,  4,  2, ZSTD_greedy  },  /* level  5 */\n    { 17, 16, 17,  3,  4,  4, ZSTD_lazy    },  /* level  6 */\n    { 17, 16, 17,  3,  4,  8, ZSTD_lazy2   },  /* level  7 */\n    { 17, 16, 17,  4,  4,  8, ZSTD_lazy2   },  /* level  8 */\n    { 17, 16, 17,  5,  4,  8, ZSTD_lazy2   },  /* level  9 */\n    { 17, 16, 17,  6,  4,  8, ZSTD_lazy2   },  /* level 10 */\n    { 17, 17, 17,  5,  4,  8, ZSTD_btlazy2 },  /* level 11 */\n    { 17, 18, 17,  7,  4, 12, ZSTD_btlazy2 },  /* level 12 */\n    { 17, 18, 17,  3,  4, 12, ZSTD_btopt   },  /* level 13.*/\n    { 17, 18, 17,  4,  3, 32, ZSTD_btopt   },  /* level 14.*/\n    { 17, 18, 17,  6,  3,256, ZSTD_btopt   },  /* level 15.*/\n    { 17, 18, 17,  6,  3,128, ZSTD_btultra },  /* level 16.*/\n    { 17, 18, 17,  8,  3,256, ZSTD_btultra },  /* level 17.*/\n    { 17, 18, 17, 10,  3,512, ZSTD_btultra },  /* level 18.*/\n    { 17, 18, 17,  5,  3,256, ZSTD_btultra2},  /* level 19.*/\n    { 17, 18, 17,  7,  3,512, ZSTD_btultra2},  /* level 20.*/\n    { 17, 18, 17,  9,  3,512, ZSTD_btultra2},  /* level 21.*/\n    { 17, 18, 17, 11,  3,999, ZSTD_btultra2},  /* level 22.*/\n},\n{   /* for srcSize <= 16 KB */\n    /* W,  C,  H,  S,  L,  T, strat */\n    { 14, 12, 13,  1,  5,  1, ZSTD_fast    },  /* base for negative levels */\n    { 14, 14, 15,  1,  5,  0, ZSTD_fast    },  /* level  1 */\n    { 14, 14, 15,  1,  4,  0, ZSTD_fast    },  /* level  2 */\n    { 14, 14, 15,  2,  4,  0, ZSTD_dfast   },  /* level  3 */\n    { 14, 14, 14,  4,  4,  2, ZSTD_greedy  },  /* level  4 */\n    { 14, 14, 14,  3,  4,  4, ZSTD_lazy    },  /* level  5.*/\n    { 14, 14, 14,  4,  4,  8, ZSTD_lazy2   },  /* level  6 */\n    { 14, 14, 14,  6,  4,  8, ZSTD_lazy2   },  /* level  7 */\n    { 14, 14, 14,  8,  4,  8, ZSTD_lazy2   },  /* level  8.*/\n    { 14, 15, 14,  5,  4,  8, ZSTD_btlazy2 },  /* level  9.*/\n    { 14, 15, 14,  9,  4,  8, ZSTD_btlazy2 },  /* level 10.*/\n    { 14, 15, 14,  3,  4, 12, ZSTD_btopt   },  /* level 11.*/\n    { 14, 15, 14,  4,  3, 24, ZSTD_btopt   },  /* level 12.*/\n    { 14, 15, 14,  5,  3, 32, ZSTD_btultra },  /* level 13.*/\n    { 14, 15, 15,  6,  3, 64, ZSTD_btultra },  /* level 14.*/\n    { 14, 15, 15,  7,  3,256, ZSTD_btultra },  /* level 15.*/\n    { 14, 15, 15,  5,  3, 48, ZSTD_btultra2},  /* level 16.*/\n    { 14, 15, 15,  6,  3,128, ZSTD_btultra2},  /* level 17.*/\n    { 14, 15, 15,  7,  3,256, ZSTD_btultra2},  /* level 18.*/\n    { 14, 15, 15,  8,  3,256, ZSTD_btultra2},  /* level 19.*/\n    { 14, 15, 15,  8,  3,512, ZSTD_btultra2},  /* level 20.*/\n    { 14, 15, 15,  9,  3,512, ZSTD_btultra2},  /* level 21.*/\n    { 14, 15, 15, 10,  3,999, ZSTD_btultra2},  /* level 22.*/\n},\n};\n\n\n\n#endif  /* ZSTD_CLEVELS_H */\n"
  },
  {
    "path": "lib/compress/fse_compress.c",
    "content": "/* ******************************************************************\n * FSE : Finite State Entropy encoder\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n *  You can contact the author at :\n *  - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *  - Public forum : https://groups.google.com/forum/#!forum/lz4c\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n/* **************************************************************\n*  Includes\n****************************************************************/\n#include \"../common/compiler.h\"\n#include \"../common/mem.h\"        /* U32, U16, etc. */\n#include \"../common/debug.h\"      /* assert, DEBUGLOG */\n#include \"hist.h\"       /* HIST_count_wksp */\n#include \"../common/bitstream.h\"\n#define FSE_STATIC_LINKING_ONLY\n#include \"../common/fse.h\"\n#include \"../common/error_private.h\"\n#define ZSTD_DEPS_NEED_MALLOC\n#define ZSTD_DEPS_NEED_MATH64\n#include \"../common/zstd_deps.h\"  /* ZSTD_memset */\n#include \"../common/bits.h\" /* ZSTD_highbit32 */\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n#define FSE_isError ERR_isError\n\n\n/* **************************************************************\n*  Templates\n****************************************************************/\n/*\n  designed to be included\n  for type-specific functions (template emulation in C)\n  Objective is to write these functions only once, for improved maintenance\n*/\n\n/* safety checks */\n#ifndef FSE_FUNCTION_EXTENSION\n#  error \"FSE_FUNCTION_EXTENSION must be defined\"\n#endif\n#ifndef FSE_FUNCTION_TYPE\n#  error \"FSE_FUNCTION_TYPE must be defined\"\n#endif\n\n/* Function names */\n#define FSE_CAT(X,Y) X##Y\n#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y)\n#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y)\n\n\n/* Function templates */\n\n/* FSE_buildCTable_wksp() :\n * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`).\n * wkspSize should be sized to handle worst case situation, which is `1<<max_tableLog * sizeof(FSE_FUNCTION_TYPE)`\n * workSpace must also be properly aligned with FSE_FUNCTION_TYPE requirements\n */\nsize_t FSE_buildCTable_wksp(FSE_CTable* ct,\n                      const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog,\n                            void* workSpace, size_t wkspSize)\n{\n    U32 const tableSize = 1 << tableLog;\n    U32 const tableMask = tableSize - 1;\n    void* const ptr = ct;\n    U16* const tableU16 = ( (U16*) ptr) + 2;\n    void* const FSCT = ((U32*)ptr) + 1 /* header */ + (tableLog ? tableSize>>1 : 1) ;\n    FSE_symbolCompressionTransform* const symbolTT = (FSE_symbolCompressionTransform*) (FSCT);\n    U32 const step = FSE_TABLESTEP(tableSize);\n    U32 const maxSV1 = maxSymbolValue+1;\n\n    U16* cumul = (U16*)workSpace;   /* size = maxSV1 */\n    FSE_FUNCTION_TYPE* const tableSymbol = (FSE_FUNCTION_TYPE*)(cumul + (maxSV1+1));  /* size = tableSize */\n\n    U32 highThreshold = tableSize-1;\n\n    assert(((size_t)workSpace & 1) == 0);  /* Must be 2 bytes-aligned */\n    if (FSE_BUILD_CTABLE_WORKSPACE_SIZE(maxSymbolValue, tableLog) > wkspSize) return ERROR(tableLog_tooLarge);\n    /* CTable header */\n    tableU16[-2] = (U16) tableLog;\n    tableU16[-1] = (U16) maxSymbolValue;\n    assert(tableLog < 16);   /* required for threshold strategy to work */\n\n    /* For explanations on how to distribute symbol values over the table :\n     * https://fastcompression.blogspot.fr/2014/02/fse-distributing-symbol-values.html */\n\n     #ifdef __clang_analyzer__\n     ZSTD_memset(tableSymbol, 0, sizeof(*tableSymbol) * tableSize);   /* useless initialization, just to keep scan-build happy */\n     #endif\n\n    /* symbol start positions */\n    {   U32 u;\n        cumul[0] = 0;\n        for (u=1; u <= maxSV1; u++) {\n            if (normalizedCounter[u-1]==-1) {  /* Low proba symbol */\n                cumul[u] = cumul[u-1] + 1;\n                tableSymbol[highThreshold--] = (FSE_FUNCTION_TYPE)(u-1);\n            } else {\n                assert(normalizedCounter[u-1] >= 0);\n                cumul[u] = cumul[u-1] + (U16)normalizedCounter[u-1];\n                assert(cumul[u] >= cumul[u-1]);  /* no overflow */\n        }   }\n        cumul[maxSV1] = (U16)(tableSize+1);\n    }\n\n    /* Spread symbols */\n    if (highThreshold == tableSize - 1) {\n        /* Case for no low prob count symbols. Lay down 8 bytes at a time\n         * to reduce branch misses since we are operating on a small block\n         */\n        BYTE* const spread = tableSymbol + tableSize; /* size = tableSize + 8 (may write beyond tableSize) */\n        {   U64 const add = 0x0101010101010101ull;\n            size_t pos = 0;\n            U64 sv = 0;\n            U32 s;\n            for (s=0; s<maxSV1; ++s, sv += add) {\n                int i;\n                int const n = normalizedCounter[s];\n                MEM_write64(spread + pos, sv);\n                for (i = 8; i < n; i += 8) {\n                    MEM_write64(spread + pos + i, sv);\n                }\n                assert(n>=0);\n                pos += (size_t)n;\n            }\n        }\n        /* Spread symbols across the table. Lack of lowprob symbols means that\n         * we don't need variable sized inner loop, so we can unroll the loop and\n         * reduce branch misses.\n         */\n        {   size_t position = 0;\n            size_t s;\n            size_t const unroll = 2; /* Experimentally determined optimal unroll */\n            assert(tableSize % unroll == 0); /* FSE_MIN_TABLELOG is 5 */\n            for (s = 0; s < (size_t)tableSize; s += unroll) {\n                size_t u;\n                for (u = 0; u < unroll; ++u) {\n                    size_t const uPosition = (position + (u * step)) & tableMask;\n                    tableSymbol[uPosition] = spread[s + u];\n                }\n                position = (position + (unroll * step)) & tableMask;\n            }\n            assert(position == 0);   /* Must have initialized all positions */\n        }\n    } else {\n        U32 position = 0;\n        U32 symbol;\n        for (symbol=0; symbol<maxSV1; symbol++) {\n            int nbOccurrences;\n            int const freq = normalizedCounter[symbol];\n            for (nbOccurrences=0; nbOccurrences<freq; nbOccurrences++) {\n                tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol;\n                position = (position + step) & tableMask;\n                while (position > highThreshold)\n                    position = (position + step) & tableMask;   /* Low proba area */\n        }   }\n        assert(position==0);  /* Must have initialized all positions */\n    }\n\n    /* Build table */\n    {   U32 u; for (u=0; u<tableSize; u++) {\n        FSE_FUNCTION_TYPE s = tableSymbol[u];   /* note : static analyzer may not understand tableSymbol is properly initialized */\n        tableU16[cumul[s]++] = (U16) (tableSize+u);   /* TableU16 : sorted by symbol order; gives next state value */\n    }   }\n\n    /* Build Symbol Transformation Table */\n    {   unsigned total = 0;\n        unsigned s;\n        for (s=0; s<=maxSymbolValue; s++) {\n            switch (normalizedCounter[s])\n            {\n            case  0:\n                /* filling nonetheless, for compatibility with FSE_getMaxNbBits() */\n                symbolTT[s].deltaNbBits = ((tableLog+1) << 16) - (1<<tableLog);\n                break;\n\n            case -1:\n            case  1:\n                symbolTT[s].deltaNbBits = (tableLog << 16) - (1<<tableLog);\n                assert(total <= INT_MAX);\n                symbolTT[s].deltaFindState = (int)(total - 1);\n                total ++;\n                break;\n            default :\n                assert(normalizedCounter[s] > 1);\n                {   U32 const maxBitsOut = tableLog - ZSTD_highbit32 ((U32)normalizedCounter[s]-1);\n                    U32 const minStatePlus = (U32)normalizedCounter[s] << maxBitsOut;\n                    symbolTT[s].deltaNbBits = (maxBitsOut << 16) - minStatePlus;\n                    symbolTT[s].deltaFindState = (int)(total - (unsigned)normalizedCounter[s]);\n                    total +=  (unsigned)normalizedCounter[s];\n    }   }   }   }\n\n#if 0  /* debug : symbol costs */\n    DEBUGLOG(5, \"\\n --- table statistics : \");\n    {   U32 symbol;\n        for (symbol=0; symbol<=maxSymbolValue; symbol++) {\n            DEBUGLOG(5, \"%3u: w=%3i,   maxBits=%u, fracBits=%.2f\",\n                symbol, normalizedCounter[symbol],\n                FSE_getMaxNbBits(symbolTT, symbol),\n                (double)FSE_bitCost(symbolTT, tableLog, symbol, 8) / 256);\n    }   }\n#endif\n\n    return 0;\n}\n\n\n\n#ifndef FSE_COMMONDEFS_ONLY\n\n/*-**************************************************************\n*  FSE NCount encoding\n****************************************************************/\nsize_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog)\n{\n    size_t const maxHeaderSize = (((maxSymbolValue+1) * tableLog\n                                   + 4 /* bitCount initialized at 4 */\n                                   + 2 /* first two symbols may use one additional bit each */) / 8)\n                                   + 1 /* round up to whole nb bytes */\n                                   + 2 /* additional two bytes for bitstream flush */;\n    return maxSymbolValue ? maxHeaderSize : FSE_NCOUNTBOUND;  /* maxSymbolValue==0 ? use default */\n}\n\nstatic size_t\nFSE_writeNCount_generic (void* header, size_t headerBufferSize,\n                   const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog,\n                         unsigned writeIsSafe)\n{\n    BYTE* const ostart = (BYTE*) header;\n    BYTE* out = ostart;\n    BYTE* const oend = ostart + headerBufferSize;\n    int nbBits;\n    const int tableSize = 1 << tableLog;\n    int remaining;\n    int threshold;\n    U32 bitStream = 0;\n    int bitCount = 0;\n    unsigned symbol = 0;\n    unsigned const alphabetSize = maxSymbolValue + 1;\n    int previousIs0 = 0;\n\n    /* Table Size */\n    bitStream += (tableLog-FSE_MIN_TABLELOG) << bitCount;\n    bitCount  += 4;\n\n    /* Init */\n    remaining = tableSize+1;   /* +1 for extra accuracy */\n    threshold = tableSize;\n    nbBits = (int)tableLog+1;\n\n    while ((symbol < alphabetSize) && (remaining>1)) {  /* stops at 1 */\n        if (previousIs0) {\n            unsigned start = symbol;\n            while ((symbol < alphabetSize) && !normalizedCounter[symbol]) symbol++;\n            if (symbol == alphabetSize) break;   /* incorrect distribution */\n            while (symbol >= start+24) {\n                start+=24;\n                bitStream += 0xFFFFU << bitCount;\n                if ((!writeIsSafe) && (out > oend-2))\n                    return ERROR(dstSize_tooSmall);   /* Buffer overflow */\n                out[0] = (BYTE) bitStream;\n                out[1] = (BYTE)(bitStream>>8);\n                out+=2;\n                bitStream>>=16;\n            }\n            while (symbol >= start+3) {\n                start+=3;\n                bitStream += 3U << bitCount;\n                bitCount += 2;\n            }\n            bitStream += (symbol-start) << bitCount;\n            bitCount += 2;\n            if (bitCount>16) {\n                if ((!writeIsSafe) && (out > oend - 2))\n                    return ERROR(dstSize_tooSmall);   /* Buffer overflow */\n                out[0] = (BYTE)bitStream;\n                out[1] = (BYTE)(bitStream>>8);\n                out += 2;\n                bitStream >>= 16;\n                bitCount -= 16;\n        }   }\n        {   int count = normalizedCounter[symbol++];\n            int const max = (2*threshold-1) - remaining;\n            remaining -= count < 0 ? -count : count;\n            count++;   /* +1 for extra accuracy */\n            if (count>=threshold)\n                count += max;   /* [0..max[ [max..threshold[ (...) [threshold+max 2*threshold[ */\n            bitStream += (U32)count << bitCount;\n            bitCount  += nbBits;\n            bitCount  -= (count<max);\n            previousIs0  = (count==1);\n            if (remaining<1) return ERROR(GENERIC);\n            while (remaining<threshold) { nbBits--; threshold>>=1; }\n        }\n        if (bitCount>16) {\n            if ((!writeIsSafe) && (out > oend - 2))\n                return ERROR(dstSize_tooSmall);   /* Buffer overflow */\n            out[0] = (BYTE)bitStream;\n            out[1] = (BYTE)(bitStream>>8);\n            out += 2;\n            bitStream >>= 16;\n            bitCount -= 16;\n    }   }\n\n    if (remaining != 1)\n        return ERROR(GENERIC);  /* incorrect normalized distribution */\n    assert(symbol <= alphabetSize);\n\n    /* flush remaining bitStream */\n    if ((!writeIsSafe) && (out > oend - 2))\n        return ERROR(dstSize_tooSmall);   /* Buffer overflow */\n    out[0] = (BYTE)bitStream;\n    out[1] = (BYTE)(bitStream>>8);\n    out+= (bitCount+7) /8;\n\n    assert(out >= ostart);\n    return (size_t)(out-ostart);\n}\n\n\nsize_t FSE_writeNCount (void* buffer, size_t bufferSize,\n                  const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)\n{\n    if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);   /* Unsupported */\n    if (tableLog < FSE_MIN_TABLELOG) return ERROR(GENERIC);   /* Unsupported */\n\n    if (bufferSize < FSE_NCountWriteBound(maxSymbolValue, tableLog))\n        return FSE_writeNCount_generic(buffer, bufferSize, normalizedCounter, maxSymbolValue, tableLog, 0);\n\n    return FSE_writeNCount_generic(buffer, bufferSize, normalizedCounter, maxSymbolValue, tableLog, 1 /* write in buffer is safe */);\n}\n\n\n/*-**************************************************************\n*  FSE Compression Code\n****************************************************************/\n\n/* provides the minimum logSize to safely represent a distribution */\nstatic unsigned FSE_minTableLog(size_t srcSize, unsigned maxSymbolValue)\n{\n    U32 minBitsSrc = ZSTD_highbit32((U32)(srcSize)) + 1;\n    U32 minBitsSymbols = ZSTD_highbit32(maxSymbolValue) + 2;\n    U32 minBits = minBitsSrc < minBitsSymbols ? minBitsSrc : minBitsSymbols;\n    assert(srcSize > 1); /* Not supported, RLE should be used instead */\n    return minBits;\n}\n\nunsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus)\n{\n    U32 maxBitsSrc = ZSTD_highbit32((U32)(srcSize - 1)) - minus;\n    U32 tableLog = maxTableLog;\n    U32 minBits = FSE_minTableLog(srcSize, maxSymbolValue);\n    assert(srcSize > 1); /* Not supported, RLE should be used instead */\n    if (tableLog==0) tableLog = FSE_DEFAULT_TABLELOG;\n    if (maxBitsSrc < tableLog) tableLog = maxBitsSrc;   /* Accuracy can be reduced */\n    if (minBits > tableLog) tableLog = minBits;   /* Need a minimum to safely represent all symbol values */\n    if (tableLog < FSE_MIN_TABLELOG) tableLog = FSE_MIN_TABLELOG;\n    if (tableLog > FSE_MAX_TABLELOG) tableLog = FSE_MAX_TABLELOG;\n    return tableLog;\n}\n\nunsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue)\n{\n    return FSE_optimalTableLog_internal(maxTableLog, srcSize, maxSymbolValue, 2);\n}\n\n/* Secondary normalization method.\n   To be used when primary method fails. */\n\nstatic size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, size_t total, U32 maxSymbolValue, short lowProbCount)\n{\n    short const NOT_YET_ASSIGNED = -2;\n    U32 s;\n    U32 distributed = 0;\n    U32 ToDistribute;\n\n    /* Init */\n    U32 const lowThreshold = (U32)(total >> tableLog);\n    U32 lowOne = (U32)((total * 3) >> (tableLog + 1));\n\n    for (s=0; s<=maxSymbolValue; s++) {\n        if (count[s] == 0) {\n            norm[s]=0;\n            continue;\n        }\n        if (count[s] <= lowThreshold) {\n            norm[s] = lowProbCount;\n            distributed++;\n            total -= count[s];\n            continue;\n        }\n        if (count[s] <= lowOne) {\n            norm[s] = 1;\n            distributed++;\n            total -= count[s];\n            continue;\n        }\n\n        norm[s]=NOT_YET_ASSIGNED;\n    }\n    ToDistribute = (1 << tableLog) - distributed;\n\n    if (ToDistribute == 0)\n        return 0;\n\n    if ((total / ToDistribute) > lowOne) {\n        /* risk of rounding to zero */\n        lowOne = (U32)((total * 3) / (ToDistribute * 2));\n        for (s=0; s<=maxSymbolValue; s++) {\n            if ((norm[s] == NOT_YET_ASSIGNED) && (count[s] <= lowOne)) {\n                norm[s] = 1;\n                distributed++;\n                total -= count[s];\n                continue;\n        }   }\n        ToDistribute = (1 << tableLog) - distributed;\n    }\n\n    if (distributed == maxSymbolValue+1) {\n        /* all values are pretty poor;\n           probably incompressible data (should have already been detected);\n           find max, then give all remaining points to max */\n        U32 maxV = 0, maxC = 0;\n        for (s=0; s<=maxSymbolValue; s++)\n            if (count[s] > maxC) { maxV=s; maxC=count[s]; }\n        norm[maxV] += (short)ToDistribute;\n        return 0;\n    }\n\n    if (total == 0) {\n        /* all of the symbols were low enough for the lowOne or lowThreshold */\n        for (s=0; ToDistribute > 0; s = (s+1)%(maxSymbolValue+1))\n            if (norm[s] > 0) { ToDistribute--; norm[s]++; }\n        return 0;\n    }\n\n    {   U64 const vStepLog = 62 - tableLog;\n        U64 const mid = (1ULL << (vStepLog-1)) - 1;\n        U64 const rStep = ZSTD_div64((((U64)1<<vStepLog) * ToDistribute) + mid, (U32)total);   /* scale on remaining */\n        U64 tmpTotal = mid;\n        for (s=0; s<=maxSymbolValue; s++) {\n            if (norm[s]==NOT_YET_ASSIGNED) {\n                U64 const end = tmpTotal + (count[s] * rStep);\n                U32 const sStart = (U32)(tmpTotal >> vStepLog);\n                U32 const sEnd = (U32)(end >> vStepLog);\n                U32 const weight = sEnd - sStart;\n                if (weight < 1)\n                    return ERROR(GENERIC);\n                norm[s] = (short)weight;\n                tmpTotal = end;\n    }   }   }\n\n    return 0;\n}\n\nsize_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog,\n                           const unsigned* count, size_t total,\n                           unsigned maxSymbolValue, unsigned useLowProbCount)\n{\n    /* Sanity checks */\n    if (tableLog==0) tableLog = FSE_DEFAULT_TABLELOG;\n    if (tableLog < FSE_MIN_TABLELOG) return ERROR(GENERIC);   /* Unsupported size */\n    if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);   /* Unsupported size */\n    if (tableLog < FSE_minTableLog(total, maxSymbolValue)) return ERROR(GENERIC);   /* Too small tableLog, compression potentially impossible */\n\n    {   static U32 const rtbTable[] = {     0, 473195, 504333, 520860, 550000, 700000, 750000, 830000 };\n        short const lowProbCount = useLowProbCount ? -1 : 1;\n        U64 const scale = 62 - tableLog;\n        U64 const step = ZSTD_div64((U64)1<<62, (U32)total);   /* <== here, one division ! */\n        U64 const vStep = 1ULL<<(scale-20);\n        int stillToDistribute = 1<<tableLog;\n        unsigned s;\n        unsigned largest=0;\n        short largestP=0;\n        U32 lowThreshold = (U32)(total >> tableLog);\n\n        for (s=0; s<=maxSymbolValue; s++) {\n            if (count[s] == total) return 0;   /* rle special case */\n            if (count[s] == 0) { normalizedCounter[s]=0; continue; }\n            if (count[s] <= lowThreshold) {\n                normalizedCounter[s] = lowProbCount;\n                stillToDistribute--;\n            } else {\n                short proba = (short)((count[s]*step) >> scale);\n                if (proba<8) {\n                    U64 restToBeat = vStep * rtbTable[proba];\n                    proba += (count[s]*step) - ((U64)proba<<scale) > restToBeat;\n                }\n                if (proba > largestP) { largestP=proba; largest=s; }\n                normalizedCounter[s] = proba;\n                stillToDistribute -= proba;\n        }   }\n        if (-stillToDistribute >= (normalizedCounter[largest] >> 1)) {\n            /* corner case, need another normalization method */\n            size_t const errorCode = FSE_normalizeM2(normalizedCounter, tableLog, count, total, maxSymbolValue, lowProbCount);\n            if (FSE_isError(errorCode)) return errorCode;\n        }\n        else normalizedCounter[largest] += (short)stillToDistribute;\n    }\n\n#if 0\n    {   /* Print Table (debug) */\n        U32 s;\n        U32 nTotal = 0;\n        for (s=0; s<=maxSymbolValue; s++)\n            RAWLOG(2, \"%3i: %4i \\n\", s, normalizedCounter[s]);\n        for (s=0; s<=maxSymbolValue; s++)\n            nTotal += abs(normalizedCounter[s]);\n        if (nTotal != (1U<<tableLog))\n            RAWLOG(2, \"Warning !!! Total == %u != %u !!!\", nTotal, 1U<<tableLog);\n        getchar();\n    }\n#endif\n\n    return tableLog;\n}\n\n/* fake FSE_CTable, for rle input (always same symbol) */\nsize_t FSE_buildCTable_rle (FSE_CTable* ct, BYTE symbolValue)\n{\n    void* ptr = ct;\n    U16* tableU16 = ( (U16*) ptr) + 2;\n    void* FSCTptr = (U32*)ptr + 2;\n    FSE_symbolCompressionTransform* symbolTT = (FSE_symbolCompressionTransform*) FSCTptr;\n\n    /* header */\n    tableU16[-2] = (U16) 0;\n    tableU16[-1] = (U16) symbolValue;\n\n    /* Build table */\n    tableU16[0] = 0;\n    tableU16[1] = 0;   /* just in case */\n\n    /* Build Symbol Transformation Table */\n    symbolTT[symbolValue].deltaNbBits = 0;\n    symbolTT[symbolValue].deltaFindState = 0;\n\n    return 0;\n}\n\n\nstatic size_t FSE_compress_usingCTable_generic (void* dst, size_t dstSize,\n                           const void* src, size_t srcSize,\n                           const FSE_CTable* ct, const unsigned fast)\n{\n    const BYTE* const istart = (const BYTE*) src;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* ip=iend;\n\n    BIT_CStream_t bitC;\n    FSE_CState_t CState1, CState2;\n\n    /* init */\n    if (srcSize <= 2) return 0;\n    { size_t const initError = BIT_initCStream(&bitC, dst, dstSize);\n      if (FSE_isError(initError)) return 0; /* not enough space available to write a bitstream */ }\n\n#define FSE_FLUSHBITS(s)  (fast ? BIT_flushBitsFast(s) : BIT_flushBits(s))\n\n    if (srcSize & 1) {\n        FSE_initCState2(&CState1, ct, *--ip);\n        FSE_initCState2(&CState2, ct, *--ip);\n        FSE_encodeSymbol(&bitC, &CState1, *--ip);\n        FSE_FLUSHBITS(&bitC);\n    } else {\n        FSE_initCState2(&CState2, ct, *--ip);\n        FSE_initCState2(&CState1, ct, *--ip);\n    }\n\n    /* join to mod 4 */\n    srcSize -= 2;\n    if ((sizeof(bitC.bitContainer)*8 > FSE_MAX_TABLELOG*4+7 ) && (srcSize & 2)) {  /* test bit 2 */\n        FSE_encodeSymbol(&bitC, &CState2, *--ip);\n        FSE_encodeSymbol(&bitC, &CState1, *--ip);\n        FSE_FLUSHBITS(&bitC);\n    }\n\n    /* 2 or 4 encoding per loop */\n    while ( ip>istart ) {\n\n        FSE_encodeSymbol(&bitC, &CState2, *--ip);\n\n        if (sizeof(bitC.bitContainer)*8 < FSE_MAX_TABLELOG*2+7 )   /* this test must be static */\n            FSE_FLUSHBITS(&bitC);\n\n        FSE_encodeSymbol(&bitC, &CState1, *--ip);\n\n        if (sizeof(bitC.bitContainer)*8 > FSE_MAX_TABLELOG*4+7 ) {  /* this test must be static */\n            FSE_encodeSymbol(&bitC, &CState2, *--ip);\n            FSE_encodeSymbol(&bitC, &CState1, *--ip);\n        }\n\n        FSE_FLUSHBITS(&bitC);\n    }\n\n    FSE_flushCState(&bitC, &CState2);\n    FSE_flushCState(&bitC, &CState1);\n    return BIT_closeCStream(&bitC);\n}\n\nsize_t FSE_compress_usingCTable (void* dst, size_t dstSize,\n                           const void* src, size_t srcSize,\n                           const FSE_CTable* ct)\n{\n    unsigned const fast = (dstSize >= FSE_BLOCKBOUND(srcSize));\n\n    if (fast)\n        return FSE_compress_usingCTable_generic(dst, dstSize, src, srcSize, ct, 1);\n    else\n        return FSE_compress_usingCTable_generic(dst, dstSize, src, srcSize, ct, 0);\n}\n\n\nsize_t FSE_compressBound(size_t size) { return FSE_COMPRESSBOUND(size); }\n\n#endif   /* FSE_COMMONDEFS_ONLY */\n"
  },
  {
    "path": "lib/compress/hist.c",
    "content": "/* ******************************************************************\n * hist : Histogram functions\n * part of Finite State Entropy project\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n *  You can contact the author at :\n *  - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *  - Public forum : https://groups.google.com/forum/#!forum/lz4c\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n/* --- dependencies --- */\n#include \"../common/mem.h\"             /* U32, BYTE, etc. */\n#include \"../common/debug.h\"           /* assert, DEBUGLOG */\n#include \"../common/error_private.h\"   /* ERROR */\n#include \"hist.h\"\n\n#if defined(ZSTD_ARCH_ARM_SVE2)\n#define HIST_FAST_THRESHOLD 500\n#else\n#define HIST_FAST_THRESHOLD 1500\n#endif\n\n\n/* --- Error management --- */\nunsigned HIST_isError(size_t code) { return ERR_isError(code); }\n\n/*-**************************************************************\n *  Histogram functions\n ****************************************************************/\nvoid HIST_add(unsigned* count, const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n    const BYTE* const end = ip + srcSize;\n\n    while (ip<end) {\n        count[*ip++]++;\n    }\n}\n\nunsigned HIST_count_simple(unsigned* count, unsigned* maxSymbolValuePtr,\n                           const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n    const BYTE* const end = ip + srcSize;\n    unsigned maxSymbolValue = *maxSymbolValuePtr;\n    unsigned largestCount=0;\n\n    ZSTD_memset(count, 0, (maxSymbolValue+1) * sizeof(*count));\n    if (srcSize==0) { *maxSymbolValuePtr = 0; return 0; }\n\n    while (ip<end) {\n        assert(*ip <= maxSymbolValue);\n        count[*ip++]++;\n    }\n\n    while (!count[maxSymbolValue]) maxSymbolValue--;\n    *maxSymbolValuePtr = maxSymbolValue;\n\n    {   U32 s;\n        for (s=0; s<=maxSymbolValue; s++)\n            if (count[s] > largestCount) largestCount = count[s];\n    }\n\n    return largestCount;\n}\n\ntypedef enum { trustInput, checkMaxSymbolValue } HIST_checkInput_e;\n\n#if defined(ZSTD_ARCH_ARM_SVE2)\nFORCE_INLINE_TEMPLATE size_t min_size(size_t a, size_t b) { return a < b ? a : b; }\n\nstatic\nsvuint16_t HIST_count_6_sve2(const BYTE* const src, size_t size, U32* const dst,\n                             const svuint8_t c0, const svuint8_t c1,\n                             const svuint8_t c2, const svuint8_t c3,\n                             const svuint8_t c4, const svuint8_t c5,\n                             const svuint16_t histmax, size_t maxCount)\n{\n    const svbool_t vl128 = svptrue_pat_b8(SV_VL16);\n    svuint16_t hh0 = svdup_n_u16(0);\n    svuint16_t hh1 = svdup_n_u16(0);\n    svuint16_t hh2 = svdup_n_u16(0);\n    svuint16_t hh3 = svdup_n_u16(0);\n    svuint16_t hh4 = svdup_n_u16(0);\n    svuint16_t hh5 = svdup_n_u16(0);\n    svuint16_t hh6 = svdup_n_u16(0);\n    svuint16_t hh7 = svdup_n_u16(0);\n    svuint16_t hh8 = svdup_n_u16(0);\n    svuint16_t hh9 = svdup_n_u16(0);\n    svuint16_t hha = svdup_n_u16(0);\n    svuint16_t hhb = svdup_n_u16(0);\n\n    size_t i = 0;\n    while (i < size) {\n        /* We can only accumulate 15 (15 * 16 <= 255) iterations of histogram\n         * in 8-bit accumulators! */\n        const size_t size240 = min_size(i + 240, size);\n\n        svbool_t pred = svwhilelt_b8_u64(i, size);\n        svuint8_t c = svld1rq_u8(pred, src + i);\n        svuint8_t h0 = svhistseg_u8(c0, c);\n        svuint8_t h1 = svhistseg_u8(c1, c);\n        svuint8_t h2 = svhistseg_u8(c2, c);\n        svuint8_t h3 = svhistseg_u8(c3, c);\n        svuint8_t h4 = svhistseg_u8(c4, c);\n        svuint8_t h5 = svhistseg_u8(c5, c);\n\n        for (i += 16; i < size240; i += 16) {\n            pred = svwhilelt_b8_u64(i, size);\n            c = svld1rq_u8(pred, src + i);\n            h0 = svadd_u8_x(vl128, h0, svhistseg_u8(c0, c));\n            h1 = svadd_u8_x(vl128, h1, svhistseg_u8(c1, c));\n            h2 = svadd_u8_x(vl128, h2, svhistseg_u8(c2, c));\n            h3 = svadd_u8_x(vl128, h3, svhistseg_u8(c3, c));\n            h4 = svadd_u8_x(vl128, h4, svhistseg_u8(c4, c));\n            h5 = svadd_u8_x(vl128, h5, svhistseg_u8(c5, c));\n        }\n\n        hh0 = svaddwb_u16(hh0, h0);\n        hh1 = svaddwt_u16(hh1, h0);\n        hh2 = svaddwb_u16(hh2, h1);\n        hh3 = svaddwt_u16(hh3, h1);\n        hh4 = svaddwb_u16(hh4, h2);\n        hh5 = svaddwt_u16(hh5, h2);\n        hh6 = svaddwb_u16(hh6, h3);\n        hh7 = svaddwt_u16(hh7, h3);\n        hh8 = svaddwb_u16(hh8, h4);\n        hh9 = svaddwt_u16(hh9, h4);\n        hha = svaddwb_u16(hha, h5);\n        hhb = svaddwt_u16(hhb, h5);\n    }\n\n    svst1_u32(svwhilelt_b32_u64( 0, maxCount), dst +  0, svshllb_n_u32(hh0, 0));\n    svst1_u32(svwhilelt_b32_u64( 4, maxCount), dst +  4, svshllt_n_u32(hh0, 0));\n    svst1_u32(svwhilelt_b32_u64( 8, maxCount), dst +  8, svshllb_n_u32(hh1, 0));\n    svst1_u32(svwhilelt_b32_u64(12, maxCount), dst + 12, svshllt_n_u32(hh1, 0));\n    svst1_u32(svwhilelt_b32_u64(16, maxCount), dst + 16, svshllb_n_u32(hh2, 0));\n    svst1_u32(svwhilelt_b32_u64(20, maxCount), dst + 20, svshllt_n_u32(hh2, 0));\n    svst1_u32(svwhilelt_b32_u64(24, maxCount), dst + 24, svshllb_n_u32(hh3, 0));\n    svst1_u32(svwhilelt_b32_u64(28, maxCount), dst + 28, svshllt_n_u32(hh3, 0));\n    svst1_u32(svwhilelt_b32_u64(32, maxCount), dst + 32, svshllb_n_u32(hh4, 0));\n    svst1_u32(svwhilelt_b32_u64(36, maxCount), dst + 36, svshllt_n_u32(hh4, 0));\n    svst1_u32(svwhilelt_b32_u64(40, maxCount), dst + 40, svshllb_n_u32(hh5, 0));\n    svst1_u32(svwhilelt_b32_u64(44, maxCount), dst + 44, svshllt_n_u32(hh5, 0));\n    svst1_u32(svwhilelt_b32_u64(48, maxCount), dst + 48, svshllb_n_u32(hh6, 0));\n    svst1_u32(svwhilelt_b32_u64(52, maxCount), dst + 52, svshllt_n_u32(hh6, 0));\n    svst1_u32(svwhilelt_b32_u64(56, maxCount), dst + 56, svshllb_n_u32(hh7, 0));\n    svst1_u32(svwhilelt_b32_u64(60, maxCount), dst + 60, svshllt_n_u32(hh7, 0));\n    svst1_u32(svwhilelt_b32_u64(64, maxCount), dst + 64, svshllb_n_u32(hh8, 0));\n    svst1_u32(svwhilelt_b32_u64(68, maxCount), dst + 68, svshllt_n_u32(hh8, 0));\n    svst1_u32(svwhilelt_b32_u64(72, maxCount), dst + 72, svshllb_n_u32(hh9, 0));\n    svst1_u32(svwhilelt_b32_u64(76, maxCount), dst + 76, svshllt_n_u32(hh9, 0));\n    svst1_u32(svwhilelt_b32_u64(80, maxCount), dst + 80, svshllb_n_u32(hha, 0));\n    svst1_u32(svwhilelt_b32_u64(84, maxCount), dst + 84, svshllt_n_u32(hha, 0));\n    svst1_u32(svwhilelt_b32_u64(88, maxCount), dst + 88, svshllb_n_u32(hhb, 0));\n    svst1_u32(svwhilelt_b32_u64(92, maxCount), dst + 92, svshllt_n_u32(hhb, 0));\n\n    hh0 = svmax_u16_x(vl128, hh0, hh1);\n    hh2 = svmax_u16_x(vl128, hh2, hh3);\n    hh4 = svmax_u16_x(vl128, hh4, hh5);\n    hh6 = svmax_u16_x(vl128, hh6, hh7);\n    hh8 = svmax_u16_x(vl128, hh8, hh9);\n    hha = svmax_u16_x(vl128, hha, hhb);\n    hh0 = svmax_u16_x(vl128, hh0, hh2);\n    hh4 = svmax_u16_x(vl128, hh4, hh6);\n    hh8 = svmax_u16_x(vl128, hh8, hha);\n    hh0 = svmax_u16_x(vl128, hh0, hh4);\n    hh8 = svmax_u16_x(vl128, hh8, histmax);\n    return svmax_u16_x(vl128, hh0, hh8);\n}\n\nstatic size_t HIST_count_sve2(unsigned* count, unsigned* maxSymbolValuePtr,\n                              const void* source, size_t sourceSize,\n                              HIST_checkInput_e check)\n{\n    const BYTE* ip = (const BYTE*)source;\n    const size_t maxCount = *maxSymbolValuePtr + 1;\n\n    assert(*maxSymbolValuePtr <= 255);\n    if (!sourceSize) {\n        ZSTD_memset(count, 0, maxCount * sizeof(*count));\n        *maxSymbolValuePtr = 0;\n        return 0;\n    }\n\n    {   const svbool_t vl128 = svptrue_pat_b8(SV_VL16);\n        const svuint8_t c0 = svreinterpret_u8(svindex_u32(0x0C040800, 0x01010101));\n        const svuint8_t c1 = svadd_n_u8_x(vl128, c0, 16);\n        const svuint8_t c2 = svadd_n_u8_x(vl128, c0, 32);\n        const svuint8_t c3 = svadd_n_u8_x(vl128, c1, 32);\n\n        svuint8_t symbolMax = svdup_n_u8(0);\n        svuint16_t hh0 = svdup_n_u16(0);\n        svuint16_t hh1 = svdup_n_u16(0);\n        svuint16_t hh2 = svdup_n_u16(0);\n        svuint16_t hh3 = svdup_n_u16(0);\n        svuint16_t hh4 = svdup_n_u16(0);\n        svuint16_t hh5 = svdup_n_u16(0);\n        svuint16_t hh6 = svdup_n_u16(0);\n        svuint16_t hh7 = svdup_n_u16(0);\n        svuint16_t max;\n        size_t maxSymbolValue;\n\n        size_t i = 0;\n        while (i < sourceSize) {\n            /* We can only accumulate 15 (15 * 16 <= 255) iterations of\n             * histogram in 8-bit accumulators! */\n            const size_t size240 = min_size(i + 240, sourceSize);\n\n            svbool_t pred = svwhilelt_b8_u64(i, sourceSize);\n            svuint8_t c = svld1rq_u8(pred, ip + i);\n            svuint8_t h0 = svhistseg_u8(c0, c);\n            svuint8_t h1 = svhistseg_u8(c1, c);\n            svuint8_t h2 = svhistseg_u8(c2, c);\n            svuint8_t h3 = svhistseg_u8(c3, c);\n            symbolMax = svmax_u8_x(vl128, symbolMax, c);\n\n            for (i += 16; i < size240; i += 16) {\n                pred = svwhilelt_b8_u64(i, sourceSize);\n                c = svld1rq_u8(pred, ip + i);\n                h0 = svadd_u8_x(vl128, h0, svhistseg_u8(c0, c));\n                h1 = svadd_u8_x(vl128, h1, svhistseg_u8(c1, c));\n                h2 = svadd_u8_x(vl128, h2, svhistseg_u8(c2, c));\n                h3 = svadd_u8_x(vl128, h3, svhistseg_u8(c3, c));\n                symbolMax = svmax_u8_x(vl128, symbolMax, c);\n            }\n\n            hh0 = svaddwb_u16(hh0, h0);\n            hh1 = svaddwt_u16(hh1, h0);\n            hh2 = svaddwb_u16(hh2, h1);\n            hh3 = svaddwt_u16(hh3, h1);\n            hh4 = svaddwb_u16(hh4, h2);\n            hh5 = svaddwt_u16(hh5, h2);\n            hh6 = svaddwb_u16(hh6, h3);\n            hh7 = svaddwt_u16(hh7, h3);\n        }\n        maxSymbolValue = svmaxv_u8(vl128, symbolMax);\n\n        if (check && maxSymbolValue > *maxSymbolValuePtr) return ERROR(maxSymbolValue_tooSmall);\n        *maxSymbolValuePtr = maxSymbolValue;\n\n        /* If the buffer size is not divisible by 16, the last elements of the final\n         * vector register read will be zeros, and these elements must be subtracted\n         * from the histogram.\n         */\n        hh0 = svsub_n_u16_m(svptrue_pat_b32(SV_VL1), hh0, -sourceSize & 15);\n\n        svst1_u32(svwhilelt_b32_u64( 0, maxCount), count +  0, svshllb_n_u32(hh0, 0));\n        svst1_u32(svwhilelt_b32_u64( 4, maxCount), count +  4, svshllt_n_u32(hh0, 0));\n        svst1_u32(svwhilelt_b32_u64( 8, maxCount), count +  8, svshllb_n_u32(hh1, 0));\n        svst1_u32(svwhilelt_b32_u64(12, maxCount), count + 12, svshllt_n_u32(hh1, 0));\n        svst1_u32(svwhilelt_b32_u64(16, maxCount), count + 16, svshllb_n_u32(hh2, 0));\n        svst1_u32(svwhilelt_b32_u64(20, maxCount), count + 20, svshllt_n_u32(hh2, 0));\n        svst1_u32(svwhilelt_b32_u64(24, maxCount), count + 24, svshllb_n_u32(hh3, 0));\n        svst1_u32(svwhilelt_b32_u64(28, maxCount), count + 28, svshllt_n_u32(hh3, 0));\n        svst1_u32(svwhilelt_b32_u64(32, maxCount), count + 32, svshllb_n_u32(hh4, 0));\n        svst1_u32(svwhilelt_b32_u64(36, maxCount), count + 36, svshllt_n_u32(hh4, 0));\n        svst1_u32(svwhilelt_b32_u64(40, maxCount), count + 40, svshllb_n_u32(hh5, 0));\n        svst1_u32(svwhilelt_b32_u64(44, maxCount), count + 44, svshllt_n_u32(hh5, 0));\n        svst1_u32(svwhilelt_b32_u64(48, maxCount), count + 48, svshllb_n_u32(hh6, 0));\n        svst1_u32(svwhilelt_b32_u64(52, maxCount), count + 52, svshllt_n_u32(hh6, 0));\n        svst1_u32(svwhilelt_b32_u64(56, maxCount), count + 56, svshllb_n_u32(hh7, 0));\n        svst1_u32(svwhilelt_b32_u64(60, maxCount), count + 60, svshllt_n_u32(hh7, 0));\n\n        hh0 = svmax_u16_x(vl128, hh0, hh1);\n        hh2 = svmax_u16_x(vl128, hh2, hh3);\n        hh4 = svmax_u16_x(vl128, hh4, hh5);\n        hh6 = svmax_u16_x(vl128, hh6, hh7);\n        hh0 = svmax_u16_x(vl128, hh0, hh2);\n        hh4 = svmax_u16_x(vl128, hh4, hh6);\n        max = svmax_u16_x(vl128, hh0, hh4);\n\n        maxSymbolValue = min_size(maxSymbolValue, maxCount);\n        if (maxSymbolValue >= 64) {\n            const svuint8_t c4 = svadd_n_u8_x(vl128, c0,  64);\n            const svuint8_t c5 = svadd_n_u8_x(vl128, c1,  64);\n            const svuint8_t c6 = svadd_n_u8_x(vl128, c2,  64);\n            const svuint8_t c7 = svadd_n_u8_x(vl128, c3,  64);\n            const svuint8_t c8 = svadd_n_u8_x(vl128, c0, 128);\n            const svuint8_t c9 = svadd_n_u8_x(vl128, c1, 128);\n\n            max = HIST_count_6_sve2(ip, sourceSize, count + 64, c4, c5, c6, c7,\n                                    c8, c9, max, maxCount - 64);\n\n            if (maxSymbolValue >= 160) {\n                const svuint8_t ca = svadd_n_u8_x(vl128, c2, 128);\n                const svuint8_t cb = svadd_n_u8_x(vl128, c3, 128);\n                const svuint8_t cc = svadd_n_u8_x(vl128, c4, 128);\n                const svuint8_t cd = svadd_n_u8_x(vl128, c5, 128);\n                const svuint8_t ce = svadd_n_u8_x(vl128, c6, 128);\n                const svuint8_t cf = svadd_n_u8_x(vl128, c7, 128);\n\n                max = HIST_count_6_sve2(ip, sourceSize, count + 160, ca, cb, cc,\n                                        cd, ce, cf, max, maxCount - 160);\n            } else if (maxCount > 160) {\n                ZSTD_memset(count + 160, 0, (maxCount - 160) * sizeof(*count));\n            }\n        } else if (maxCount > 64) {\n            ZSTD_memset(count + 64, 0, (maxCount - 64) * sizeof(*count));\n        }\n\n        return svmaxv_u16(vl128, max);\n    }\n}\n#endif\n\n/* HIST_count_parallel_wksp() :\n * store histogram into 4 intermediate tables, recombined at the end.\n * this design makes better use of OoO cpus,\n * and is noticeably faster when some values are heavily repeated.\n * But it needs some additional workspace for intermediate tables.\n * `workSpace` must be a U32 table of size >= HIST_WKSP_SIZE_U32.\n * @return : largest histogram frequency,\n *           or an error code (notably when histogram's alphabet is larger than *maxSymbolValuePtr) */\nstatic UNUSED_ATTR\nsize_t HIST_count_parallel_wksp(unsigned* count, unsigned* maxSymbolValuePtr,\n                                const void* source, size_t sourceSize,\n                                HIST_checkInput_e check,\n                                U32* const workSpace)\n{\n    const BYTE* ip = (const BYTE*)source;\n    const BYTE* const iend = ip+sourceSize;\n    size_t const countSize = (*maxSymbolValuePtr + 1) * sizeof(*count);\n    unsigned max=0;\n    U32* const Counting1 = workSpace;\n    U32* const Counting2 = Counting1 + 256;\n    U32* const Counting3 = Counting2 + 256;\n    U32* const Counting4 = Counting3 + 256;\n\n    /* safety checks */\n    assert(*maxSymbolValuePtr <= 255);\n    if (!sourceSize) {\n        ZSTD_memset(count, 0, countSize);\n        *maxSymbolValuePtr = 0;\n        return 0;\n    }\n    ZSTD_memset(workSpace, 0, 4*256*sizeof(unsigned));\n\n    /* by stripes of 16 bytes */\n    {   U32 cached = MEM_read32(ip); ip += 4;\n        while (ip < iend-15) {\n            U32 c = cached; cached = MEM_read32(ip); ip += 4;\n            Counting1[(BYTE) c     ]++;\n            Counting2[(BYTE)(c>>8) ]++;\n            Counting3[(BYTE)(c>>16)]++;\n            Counting4[       c>>24 ]++;\n            c = cached; cached = MEM_read32(ip); ip += 4;\n            Counting1[(BYTE) c     ]++;\n            Counting2[(BYTE)(c>>8) ]++;\n            Counting3[(BYTE)(c>>16)]++;\n            Counting4[       c>>24 ]++;\n            c = cached; cached = MEM_read32(ip); ip += 4;\n            Counting1[(BYTE) c     ]++;\n            Counting2[(BYTE)(c>>8) ]++;\n            Counting3[(BYTE)(c>>16)]++;\n            Counting4[       c>>24 ]++;\n            c = cached; cached = MEM_read32(ip); ip += 4;\n            Counting1[(BYTE) c     ]++;\n            Counting2[(BYTE)(c>>8) ]++;\n            Counting3[(BYTE)(c>>16)]++;\n            Counting4[       c>>24 ]++;\n        }\n        ip-=4;\n    }\n\n    /* finish last symbols */\n    while (ip<iend) Counting1[*ip++]++;\n\n    {   U32 s;\n        for (s=0; s<256; s++) {\n            Counting1[s] += Counting2[s] + Counting3[s] + Counting4[s];\n            if (Counting1[s] > max) max = Counting1[s];\n    }   }\n\n    {   unsigned maxSymbolValue = 255;\n        while (!Counting1[maxSymbolValue]) maxSymbolValue--;\n        if (check && maxSymbolValue > *maxSymbolValuePtr) return ERROR(maxSymbolValue_tooSmall);\n        *maxSymbolValuePtr = maxSymbolValue;\n        ZSTD_memmove(count, Counting1, countSize);   /* in case count & Counting1 are overlapping */\n    }\n    return (size_t)max;\n}\n\n/* HIST_countFast_wksp() :\n * Same as HIST_countFast(), but using an externally provided scratch buffer.\n * `workSpace` is a writable buffer which must be 4-bytes aligned,\n * `workSpaceSize` must be >= HIST_WKSP_SIZE\n */\nsize_t HIST_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr,\n                          const void* source, size_t sourceSize,\n                          void* workSpace, size_t workSpaceSize)\n{\n    if (sourceSize < HIST_FAST_THRESHOLD) /* heuristic threshold */\n        return HIST_count_simple(count, maxSymbolValuePtr, source, sourceSize);\n#if defined(ZSTD_ARCH_ARM_SVE2)\n    (void)workSpace;\n    (void)workSpaceSize;\n    return HIST_count_sve2(count, maxSymbolValuePtr, source, sourceSize, trustInput);\n#else\n    if ((size_t)workSpace & 3) return ERROR(GENERIC);  /* must be aligned on 4-bytes boundaries */\n    if (workSpaceSize < HIST_WKSP_SIZE) return ERROR(workSpace_tooSmall);\n    return HIST_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, trustInput, (U32*)workSpace);\n#endif\n}\n\n/* HIST_count_wksp() :\n * Same as HIST_count(), but using an externally provided scratch buffer.\n * `workSpace` size must be table of >= HIST_WKSP_SIZE_U32 unsigned */\nsize_t HIST_count_wksp(unsigned* count, unsigned* maxSymbolValuePtr,\n                       const void* source, size_t sourceSize,\n                       void* workSpace, size_t workSpaceSize)\n{\n#if defined(ZSTD_ARCH_ARM_SVE2)\n    if (*maxSymbolValuePtr < 255)\n        return HIST_count_sve2(count, maxSymbolValuePtr, source, sourceSize, checkMaxSymbolValue);\n#else\n    if ((size_t)workSpace & 3) return ERROR(GENERIC);  /* must be aligned on 4-bytes boundaries */\n    if (workSpaceSize < HIST_WKSP_SIZE) return ERROR(workSpace_tooSmall);\n    if (*maxSymbolValuePtr < 255)\n        return HIST_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, checkMaxSymbolValue, (U32*)workSpace);\n#endif\n    *maxSymbolValuePtr = 255;\n    return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, workSpace, workSpaceSize);\n}\n\n#ifndef ZSTD_NO_UNUSED_FUNCTIONS\n/* fast variant (unsafe : won't check if src contains values beyond count[] limit) */\nsize_t HIST_countFast(unsigned* count, unsigned* maxSymbolValuePtr,\n                     const void* source, size_t sourceSize)\n{\n    unsigned tmpCounters[HIST_WKSP_SIZE_U32];\n    return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, tmpCounters, sizeof(tmpCounters));\n}\n\nsize_t HIST_count(unsigned* count, unsigned* maxSymbolValuePtr,\n                 const void* src, size_t srcSize)\n{\n    unsigned tmpCounters[HIST_WKSP_SIZE_U32];\n    return HIST_count_wksp(count, maxSymbolValuePtr, src, srcSize, tmpCounters, sizeof(tmpCounters));\n}\n#endif\n"
  },
  {
    "path": "lib/compress/hist.h",
    "content": "/* ******************************************************************\n * hist : Histogram functions\n * part of Finite State Entropy project\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n *  You can contact the author at :\n *  - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *  - Public forum : https://groups.google.com/forum/#!forum/lz4c\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n/* --- dependencies --- */\n#include \"../common/zstd_deps.h\"   /* size_t */\n\n\n/* --- simple histogram functions --- */\n\n/*! HIST_count():\n *  Provides the precise count of each byte within a table 'count'.\n * 'count' is a table of unsigned int, of minimum size (*maxSymbolValuePtr+1).\n *  Updates *maxSymbolValuePtr with actual largest symbol value detected.\n * @return : count of the most frequent symbol (which isn't identified).\n *           or an error code, which can be tested using HIST_isError().\n *           note : if return == srcSize, there is only one symbol.\n */\nsize_t HIST_count(unsigned* count, unsigned* maxSymbolValuePtr,\n                  const void* src, size_t srcSize);\n\nunsigned HIST_isError(size_t code);  /**< tells if a return value is an error code */\n\n\n/* --- advanced histogram functions --- */\n\n#if defined(__ARM_FEATURE_SVE2)\n#define HIST_WKSP_SIZE_U32 0\n#else\n#define HIST_WKSP_SIZE_U32 1024\n#endif\n#define HIST_WKSP_SIZE    (HIST_WKSP_SIZE_U32 * sizeof(unsigned))\n/** HIST_count_wksp() :\n *  Same as HIST_count(), but using an externally provided scratch buffer.\n *  Benefit is this function will use very little stack space.\n * `workSpace` is a writable buffer which must be 4-bytes aligned,\n * `workSpaceSize` must be >= HIST_WKSP_SIZE\n */\nsize_t HIST_count_wksp(unsigned* count, unsigned* maxSymbolValuePtr,\n                       const void* src, size_t srcSize,\n                       void* workSpace, size_t workSpaceSize);\n\n/** HIST_countFast() :\n *  same as HIST_count(), but blindly trusts that all byte values within src are <= *maxSymbolValuePtr.\n *  This function is unsafe, and will segfault if any value within `src` is `> *maxSymbolValuePtr`\n */\nsize_t HIST_countFast(unsigned* count, unsigned* maxSymbolValuePtr,\n                      const void* src, size_t srcSize);\n\n/** HIST_countFast_wksp() :\n *  Same as HIST_countFast(), but using an externally provided scratch buffer.\n * `workSpace` is a writable buffer which must be 4-bytes aligned,\n * `workSpaceSize` must be >= HIST_WKSP_SIZE\n */\nsize_t HIST_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr,\n                           const void* src, size_t srcSize,\n                           void* workSpace, size_t workSpaceSize);\n\n/*! HIST_count_simple() :\n *  Same as HIST_countFast(), this function is unsafe,\n *  and will segfault if any value within `src` is `> *maxSymbolValuePtr`.\n *  It is also a bit slower for large inputs.\n *  However, it does not need any additional memory (not even on stack).\n * @return : count of the most frequent symbol.\n *  Note this function doesn't produce any error (i.e. it must succeed).\n */\nunsigned HIST_count_simple(unsigned* count, unsigned* maxSymbolValuePtr,\n                           const void* src, size_t srcSize);\n\n/*! HIST_add() :\n *  Lowest level: just add nb of occurrences of characters from @src into @count.\n *  @count is not reset. @count array is presumed large enough (i.e. 1 KB).\n @  This function does not need any additional stack memory.\n */\nvoid HIST_add(unsigned* count, const void* src, size_t srcSize);\n"
  },
  {
    "path": "lib/compress/huf_compress.c",
    "content": "/* ******************************************************************\n * Huffman encoder, part of New Generation Entropy library\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n *  You can contact the author at :\n *  - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *  - Public forum : https://groups.google.com/forum/#!forum/lz4c\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n/* **************************************************************\n*  Compiler specifics\n****************************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#endif\n\n\n/* **************************************************************\n*  Includes\n****************************************************************/\n#include \"../common/zstd_deps.h\"     /* ZSTD_memcpy, ZSTD_memset */\n#include \"../common/compiler.h\"\n#include \"../common/bitstream.h\"\n#include \"hist.h\"\n#define FSE_STATIC_LINKING_ONLY   /* FSE_optimalTableLog_internal */\n#include \"../common/fse.h\"        /* header compression */\n#include \"../common/huf.h\"\n#include \"../common/error_private.h\"\n#include \"../common/bits.h\"       /* ZSTD_highbit32 */\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n#define HUF_isError ERR_isError\n#define HUF_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c)   /* use only *after* variable declarations */\n\n\n/* **************************************************************\n*  Required declarations\n****************************************************************/\ntypedef struct nodeElt_s {\n    U32 count;\n    U16 parent;\n    BYTE byte;\n    BYTE nbBits;\n} nodeElt;\n\n\n/* **************************************************************\n*  Debug Traces\n****************************************************************/\n\n#if DEBUGLEVEL >= 2\n\nstatic size_t showU32(const U32* arr, size_t size)\n{\n    size_t u;\n    for (u=0; u<size; u++) {\n        RAWLOG(6, \" %u\", arr[u]); (void)arr;\n    }\n    RAWLOG(6, \" \\n\");\n    return size;\n}\n\nstatic size_t HUF_getNbBits(HUF_CElt elt);\n\nstatic size_t showCTableBits(const HUF_CElt* ctable, size_t size)\n{\n    size_t u;\n    for (u=0; u<size; u++) {\n        RAWLOG(6, \" %zu\", HUF_getNbBits(ctable[u])); (void)ctable;\n    }\n    RAWLOG(6, \" \\n\");\n    return size;\n\n}\n\nstatic size_t showHNodeSymbols(const nodeElt* hnode, size_t size)\n{\n    size_t u;\n    for (u=0; u<size; u++) {\n        RAWLOG(6, \" %u\", hnode[u].byte); (void)hnode;\n    }\n    RAWLOG(6, \" \\n\");\n    return size;\n}\n\nstatic size_t showHNodeBits(const nodeElt* hnode, size_t size)\n{\n    size_t u;\n    for (u=0; u<size; u++) {\n        RAWLOG(6, \" %u\", hnode[u].nbBits); (void)hnode;\n    }\n    RAWLOG(6, \" \\n\");\n    return size;\n}\n\n#endif\n\n\n/* *******************************************************\n*  HUF : Huffman block compression\n*********************************************************/\n#define HUF_WORKSPACE_MAX_ALIGNMENT 8\n\nstatic void* HUF_alignUpWorkspace(void* workspace, size_t* workspaceSizePtr, size_t align)\n{\n    size_t const mask = align - 1;\n    size_t const rem = (size_t)workspace & mask;\n    size_t const add = (align - rem) & mask;\n    BYTE* const aligned = (BYTE*)workspace + add;\n    assert((align & (align - 1)) == 0); /* pow 2 */\n    assert(align <= HUF_WORKSPACE_MAX_ALIGNMENT);\n    if (*workspaceSizePtr >= add) {\n        assert(add < align);\n        assert(((size_t)aligned & mask) == 0);\n        *workspaceSizePtr -= add;\n        return aligned;\n    } else {\n        *workspaceSizePtr = 0;\n        return NULL;\n    }\n}\n\n\n/* HUF_compressWeights() :\n * Same as FSE_compress(), but dedicated to huff0's weights compression.\n * The use case needs much less stack memory.\n * Note : all elements within weightTable are supposed to be <= HUF_TABLELOG_MAX.\n */\n#define MAX_FSE_TABLELOG_FOR_HUFF_HEADER 6\n\ntypedef struct {\n    FSE_CTable CTable[FSE_CTABLE_SIZE_U32(MAX_FSE_TABLELOG_FOR_HUFF_HEADER, HUF_TABLELOG_MAX)];\n    U32 scratchBuffer[FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(HUF_TABLELOG_MAX, MAX_FSE_TABLELOG_FOR_HUFF_HEADER)];\n    unsigned count[HUF_TABLELOG_MAX+1];\n    S16 norm[HUF_TABLELOG_MAX+1];\n} HUF_CompressWeightsWksp;\n\nstatic size_t\nHUF_compressWeights(void* dst, size_t dstSize,\n              const void* weightTable, size_t wtSize,\n                    void* workspace, size_t workspaceSize)\n{\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + dstSize;\n\n    unsigned maxSymbolValue = HUF_TABLELOG_MAX;\n    U32 tableLog = MAX_FSE_TABLELOG_FOR_HUFF_HEADER;\n    HUF_CompressWeightsWksp* wksp = (HUF_CompressWeightsWksp*)HUF_alignUpWorkspace(workspace, &workspaceSize, ZSTD_ALIGNOF(U32));\n\n    if (workspaceSize < sizeof(HUF_CompressWeightsWksp)) return ERROR(GENERIC);\n\n    /* init conditions */\n    if (wtSize <= 1) return 0;  /* Not compressible */\n\n    /* Scan input and build symbol stats */\n    {   unsigned const maxCount = HIST_count_simple(wksp->count, &maxSymbolValue, weightTable, wtSize);   /* never fails */\n        if (maxCount == wtSize) return 1;   /* only a single symbol in src : rle */\n        if (maxCount == 1) return 0;        /* each symbol present maximum once => not compressible */\n    }\n\n    tableLog = FSE_optimalTableLog(tableLog, wtSize, maxSymbolValue);\n    CHECK_F( FSE_normalizeCount(wksp->norm, tableLog, wksp->count, wtSize, maxSymbolValue, /* useLowProbCount */ 0) );\n\n    /* Write table description header */\n    {   CHECK_V_F(hSize, FSE_writeNCount(op, (size_t)(oend-op), wksp->norm, maxSymbolValue, tableLog) );\n        op += hSize;\n    }\n\n    /* Compress */\n    CHECK_F( FSE_buildCTable_wksp(wksp->CTable, wksp->norm, maxSymbolValue, tableLog, wksp->scratchBuffer, sizeof(wksp->scratchBuffer)) );\n    {   CHECK_V_F(cSize, FSE_compress_usingCTable(op, (size_t)(oend - op), weightTable, wtSize, wksp->CTable) );\n        if (cSize == 0) return 0;   /* not enough space for compressed data */\n        op += cSize;\n    }\n\n    return (size_t)(op-ostart);\n}\n\nstatic size_t HUF_getNbBits(HUF_CElt elt)\n{\n    return elt & 0xFF;\n}\n\nstatic size_t HUF_getNbBitsFast(HUF_CElt elt)\n{\n    return elt;\n}\n\nstatic size_t HUF_getValue(HUF_CElt elt)\n{\n    return elt & ~(size_t)0xFF;\n}\n\nstatic size_t HUF_getValueFast(HUF_CElt elt)\n{\n    return elt;\n}\n\nstatic void HUF_setNbBits(HUF_CElt* elt, size_t nbBits)\n{\n    assert(nbBits <= HUF_TABLELOG_ABSOLUTEMAX);\n    *elt = nbBits;\n}\n\nstatic void HUF_setValue(HUF_CElt* elt, size_t value)\n{\n    size_t const nbBits = HUF_getNbBits(*elt);\n    if (nbBits > 0) {\n        assert((value >> nbBits) == 0);\n        *elt |= value << (sizeof(HUF_CElt) * 8 - nbBits);\n    }\n}\n\nHUF_CTableHeader HUF_readCTableHeader(HUF_CElt const* ctable)\n{\n    HUF_CTableHeader header;\n    ZSTD_memcpy(&header, ctable, sizeof(header));\n    return header;\n}\n\nstatic void HUF_writeCTableHeader(HUF_CElt* ctable, U32 tableLog, U32 maxSymbolValue)\n{\n    HUF_CTableHeader header;\n    HUF_STATIC_ASSERT(sizeof(ctable[0]) == sizeof(header));\n    ZSTD_memset(&header, 0, sizeof(header));\n    assert(tableLog < 256);\n    header.tableLog = (BYTE)tableLog;\n    assert(maxSymbolValue < 256);\n    header.maxSymbolValue = (BYTE)maxSymbolValue;\n    ZSTD_memcpy(ctable, &header, sizeof(header));\n}\n\ntypedef struct {\n    HUF_CompressWeightsWksp wksp;\n    BYTE bitsToWeight[HUF_TABLELOG_MAX + 1];   /* precomputed conversion table */\n    BYTE huffWeight[HUF_SYMBOLVALUE_MAX];\n} HUF_WriteCTableWksp;\n\nsize_t HUF_writeCTable_wksp(void* dst, size_t maxDstSize,\n                            const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog,\n                            void* workspace, size_t workspaceSize)\n{\n    HUF_CElt const* const ct = CTable + 1;\n    BYTE* op = (BYTE*)dst;\n    U32 n;\n    HUF_WriteCTableWksp* wksp = (HUF_WriteCTableWksp*)HUF_alignUpWorkspace(workspace, &workspaceSize, ZSTD_ALIGNOF(U32));\n\n    HUF_STATIC_ASSERT(HUF_CTABLE_WORKSPACE_SIZE >= sizeof(HUF_WriteCTableWksp));\n\n    assert(HUF_readCTableHeader(CTable).maxSymbolValue == maxSymbolValue);\n    assert(HUF_readCTableHeader(CTable).tableLog == huffLog);\n\n    /* check conditions */\n    if (workspaceSize < sizeof(HUF_WriteCTableWksp)) return ERROR(GENERIC);\n    if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge);\n\n    /* convert to weight */\n    wksp->bitsToWeight[0] = 0;\n    for (n=1; n<huffLog+1; n++)\n        wksp->bitsToWeight[n] = (BYTE)(huffLog + 1 - n);\n    for (n=0; n<maxSymbolValue; n++)\n        wksp->huffWeight[n] = wksp->bitsToWeight[HUF_getNbBits(ct[n])];\n\n    /* attempt weights compression by FSE */\n    if (maxDstSize < 1) return ERROR(dstSize_tooSmall);\n    {   CHECK_V_F(hSize, HUF_compressWeights(op+1, maxDstSize-1, wksp->huffWeight, maxSymbolValue, &wksp->wksp, sizeof(wksp->wksp)) );\n        if ((hSize>1) & (hSize < maxSymbolValue/2)) {   /* FSE compressed */\n            op[0] = (BYTE)hSize;\n            return hSize+1;\n    }   }\n\n    /* write raw values as 4-bits (max : 15) */\n    if (maxSymbolValue > (256-128)) return ERROR(GENERIC);   /* should not happen : likely means source cannot be compressed */\n    if (((maxSymbolValue+1)/2) + 1 > maxDstSize) return ERROR(dstSize_tooSmall);   /* not enough space within dst buffer */\n    op[0] = (BYTE)(128 /*special case*/ + (maxSymbolValue-1));\n    wksp->huffWeight[maxSymbolValue] = 0;   /* to be sure it doesn't cause msan issue in final combination */\n    for (n=0; n<maxSymbolValue; n+=2)\n        op[(n/2)+1] = (BYTE)((wksp->huffWeight[n] << 4) + wksp->huffWeight[n+1]);\n    return ((maxSymbolValue+1)/2) + 1;\n}\n\n\nsize_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned* hasZeroWeights)\n{\n    BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1];   /* init not required, even though some static analyzer may complain */\n    U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1];   /* large enough for values from 0 to 16 */\n    U32 tableLog = 0;\n    U32 nbSymbols = 0;\n    HUF_CElt* const ct = CTable + 1;\n\n    /* get symbol weights */\n    CHECK_V_F(readSize, HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX+1, rankVal, &nbSymbols, &tableLog, src, srcSize));\n    *hasZeroWeights = (rankVal[0] > 0);\n\n    /* check result */\n    if (tableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);\n    if (nbSymbols > *maxSymbolValuePtr+1) return ERROR(maxSymbolValue_tooSmall);\n\n    *maxSymbolValuePtr = nbSymbols - 1;\n\n    HUF_writeCTableHeader(CTable, tableLog, *maxSymbolValuePtr);\n\n    /* Prepare base value per rank */\n    {   U32 n, nextRankStart = 0;\n        for (n=1; n<=tableLog; n++) {\n            U32 curr = nextRankStart;\n            nextRankStart += (rankVal[n] << (n-1));\n            rankVal[n] = curr;\n    }   }\n\n    /* fill nbBits */\n    {   U32 n; for (n=0; n<nbSymbols; n++) {\n            const U32 w = huffWeight[n];\n            HUF_setNbBits(ct + n, (BYTE)(tableLog + 1 - w) & -(w != 0));\n    }   }\n\n    /* fill val */\n    {   U16 nbPerRank[HUF_TABLELOG_MAX+2]  = {0};  /* support w=0=>n=tableLog+1 */\n        U16 valPerRank[HUF_TABLELOG_MAX+2] = {0};\n        { U32 n; for (n=0; n<nbSymbols; n++) nbPerRank[HUF_getNbBits(ct[n])]++; }\n        /* determine stating value per rank */\n        valPerRank[tableLog+1] = 0;   /* for w==0 */\n        {   U16 min = 0;\n            U32 n; for (n=tableLog; n>0; n--) {  /* start at n=tablelog <-> w=1 */\n                valPerRank[n] = min;     /* get starting value within each rank */\n                min += nbPerRank[n];\n                min >>= 1;\n        }   }\n        /* assign value within rank, symbol order */\n        { U32 n; for (n=0; n<nbSymbols; n++) HUF_setValue(ct + n, valPerRank[HUF_getNbBits(ct[n])]++); }\n    }\n\n    return readSize;\n}\n\nU32 HUF_getNbBitsFromCTable(HUF_CElt const* CTable, U32 symbolValue)\n{\n    const HUF_CElt* const ct = CTable + 1;\n    assert(symbolValue <= HUF_SYMBOLVALUE_MAX);\n    if (symbolValue > HUF_readCTableHeader(CTable).maxSymbolValue)\n        return 0;\n    return (U32)HUF_getNbBits(ct[symbolValue]);\n}\n\n\n/**\n * HUF_setMaxHeight():\n * Try to enforce @targetNbBits on the Huffman tree described in @huffNode.\n *\n * It attempts to convert all nodes with nbBits > @targetNbBits\n * to employ @targetNbBits instead. Then it adjusts the tree\n * so that it remains a valid canonical Huffman tree.\n *\n * @pre               The sum of the ranks of each symbol == 2^largestBits,\n *                    where largestBits == huffNode[lastNonNull].nbBits.\n * @post              The sum of the ranks of each symbol == 2^largestBits,\n *                    where largestBits is the return value (expected <= targetNbBits).\n *\n * @param huffNode    The Huffman tree modified in place to enforce targetNbBits.\n *                    It's presumed sorted, from most frequent to rarest symbol.\n * @param lastNonNull The symbol with the lowest count in the Huffman tree.\n * @param targetNbBits  The allowed number of bits, which the Huffman tree\n *                    may not respect. After this function the Huffman tree will\n *                    respect targetNbBits.\n * @return            The maximum number of bits of the Huffman tree after adjustment.\n */\nstatic U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 targetNbBits)\n{\n    const U32 largestBits = huffNode[lastNonNull].nbBits;\n    /* early exit : no elt > targetNbBits, so the tree is already valid. */\n    if (largestBits <= targetNbBits) return largestBits;\n\n    DEBUGLOG(5, \"HUF_setMaxHeight (targetNbBits = %u)\", targetNbBits);\n\n    /* there are several too large elements (at least >= 2) */\n    {   int totalCost = 0;\n        const U32 baseCost = 1 << (largestBits - targetNbBits);\n        int n = (int)lastNonNull;\n\n        /* Adjust any ranks > targetNbBits to targetNbBits.\n         * Compute totalCost, which is how far the sum of the ranks is\n         * we are over 2^largestBits after adjust the offending ranks.\n         */\n        while (huffNode[n].nbBits > targetNbBits) {\n            totalCost += baseCost - (1 << (largestBits - huffNode[n].nbBits));\n            huffNode[n].nbBits = (BYTE)targetNbBits;\n            n--;\n        }\n        /* n stops at huffNode[n].nbBits <= targetNbBits */\n        assert(huffNode[n].nbBits <= targetNbBits);\n        /* n end at index of smallest symbol using < targetNbBits */\n        while (huffNode[n].nbBits == targetNbBits) --n;\n\n        /* renorm totalCost from 2^largestBits to 2^targetNbBits\n         * note : totalCost is necessarily a multiple of baseCost */\n        assert(((U32)totalCost & (baseCost - 1)) == 0);\n        totalCost >>= (largestBits - targetNbBits);\n        assert(totalCost > 0);\n\n        /* repay normalized cost */\n        {   U32 const noSymbol = 0xF0F0F0F0;\n            U32 rankLast[HUF_TABLELOG_MAX+2];\n\n            /* Get pos of last (smallest = lowest cum. count) symbol per rank */\n            ZSTD_memset(rankLast, 0xF0, sizeof(rankLast));\n            {   U32 currentNbBits = targetNbBits;\n                int pos;\n                for (pos=n ; pos >= 0; pos--) {\n                    if (huffNode[pos].nbBits >= currentNbBits) continue;\n                    currentNbBits = huffNode[pos].nbBits;   /* < targetNbBits */\n                    rankLast[targetNbBits-currentNbBits] = (U32)pos;\n            }   }\n\n            while (totalCost > 0) {\n                /* Try to reduce the next power of 2 above totalCost because we\n                 * gain back half the rank.\n                 */\n                U32 nBitsToDecrease = ZSTD_highbit32((U32)totalCost) + 1;\n                assert(nBitsToDecrease <= HUF_TABLELOG_MAX+1);\n                for ( ; nBitsToDecrease > 1; nBitsToDecrease--) {\n                    U32 const highPos = rankLast[nBitsToDecrease];\n                    U32 const lowPos = rankLast[nBitsToDecrease-1];\n                    if (highPos == noSymbol) continue;\n                    /* Decrease highPos if no symbols of lowPos or if it is\n                     * not cheaper to remove 2 lowPos than highPos.\n                     */\n                    if (lowPos == noSymbol) break;\n                    {   U32 const highTotal = huffNode[highPos].count;\n                        U32 const lowTotal = 2 * huffNode[lowPos].count;\n                        if (highTotal <= lowTotal) break;\n                }   }\n                /* only triggered when no more rank 1 symbol left => find closest one (note : there is necessarily at least one !) */\n                assert(rankLast[nBitsToDecrease] != noSymbol || nBitsToDecrease == 1);\n                /* HUF_MAX_TABLELOG test just to please gcc 5+; but it should not be necessary */\n                while ((nBitsToDecrease<=HUF_TABLELOG_MAX) && (rankLast[nBitsToDecrease] == noSymbol))\n                    nBitsToDecrease++;\n                assert(rankLast[nBitsToDecrease] != noSymbol);\n                /* Increase the number of bits to gain back half the rank cost. */\n                totalCost -= 1 << (nBitsToDecrease-1);\n                huffNode[rankLast[nBitsToDecrease]].nbBits++;\n\n                /* Fix up the new rank.\n                 * If the new rank was empty, this symbol is now its smallest.\n                 * Otherwise, this symbol will be the largest in the new rank so no adjustment.\n                 */\n                if (rankLast[nBitsToDecrease-1] == noSymbol)\n                    rankLast[nBitsToDecrease-1] = rankLast[nBitsToDecrease];\n                /* Fix up the old rank.\n                 * If the symbol was at position 0, meaning it was the highest weight symbol in the tree,\n                 * it must be the only symbol in its rank, so the old rank now has no symbols.\n                 * Otherwise, since the Huffman nodes are sorted by count, the previous position is now\n                 * the smallest node in the rank. If the previous position belongs to a different rank,\n                 * then the rank is now empty.\n                 */\n                if (rankLast[nBitsToDecrease] == 0)    /* special case, reached largest symbol */\n                    rankLast[nBitsToDecrease] = noSymbol;\n                else {\n                    rankLast[nBitsToDecrease]--;\n                    if (huffNode[rankLast[nBitsToDecrease]].nbBits != targetNbBits-nBitsToDecrease)\n                        rankLast[nBitsToDecrease] = noSymbol;   /* this rank is now empty */\n                }\n            }   /* while (totalCost > 0) */\n\n            /* If we've removed too much weight, then we have to add it back.\n             * To avoid overshooting again, we only adjust the smallest rank.\n             * We take the largest nodes from the lowest rank 0 and move them\n             * to rank 1. There's guaranteed to be enough rank 0 symbols because\n             * TODO.\n             */\n            while (totalCost < 0) {  /* Sometimes, cost correction overshoot */\n                /* special case : no rank 1 symbol (using targetNbBits-1);\n                 * let's create one from largest rank 0 (using targetNbBits).\n                 */\n                if (rankLast[1] == noSymbol) {\n                    while (huffNode[n].nbBits == targetNbBits) n--;\n                    huffNode[n+1].nbBits--;\n                    assert(n >= 0);\n                    rankLast[1] = (U32)(n+1);\n                    totalCost++;\n                    continue;\n                }\n                huffNode[ rankLast[1] + 1 ].nbBits--;\n                rankLast[1]++;\n                totalCost ++;\n            }\n        }   /* repay normalized cost */\n    }   /* there are several too large elements (at least >= 2) */\n\n    return targetNbBits;\n}\n\ntypedef struct {\n    U16 base;\n    U16 curr;\n} rankPos;\n\ntypedef nodeElt huffNodeTable[2 * (HUF_SYMBOLVALUE_MAX + 1)];\n\n/* Number of buckets available for HUF_sort() */\n#define RANK_POSITION_TABLE_SIZE 192\n\ntypedef struct {\n  huffNodeTable huffNodeTbl;\n  rankPos rankPosition[RANK_POSITION_TABLE_SIZE];\n} HUF_buildCTable_wksp_tables;\n\n/* RANK_POSITION_DISTINCT_COUNT_CUTOFF == Cutoff point in HUF_sort() buckets for which we use log2 bucketing.\n * Strategy is to use as many buckets as possible for representing distinct\n * counts while using the remainder to represent all \"large\" counts.\n *\n * To satisfy this requirement for 192 buckets, we can do the following:\n * Let buckets 0-166 represent distinct counts of [0, 166]\n * Let buckets 166 to 192 represent all remaining counts up to RANK_POSITION_MAX_COUNT_LOG using log2 bucketing.\n */\n#define RANK_POSITION_MAX_COUNT_LOG 32\n#define RANK_POSITION_LOG_BUCKETS_BEGIN ((RANK_POSITION_TABLE_SIZE - 1) - RANK_POSITION_MAX_COUNT_LOG - 1 /* == 158 */)\n#define RANK_POSITION_DISTINCT_COUNT_CUTOFF (RANK_POSITION_LOG_BUCKETS_BEGIN + ZSTD_highbit32(RANK_POSITION_LOG_BUCKETS_BEGIN) /* == 166 */)\n\n/* Return the appropriate bucket index for a given count. See definition of\n * RANK_POSITION_DISTINCT_COUNT_CUTOFF for explanation of bucketing strategy.\n */\nstatic U32 HUF_getIndex(U32 const count) {\n    return (count < RANK_POSITION_DISTINCT_COUNT_CUTOFF)\n        ? count\n        : ZSTD_highbit32(count) + RANK_POSITION_LOG_BUCKETS_BEGIN;\n}\n\n/* Helper swap function for HUF_quickSortPartition() */\nstatic void HUF_swapNodes(nodeElt* a, nodeElt* b) {\n\tnodeElt tmp = *a;\n\t*a = *b;\n\t*b = tmp;\n}\n\n/* Returns 0 if the huffNode array is not sorted by descending count */\nMEM_STATIC int HUF_isSorted(nodeElt huffNode[], U32 const maxSymbolValue1) {\n    U32 i;\n    for (i = 1; i < maxSymbolValue1; ++i) {\n        if (huffNode[i].count > huffNode[i-1].count) {\n            return 0;\n        }\n    }\n    return 1;\n}\n\n/* Insertion sort by descending order */\nHINT_INLINE void HUF_insertionSort(nodeElt huffNode[], int const low, int const high) {\n    int i;\n    int const size = high-low+1;\n    huffNode += low;\n    for (i = 1; i < size; ++i) {\n        nodeElt const key = huffNode[i];\n        int j = i - 1;\n        while (j >= 0 && huffNode[j].count < key.count) {\n            huffNode[j + 1] = huffNode[j];\n            j--;\n        }\n        huffNode[j + 1] = key;\n    }\n}\n\n/* Pivot helper function for quicksort. */\nstatic int HUF_quickSortPartition(nodeElt arr[], int const low, int const high) {\n    /* Simply select rightmost element as pivot. \"Better\" selectors like\n     * median-of-three don't experimentally appear to have any benefit.\n     */\n    U32 const pivot = arr[high].count;\n    int i = low - 1;\n    int j = low;\n    for ( ; j < high; j++) {\n        if (arr[j].count > pivot) {\n            i++;\n            HUF_swapNodes(&arr[i], &arr[j]);\n        }\n    }\n    HUF_swapNodes(&arr[i + 1], &arr[high]);\n    return i + 1;\n}\n\n/* Classic quicksort by descending with partially iterative calls\n * to reduce worst case callstack size.\n */\nstatic void HUF_simpleQuickSort(nodeElt arr[], int low, int high) {\n    int const kInsertionSortThreshold = 8;\n    if (high - low < kInsertionSortThreshold) {\n        HUF_insertionSort(arr, low, high);\n        return;\n    }\n    while (low < high) {\n        int const idx = HUF_quickSortPartition(arr, low, high);\n        if (idx - low < high - idx) {\n            HUF_simpleQuickSort(arr, low, idx - 1);\n            low = idx + 1;\n        } else {\n            HUF_simpleQuickSort(arr, idx + 1, high);\n            high = idx - 1;\n        }\n    }\n}\n\n/**\n * HUF_sort():\n * Sorts the symbols [0, maxSymbolValue] by count[symbol] in decreasing order.\n * This is a typical bucket sorting strategy that uses either quicksort or insertion sort to sort each bucket.\n *\n * @param[out] huffNode       Sorted symbols by decreasing count. Only members `.count` and `.byte` are filled.\n *                            Must have (maxSymbolValue + 1) entries.\n * @param[in]  count          Histogram of the symbols.\n * @param[in]  maxSymbolValue Maximum symbol value.\n * @param      rankPosition   This is a scratch workspace. Must have RANK_POSITION_TABLE_SIZE entries.\n */\nstatic void HUF_sort(nodeElt huffNode[], const unsigned count[], U32 const maxSymbolValue, rankPos rankPosition[]) {\n    U32 n;\n    U32 const maxSymbolValue1 = maxSymbolValue+1;\n\n    /* Compute base and set curr to base.\n     * For symbol s let lowerRank = HUF_getIndex(count[n]) and rank = lowerRank + 1.\n     * See HUF_getIndex to see bucketing strategy.\n     * We attribute each symbol to lowerRank's base value, because we want to know where\n     * each rank begins in the output, so for rank R we want to count ranks R+1 and above.\n     */\n    ZSTD_memset(rankPosition, 0, sizeof(*rankPosition) * RANK_POSITION_TABLE_SIZE);\n    for (n = 0; n < maxSymbolValue1; ++n) {\n        U32 lowerRank = HUF_getIndex(count[n]);\n        assert(lowerRank < RANK_POSITION_TABLE_SIZE - 1);\n        rankPosition[lowerRank].base++;\n    }\n\n    assert(rankPosition[RANK_POSITION_TABLE_SIZE - 1].base == 0);\n    /* Set up the rankPosition table */\n    for (n = RANK_POSITION_TABLE_SIZE - 1; n > 0; --n) {\n        rankPosition[n-1].base += rankPosition[n].base;\n        rankPosition[n-1].curr = rankPosition[n-1].base;\n    }\n\n    /* Insert each symbol into their appropriate bucket, setting up rankPosition table. */\n    for (n = 0; n < maxSymbolValue1; ++n) {\n        U32 const c = count[n];\n        U32 const r = HUF_getIndex(c) + 1;\n        U32 const pos = rankPosition[r].curr++;\n        assert(pos < maxSymbolValue1);\n        huffNode[pos].count = c;\n        huffNode[pos].byte  = (BYTE)n;\n    }\n\n    /* Sort each bucket. */\n    for (n = RANK_POSITION_DISTINCT_COUNT_CUTOFF; n < RANK_POSITION_TABLE_SIZE - 1; ++n) {\n        int const bucketSize = rankPosition[n].curr - rankPosition[n].base;\n        U32 const bucketStartIdx = rankPosition[n].base;\n        if (bucketSize > 1) {\n            assert(bucketStartIdx < maxSymbolValue1);\n            HUF_simpleQuickSort(huffNode + bucketStartIdx, 0, bucketSize-1);\n        }\n    }\n\n    assert(HUF_isSorted(huffNode, maxSymbolValue1));\n}\n\n\n/** HUF_buildCTable_wksp() :\n *  Same as HUF_buildCTable(), but using externally allocated scratch buffer.\n *  `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as sizeof(HUF_buildCTable_wksp_tables).\n */\n#define STARTNODE (HUF_SYMBOLVALUE_MAX+1)\n\n/* HUF_buildTree():\n * Takes the huffNode array sorted by HUF_sort() and builds an unlimited-depth Huffman tree.\n *\n * @param huffNode        The array sorted by HUF_sort(). Builds the Huffman tree in this array.\n * @param maxSymbolValue  The maximum symbol value.\n * @return                The smallest node in the Huffman tree (by count).\n */\nstatic int HUF_buildTree(nodeElt* huffNode, U32 maxSymbolValue)\n{\n    nodeElt* const huffNode0 = huffNode - 1;\n    int nonNullRank;\n    int lowS, lowN;\n    int nodeNb = STARTNODE;\n    int n, nodeRoot;\n    DEBUGLOG(5, \"HUF_buildTree (alphabet size = %u)\", maxSymbolValue + 1);\n    /* init for parents */\n    nonNullRank = (int)maxSymbolValue;\n    while(huffNode[nonNullRank].count == 0) nonNullRank--;\n    lowS = nonNullRank; nodeRoot = nodeNb + lowS - 1; lowN = nodeNb;\n    huffNode[nodeNb].count = huffNode[lowS].count + huffNode[lowS-1].count;\n    huffNode[lowS].parent = huffNode[lowS-1].parent = (U16)nodeNb;\n    nodeNb++; lowS-=2;\n    for (n=nodeNb; n<=nodeRoot; n++) huffNode[n].count = (U32)(1U<<30);\n    huffNode0[0].count = (U32)(1U<<31);  /* fake entry, strong barrier */\n\n    /* create parents */\n    while (nodeNb <= nodeRoot) {\n        int const n1 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++;\n        int const n2 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++;\n        huffNode[nodeNb].count = huffNode[n1].count + huffNode[n2].count;\n        huffNode[n1].parent = huffNode[n2].parent = (U16)nodeNb;\n        nodeNb++;\n    }\n\n    /* distribute weights (unlimited tree height) */\n    huffNode[nodeRoot].nbBits = 0;\n    for (n=nodeRoot-1; n>=STARTNODE; n--)\n        huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1;\n    for (n=0; n<=nonNullRank; n++)\n        huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1;\n\n    DEBUGLOG(6, \"Initial distribution of bits completed (%zu sorted symbols)\", showHNodeBits(huffNode, maxSymbolValue+1));\n\n    return nonNullRank;\n}\n\n/**\n * HUF_buildCTableFromTree():\n * Build the CTable given the Huffman tree in huffNode.\n *\n * @param[out] CTable         The output Huffman CTable.\n * @param      huffNode       The Huffman tree.\n * @param      nonNullRank    The last and smallest node in the Huffman tree.\n * @param      maxSymbolValue The maximum symbol value.\n * @param      maxNbBits      The exact maximum number of bits used in the Huffman tree.\n */\nstatic void HUF_buildCTableFromTree(HUF_CElt* CTable, nodeElt const* huffNode, int nonNullRank, U32 maxSymbolValue, U32 maxNbBits)\n{\n    HUF_CElt* const ct = CTable + 1;\n    /* fill result into ctable (val, nbBits) */\n    int n;\n    U16 nbPerRank[HUF_TABLELOG_MAX+1] = {0};\n    U16 valPerRank[HUF_TABLELOG_MAX+1] = {0};\n    int const alphabetSize = (int)(maxSymbolValue + 1);\n    for (n=0; n<=nonNullRank; n++)\n        nbPerRank[huffNode[n].nbBits]++;\n    /* determine starting value per rank */\n    {   U16 min = 0;\n        for (n=(int)maxNbBits; n>0; n--) {\n            valPerRank[n] = min;      /* get starting value within each rank */\n            min += nbPerRank[n];\n            min >>= 1;\n    }   }\n    for (n=0; n<alphabetSize; n++)\n        HUF_setNbBits(ct + huffNode[n].byte, huffNode[n].nbBits);   /* push nbBits per symbol, symbol order */\n    for (n=0; n<alphabetSize; n++)\n        HUF_setValue(ct + n, valPerRank[HUF_getNbBits(ct[n])]++);   /* assign value within rank, symbol order */\n\n    HUF_writeCTableHeader(CTable, maxNbBits, maxSymbolValue);\n}\n\nsize_t\nHUF_buildCTable_wksp(HUF_CElt* CTable, const unsigned* count, U32 maxSymbolValue, U32 maxNbBits,\n                     void* workSpace, size_t wkspSize)\n{\n    HUF_buildCTable_wksp_tables* const wksp_tables =\n        (HUF_buildCTable_wksp_tables*)HUF_alignUpWorkspace(workSpace, &wkspSize, ZSTD_ALIGNOF(U32));\n    nodeElt* const huffNode0 = wksp_tables->huffNodeTbl;\n    nodeElt* const huffNode = huffNode0+1;\n    int nonNullRank;\n\n    HUF_STATIC_ASSERT(HUF_CTABLE_WORKSPACE_SIZE == sizeof(HUF_buildCTable_wksp_tables));\n\n    DEBUGLOG(5, \"HUF_buildCTable_wksp (alphabet size = %u)\", maxSymbolValue+1);\n\n    /* safety checks */\n    if (wkspSize < sizeof(HUF_buildCTable_wksp_tables))\n        return ERROR(workSpace_tooSmall);\n    if (maxNbBits == 0) maxNbBits = HUF_TABLELOG_DEFAULT;\n    if (maxSymbolValue > HUF_SYMBOLVALUE_MAX)\n        return ERROR(maxSymbolValue_tooLarge);\n    ZSTD_memset(huffNode0, 0, sizeof(huffNodeTable));\n\n    /* sort, decreasing order */\n    HUF_sort(huffNode, count, maxSymbolValue, wksp_tables->rankPosition);\n    DEBUGLOG(6, \"sorted symbols completed (%zu symbols)\", showHNodeSymbols(huffNode, maxSymbolValue+1));\n\n    /* build tree */\n    nonNullRank = HUF_buildTree(huffNode, maxSymbolValue);\n\n    /* determine and enforce maxTableLog */\n    maxNbBits = HUF_setMaxHeight(huffNode, (U32)nonNullRank, maxNbBits);\n    if (maxNbBits > HUF_TABLELOG_MAX) return ERROR(GENERIC);   /* check fit into table */\n\n    HUF_buildCTableFromTree(CTable, huffNode, nonNullRank, maxSymbolValue, maxNbBits);\n\n    return maxNbBits;\n}\n\nsize_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue)\n{\n    HUF_CElt const* ct = CTable + 1;\n    size_t nbBits = 0;\n    int s;\n    for (s = 0; s <= (int)maxSymbolValue; ++s) {\n        nbBits += HUF_getNbBits(ct[s]) * count[s];\n    }\n    return nbBits >> 3;\n}\n\nint HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue) {\n    HUF_CTableHeader header = HUF_readCTableHeader(CTable);\n    HUF_CElt const* ct = CTable + 1;\n    int bad = 0;\n    int s;\n\n    assert(header.tableLog <= HUF_TABLELOG_ABSOLUTEMAX);\n\n    if (header.maxSymbolValue < maxSymbolValue)\n        return 0;\n\n    for (s = 0; s <= (int)maxSymbolValue; ++s) {\n        bad |= (count[s] != 0) & (HUF_getNbBits(ct[s]) == 0);\n    }\n    return !bad;\n}\n\nsize_t HUF_compressBound(size_t size) { return HUF_COMPRESSBOUND(size); }\n\n/** HUF_CStream_t:\n * Huffman uses its own BIT_CStream_t implementation.\n * There are three major differences from BIT_CStream_t:\n *   1. HUF_addBits() takes a HUF_CElt (size_t) which is\n *      the pair (nbBits, value) in the format:\n *      format:\n *        - Bits [0, 4)            = nbBits\n *        - Bits [4, 64 - nbBits)  = 0\n *        - Bits [64 - nbBits, 64) = value\n *   2. The bitContainer is built from the upper bits and\n *      right shifted. E.g. to add a new value of N bits\n *      you right shift the bitContainer by N, then or in\n *      the new value into the N upper bits.\n *   3. The bitstream has two bit containers. You can add\n *      bits to the second container and merge them into\n *      the first container.\n */\n\n#define HUF_BITS_IN_CONTAINER (sizeof(size_t) * 8)\n\ntypedef struct {\n    size_t bitContainer[2];\n    size_t bitPos[2];\n\n    BYTE* startPtr;\n    BYTE* ptr;\n    BYTE* endPtr;\n} HUF_CStream_t;\n\n/**! HUF_initCStream():\n * Initializes the bitstream.\n * @returns 0 or an error code.\n */\nstatic size_t HUF_initCStream(HUF_CStream_t* bitC,\n                                  void* startPtr, size_t dstCapacity)\n{\n    ZSTD_memset(bitC, 0, sizeof(*bitC));\n    bitC->startPtr = (BYTE*)startPtr;\n    bitC->ptr = bitC->startPtr;\n    bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->bitContainer[0]);\n    if (dstCapacity <= sizeof(bitC->bitContainer[0])) return ERROR(dstSize_tooSmall);\n    return 0;\n}\n\n/*! HUF_addBits():\n * Adds the symbol stored in HUF_CElt elt to the bitstream.\n *\n * @param elt   The element we're adding. This is a (nbBits, value) pair.\n *              See the HUF_CStream_t docs for the format.\n * @param idx   Insert into the bitstream at this idx.\n * @param kFast This is a template parameter. If the bitstream is guaranteed\n *              to have at least 4 unused bits after this call it may be 1,\n *              otherwise it must be 0. HUF_addBits() is faster when fast is set.\n */\nFORCE_INLINE_TEMPLATE void HUF_addBits(HUF_CStream_t* bitC, HUF_CElt elt, int idx, int kFast)\n{\n    assert(idx <= 1);\n    assert(HUF_getNbBits(elt) <= HUF_TABLELOG_ABSOLUTEMAX);\n    /* This is efficient on x86-64 with BMI2 because shrx\n     * only reads the low 6 bits of the register. The compiler\n     * knows this and elides the mask. When fast is set,\n     * every operation can use the same value loaded from elt.\n     */\n    bitC->bitContainer[idx] >>= HUF_getNbBits(elt);\n    bitC->bitContainer[idx] |= kFast ? HUF_getValueFast(elt) : HUF_getValue(elt);\n    /* We only read the low 8 bits of bitC->bitPos[idx] so it\n     * doesn't matter that the high bits have noise from the value.\n     */\n    bitC->bitPos[idx] += HUF_getNbBitsFast(elt);\n    assert((bitC->bitPos[idx] & 0xFF) <= HUF_BITS_IN_CONTAINER);\n    /* The last 4-bits of elt are dirty if fast is set,\n     * so we must not be overwriting bits that have already been\n     * inserted into the bit container.\n     */\n#if DEBUGLEVEL >= 1\n    {\n        size_t const nbBits = HUF_getNbBits(elt);\n        size_t const dirtyBits = nbBits == 0 ? 0 : ZSTD_highbit32((U32)nbBits) + 1;\n        (void)dirtyBits;\n        /* Middle bits are 0. */\n        assert(((elt >> dirtyBits) << (dirtyBits + nbBits)) == 0);\n        /* We didn't overwrite any bits in the bit container. */\n        assert(!kFast || (bitC->bitPos[idx] & 0xFF) <= HUF_BITS_IN_CONTAINER);\n        (void)dirtyBits;\n    }\n#endif\n}\n\nFORCE_INLINE_TEMPLATE void HUF_zeroIndex1(HUF_CStream_t* bitC)\n{\n    bitC->bitContainer[1] = 0;\n    bitC->bitPos[1] = 0;\n}\n\n/*! HUF_mergeIndex1() :\n * Merges the bit container @ index 1 into the bit container @ index 0\n * and zeros the bit container @ index 1.\n */\nFORCE_INLINE_TEMPLATE void HUF_mergeIndex1(HUF_CStream_t* bitC)\n{\n    assert((bitC->bitPos[1] & 0xFF) < HUF_BITS_IN_CONTAINER);\n    bitC->bitContainer[0] >>= (bitC->bitPos[1] & 0xFF);\n    bitC->bitContainer[0] |= bitC->bitContainer[1];\n    bitC->bitPos[0] += bitC->bitPos[1];\n    assert((bitC->bitPos[0] & 0xFF) <= HUF_BITS_IN_CONTAINER);\n}\n\n/*! HUF_flushBits() :\n* Flushes the bits in the bit container @ index 0.\n*\n* @post bitPos will be < 8.\n* @param kFast If kFast is set then we must know a-priori that\n*              the bit container will not overflow.\n*/\nFORCE_INLINE_TEMPLATE void HUF_flushBits(HUF_CStream_t* bitC, int kFast)\n{\n    /* The upper bits of bitPos are noisy, so we must mask by 0xFF. */\n    size_t const nbBits = bitC->bitPos[0] & 0xFF;\n    size_t const nbBytes = nbBits >> 3;\n    /* The top nbBits bits of bitContainer are the ones we need. */\n    size_t const bitContainer = bitC->bitContainer[0] >> (HUF_BITS_IN_CONTAINER - nbBits);\n    /* Mask bitPos to account for the bytes we consumed. */\n    bitC->bitPos[0] &= 7;\n    assert(nbBits > 0);\n    assert(nbBits <= sizeof(bitC->bitContainer[0]) * 8);\n    assert(bitC->ptr <= bitC->endPtr);\n    MEM_writeLEST(bitC->ptr, bitContainer);\n    bitC->ptr += nbBytes;\n    assert(!kFast || bitC->ptr <= bitC->endPtr);\n    if (!kFast && bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr;\n    /* bitContainer doesn't need to be modified because the leftover\n     * bits are already the top bitPos bits. And we don't care about\n     * noise in the lower values.\n     */\n}\n\n/*! HUF_endMark()\n * @returns The Huffman stream end mark: A 1-bit value = 1.\n */\nstatic HUF_CElt HUF_endMark(void)\n{\n    HUF_CElt endMark;\n    HUF_setNbBits(&endMark, 1);\n    HUF_setValue(&endMark, 1);\n    return endMark;\n}\n\n/*! HUF_closeCStream() :\n *  @return Size of CStream, in bytes,\n *          or 0 if it could not fit into dstBuffer */\nstatic size_t HUF_closeCStream(HUF_CStream_t* bitC)\n{\n    HUF_addBits(bitC, HUF_endMark(), /* idx */ 0, /* kFast */ 0);\n    HUF_flushBits(bitC, /* kFast */ 0);\n    {\n        size_t const nbBits = bitC->bitPos[0] & 0xFF;\n        if (bitC->ptr >= bitC->endPtr) return 0; /* overflow detected */\n        return (size_t)(bitC->ptr - bitC->startPtr) + (nbBits > 0);\n    }\n}\n\nFORCE_INLINE_TEMPLATE void\nHUF_encodeSymbol(HUF_CStream_t* bitCPtr, U32 symbol, const HUF_CElt* CTable, int idx, int fast)\n{\n    HUF_addBits(bitCPtr, CTable[symbol], idx, fast);\n}\n\nFORCE_INLINE_TEMPLATE void\nHUF_compress1X_usingCTable_internal_body_loop(HUF_CStream_t* bitC,\n                                   const BYTE* ip, size_t srcSize,\n                                   const HUF_CElt* ct,\n                                   int kUnroll, int kFastFlush, int kLastFast)\n{\n    /* Join to kUnroll */\n    int n = (int)srcSize;\n    int rem = n % kUnroll;\n    if (rem > 0) {\n        for (; rem > 0; --rem) {\n            HUF_encodeSymbol(bitC, ip[--n], ct, 0, /* fast */ 0);\n        }\n        HUF_flushBits(bitC, kFastFlush);\n    }\n    assert(n % kUnroll == 0);\n\n    /* Join to 2 * kUnroll */\n    if (n % (2 * kUnroll)) {\n        int u;\n        for (u = 1; u < kUnroll; ++u) {\n            HUF_encodeSymbol(bitC, ip[n - u], ct, 0, 1);\n        }\n        HUF_encodeSymbol(bitC, ip[n - kUnroll], ct, 0, kLastFast);\n        HUF_flushBits(bitC, kFastFlush);\n        n -= kUnroll;\n    }\n    assert(n % (2 * kUnroll) == 0);\n\n    for (; n>0; n-= 2 * kUnroll) {\n        /* Encode kUnroll symbols into the bitstream @ index 0. */\n        int u;\n        for (u = 1; u < kUnroll; ++u) {\n            HUF_encodeSymbol(bitC, ip[n - u], ct, /* idx */ 0, /* fast */ 1);\n        }\n        HUF_encodeSymbol(bitC, ip[n - kUnroll], ct, /* idx */ 0, /* fast */ kLastFast);\n        HUF_flushBits(bitC, kFastFlush);\n        /* Encode kUnroll symbols into the bitstream @ index 1.\n         * This allows us to start filling the bit container\n         * without any data dependencies.\n         */\n        HUF_zeroIndex1(bitC);\n        for (u = 1; u < kUnroll; ++u) {\n            HUF_encodeSymbol(bitC, ip[n - kUnroll - u], ct, /* idx */ 1, /* fast */ 1);\n        }\n        HUF_encodeSymbol(bitC, ip[n - kUnroll - kUnroll], ct, /* idx */ 1, /* fast */ kLastFast);\n        /* Merge bitstream @ index 1 into the bitstream @ index 0 */\n        HUF_mergeIndex1(bitC);\n        HUF_flushBits(bitC, kFastFlush);\n    }\n    assert(n == 0);\n\n}\n\n/**\n * Returns a tight upper bound on the output space needed by Huffman\n * with 8 bytes buffer to handle over-writes. If the output is at least\n * this large we don't need to do bounds checks during Huffman encoding.\n */\nstatic size_t HUF_tightCompressBound(size_t srcSize, size_t tableLog)\n{\n    return ((srcSize * tableLog) >> 3) + 8;\n}\n\n\nFORCE_INLINE_TEMPLATE size_t\nHUF_compress1X_usingCTable_internal_body(void* dst, size_t dstSize,\n                                   const void* src, size_t srcSize,\n                                   const HUF_CElt* CTable)\n{\n    U32 const tableLog = HUF_readCTableHeader(CTable).tableLog;\n    HUF_CElt const* ct = CTable + 1;\n    const BYTE* ip = (const BYTE*) src;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = ostart + dstSize;\n    HUF_CStream_t bitC;\n\n    /* init */\n    if (dstSize < 8) return 0;   /* not enough space to compress */\n    { BYTE* op = ostart;\n      size_t const initErr = HUF_initCStream(&bitC, op, (size_t)(oend-op));\n      if (HUF_isError(initErr)) return 0; }\n\n    if (dstSize < HUF_tightCompressBound(srcSize, (size_t)tableLog) || tableLog > 11)\n        HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ MEM_32bits() ? 2 : 4, /* kFast */ 0, /* kLastFast */ 0);\n    else {\n        if (MEM_32bits()) {\n            switch (tableLog) {\n            case 11:\n                HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 2, /* kFastFlush */ 1, /* kLastFast */ 0);\n                break;\n            case 10: ZSTD_FALLTHROUGH;\n            case 9: ZSTD_FALLTHROUGH;\n            case 8:\n                HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 2, /* kFastFlush */ 1, /* kLastFast */ 1);\n                break;\n            case 7: ZSTD_FALLTHROUGH;\n            default:\n                HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 3, /* kFastFlush */ 1, /* kLastFast */ 1);\n                break;\n            }\n        } else {\n            switch (tableLog) {\n            case 11:\n                HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 5, /* kFastFlush */ 1, /* kLastFast */ 0);\n                break;\n            case 10:\n                HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 5, /* kFastFlush */ 1, /* kLastFast */ 1);\n                break;\n            case 9:\n                HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 6, /* kFastFlush */ 1, /* kLastFast */ 0);\n                break;\n            case 8:\n                HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 7, /* kFastFlush */ 1, /* kLastFast */ 0);\n                break;\n            case 7:\n                HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 8, /* kFastFlush */ 1, /* kLastFast */ 0);\n                break;\n            case 6: ZSTD_FALLTHROUGH;\n            default:\n                HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 9, /* kFastFlush */ 1, /* kLastFast */ 1);\n                break;\n            }\n        }\n    }\n    assert(bitC.ptr <= bitC.endPtr);\n\n    return HUF_closeCStream(&bitC);\n}\n\n#if DYNAMIC_BMI2\n\nstatic BMI2_TARGET_ATTRIBUTE size_t\nHUF_compress1X_usingCTable_internal_bmi2(void* dst, size_t dstSize,\n                                   const void* src, size_t srcSize,\n                                   const HUF_CElt* CTable)\n{\n    return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable);\n}\n\nstatic size_t\nHUF_compress1X_usingCTable_internal_default(void* dst, size_t dstSize,\n                                      const void* src, size_t srcSize,\n                                      const HUF_CElt* CTable)\n{\n    return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable);\n}\n\nstatic size_t\nHUF_compress1X_usingCTable_internal(void* dst, size_t dstSize,\n                              const void* src, size_t srcSize,\n                              const HUF_CElt* CTable, const int flags)\n{\n    if (flags & HUF_flags_bmi2) {\n        return HUF_compress1X_usingCTable_internal_bmi2(dst, dstSize, src, srcSize, CTable);\n    }\n    return HUF_compress1X_usingCTable_internal_default(dst, dstSize, src, srcSize, CTable);\n}\n\n#else\n\nstatic size_t\nHUF_compress1X_usingCTable_internal(void* dst, size_t dstSize,\n                              const void* src, size_t srcSize,\n                              const HUF_CElt* CTable, const int flags)\n{\n    (void)flags;\n    return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable);\n}\n\n#endif\n\nsize_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int flags)\n{\n    return HUF_compress1X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, flags);\n}\n\nstatic size_t\nHUF_compress4X_usingCTable_internal(void* dst, size_t dstSize,\n                              const void* src, size_t srcSize,\n                              const HUF_CElt* CTable, int flags)\n{\n    size_t const segmentSize = (srcSize+3)/4;   /* first 3 segments */\n    const BYTE* ip = (const BYTE*) src;\n    const BYTE* const iend = ip + srcSize;\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* const oend = ostart + dstSize;\n    BYTE* op = ostart;\n\n    if (dstSize < 6 + 1 + 1 + 1 + 8) return 0;   /* minimum space to compress successfully */\n    if (srcSize < 12) return 0;   /* no saving possible : too small input */\n    op += 6;   /* jumpTable */\n\n    assert(op <= oend);\n    {   CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, flags) );\n        if (cSize == 0 || cSize > 65535) return 0;\n        MEM_writeLE16(ostart, (U16)cSize);\n        op += cSize;\n    }\n\n    ip += segmentSize;\n    assert(op <= oend);\n    {   CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, flags) );\n        if (cSize == 0 || cSize > 65535) return 0;\n        MEM_writeLE16(ostart+2, (U16)cSize);\n        op += cSize;\n    }\n\n    ip += segmentSize;\n    assert(op <= oend);\n    {   CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, flags) );\n        if (cSize == 0 || cSize > 65535) return 0;\n        MEM_writeLE16(ostart+4, (U16)cSize);\n        op += cSize;\n    }\n\n    ip += segmentSize;\n    assert(op <= oend);\n    assert(ip <= iend);\n    {   CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, (size_t)(iend-ip), CTable, flags) );\n        if (cSize == 0 || cSize > 65535) return 0;\n        op += cSize;\n    }\n\n    return (size_t)(op-ostart);\n}\n\nsize_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int flags)\n{\n    return HUF_compress4X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, flags);\n}\n\ntypedef enum { HUF_singleStream, HUF_fourStreams } HUF_nbStreams_e;\n\nstatic size_t HUF_compressCTable_internal(\n                BYTE* const ostart, BYTE* op, BYTE* const oend,\n                const void* src, size_t srcSize,\n                HUF_nbStreams_e nbStreams, const HUF_CElt* CTable, const int flags)\n{\n    size_t const cSize = (nbStreams==HUF_singleStream) ?\n                         HUF_compress1X_usingCTable_internal(op, (size_t)(oend - op), src, srcSize, CTable, flags) :\n                         HUF_compress4X_usingCTable_internal(op, (size_t)(oend - op), src, srcSize, CTable, flags);\n    if (HUF_isError(cSize)) { return cSize; }\n    if (cSize==0) { return 0; }   /* uncompressible */\n    op += cSize;\n    /* check compressibility */\n    assert(op >= ostart);\n    if ((size_t)(op-ostart) >= srcSize-1) { return 0; }\n    return (size_t)(op-ostart);\n}\n\ntypedef struct {\n    unsigned count[HUF_SYMBOLVALUE_MAX + 1];\n    HUF_CElt CTable[HUF_CTABLE_SIZE_ST(HUF_SYMBOLVALUE_MAX)];\n    union {\n        HUF_buildCTable_wksp_tables buildCTable_wksp;\n        HUF_WriteCTableWksp writeCTable_wksp;\n        U32 hist_wksp[HIST_WKSP_SIZE_U32];\n    } wksps;\n} HUF_compress_tables_t;\n\n#define SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE 4096\n#define SUSPECT_INCOMPRESSIBLE_SAMPLE_RATIO 10  /* Must be >= 2 */\n\nunsigned HUF_cardinality(const unsigned* count, unsigned maxSymbolValue)\n{\n    unsigned cardinality = 0;\n    unsigned i;\n\n    for (i = 0; i < maxSymbolValue + 1; i++) {\n        if (count[i] != 0) cardinality += 1;\n    }\n\n    return cardinality;\n}\n\nunsigned HUF_minTableLog(unsigned symbolCardinality)\n{\n    U32 minBitsSymbols = ZSTD_highbit32(symbolCardinality) + 1;\n    return minBitsSymbols;\n}\n\nunsigned HUF_optimalTableLog(\n            unsigned maxTableLog,\n            size_t srcSize,\n            unsigned maxSymbolValue,\n            void* workSpace, size_t wkspSize,\n            HUF_CElt* table,\n      const unsigned* count,\n            int flags)\n{\n    assert(srcSize > 1); /* Not supported, RLE should be used instead */\n    assert(wkspSize >= sizeof(HUF_buildCTable_wksp_tables));\n\n    if (!(flags & HUF_flags_optimalDepth)) {\n        /* cheap evaluation, based on FSE */\n        return FSE_optimalTableLog_internal(maxTableLog, srcSize, maxSymbolValue, 1);\n    }\n\n    {   BYTE* dst = (BYTE*)workSpace + sizeof(HUF_WriteCTableWksp);\n        size_t dstSize = wkspSize - sizeof(HUF_WriteCTableWksp);\n        size_t hSize, newSize;\n        const unsigned symbolCardinality = HUF_cardinality(count, maxSymbolValue);\n        const unsigned minTableLog = HUF_minTableLog(symbolCardinality);\n        size_t optSize = ((size_t) ~0) - 1;\n        unsigned optLog = maxTableLog, optLogGuess;\n\n        DEBUGLOG(6, \"HUF_optimalTableLog: probing huf depth (srcSize=%zu)\", srcSize);\n\n        /* Search until size increases */\n        for (optLogGuess = minTableLog; optLogGuess <= maxTableLog; optLogGuess++) {\n            DEBUGLOG(7, \"checking for huffLog=%u\", optLogGuess);\n\n            {   size_t maxBits = HUF_buildCTable_wksp(table, count, maxSymbolValue, optLogGuess, workSpace, wkspSize);\n                if (ERR_isError(maxBits)) continue;\n\n                if (maxBits < optLogGuess && optLogGuess > minTableLog) break;\n\n                hSize = HUF_writeCTable_wksp(dst, dstSize, table, maxSymbolValue, (U32)maxBits, workSpace, wkspSize);\n            }\n\n            if (ERR_isError(hSize)) continue;\n\n            newSize = HUF_estimateCompressedSize(table, count, maxSymbolValue) + hSize;\n\n            if (newSize > optSize + 1) {\n                break;\n            }\n\n            if (newSize < optSize) {\n                optSize = newSize;\n                optLog = optLogGuess;\n            }\n        }\n        assert(optLog <= HUF_TABLELOG_MAX);\n        return optLog;\n    }\n}\n\n/* HUF_compress_internal() :\n * `workSpace_align4` must be aligned on 4-bytes boundaries,\n * and occupies the same space as a table of HUF_WORKSPACE_SIZE_U64 unsigned */\nstatic size_t\nHUF_compress_internal (void* dst, size_t dstSize,\n                 const void* src, size_t srcSize,\n                       unsigned maxSymbolValue, unsigned huffLog,\n                       HUF_nbStreams_e nbStreams,\n                       void* workSpace, size_t wkspSize,\n                       HUF_CElt* oldHufTable, HUF_repeat* repeat, int flags)\n{\n    HUF_compress_tables_t* const table = (HUF_compress_tables_t*)HUF_alignUpWorkspace(workSpace, &wkspSize, ZSTD_ALIGNOF(size_t));\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = ostart + dstSize;\n    BYTE* op = ostart;\n\n    DEBUGLOG(5, \"HUF_compress_internal (srcSize=%zu)\", srcSize);\n    HUF_STATIC_ASSERT(sizeof(*table) + HUF_WORKSPACE_MAX_ALIGNMENT <= HUF_WORKSPACE_SIZE);\n\n    /* checks & inits */\n    if (wkspSize < sizeof(*table)) return ERROR(workSpace_tooSmall);\n    if (!srcSize) return 0;  /* Uncompressed */\n    if (!dstSize) return 0;  /* cannot fit anything within dst budget */\n    if (srcSize > HUF_BLOCKSIZE_MAX) return ERROR(srcSize_wrong);   /* current block size limit */\n    if (huffLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);\n    if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge);\n    if (!maxSymbolValue) maxSymbolValue = HUF_SYMBOLVALUE_MAX;\n    if (!huffLog) huffLog = HUF_TABLELOG_DEFAULT;\n\n    /* Heuristic : If old table is valid, use it for small inputs */\n    if ((flags & HUF_flags_preferRepeat) && repeat && *repeat == HUF_repeat_valid) {\n        return HUF_compressCTable_internal(ostart, op, oend,\n                                           src, srcSize,\n                                           nbStreams, oldHufTable, flags);\n    }\n\n    /* If uncompressible data is suspected, do a smaller sampling first */\n    DEBUG_STATIC_ASSERT(SUSPECT_INCOMPRESSIBLE_SAMPLE_RATIO >= 2);\n    if ((flags & HUF_flags_suspectUncompressible) && srcSize >= (SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE * SUSPECT_INCOMPRESSIBLE_SAMPLE_RATIO)) {\n        size_t largestTotal = 0;\n        DEBUGLOG(5, \"input suspected incompressible : sampling to check\");\n        {   unsigned maxSymbolValueBegin = maxSymbolValue;\n            CHECK_V_F(largestBegin, HIST_count_simple (table->count, &maxSymbolValueBegin, (const BYTE*)src, SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE) );\n            largestTotal += largestBegin;\n        }\n        {   unsigned maxSymbolValueEnd = maxSymbolValue;\n            CHECK_V_F(largestEnd, HIST_count_simple (table->count, &maxSymbolValueEnd, (const BYTE*)src + srcSize - SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE, SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE) );\n            largestTotal += largestEnd;\n        }\n        if (largestTotal <= ((2 * SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE) >> 7)+4) return 0;   /* heuristic : probably not compressible enough */\n    }\n\n    /* Scan input and build symbol stats */\n    {   CHECK_V_F(largest, HIST_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize, table->wksps.hist_wksp, sizeof(table->wksps.hist_wksp)) );\n        if (largest == srcSize) { *ostart = ((const BYTE*)src)[0]; return 1; }   /* single symbol, rle */\n        if (largest <= (srcSize >> 7)+4) return 0;   /* heuristic : probably not compressible enough */\n    }\n    DEBUGLOG(6, \"histogram detail completed (%zu symbols)\", showU32(table->count, maxSymbolValue+1));\n\n    /* Check validity of previous table */\n    if ( repeat\n      && *repeat == HUF_repeat_check\n      && !HUF_validateCTable(oldHufTable, table->count, maxSymbolValue)) {\n        *repeat = HUF_repeat_none;\n    }\n    /* Heuristic : use existing table for small inputs */\n    if ((flags & HUF_flags_preferRepeat) && repeat && *repeat != HUF_repeat_none) {\n        return HUF_compressCTable_internal(ostart, op, oend,\n                                           src, srcSize,\n                                           nbStreams, oldHufTable, flags);\n    }\n\n    /* Build Huffman Tree */\n    huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue, &table->wksps, sizeof(table->wksps), table->CTable, table->count, flags);\n    {   size_t const maxBits = HUF_buildCTable_wksp(table->CTable, table->count,\n                                            maxSymbolValue, huffLog,\n                                            &table->wksps.buildCTable_wksp, sizeof(table->wksps.buildCTable_wksp));\n        CHECK_F(maxBits);\n        huffLog = (U32)maxBits;\n        DEBUGLOG(6, \"bit distribution completed (%zu symbols)\", showCTableBits(table->CTable + 1, maxSymbolValue+1));\n    }\n\n    /* Write table description header */\n    {   CHECK_V_F(hSize, HUF_writeCTable_wksp(op, dstSize, table->CTable, maxSymbolValue, huffLog,\n                                              &table->wksps.writeCTable_wksp, sizeof(table->wksps.writeCTable_wksp)) );\n        /* Check if using previous huffman table is beneficial */\n        if (repeat && *repeat != HUF_repeat_none) {\n            size_t const oldSize = HUF_estimateCompressedSize(oldHufTable, table->count, maxSymbolValue);\n            size_t const newSize = HUF_estimateCompressedSize(table->CTable, table->count, maxSymbolValue);\n            if (oldSize <= hSize + newSize || hSize + 12 >= srcSize) {\n                return HUF_compressCTable_internal(ostart, op, oend,\n                                                   src, srcSize,\n                                                   nbStreams, oldHufTable, flags);\n        }   }\n\n        /* Use the new huffman table */\n        if (hSize + 12ul >= srcSize) { return 0; }\n        op += hSize;\n        if (repeat) { *repeat = HUF_repeat_none; }\n        if (oldHufTable)\n            ZSTD_memcpy(oldHufTable, table->CTable, sizeof(table->CTable));  /* Save new table */\n    }\n    return HUF_compressCTable_internal(ostart, op, oend,\n                                       src, srcSize,\n                                       nbStreams, table->CTable, flags);\n}\n\nsize_t HUF_compress1X_repeat (void* dst, size_t dstSize,\n                      const void* src, size_t srcSize,\n                      unsigned maxSymbolValue, unsigned huffLog,\n                      void* workSpace, size_t wkspSize,\n                      HUF_CElt* hufTable, HUF_repeat* repeat, int flags)\n{\n    DEBUGLOG(5, \"HUF_compress1X_repeat (srcSize = %zu)\", srcSize);\n    return HUF_compress_internal(dst, dstSize, src, srcSize,\n                                 maxSymbolValue, huffLog, HUF_singleStream,\n                                 workSpace, wkspSize, hufTable,\n                                 repeat, flags);\n}\n\n/* HUF_compress4X_repeat():\n * compress input using 4 streams.\n * consider skipping quickly\n * reuse an existing huffman compression table */\nsize_t HUF_compress4X_repeat (void* dst, size_t dstSize,\n                      const void* src, size_t srcSize,\n                      unsigned maxSymbolValue, unsigned huffLog,\n                      void* workSpace, size_t wkspSize,\n                      HUF_CElt* hufTable, HUF_repeat* repeat, int flags)\n{\n    DEBUGLOG(5, \"HUF_compress4X_repeat (srcSize = %zu)\", srcSize);\n    return HUF_compress_internal(dst, dstSize, src, srcSize,\n                                 maxSymbolValue, huffLog, HUF_fourStreams,\n                                 workSpace, wkspSize,\n                                 hufTable, repeat, flags);\n}\n"
  },
  {
    "path": "lib/compress/zstd_compress.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/*-*************************************\n*  Dependencies\n***************************************/\n#include \"../common/allocations.h\"  /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */\n#include \"../common/zstd_deps.h\"  /* INT_MAX, ZSTD_memset, ZSTD_memcpy */\n#include \"../common/mem.h\"\n#include \"../common/error_private.h\"\n#include \"hist.h\"           /* HIST_countFast_wksp */\n#define FSE_STATIC_LINKING_ONLY   /* FSE_encodeSymbol */\n#include \"../common/fse.h\"\n#include \"../common/huf.h\"\n#include \"zstd_compress_internal.h\"\n#include \"zstd_compress_sequences.h\"\n#include \"zstd_compress_literals.h\"\n#include \"zstd_fast.h\"\n#include \"zstd_double_fast.h\"\n#include \"zstd_lazy.h\"\n#include \"zstd_opt.h\"\n#include \"zstd_ldm.h\"\n#include \"zstd_compress_superblock.h\"\n#include  \"../common/bits.h\"      /* ZSTD_highbit32, ZSTD_rotateRight_U64 */\n\n/* ***************************************************************\n*  Tuning parameters\n*****************************************************************/\n/*!\n * COMPRESS_HEAPMODE :\n * Select how default decompression function ZSTD_compress() allocates its context,\n * on stack (0, default), or into heap (1).\n * Note that functions with explicit context such as ZSTD_compressCCtx() are unaffected.\n */\n#ifndef ZSTD_COMPRESS_HEAPMODE\n#  define ZSTD_COMPRESS_HEAPMODE 0\n#endif\n\n/*!\n * ZSTD_HASHLOG3_MAX :\n * Maximum size of the hash table dedicated to find 3-bytes matches,\n * in log format, aka 17 => 1 << 17 == 128Ki positions.\n * This structure is only used in zstd_opt.\n * Since allocation is centralized for all strategies, it has to be known here.\n * The actual (selected) size of the hash table is then stored in ZSTD_MatchState_t.hashLog3,\n * so that zstd_opt.c doesn't need to know about this constant.\n */\n#ifndef ZSTD_HASHLOG3_MAX\n#  define ZSTD_HASHLOG3_MAX 17\n#endif\n\n\n/*-*************************************\n*  Forward declarations\n***************************************/\nsize_t convertSequences_noRepcodes(SeqDef* dstSeqs, const ZSTD_Sequence* inSeqs,\n    size_t nbSequences);\n\n\n/*-*************************************\n*  Helper functions\n***************************************/\n/* ZSTD_compressBound()\n * Note that the result from this function is only valid for\n * the one-pass compression functions.\n * When employing the streaming mode,\n * if flushes are frequently altering the size of blocks,\n * the overhead from block headers can make the compressed data larger\n * than the return value of ZSTD_compressBound().\n */\nsize_t ZSTD_compressBound(size_t srcSize) {\n    size_t const r = ZSTD_COMPRESSBOUND(srcSize);\n    if (r==0) return ERROR(srcSize_wrong);\n    return r;\n}\n\n\n/*-*************************************\n*  Context memory management\n***************************************/\nstruct ZSTD_CDict_s {\n    const void* dictContent;\n    size_t dictContentSize;\n    ZSTD_dictContentType_e dictContentType; /* The dictContentType the CDict was created with */\n    U32* entropyWorkspace; /* entropy workspace of HUF_WORKSPACE_SIZE bytes */\n    ZSTD_cwksp workspace;\n    ZSTD_MatchState_t matchState;\n    ZSTD_compressedBlockState_t cBlockState;\n    ZSTD_customMem customMem;\n    U32 dictID;\n    int compressionLevel; /* 0 indicates that advanced API was used to select CDict params */\n    ZSTD_ParamSwitch_e useRowMatchFinder; /* Indicates whether the CDict was created with params that would use\n                                           * row-based matchfinder. Unless the cdict is reloaded, we will use\n                                           * the same greedy/lazy matchfinder at compression time.\n                                           */\n};  /* typedef'd to ZSTD_CDict within \"zstd.h\" */\n\nZSTD_CCtx* ZSTD_createCCtx(void)\n{\n    return ZSTD_createCCtx_advanced(ZSTD_defaultCMem);\n}\n\nstatic void ZSTD_initCCtx(ZSTD_CCtx* cctx, ZSTD_customMem memManager)\n{\n    assert(cctx != NULL);\n    ZSTD_memset(cctx, 0, sizeof(*cctx));\n    cctx->customMem = memManager;\n    cctx->bmi2 = ZSTD_cpuSupportsBmi2();\n    {   size_t const err = ZSTD_CCtx_reset(cctx, ZSTD_reset_parameters);\n        assert(!ZSTD_isError(err));\n        (void)err;\n    }\n}\n\nZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)\n{\n    ZSTD_STATIC_ASSERT(zcss_init==0);\n    ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN==(0ULL - 1));\n    if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;\n    {   ZSTD_CCtx* const cctx = (ZSTD_CCtx*)ZSTD_customMalloc(sizeof(ZSTD_CCtx), customMem);\n        if (!cctx) return NULL;\n        ZSTD_initCCtx(cctx, customMem);\n        return cctx;\n    }\n}\n\nZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize)\n{\n    ZSTD_cwksp ws;\n    ZSTD_CCtx* cctx;\n    if (workspaceSize <= sizeof(ZSTD_CCtx)) return NULL;  /* minimum size */\n    if ((size_t)workspace & 7) return NULL;  /* must be 8-aligned */\n    ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_static_alloc);\n\n    cctx = (ZSTD_CCtx*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CCtx));\n    if (cctx == NULL) return NULL;\n\n    ZSTD_memset(cctx, 0, sizeof(ZSTD_CCtx));\n    ZSTD_cwksp_move(&cctx->workspace, &ws);\n    cctx->staticSize = workspaceSize;\n\n    /* statically sized space. tmpWorkspace never moves (but prev/next block swap places) */\n    if (!ZSTD_cwksp_check_available(&cctx->workspace, TMP_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL;\n    cctx->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t));\n    cctx->blockState.nextCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t));\n    cctx->tmpWorkspace = ZSTD_cwksp_reserve_object(&cctx->workspace, TMP_WORKSPACE_SIZE);\n    cctx->tmpWkspSize = TMP_WORKSPACE_SIZE;\n    cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());\n    return cctx;\n}\n\n/**\n * Clears and frees all of the dictionaries in the CCtx.\n */\nstatic void ZSTD_clearAllDicts(ZSTD_CCtx* cctx)\n{\n    ZSTD_customFree(cctx->localDict.dictBuffer, cctx->customMem);\n    ZSTD_freeCDict(cctx->localDict.cdict);\n    ZSTD_memset(&cctx->localDict, 0, sizeof(cctx->localDict));\n    ZSTD_memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict));\n    cctx->cdict = NULL;\n}\n\nstatic size_t ZSTD_sizeof_localDict(ZSTD_localDict dict)\n{\n    size_t const bufferSize = dict.dictBuffer != NULL ? dict.dictSize : 0;\n    size_t const cdictSize = ZSTD_sizeof_CDict(dict.cdict);\n    return bufferSize + cdictSize;\n}\n\nstatic void ZSTD_freeCCtxContent(ZSTD_CCtx* cctx)\n{\n    assert(cctx != NULL);\n    assert(cctx->staticSize == 0);\n    ZSTD_clearAllDicts(cctx);\n#ifdef ZSTD_MULTITHREAD\n    ZSTDMT_freeCCtx(cctx->mtctx); cctx->mtctx = NULL;\n#endif\n    ZSTD_cwksp_free(&cctx->workspace, cctx->customMem);\n}\n\nsize_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)\n{\n    DEBUGLOG(3, \"ZSTD_freeCCtx (address: %p)\", (void*)cctx);\n    if (cctx==NULL) return 0;   /* support free on NULL */\n    RETURN_ERROR_IF(cctx->staticSize, memory_allocation,\n                    \"not compatible with static CCtx\");\n    {   int cctxInWorkspace = ZSTD_cwksp_owns_buffer(&cctx->workspace, cctx);\n        ZSTD_freeCCtxContent(cctx);\n        if (!cctxInWorkspace) ZSTD_customFree(cctx, cctx->customMem);\n    }\n    return 0;\n}\n\n\nstatic size_t ZSTD_sizeof_mtctx(const ZSTD_CCtx* cctx)\n{\n#ifdef ZSTD_MULTITHREAD\n    return ZSTDMT_sizeof_CCtx(cctx->mtctx);\n#else\n    (void)cctx;\n    return 0;\n#endif\n}\n\n\nsize_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)\n{\n    if (cctx==NULL) return 0;   /* support sizeof on NULL */\n    /* cctx may be in the workspace */\n    return (cctx->workspace.workspace == cctx ? 0 : sizeof(*cctx))\n           + ZSTD_cwksp_sizeof(&cctx->workspace)\n           + ZSTD_sizeof_localDict(cctx->localDict)\n           + ZSTD_sizeof_mtctx(cctx);\n}\n\nsize_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs)\n{\n    return ZSTD_sizeof_CCtx(zcs);  /* same object */\n}\n\n/* private API call, for dictBuilder only */\nconst SeqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); }\n\n/* Returns true if the strategy supports using a row based matchfinder */\nstatic int ZSTD_rowMatchFinderSupported(const ZSTD_strategy strategy) {\n    return (strategy >= ZSTD_greedy && strategy <= ZSTD_lazy2);\n}\n\n/* Returns true if the strategy and useRowMatchFinder mode indicate that we will use the row based matchfinder\n * for this compression.\n */\nstatic int ZSTD_rowMatchFinderUsed(const ZSTD_strategy strategy, const ZSTD_ParamSwitch_e mode) {\n    assert(mode != ZSTD_ps_auto);\n    return ZSTD_rowMatchFinderSupported(strategy) && (mode == ZSTD_ps_enable);\n}\n\n/* Returns row matchfinder usage given an initial mode and cParams */\nstatic ZSTD_ParamSwitch_e ZSTD_resolveRowMatchFinderMode(ZSTD_ParamSwitch_e mode,\n                                                         const ZSTD_compressionParameters* const cParams) {\n#ifdef ZSTD_LINUX_KERNEL\n    /* The Linux Kernel does not use SIMD, and 128KB is a very common size, e.g. in BtrFS.\n     * The row match finder is slower for this size without SIMD, so disable it.\n     */\n    const unsigned kWindowLogLowerBound = 17;\n#else\n    const unsigned kWindowLogLowerBound = 14;\n#endif\n    if (mode != ZSTD_ps_auto) return mode; /* if requested enabled, but no SIMD, we still will use row matchfinder */\n    mode = ZSTD_ps_disable;\n    if (!ZSTD_rowMatchFinderSupported(cParams->strategy)) return mode;\n    if (cParams->windowLog > kWindowLogLowerBound) mode = ZSTD_ps_enable;\n    return mode;\n}\n\n/* Returns block splitter usage (generally speaking, when using slower/stronger compression modes) */\nstatic ZSTD_ParamSwitch_e ZSTD_resolveBlockSplitterMode(ZSTD_ParamSwitch_e mode,\n                                                        const ZSTD_compressionParameters* const cParams) {\n    if (mode != ZSTD_ps_auto) return mode;\n    return (cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 17) ? ZSTD_ps_enable : ZSTD_ps_disable;\n}\n\n/* Returns 1 if the arguments indicate that we should allocate a chainTable, 0 otherwise */\nstatic int ZSTD_allocateChainTable(const ZSTD_strategy strategy,\n                                   const ZSTD_ParamSwitch_e useRowMatchFinder,\n                                   const U32 forDDSDict) {\n    assert(useRowMatchFinder != ZSTD_ps_auto);\n    /* We always should allocate a chaintable if we are allocating a matchstate for a DDS dictionary matchstate.\n     * We do not allocate a chaintable if we are using ZSTD_fast, or are using the row-based matchfinder.\n     */\n    return forDDSDict || ((strategy != ZSTD_fast) && !ZSTD_rowMatchFinderUsed(strategy, useRowMatchFinder));\n}\n\n/* Returns ZSTD_ps_enable if compression parameters are such that we should\n * enable long distance matching (wlog >= 27, strategy >= btopt).\n * Returns ZSTD_ps_disable otherwise.\n */\nstatic ZSTD_ParamSwitch_e ZSTD_resolveEnableLdm(ZSTD_ParamSwitch_e mode,\n                                 const ZSTD_compressionParameters* const cParams) {\n    if (mode != ZSTD_ps_auto) return mode;\n    return (cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 27) ? ZSTD_ps_enable : ZSTD_ps_disable;\n}\n\nstatic int ZSTD_resolveExternalSequenceValidation(int mode) {\n    return mode;\n}\n\n/* Resolves maxBlockSize to the default if no value is present. */\nstatic size_t ZSTD_resolveMaxBlockSize(size_t maxBlockSize) {\n    if (maxBlockSize == 0) {\n        return ZSTD_BLOCKSIZE_MAX;\n    } else {\n        return maxBlockSize;\n    }\n}\n\nstatic ZSTD_ParamSwitch_e ZSTD_resolveExternalRepcodeSearch(ZSTD_ParamSwitch_e value, int cLevel) {\n    if (value != ZSTD_ps_auto) return value;\n    if (cLevel < 10) {\n        return ZSTD_ps_disable;\n    } else {\n        return ZSTD_ps_enable;\n    }\n}\n\n/* Returns 1 if compression parameters are such that CDict hashtable and chaintable indices are tagged.\n * If so, the tags need to be removed in ZSTD_resetCCtx_byCopyingCDict. */\nstatic int ZSTD_CDictIndicesAreTagged(const ZSTD_compressionParameters* const cParams) {\n    return cParams->strategy == ZSTD_fast || cParams->strategy == ZSTD_dfast;\n}\n\nstatic ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams(\n        ZSTD_compressionParameters cParams)\n{\n    ZSTD_CCtx_params cctxParams;\n    /* should not matter, as all cParams are presumed properly defined */\n    ZSTD_CCtxParams_init(&cctxParams, ZSTD_CLEVEL_DEFAULT);\n    cctxParams.cParams = cParams;\n\n    /* Adjust advanced params according to cParams */\n    cctxParams.ldmParams.enableLdm = ZSTD_resolveEnableLdm(cctxParams.ldmParams.enableLdm, &cParams);\n    if (cctxParams.ldmParams.enableLdm == ZSTD_ps_enable) {\n        ZSTD_ldm_adjustParameters(&cctxParams.ldmParams, &cParams);\n        assert(cctxParams.ldmParams.hashLog >= cctxParams.ldmParams.bucketSizeLog);\n        assert(cctxParams.ldmParams.hashRateLog < 32);\n    }\n    cctxParams.postBlockSplitter = ZSTD_resolveBlockSplitterMode(cctxParams.postBlockSplitter, &cParams);\n    cctxParams.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams.useRowMatchFinder, &cParams);\n    cctxParams.validateSequences = ZSTD_resolveExternalSequenceValidation(cctxParams.validateSequences);\n    cctxParams.maxBlockSize = ZSTD_resolveMaxBlockSize(cctxParams.maxBlockSize);\n    cctxParams.searchForExternalRepcodes = ZSTD_resolveExternalRepcodeSearch(cctxParams.searchForExternalRepcodes,\n                                                                             cctxParams.compressionLevel);\n    assert(!ZSTD_checkCParams(cParams));\n    return cctxParams;\n}\n\nstatic ZSTD_CCtx_params* ZSTD_createCCtxParams_advanced(\n        ZSTD_customMem customMem)\n{\n    ZSTD_CCtx_params* params;\n    if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;\n    params = (ZSTD_CCtx_params*)ZSTD_customCalloc(\n            sizeof(ZSTD_CCtx_params), customMem);\n    if (!params) { return NULL; }\n    ZSTD_CCtxParams_init(params, ZSTD_CLEVEL_DEFAULT);\n    params->customMem = customMem;\n    return params;\n}\n\nZSTD_CCtx_params* ZSTD_createCCtxParams(void)\n{\n    return ZSTD_createCCtxParams_advanced(ZSTD_defaultCMem);\n}\n\nsize_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params)\n{\n    if (params == NULL) { return 0; }\n    ZSTD_customFree(params, params->customMem);\n    return 0;\n}\n\nsize_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params)\n{\n    return ZSTD_CCtxParams_init(params, ZSTD_CLEVEL_DEFAULT);\n}\n\nsize_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) {\n    RETURN_ERROR_IF(!cctxParams, GENERIC, \"NULL pointer!\");\n    ZSTD_memset(cctxParams, 0, sizeof(*cctxParams));\n    cctxParams->compressionLevel = compressionLevel;\n    cctxParams->fParams.contentSizeFlag = 1;\n    return 0;\n}\n\n#define ZSTD_NO_CLEVEL 0\n\n/**\n * Initializes `cctxParams` from `params` and `compressionLevel`.\n * @param compressionLevel If params are derived from a compression level then that compression level, otherwise ZSTD_NO_CLEVEL.\n */\nstatic void\nZSTD_CCtxParams_init_internal(ZSTD_CCtx_params* cctxParams,\n                        const ZSTD_parameters* params,\n                              int compressionLevel)\n{\n    assert(!ZSTD_checkCParams(params->cParams));\n    ZSTD_memset(cctxParams, 0, sizeof(*cctxParams));\n    cctxParams->cParams = params->cParams;\n    cctxParams->fParams = params->fParams;\n    /* Should not matter, as all cParams are presumed properly defined.\n     * But, set it for tracing anyway.\n     */\n    cctxParams->compressionLevel = compressionLevel;\n    cctxParams->useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams->useRowMatchFinder, &params->cParams);\n    cctxParams->postBlockSplitter = ZSTD_resolveBlockSplitterMode(cctxParams->postBlockSplitter, &params->cParams);\n    cctxParams->ldmParams.enableLdm = ZSTD_resolveEnableLdm(cctxParams->ldmParams.enableLdm, &params->cParams);\n    cctxParams->validateSequences = ZSTD_resolveExternalSequenceValidation(cctxParams->validateSequences);\n    cctxParams->maxBlockSize = ZSTD_resolveMaxBlockSize(cctxParams->maxBlockSize);\n    cctxParams->searchForExternalRepcodes = ZSTD_resolveExternalRepcodeSearch(cctxParams->searchForExternalRepcodes, compressionLevel);\n    DEBUGLOG(4, \"ZSTD_CCtxParams_init_internal: useRowMatchFinder=%d, useBlockSplitter=%d ldm=%d\",\n                cctxParams->useRowMatchFinder, cctxParams->postBlockSplitter, cctxParams->ldmParams.enableLdm);\n}\n\nsize_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params)\n{\n    RETURN_ERROR_IF(!cctxParams, GENERIC, \"NULL pointer!\");\n    FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , \"\");\n    ZSTD_CCtxParams_init_internal(cctxParams, &params, ZSTD_NO_CLEVEL);\n    return 0;\n}\n\n/**\n * Sets cctxParams' cParams and fParams from params, but otherwise leaves them alone.\n * @param params Validated zstd parameters.\n */\nstatic void ZSTD_CCtxParams_setZstdParams(\n        ZSTD_CCtx_params* cctxParams, const ZSTD_parameters* params)\n{\n    assert(!ZSTD_checkCParams(params->cParams));\n    cctxParams->cParams = params->cParams;\n    cctxParams->fParams = params->fParams;\n    /* Should not matter, as all cParams are presumed properly defined.\n     * But, set it for tracing anyway.\n     */\n    cctxParams->compressionLevel = ZSTD_NO_CLEVEL;\n}\n\nZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)\n{\n    ZSTD_bounds bounds = { 0, 0, 0 };\n\n    switch(param)\n    {\n    case ZSTD_c_compressionLevel:\n        bounds.lowerBound = ZSTD_minCLevel();\n        bounds.upperBound = ZSTD_maxCLevel();\n        return bounds;\n\n    case ZSTD_c_windowLog:\n        bounds.lowerBound = ZSTD_WINDOWLOG_MIN;\n        bounds.upperBound = ZSTD_WINDOWLOG_MAX;\n        return bounds;\n\n    case ZSTD_c_hashLog:\n        bounds.lowerBound = ZSTD_HASHLOG_MIN;\n        bounds.upperBound = ZSTD_HASHLOG_MAX;\n        return bounds;\n\n    case ZSTD_c_chainLog:\n        bounds.lowerBound = ZSTD_CHAINLOG_MIN;\n        bounds.upperBound = ZSTD_CHAINLOG_MAX;\n        return bounds;\n\n    case ZSTD_c_searchLog:\n        bounds.lowerBound = ZSTD_SEARCHLOG_MIN;\n        bounds.upperBound = ZSTD_SEARCHLOG_MAX;\n        return bounds;\n\n    case ZSTD_c_minMatch:\n        bounds.lowerBound = ZSTD_MINMATCH_MIN;\n        bounds.upperBound = ZSTD_MINMATCH_MAX;\n        return bounds;\n\n    case ZSTD_c_targetLength:\n        bounds.lowerBound = ZSTD_TARGETLENGTH_MIN;\n        bounds.upperBound = ZSTD_TARGETLENGTH_MAX;\n        return bounds;\n\n    case ZSTD_c_strategy:\n        bounds.lowerBound = ZSTD_STRATEGY_MIN;\n        bounds.upperBound = ZSTD_STRATEGY_MAX;\n        return bounds;\n\n    case ZSTD_c_contentSizeFlag:\n        bounds.lowerBound = 0;\n        bounds.upperBound = 1;\n        return bounds;\n\n    case ZSTD_c_checksumFlag:\n        bounds.lowerBound = 0;\n        bounds.upperBound = 1;\n        return bounds;\n\n    case ZSTD_c_dictIDFlag:\n        bounds.lowerBound = 0;\n        bounds.upperBound = 1;\n        return bounds;\n\n    case ZSTD_c_nbWorkers:\n        bounds.lowerBound = 0;\n#ifdef ZSTD_MULTITHREAD\n        bounds.upperBound = ZSTDMT_NBWORKERS_MAX;\n#else\n        bounds.upperBound = 0;\n#endif\n        return bounds;\n\n    case ZSTD_c_jobSize:\n        bounds.lowerBound = 0;\n#ifdef ZSTD_MULTITHREAD\n        bounds.upperBound = ZSTDMT_JOBSIZE_MAX;\n#else\n        bounds.upperBound = 0;\n#endif\n        return bounds;\n\n    case ZSTD_c_overlapLog:\n#ifdef ZSTD_MULTITHREAD\n        bounds.lowerBound = ZSTD_OVERLAPLOG_MIN;\n        bounds.upperBound = ZSTD_OVERLAPLOG_MAX;\n#else\n        bounds.lowerBound = 0;\n        bounds.upperBound = 0;\n#endif\n        return bounds;\n\n    case ZSTD_c_enableDedicatedDictSearch:\n        bounds.lowerBound = 0;\n        bounds.upperBound = 1;\n        return bounds;\n\n    case ZSTD_c_enableLongDistanceMatching:\n        bounds.lowerBound = (int)ZSTD_ps_auto;\n        bounds.upperBound = (int)ZSTD_ps_disable;\n        return bounds;\n\n    case ZSTD_c_ldmHashLog:\n        bounds.lowerBound = ZSTD_LDM_HASHLOG_MIN;\n        bounds.upperBound = ZSTD_LDM_HASHLOG_MAX;\n        return bounds;\n\n    case ZSTD_c_ldmMinMatch:\n        bounds.lowerBound = ZSTD_LDM_MINMATCH_MIN;\n        bounds.upperBound = ZSTD_LDM_MINMATCH_MAX;\n        return bounds;\n\n    case ZSTD_c_ldmBucketSizeLog:\n        bounds.lowerBound = ZSTD_LDM_BUCKETSIZELOG_MIN;\n        bounds.upperBound = ZSTD_LDM_BUCKETSIZELOG_MAX;\n        return bounds;\n\n    case ZSTD_c_ldmHashRateLog:\n        bounds.lowerBound = ZSTD_LDM_HASHRATELOG_MIN;\n        bounds.upperBound = ZSTD_LDM_HASHRATELOG_MAX;\n        return bounds;\n\n    /* experimental parameters */\n    case ZSTD_c_rsyncable:\n        bounds.lowerBound = 0;\n        bounds.upperBound = 1;\n        return bounds;\n\n    case ZSTD_c_forceMaxWindow :\n        bounds.lowerBound = 0;\n        bounds.upperBound = 1;\n        return bounds;\n\n    case ZSTD_c_format:\n        ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);\n        bounds.lowerBound = ZSTD_f_zstd1;\n        bounds.upperBound = ZSTD_f_zstd1_magicless;   /* note : how to ensure at compile time that this is the highest value enum ? */\n        return bounds;\n\n    case ZSTD_c_forceAttachDict:\n        ZSTD_STATIC_ASSERT(ZSTD_dictDefaultAttach < ZSTD_dictForceLoad);\n        bounds.lowerBound = ZSTD_dictDefaultAttach;\n        bounds.upperBound = ZSTD_dictForceLoad;       /* note : how to ensure at compile time that this is the highest value enum ? */\n        return bounds;\n\n    case ZSTD_c_literalCompressionMode:\n        ZSTD_STATIC_ASSERT(ZSTD_ps_auto < ZSTD_ps_enable && ZSTD_ps_enable < ZSTD_ps_disable);\n        bounds.lowerBound = (int)ZSTD_ps_auto;\n        bounds.upperBound = (int)ZSTD_ps_disable;\n        return bounds;\n\n    case ZSTD_c_targetCBlockSize:\n        bounds.lowerBound = ZSTD_TARGETCBLOCKSIZE_MIN;\n        bounds.upperBound = ZSTD_TARGETCBLOCKSIZE_MAX;\n        return bounds;\n\n    case ZSTD_c_srcSizeHint:\n        bounds.lowerBound = ZSTD_SRCSIZEHINT_MIN;\n        bounds.upperBound = ZSTD_SRCSIZEHINT_MAX;\n        return bounds;\n\n    case ZSTD_c_stableInBuffer:\n    case ZSTD_c_stableOutBuffer:\n        bounds.lowerBound = (int)ZSTD_bm_buffered;\n        bounds.upperBound = (int)ZSTD_bm_stable;\n        return bounds;\n\n    case ZSTD_c_blockDelimiters:\n        bounds.lowerBound = (int)ZSTD_sf_noBlockDelimiters;\n        bounds.upperBound = (int)ZSTD_sf_explicitBlockDelimiters;\n        return bounds;\n\n    case ZSTD_c_validateSequences:\n        bounds.lowerBound = 0;\n        bounds.upperBound = 1;\n        return bounds;\n\n    case ZSTD_c_splitAfterSequences:\n        bounds.lowerBound = (int)ZSTD_ps_auto;\n        bounds.upperBound = (int)ZSTD_ps_disable;\n        return bounds;\n\n    case ZSTD_c_blockSplitterLevel:\n        bounds.lowerBound = 0;\n        bounds.upperBound = ZSTD_BLOCKSPLITTER_LEVEL_MAX;\n        return bounds;\n\n    case ZSTD_c_useRowMatchFinder:\n        bounds.lowerBound = (int)ZSTD_ps_auto;\n        bounds.upperBound = (int)ZSTD_ps_disable;\n        return bounds;\n\n    case ZSTD_c_deterministicRefPrefix:\n        bounds.lowerBound = 0;\n        bounds.upperBound = 1;\n        return bounds;\n\n    case ZSTD_c_prefetchCDictTables:\n        bounds.lowerBound = (int)ZSTD_ps_auto;\n        bounds.upperBound = (int)ZSTD_ps_disable;\n        return bounds;\n\n    case ZSTD_c_enableSeqProducerFallback:\n        bounds.lowerBound = 0;\n        bounds.upperBound = 1;\n        return bounds;\n\n    case ZSTD_c_maxBlockSize:\n        bounds.lowerBound = ZSTD_BLOCKSIZE_MAX_MIN;\n        bounds.upperBound = ZSTD_BLOCKSIZE_MAX;\n        return bounds;\n\n    case ZSTD_c_repcodeResolution:\n        bounds.lowerBound = (int)ZSTD_ps_auto;\n        bounds.upperBound = (int)ZSTD_ps_disable;\n        return bounds;\n\n    default:\n        bounds.error = ERROR(parameter_unsupported);\n        return bounds;\n    }\n}\n\n/* ZSTD_cParam_clampBounds:\n * Clamps the value into the bounded range.\n */\nstatic size_t ZSTD_cParam_clampBounds(ZSTD_cParameter cParam, int* value)\n{\n    ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam);\n    if (ZSTD_isError(bounds.error)) return bounds.error;\n    if (*value < bounds.lowerBound) *value = bounds.lowerBound;\n    if (*value > bounds.upperBound) *value = bounds.upperBound;\n    return 0;\n}\n\n#define BOUNDCHECK(cParam, val)                                       \\\n    do {                                                              \\\n        RETURN_ERROR_IF(!ZSTD_cParam_withinBounds(cParam,val),        \\\n                        parameter_outOfBound, \"Param out of bounds\"); \\\n    } while (0)\n\n\nstatic int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)\n{\n    switch(param)\n    {\n    case ZSTD_c_compressionLevel:\n    case ZSTD_c_hashLog:\n    case ZSTD_c_chainLog:\n    case ZSTD_c_searchLog:\n    case ZSTD_c_minMatch:\n    case ZSTD_c_targetLength:\n    case ZSTD_c_strategy:\n    case ZSTD_c_blockSplitterLevel:\n        return 1;\n\n    case ZSTD_c_format:\n    case ZSTD_c_windowLog:\n    case ZSTD_c_contentSizeFlag:\n    case ZSTD_c_checksumFlag:\n    case ZSTD_c_dictIDFlag:\n    case ZSTD_c_forceMaxWindow :\n    case ZSTD_c_nbWorkers:\n    case ZSTD_c_jobSize:\n    case ZSTD_c_overlapLog:\n    case ZSTD_c_rsyncable:\n    case ZSTD_c_enableDedicatedDictSearch:\n    case ZSTD_c_enableLongDistanceMatching:\n    case ZSTD_c_ldmHashLog:\n    case ZSTD_c_ldmMinMatch:\n    case ZSTD_c_ldmBucketSizeLog:\n    case ZSTD_c_ldmHashRateLog:\n    case ZSTD_c_forceAttachDict:\n    case ZSTD_c_literalCompressionMode:\n    case ZSTD_c_targetCBlockSize:\n    case ZSTD_c_srcSizeHint:\n    case ZSTD_c_stableInBuffer:\n    case ZSTD_c_stableOutBuffer:\n    case ZSTD_c_blockDelimiters:\n    case ZSTD_c_validateSequences:\n    case ZSTD_c_splitAfterSequences:\n    case ZSTD_c_useRowMatchFinder:\n    case ZSTD_c_deterministicRefPrefix:\n    case ZSTD_c_prefetchCDictTables:\n    case ZSTD_c_enableSeqProducerFallback:\n    case ZSTD_c_maxBlockSize:\n    case ZSTD_c_repcodeResolution:\n    default:\n        return 0;\n    }\n}\n\nsize_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value)\n{\n    DEBUGLOG(4, \"ZSTD_CCtx_setParameter (%i, %i)\", (int)param, value);\n    if (cctx->streamStage != zcss_init) {\n        if (ZSTD_isUpdateAuthorized(param)) {\n            cctx->cParamsChanged = 1;\n        } else {\n            RETURN_ERROR(stage_wrong, \"can only set params in cctx init stage\");\n    }   }\n\n    switch(param)\n    {\n    case ZSTD_c_nbWorkers:\n        RETURN_ERROR_IF((value!=0) && cctx->staticSize, parameter_unsupported,\n                        \"MT not compatible with static alloc\");\n        break;\n\n    case ZSTD_c_compressionLevel:\n    case ZSTD_c_windowLog:\n    case ZSTD_c_hashLog:\n    case ZSTD_c_chainLog:\n    case ZSTD_c_searchLog:\n    case ZSTD_c_minMatch:\n    case ZSTD_c_targetLength:\n    case ZSTD_c_strategy:\n    case ZSTD_c_ldmHashRateLog:\n    case ZSTD_c_format:\n    case ZSTD_c_contentSizeFlag:\n    case ZSTD_c_checksumFlag:\n    case ZSTD_c_dictIDFlag:\n    case ZSTD_c_forceMaxWindow:\n    case ZSTD_c_forceAttachDict:\n    case ZSTD_c_literalCompressionMode:\n    case ZSTD_c_jobSize:\n    case ZSTD_c_overlapLog:\n    case ZSTD_c_rsyncable:\n    case ZSTD_c_enableDedicatedDictSearch:\n    case ZSTD_c_enableLongDistanceMatching:\n    case ZSTD_c_ldmHashLog:\n    case ZSTD_c_ldmMinMatch:\n    case ZSTD_c_ldmBucketSizeLog:\n    case ZSTD_c_targetCBlockSize:\n    case ZSTD_c_srcSizeHint:\n    case ZSTD_c_stableInBuffer:\n    case ZSTD_c_stableOutBuffer:\n    case ZSTD_c_blockDelimiters:\n    case ZSTD_c_validateSequences:\n    case ZSTD_c_splitAfterSequences:\n    case ZSTD_c_blockSplitterLevel:\n    case ZSTD_c_useRowMatchFinder:\n    case ZSTD_c_deterministicRefPrefix:\n    case ZSTD_c_prefetchCDictTables:\n    case ZSTD_c_enableSeqProducerFallback:\n    case ZSTD_c_maxBlockSize:\n    case ZSTD_c_repcodeResolution:\n        break;\n\n    default: RETURN_ERROR(parameter_unsupported, \"unknown parameter\");\n    }\n    return ZSTD_CCtxParams_setParameter(&cctx->requestedParams, param, value);\n}\n\nsize_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,\n                                    ZSTD_cParameter param, int value)\n{\n    DEBUGLOG(4, \"ZSTD_CCtxParams_setParameter (%i, %i)\", (int)param, value);\n    switch(param)\n    {\n    case ZSTD_c_format :\n        BOUNDCHECK(ZSTD_c_format, value);\n        CCtxParams->format = (ZSTD_format_e)value;\n        return (size_t)CCtxParams->format;\n\n    case ZSTD_c_compressionLevel : {\n        FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), \"\");\n        if (value == 0)\n            CCtxParams->compressionLevel = ZSTD_CLEVEL_DEFAULT; /* 0 == default */\n        else\n            CCtxParams->compressionLevel = value;\n        if (CCtxParams->compressionLevel >= 0) return (size_t)CCtxParams->compressionLevel;\n        return 0;  /* return type (size_t) cannot represent negative values */\n    }\n\n    case ZSTD_c_windowLog :\n        if (value!=0)   /* 0 => use default */\n            BOUNDCHECK(ZSTD_c_windowLog, value);\n        CCtxParams->cParams.windowLog = (U32)value;\n        return CCtxParams->cParams.windowLog;\n\n    case ZSTD_c_hashLog :\n        if (value!=0)   /* 0 => use default */\n            BOUNDCHECK(ZSTD_c_hashLog, value);\n        CCtxParams->cParams.hashLog = (U32)value;\n        return CCtxParams->cParams.hashLog;\n\n    case ZSTD_c_chainLog :\n        if (value!=0)   /* 0 => use default */\n            BOUNDCHECK(ZSTD_c_chainLog, value);\n        CCtxParams->cParams.chainLog = (U32)value;\n        return CCtxParams->cParams.chainLog;\n\n    case ZSTD_c_searchLog :\n        if (value!=0)   /* 0 => use default */\n            BOUNDCHECK(ZSTD_c_searchLog, value);\n        CCtxParams->cParams.searchLog = (U32)value;\n        return (size_t)value;\n\n    case ZSTD_c_minMatch :\n        if (value!=0)   /* 0 => use default */\n            BOUNDCHECK(ZSTD_c_minMatch, value);\n        CCtxParams->cParams.minMatch = (U32)value;\n        return CCtxParams->cParams.minMatch;\n\n    case ZSTD_c_targetLength :\n        BOUNDCHECK(ZSTD_c_targetLength, value);\n        CCtxParams->cParams.targetLength = (U32)value;\n        return CCtxParams->cParams.targetLength;\n\n    case ZSTD_c_strategy :\n        if (value!=0)   /* 0 => use default */\n            BOUNDCHECK(ZSTD_c_strategy, value);\n        CCtxParams->cParams.strategy = (ZSTD_strategy)value;\n        return (size_t)CCtxParams->cParams.strategy;\n\n    case ZSTD_c_contentSizeFlag :\n        /* Content size written in frame header _when known_ (default:1) */\n        DEBUGLOG(4, \"set content size flag = %u\", (value!=0));\n        CCtxParams->fParams.contentSizeFlag = value != 0;\n        return (size_t)CCtxParams->fParams.contentSizeFlag;\n\n    case ZSTD_c_checksumFlag :\n        /* A 32-bits content checksum will be calculated and written at end of frame (default:0) */\n        CCtxParams->fParams.checksumFlag = value != 0;\n        return (size_t)CCtxParams->fParams.checksumFlag;\n\n    case ZSTD_c_dictIDFlag : /* When applicable, dictionary's dictID is provided in frame header (default:1) */\n        DEBUGLOG(4, \"set dictIDFlag = %u\", (value!=0));\n        CCtxParams->fParams.noDictIDFlag = !value;\n        return !CCtxParams->fParams.noDictIDFlag;\n\n    case ZSTD_c_forceMaxWindow :\n        CCtxParams->forceWindow = (value != 0);\n        return (size_t)CCtxParams->forceWindow;\n\n    case ZSTD_c_forceAttachDict : {\n        const ZSTD_dictAttachPref_e pref = (ZSTD_dictAttachPref_e)value;\n        BOUNDCHECK(ZSTD_c_forceAttachDict, (int)pref);\n        CCtxParams->attachDictPref = pref;\n        return CCtxParams->attachDictPref;\n    }\n\n    case ZSTD_c_literalCompressionMode : {\n        const ZSTD_ParamSwitch_e lcm = (ZSTD_ParamSwitch_e)value;\n        BOUNDCHECK(ZSTD_c_literalCompressionMode, (int)lcm);\n        CCtxParams->literalCompressionMode = lcm;\n        return CCtxParams->literalCompressionMode;\n    }\n\n    case ZSTD_c_nbWorkers :\n#ifndef ZSTD_MULTITHREAD\n        RETURN_ERROR_IF(value!=0, parameter_unsupported, \"not compiled with multithreading\");\n        return 0;\n#else\n        FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), \"\");\n        CCtxParams->nbWorkers = value;\n        return (size_t)(CCtxParams->nbWorkers);\n#endif\n\n    case ZSTD_c_jobSize :\n#ifndef ZSTD_MULTITHREAD\n        RETURN_ERROR_IF(value!=0, parameter_unsupported, \"not compiled with multithreading\");\n        return 0;\n#else\n        /* Adjust to the minimum non-default value. */\n        if (value != 0 && value < ZSTDMT_JOBSIZE_MIN)\n            value = ZSTDMT_JOBSIZE_MIN;\n        FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), \"\");\n        assert(value >= 0);\n        CCtxParams->jobSize = (size_t)value;\n        return CCtxParams->jobSize;\n#endif\n\n    case ZSTD_c_overlapLog :\n#ifndef ZSTD_MULTITHREAD\n        RETURN_ERROR_IF(value!=0, parameter_unsupported, \"not compiled with multithreading\");\n        return 0;\n#else\n        FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value), \"\");\n        CCtxParams->overlapLog = value;\n        return (size_t)CCtxParams->overlapLog;\n#endif\n\n    case ZSTD_c_rsyncable :\n#ifndef ZSTD_MULTITHREAD\n        RETURN_ERROR_IF(value!=0, parameter_unsupported, \"not compiled with multithreading\");\n        return 0;\n#else\n        FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value), \"\");\n        CCtxParams->rsyncable = value;\n        return (size_t)CCtxParams->rsyncable;\n#endif\n\n    case ZSTD_c_enableDedicatedDictSearch :\n        CCtxParams->enableDedicatedDictSearch = (value!=0);\n        return (size_t)CCtxParams->enableDedicatedDictSearch;\n\n    case ZSTD_c_enableLongDistanceMatching :\n        BOUNDCHECK(ZSTD_c_enableLongDistanceMatching, value);\n        CCtxParams->ldmParams.enableLdm = (ZSTD_ParamSwitch_e)value;\n        return CCtxParams->ldmParams.enableLdm;\n\n    case ZSTD_c_ldmHashLog :\n        if (value!=0)   /* 0 ==> auto */\n            BOUNDCHECK(ZSTD_c_ldmHashLog, value);\n        CCtxParams->ldmParams.hashLog = (U32)value;\n        return CCtxParams->ldmParams.hashLog;\n\n    case ZSTD_c_ldmMinMatch :\n        if (value!=0)   /* 0 ==> default */\n            BOUNDCHECK(ZSTD_c_ldmMinMatch, value);\n        CCtxParams->ldmParams.minMatchLength = (U32)value;\n        return CCtxParams->ldmParams.minMatchLength;\n\n    case ZSTD_c_ldmBucketSizeLog :\n        if (value!=0)   /* 0 ==> default */\n            BOUNDCHECK(ZSTD_c_ldmBucketSizeLog, value);\n        CCtxParams->ldmParams.bucketSizeLog = (U32)value;\n        return CCtxParams->ldmParams.bucketSizeLog;\n\n    case ZSTD_c_ldmHashRateLog :\n        if (value!=0)   /* 0 ==> default */\n            BOUNDCHECK(ZSTD_c_ldmHashRateLog, value);\n        CCtxParams->ldmParams.hashRateLog = (U32)value;\n        return CCtxParams->ldmParams.hashRateLog;\n\n    case ZSTD_c_targetCBlockSize :\n        if (value!=0) {  /* 0 ==> default */\n            value = MAX(value, ZSTD_TARGETCBLOCKSIZE_MIN);\n            BOUNDCHECK(ZSTD_c_targetCBlockSize, value);\n        }\n        CCtxParams->targetCBlockSize = (U32)value;\n        return CCtxParams->targetCBlockSize;\n\n    case ZSTD_c_srcSizeHint :\n        if (value!=0)    /* 0 ==> default */\n            BOUNDCHECK(ZSTD_c_srcSizeHint, value);\n        CCtxParams->srcSizeHint = value;\n        return (size_t)CCtxParams->srcSizeHint;\n\n    case ZSTD_c_stableInBuffer:\n        BOUNDCHECK(ZSTD_c_stableInBuffer, value);\n        CCtxParams->inBufferMode = (ZSTD_bufferMode_e)value;\n        return CCtxParams->inBufferMode;\n\n    case ZSTD_c_stableOutBuffer:\n        BOUNDCHECK(ZSTD_c_stableOutBuffer, value);\n        CCtxParams->outBufferMode = (ZSTD_bufferMode_e)value;\n        return CCtxParams->outBufferMode;\n\n    case ZSTD_c_blockDelimiters:\n        BOUNDCHECK(ZSTD_c_blockDelimiters, value);\n        CCtxParams->blockDelimiters = (ZSTD_SequenceFormat_e)value;\n        return CCtxParams->blockDelimiters;\n\n    case ZSTD_c_validateSequences:\n        BOUNDCHECK(ZSTD_c_validateSequences, value);\n        CCtxParams->validateSequences = value;\n        return (size_t)CCtxParams->validateSequences;\n\n    case ZSTD_c_splitAfterSequences:\n        BOUNDCHECK(ZSTD_c_splitAfterSequences, value);\n        CCtxParams->postBlockSplitter = (ZSTD_ParamSwitch_e)value;\n        return CCtxParams->postBlockSplitter;\n\n    case ZSTD_c_blockSplitterLevel:\n        BOUNDCHECK(ZSTD_c_blockSplitterLevel, value);\n        CCtxParams->preBlockSplitter_level = value;\n        return (size_t)CCtxParams->preBlockSplitter_level;\n\n    case ZSTD_c_useRowMatchFinder:\n        BOUNDCHECK(ZSTD_c_useRowMatchFinder, value);\n        CCtxParams->useRowMatchFinder = (ZSTD_ParamSwitch_e)value;\n        return CCtxParams->useRowMatchFinder;\n\n    case ZSTD_c_deterministicRefPrefix:\n        BOUNDCHECK(ZSTD_c_deterministicRefPrefix, value);\n        CCtxParams->deterministicRefPrefix = !!value;\n        return (size_t)CCtxParams->deterministicRefPrefix;\n\n    case ZSTD_c_prefetchCDictTables:\n        BOUNDCHECK(ZSTD_c_prefetchCDictTables, value);\n        CCtxParams->prefetchCDictTables = (ZSTD_ParamSwitch_e)value;\n        return CCtxParams->prefetchCDictTables;\n\n    case ZSTD_c_enableSeqProducerFallback:\n        BOUNDCHECK(ZSTD_c_enableSeqProducerFallback, value);\n        CCtxParams->enableMatchFinderFallback = value;\n        return (size_t)CCtxParams->enableMatchFinderFallback;\n\n    case ZSTD_c_maxBlockSize:\n        if (value!=0)    /* 0 ==> default */\n            BOUNDCHECK(ZSTD_c_maxBlockSize, value);\n        assert(value>=0);\n        CCtxParams->maxBlockSize = (size_t)value;\n        return CCtxParams->maxBlockSize;\n\n    case ZSTD_c_repcodeResolution:\n        BOUNDCHECK(ZSTD_c_repcodeResolution, value);\n        CCtxParams->searchForExternalRepcodes = (ZSTD_ParamSwitch_e)value;\n        return CCtxParams->searchForExternalRepcodes;\n\n    default: RETURN_ERROR(parameter_unsupported, \"unknown parameter\");\n    }\n}\n\nsize_t ZSTD_CCtx_getParameter(ZSTD_CCtx const* cctx, ZSTD_cParameter param, int* value)\n{\n    return ZSTD_CCtxParams_getParameter(&cctx->requestedParams, param, value);\n}\n\nsize_t ZSTD_CCtxParams_getParameter(\n        ZSTD_CCtx_params const* CCtxParams, ZSTD_cParameter param, int* value)\n{\n    switch(param)\n    {\n    case ZSTD_c_format :\n        *value = (int)CCtxParams->format;\n        break;\n    case ZSTD_c_compressionLevel :\n        *value = CCtxParams->compressionLevel;\n        break;\n    case ZSTD_c_windowLog :\n        *value = (int)CCtxParams->cParams.windowLog;\n        break;\n    case ZSTD_c_hashLog :\n        *value = (int)CCtxParams->cParams.hashLog;\n        break;\n    case ZSTD_c_chainLog :\n        *value = (int)CCtxParams->cParams.chainLog;\n        break;\n    case ZSTD_c_searchLog :\n        *value = (int)CCtxParams->cParams.searchLog;\n        break;\n    case ZSTD_c_minMatch :\n        *value = (int)CCtxParams->cParams.minMatch;\n        break;\n    case ZSTD_c_targetLength :\n        *value = (int)CCtxParams->cParams.targetLength;\n        break;\n    case ZSTD_c_strategy :\n        *value = (int)CCtxParams->cParams.strategy;\n        break;\n    case ZSTD_c_contentSizeFlag :\n        *value = CCtxParams->fParams.contentSizeFlag;\n        break;\n    case ZSTD_c_checksumFlag :\n        *value = CCtxParams->fParams.checksumFlag;\n        break;\n    case ZSTD_c_dictIDFlag :\n        *value = !CCtxParams->fParams.noDictIDFlag;\n        break;\n    case ZSTD_c_forceMaxWindow :\n        *value = CCtxParams->forceWindow;\n        break;\n    case ZSTD_c_forceAttachDict :\n        *value = (int)CCtxParams->attachDictPref;\n        break;\n    case ZSTD_c_literalCompressionMode :\n        *value = (int)CCtxParams->literalCompressionMode;\n        break;\n    case ZSTD_c_nbWorkers :\n#ifndef ZSTD_MULTITHREAD\n        assert(CCtxParams->nbWorkers == 0);\n#endif\n        *value = CCtxParams->nbWorkers;\n        break;\n    case ZSTD_c_jobSize :\n#ifndef ZSTD_MULTITHREAD\n        RETURN_ERROR(parameter_unsupported, \"not compiled with multithreading\");\n#else\n        assert(CCtxParams->jobSize <= INT_MAX);\n        *value = (int)CCtxParams->jobSize;\n        break;\n#endif\n    case ZSTD_c_overlapLog :\n#ifndef ZSTD_MULTITHREAD\n        RETURN_ERROR(parameter_unsupported, \"not compiled with multithreading\");\n#else\n        *value = CCtxParams->overlapLog;\n        break;\n#endif\n    case ZSTD_c_rsyncable :\n#ifndef ZSTD_MULTITHREAD\n        RETURN_ERROR(parameter_unsupported, \"not compiled with multithreading\");\n#else\n        *value = CCtxParams->rsyncable;\n        break;\n#endif\n    case ZSTD_c_enableDedicatedDictSearch :\n        *value = CCtxParams->enableDedicatedDictSearch;\n        break;\n    case ZSTD_c_enableLongDistanceMatching :\n        *value = (int)CCtxParams->ldmParams.enableLdm;\n        break;\n    case ZSTD_c_ldmHashLog :\n        *value = (int)CCtxParams->ldmParams.hashLog;\n        break;\n    case ZSTD_c_ldmMinMatch :\n        *value = (int)CCtxParams->ldmParams.minMatchLength;\n        break;\n    case ZSTD_c_ldmBucketSizeLog :\n        *value = (int)CCtxParams->ldmParams.bucketSizeLog;\n        break;\n    case ZSTD_c_ldmHashRateLog :\n        *value = (int)CCtxParams->ldmParams.hashRateLog;\n        break;\n    case ZSTD_c_targetCBlockSize :\n        *value = (int)CCtxParams->targetCBlockSize;\n        break;\n    case ZSTD_c_srcSizeHint :\n        *value = (int)CCtxParams->srcSizeHint;\n        break;\n    case ZSTD_c_stableInBuffer :\n        *value = (int)CCtxParams->inBufferMode;\n        break;\n    case ZSTD_c_stableOutBuffer :\n        *value = (int)CCtxParams->outBufferMode;\n        break;\n    case ZSTD_c_blockDelimiters :\n        *value = (int)CCtxParams->blockDelimiters;\n        break;\n    case ZSTD_c_validateSequences :\n        *value = (int)CCtxParams->validateSequences;\n        break;\n    case ZSTD_c_splitAfterSequences :\n        *value = (int)CCtxParams->postBlockSplitter;\n        break;\n    case ZSTD_c_blockSplitterLevel :\n        *value = CCtxParams->preBlockSplitter_level;\n        break;\n    case ZSTD_c_useRowMatchFinder :\n        *value = (int)CCtxParams->useRowMatchFinder;\n        break;\n    case ZSTD_c_deterministicRefPrefix:\n        *value = (int)CCtxParams->deterministicRefPrefix;\n        break;\n    case ZSTD_c_prefetchCDictTables:\n        *value = (int)CCtxParams->prefetchCDictTables;\n        break;\n    case ZSTD_c_enableSeqProducerFallback:\n        *value = CCtxParams->enableMatchFinderFallback;\n        break;\n    case ZSTD_c_maxBlockSize:\n        *value = (int)CCtxParams->maxBlockSize;\n        break;\n    case ZSTD_c_repcodeResolution:\n        *value = (int)CCtxParams->searchForExternalRepcodes;\n        break;\n    default: RETURN_ERROR(parameter_unsupported, \"unknown parameter\");\n    }\n    return 0;\n}\n\n/** ZSTD_CCtx_setParametersUsingCCtxParams() :\n *  just applies `params` into `cctx`\n *  no action is performed, parameters are merely stored.\n *  If ZSTDMT is enabled, parameters are pushed to cctx->mtctx.\n *    This is possible even if a compression is ongoing.\n *    In which case, new parameters will be applied on the fly, starting with next compression job.\n */\nsize_t ZSTD_CCtx_setParametersUsingCCtxParams(\n        ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params)\n{\n    DEBUGLOG(4, \"ZSTD_CCtx_setParametersUsingCCtxParams\");\n    RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,\n                    \"The context is in the wrong stage!\");\n    RETURN_ERROR_IF(cctx->cdict, stage_wrong,\n                    \"Can't override parameters with cdict attached (some must \"\n                    \"be inherited from the cdict).\");\n\n    cctx->requestedParams = *params;\n    return 0;\n}\n\nsize_t ZSTD_CCtx_setCParams(ZSTD_CCtx* cctx, ZSTD_compressionParameters cparams)\n{\n    ZSTD_STATIC_ASSERT(sizeof(cparams) == 7 * 4 /* all params are listed below */);\n    DEBUGLOG(4, \"ZSTD_CCtx_setCParams\");\n    /* only update if all parameters are valid */\n    FORWARD_IF_ERROR(ZSTD_checkCParams(cparams), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, (int)cparams.windowLog), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_chainLog, (int)cparams.chainLog), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, (int)cparams.hashLog), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_searchLog, (int)cparams.searchLog), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, (int)cparams.minMatch), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_targetLength, (int)cparams.targetLength), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_strategy, (int)cparams.strategy), \"\");\n    return 0;\n}\n\nsize_t ZSTD_CCtx_setFParams(ZSTD_CCtx* cctx, ZSTD_frameParameters fparams)\n{\n    ZSTD_STATIC_ASSERT(sizeof(fparams) == 3 * 4 /* all params are listed below */);\n    DEBUGLOG(4, \"ZSTD_CCtx_setFParams\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_contentSizeFlag, fparams.contentSizeFlag != 0), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, fparams.checksumFlag != 0), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_dictIDFlag, fparams.noDictIDFlag == 0), \"\");\n    return 0;\n}\n\nsize_t ZSTD_CCtx_setParams(ZSTD_CCtx* cctx, ZSTD_parameters params)\n{\n    DEBUGLOG(4, \"ZSTD_CCtx_setParams\");\n    /* First check cParams, because we want to update all or none. */\n    FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams), \"\");\n    /* Next set fParams, because this could fail if the cctx isn't in init stage. */\n    FORWARD_IF_ERROR(ZSTD_CCtx_setFParams(cctx, params.fParams), \"\");\n    /* Finally set cParams, which should succeed. */\n    FORWARD_IF_ERROR(ZSTD_CCtx_setCParams(cctx, params.cParams), \"\");\n    return 0;\n}\n\nsize_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize)\n{\n    DEBUGLOG(4, \"ZSTD_CCtx_setPledgedSrcSize to %llu bytes\", pledgedSrcSize);\n    RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,\n                    \"Can't set pledgedSrcSize when not in init stage.\");\n    cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;\n    return 0;\n}\n\nstatic ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams(\n        int const compressionLevel,\n        size_t const dictSize);\nstatic int ZSTD_dedicatedDictSearch_isSupported(\n        const ZSTD_compressionParameters* cParams);\nstatic void ZSTD_dedicatedDictSearch_revertCParams(\n        ZSTD_compressionParameters* cParams);\n\n/**\n * Initializes the local dictionary using requested parameters.\n * NOTE: Initialization does not employ the pledged src size,\n * because the dictionary may be used for multiple compressions.\n */\nstatic size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx)\n{\n    ZSTD_localDict* const dl = &cctx->localDict;\n    if (dl->dict == NULL) {\n        /* No local dictionary. */\n        assert(dl->dictBuffer == NULL);\n        assert(dl->cdict == NULL);\n        assert(dl->dictSize == 0);\n        return 0;\n    }\n    if (dl->cdict != NULL) {\n        /* Local dictionary already initialized. */\n        assert(cctx->cdict == dl->cdict);\n        return 0;\n    }\n    assert(dl->dictSize > 0);\n    assert(cctx->cdict == NULL);\n    assert(cctx->prefixDict.dict == NULL);\n\n    dl->cdict = ZSTD_createCDict_advanced2(\n            dl->dict,\n            dl->dictSize,\n            ZSTD_dlm_byRef,\n            dl->dictContentType,\n            &cctx->requestedParams,\n            cctx->customMem);\n    RETURN_ERROR_IF(!dl->cdict, memory_allocation, \"ZSTD_createCDict_advanced failed\");\n    cctx->cdict = dl->cdict;\n    return 0;\n}\n\nsize_t ZSTD_CCtx_loadDictionary_advanced(\n        ZSTD_CCtx* cctx,\n        const void* dict, size_t dictSize,\n        ZSTD_dictLoadMethod_e dictLoadMethod,\n        ZSTD_dictContentType_e dictContentType)\n{\n    DEBUGLOG(4, \"ZSTD_CCtx_loadDictionary_advanced (size: %u)\", (U32)dictSize);\n    RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,\n                    \"Can't load a dictionary when cctx is not in init stage.\");\n    ZSTD_clearAllDicts(cctx);  /* erase any previously set dictionary */\n    if (dict == NULL || dictSize == 0)  /* no dictionary */\n        return 0;\n    if (dictLoadMethod == ZSTD_dlm_byRef) {\n        cctx->localDict.dict = dict;\n    } else {\n        /* copy dictionary content inside CCtx to own its lifetime */\n        void* dictBuffer;\n        RETURN_ERROR_IF(cctx->staticSize, memory_allocation,\n                        \"static CCtx can't allocate for an internal copy of dictionary\");\n        dictBuffer = ZSTD_customMalloc(dictSize, cctx->customMem);\n        RETURN_ERROR_IF(dictBuffer==NULL, memory_allocation,\n                        \"allocation failed for dictionary content\");\n        ZSTD_memcpy(dictBuffer, dict, dictSize);\n        cctx->localDict.dictBuffer = dictBuffer;  /* owned ptr to free */\n        cctx->localDict.dict = dictBuffer;        /* read-only reference */\n    }\n    cctx->localDict.dictSize = dictSize;\n    cctx->localDict.dictContentType = dictContentType;\n    return 0;\n}\n\nsize_t ZSTD_CCtx_loadDictionary_byReference(\n      ZSTD_CCtx* cctx, const void* dict, size_t dictSize)\n{\n    return ZSTD_CCtx_loadDictionary_advanced(\n            cctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto);\n}\n\nsize_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)\n{\n    return ZSTD_CCtx_loadDictionary_advanced(\n            cctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto);\n}\n\n\nsize_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)\n{\n    RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,\n                    \"Can't ref a dict when ctx not in init stage.\");\n    /* Free the existing local cdict (if any) to save memory. */\n    ZSTD_clearAllDicts(cctx);\n    cctx->cdict = cdict;\n    return 0;\n}\n\nsize_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool)\n{\n    RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,\n                    \"Can't ref a pool when ctx not in init stage.\");\n    cctx->pool = pool;\n    return 0;\n}\n\nsize_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize)\n{\n    return ZSTD_CCtx_refPrefix_advanced(cctx, prefix, prefixSize, ZSTD_dct_rawContent);\n}\n\nsize_t ZSTD_CCtx_refPrefix_advanced(\n        ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)\n{\n    RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,\n                    \"Can't ref a prefix when ctx not in init stage.\");\n    ZSTD_clearAllDicts(cctx);\n    if (prefix != NULL && prefixSize > 0) {\n        cctx->prefixDict.dict = prefix;\n        cctx->prefixDict.dictSize = prefixSize;\n        cctx->prefixDict.dictContentType = dictContentType;\n    }\n    return 0;\n}\n\n/*! ZSTD_CCtx_reset() :\n *  Also dumps dictionary */\nsize_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset)\n{\n    if ( (reset == ZSTD_reset_session_only)\n      || (reset == ZSTD_reset_session_and_parameters) ) {\n        cctx->streamStage = zcss_init;\n        cctx->pledgedSrcSizePlusOne = 0;\n    }\n    if ( (reset == ZSTD_reset_parameters)\n      || (reset == ZSTD_reset_session_and_parameters) ) {\n        RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,\n                        \"Reset parameters is only possible during init stage.\");\n        ZSTD_clearAllDicts(cctx);\n        return ZSTD_CCtxParams_reset(&cctx->requestedParams);\n    }\n    return 0;\n}\n\n\n/** ZSTD_checkCParams() :\n    control CParam values remain within authorized range.\n    @return : 0, or an error code if one value is beyond authorized range */\nsize_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)\n{\n    BOUNDCHECK(ZSTD_c_windowLog, (int)cParams.windowLog);\n    BOUNDCHECK(ZSTD_c_chainLog,  (int)cParams.chainLog);\n    BOUNDCHECK(ZSTD_c_hashLog,   (int)cParams.hashLog);\n    BOUNDCHECK(ZSTD_c_searchLog, (int)cParams.searchLog);\n    BOUNDCHECK(ZSTD_c_minMatch,  (int)cParams.minMatch);\n    BOUNDCHECK(ZSTD_c_targetLength,(int)cParams.targetLength);\n    BOUNDCHECK(ZSTD_c_strategy,  (int)cParams.strategy);\n    return 0;\n}\n\n/** ZSTD_clampCParams() :\n *  make CParam values within valid range.\n *  @return : valid CParams */\nstatic ZSTD_compressionParameters\nZSTD_clampCParams(ZSTD_compressionParameters cParams)\n{\n#   define CLAMP_TYPE(cParam, val, type)                                      \\\n        do {                                                                  \\\n            ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam);         \\\n            if ((int)val<bounds.lowerBound) val=(type)bounds.lowerBound;      \\\n            else if ((int)val>bounds.upperBound) val=(type)bounds.upperBound; \\\n        } while (0)\n#   define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, unsigned)\n    CLAMP(ZSTD_c_windowLog, cParams.windowLog);\n    CLAMP(ZSTD_c_chainLog,  cParams.chainLog);\n    CLAMP(ZSTD_c_hashLog,   cParams.hashLog);\n    CLAMP(ZSTD_c_searchLog, cParams.searchLog);\n    CLAMP(ZSTD_c_minMatch,  cParams.minMatch);\n    CLAMP(ZSTD_c_targetLength,cParams.targetLength);\n    CLAMP_TYPE(ZSTD_c_strategy,cParams.strategy, ZSTD_strategy);\n    return cParams;\n}\n\n/** ZSTD_cycleLog() :\n *  condition for correct operation : hashLog > 1 */\nU32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)\n{\n    U32 const btScale = ((U32)strat >= (U32)ZSTD_btlazy2);\n    return hashLog - btScale;\n}\n\n/** ZSTD_dictAndWindowLog() :\n * Returns an adjusted window log that is large enough to fit the source and the dictionary.\n * The zstd format says that the entire dictionary is valid if one byte of the dictionary\n * is within the window. So the hashLog and chainLog should be large enough to reference both\n * the dictionary and the window. So we must use this adjusted dictAndWindowLog when downsizing\n * the hashLog and windowLog.\n * NOTE: srcSize must not be ZSTD_CONTENTSIZE_UNKNOWN.\n */\nstatic U32 ZSTD_dictAndWindowLog(U32 windowLog, U64 srcSize, U64 dictSize)\n{\n    const U64 maxWindowSize = 1ULL << ZSTD_WINDOWLOG_MAX;\n    /* No dictionary ==> No change */\n    if (dictSize == 0) {\n        return windowLog;\n    }\n    assert(windowLog <= ZSTD_WINDOWLOG_MAX);\n    assert(srcSize != ZSTD_CONTENTSIZE_UNKNOWN); /* Handled in ZSTD_adjustCParams_internal() */\n    {\n        U64 const windowSize = 1ULL << windowLog;\n        U64 const dictAndWindowSize = dictSize + windowSize;\n        /* If the window size is already large enough to fit both the source and the dictionary\n         * then just use the window size. Otherwise adjust so that it fits the dictionary and\n         * the window.\n         */\n        if (windowSize >= dictSize + srcSize) {\n            return windowLog; /* Window size large enough already */\n        } else if (dictAndWindowSize >= maxWindowSize) {\n            return ZSTD_WINDOWLOG_MAX; /* Larger than max window log */\n        } else  {\n            return ZSTD_highbit32((U32)dictAndWindowSize - 1) + 1;\n        }\n    }\n}\n\n/** ZSTD_adjustCParams_internal() :\n *  optimize `cPar` for a specified input (`srcSize` and `dictSize`).\n *  mostly downsize to reduce memory consumption and initialization latency.\n * `srcSize` can be ZSTD_CONTENTSIZE_UNKNOWN when not known.\n * `mode` is the mode for parameter adjustment. See docs for `ZSTD_CParamMode_e`.\n *  note : `srcSize==0` means 0!\n *  condition : cPar is presumed validated (can be checked using ZSTD_checkCParams()). */\nstatic ZSTD_compressionParameters\nZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,\n                            unsigned long long srcSize,\n                            size_t dictSize,\n                            ZSTD_CParamMode_e mode,\n                            ZSTD_ParamSwitch_e useRowMatchFinder)\n{\n    const U64 minSrcSize = 513; /* (1<<9) + 1 */\n    const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1);\n    assert(ZSTD_checkCParams(cPar)==0);\n\n    /* Cascade the selected strategy down to the next-highest one built into\n     * this binary. */\n#ifdef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR\n    if (cPar.strategy == ZSTD_btultra2) {\n        cPar.strategy = ZSTD_btultra;\n    }\n    if (cPar.strategy == ZSTD_btultra) {\n        cPar.strategy = ZSTD_btopt;\n    }\n#endif\n#ifdef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR\n    if (cPar.strategy == ZSTD_btopt) {\n        cPar.strategy = ZSTD_btlazy2;\n    }\n#endif\n#ifdef ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR\n    if (cPar.strategy == ZSTD_btlazy2) {\n        cPar.strategy = ZSTD_lazy2;\n    }\n#endif\n#ifdef ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR\n    if (cPar.strategy == ZSTD_lazy2) {\n        cPar.strategy = ZSTD_lazy;\n    }\n#endif\n#ifdef ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR\n    if (cPar.strategy == ZSTD_lazy) {\n        cPar.strategy = ZSTD_greedy;\n    }\n#endif\n#ifdef ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR\n    if (cPar.strategy == ZSTD_greedy) {\n        cPar.strategy = ZSTD_dfast;\n    }\n#endif\n#ifdef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR\n    if (cPar.strategy == ZSTD_dfast) {\n        cPar.strategy = ZSTD_fast;\n        cPar.targetLength = 0;\n    }\n#endif\n\n    switch (mode) {\n    case ZSTD_cpm_unknown:\n    case ZSTD_cpm_noAttachDict:\n        /* If we don't know the source size, don't make any\n         * assumptions about it. We will already have selected\n         * smaller parameters if a dictionary is in use.\n         */\n        break;\n    case ZSTD_cpm_createCDict:\n        /* Assume a small source size when creating a dictionary\n         * with an unknown source size.\n         */\n        if (dictSize && srcSize == ZSTD_CONTENTSIZE_UNKNOWN)\n            srcSize = minSrcSize;\n        break;\n    case ZSTD_cpm_attachDict:\n        /* Dictionary has its own dedicated parameters which have\n         * already been selected. We are selecting parameters\n         * for only the source.\n         */\n        dictSize = 0;\n        break;\n    default:\n        assert(0);\n        break;\n    }\n\n    /* resize windowLog if input is small enough, to use less memory */\n    if ( (srcSize <= maxWindowResize)\n      && (dictSize <= maxWindowResize) )  {\n        U32 const tSize = (U32)(srcSize + dictSize);\n        static U32 const hashSizeMin = 1 << ZSTD_HASHLOG_MIN;\n        U32 const srcLog = (tSize < hashSizeMin) ? ZSTD_HASHLOG_MIN :\n                            ZSTD_highbit32(tSize-1) + 1;\n        if (cPar.windowLog > srcLog) cPar.windowLog = srcLog;\n    }\n    if (srcSize != ZSTD_CONTENTSIZE_UNKNOWN) {\n        U32 const dictAndWindowLog = ZSTD_dictAndWindowLog(cPar.windowLog, (U64)srcSize, (U64)dictSize);\n        U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy);\n        if (cPar.hashLog > dictAndWindowLog+1) cPar.hashLog = dictAndWindowLog+1;\n        if (cycleLog > dictAndWindowLog)\n            cPar.chainLog -= (cycleLog - dictAndWindowLog);\n    }\n\n    if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN)\n        cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN;  /* minimum wlog required for valid frame header */\n\n    /* We can't use more than 32 bits of hash in total, so that means that we require:\n     * (hashLog + 8) <= 32 && (chainLog + 8) <= 32\n     */\n    if (mode == ZSTD_cpm_createCDict && ZSTD_CDictIndicesAreTagged(&cPar)) {\n        U32 const maxShortCacheHashLog = 32 - ZSTD_SHORT_CACHE_TAG_BITS;\n        if (cPar.hashLog > maxShortCacheHashLog) {\n            cPar.hashLog = maxShortCacheHashLog;\n        }\n        if (cPar.chainLog > maxShortCacheHashLog) {\n            cPar.chainLog = maxShortCacheHashLog;\n        }\n    }\n\n\n    /* At this point, we aren't 100% sure if we are using the row match finder.\n     * Unless it is explicitly disabled, conservatively assume that it is enabled.\n     * In this case it will only be disabled for small sources, so shrinking the\n     * hash log a little bit shouldn't result in any ratio loss.\n     */\n    if (useRowMatchFinder == ZSTD_ps_auto)\n        useRowMatchFinder = ZSTD_ps_enable;\n\n    /* We can't hash more than 32-bits in total. So that means that we require:\n     * (hashLog - rowLog + 8) <= 32\n     */\n    if (ZSTD_rowMatchFinderUsed(cPar.strategy, useRowMatchFinder)) {\n        /* Switch to 32-entry rows if searchLog is 5 (or more) */\n        U32 const rowLog = BOUNDED(4, cPar.searchLog, 6);\n        U32 const maxRowHashLog = 32 - ZSTD_ROW_HASH_TAG_BITS;\n        U32 const maxHashLog = maxRowHashLog + rowLog;\n        assert(cPar.hashLog >= rowLog);\n        if (cPar.hashLog > maxHashLog) {\n            cPar.hashLog = maxHashLog;\n        }\n    }\n\n    return cPar;\n}\n\nZSTD_compressionParameters\nZSTD_adjustCParams(ZSTD_compressionParameters cPar,\n                   unsigned long long srcSize,\n                   size_t dictSize)\n{\n    cPar = ZSTD_clampCParams(cPar);   /* resulting cPar is necessarily valid (all parameters within range) */\n    if (srcSize == 0) srcSize = ZSTD_CONTENTSIZE_UNKNOWN;\n    return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize, ZSTD_cpm_unknown, ZSTD_ps_auto);\n}\n\nstatic ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode);\nstatic ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode);\n\nstatic void ZSTD_overrideCParams(\n              ZSTD_compressionParameters* cParams,\n        const ZSTD_compressionParameters* overrides)\n{\n    if (overrides->windowLog)    cParams->windowLog    = overrides->windowLog;\n    if (overrides->hashLog)      cParams->hashLog      = overrides->hashLog;\n    if (overrides->chainLog)     cParams->chainLog     = overrides->chainLog;\n    if (overrides->searchLog)    cParams->searchLog    = overrides->searchLog;\n    if (overrides->minMatch)     cParams->minMatch     = overrides->minMatch;\n    if (overrides->targetLength) cParams->targetLength = overrides->targetLength;\n    if (overrides->strategy)     cParams->strategy     = overrides->strategy;\n}\n\nZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(\n        const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode)\n{\n    ZSTD_compressionParameters cParams;\n    if (srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN && CCtxParams->srcSizeHint > 0) {\n        assert(CCtxParams->srcSizeHint>=0);\n        srcSizeHint = (U64)CCtxParams->srcSizeHint;\n    }\n    cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize, mode);\n    if (CCtxParams->ldmParams.enableLdm == ZSTD_ps_enable) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;\n    ZSTD_overrideCParams(&cParams, &CCtxParams->cParams);\n    assert(!ZSTD_checkCParams(cParams));\n    /* srcSizeHint == 0 means 0 */\n    return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize, mode, CCtxParams->useRowMatchFinder);\n}\n\nstatic size_t\nZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,\n                       const ZSTD_ParamSwitch_e useRowMatchFinder,\n                       const int enableDedicatedDictSearch,\n                       const U32 forCCtx)\n{\n    /* chain table size should be 0 for fast or row-hash strategies */\n    size_t const chainSize = ZSTD_allocateChainTable(cParams->strategy, useRowMatchFinder, enableDedicatedDictSearch && !forCCtx)\n                                ? ((size_t)1 << cParams->chainLog)\n                                : 0;\n    size_t const hSize = ((size_t)1) << cParams->hashLog;\n    U32    const hashLog3 = (forCCtx && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;\n    size_t const h3Size = hashLog3 ? ((size_t)1) << hashLog3 : 0;\n    /* We don't use ZSTD_cwksp_alloc_size() here because the tables aren't\n     * surrounded by redzones in ASAN. */\n    size_t const tableSpace = chainSize * sizeof(U32)\n                            + hSize * sizeof(U32)\n                            + h3Size * sizeof(U32);\n    size_t const optPotentialSpace =\n        ZSTD_cwksp_aligned64_alloc_size((MaxML+1) * sizeof(U32))\n      + ZSTD_cwksp_aligned64_alloc_size((MaxLL+1) * sizeof(U32))\n      + ZSTD_cwksp_aligned64_alloc_size((MaxOff+1) * sizeof(U32))\n      + ZSTD_cwksp_aligned64_alloc_size((1<<Litbits) * sizeof(U32))\n      + ZSTD_cwksp_aligned64_alloc_size(ZSTD_OPT_SIZE * sizeof(ZSTD_match_t))\n      + ZSTD_cwksp_aligned64_alloc_size(ZSTD_OPT_SIZE * sizeof(ZSTD_optimal_t));\n    size_t const lazyAdditionalSpace = ZSTD_rowMatchFinderUsed(cParams->strategy, useRowMatchFinder)\n                                            ? ZSTD_cwksp_aligned64_alloc_size(hSize)\n                                            : 0;\n    size_t const optSpace = (forCCtx && (cParams->strategy >= ZSTD_btopt))\n                                ? optPotentialSpace\n                                : 0;\n    size_t const slackSpace = ZSTD_cwksp_slack_space_required();\n\n    /* tables are guaranteed to be sized in multiples of 64 bytes (or 16 uint32_t) */\n    ZSTD_STATIC_ASSERT(ZSTD_HASHLOG_MIN >= 4 && ZSTD_WINDOWLOG_MIN >= 4 && ZSTD_CHAINLOG_MIN >= 4);\n    assert(useRowMatchFinder != ZSTD_ps_auto);\n\n    DEBUGLOG(4, \"chainSize: %u - hSize: %u - h3Size: %u\",\n                (U32)chainSize, (U32)hSize, (U32)h3Size);\n    return tableSpace + optSpace + slackSpace + lazyAdditionalSpace;\n}\n\n/* Helper function for calculating memory requirements.\n * Gives a tighter bound than ZSTD_sequenceBound() by taking minMatch into account. */\nstatic size_t ZSTD_maxNbSeq(size_t blockSize, unsigned minMatch, int useSequenceProducer) {\n    U32 const divider = (minMatch==3 || useSequenceProducer) ? 3 : 4;\n    return blockSize / divider;\n}\n\nstatic size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal(\n        const ZSTD_compressionParameters* cParams,\n        const ldmParams_t* ldmParams,\n        const int isStatic,\n        const ZSTD_ParamSwitch_e useRowMatchFinder,\n        const size_t buffInSize,\n        const size_t buffOutSize,\n        const U64 pledgedSrcSize,\n        int useSequenceProducer,\n        size_t maxBlockSize)\n{\n    size_t const windowSize = (size_t) BOUNDED(1ULL, 1ULL << cParams->windowLog, pledgedSrcSize);\n    size_t const blockSize = MIN(ZSTD_resolveMaxBlockSize(maxBlockSize), windowSize);\n    size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, cParams->minMatch, useSequenceProducer);\n    size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize)\n                            + ZSTD_cwksp_aligned64_alloc_size(maxNbSeq * sizeof(SeqDef))\n                            + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE));\n    size_t const tmpWorkSpace = ZSTD_cwksp_alloc_size(TMP_WORKSPACE_SIZE);\n    size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t));\n    size_t const matchStateSize = ZSTD_sizeof_matchState(cParams, useRowMatchFinder, /* enableDedicatedDictSearch */ 0, /* forCCtx */ 1);\n\n    size_t const ldmSpace = ZSTD_ldm_getTableSize(*ldmParams);\n    size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(*ldmParams, blockSize);\n    size_t const ldmSeqSpace = ldmParams->enableLdm == ZSTD_ps_enable ?\n        ZSTD_cwksp_aligned64_alloc_size(maxNbLdmSeq * sizeof(rawSeq)) : 0;\n\n\n    size_t const bufferSpace = ZSTD_cwksp_alloc_size(buffInSize)\n                             + ZSTD_cwksp_alloc_size(buffOutSize);\n\n    size_t const cctxSpace = isStatic ? ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx)) : 0;\n\n    size_t const maxNbExternalSeq = ZSTD_sequenceBound(blockSize);\n    size_t const externalSeqSpace = useSequenceProducer\n        ? ZSTD_cwksp_aligned64_alloc_size(maxNbExternalSeq * sizeof(ZSTD_Sequence))\n        : 0;\n\n    size_t const neededSpace =\n        cctxSpace +\n        tmpWorkSpace +\n        blockStateSpace +\n        ldmSpace +\n        ldmSeqSpace +\n        matchStateSize +\n        tokenSpace +\n        bufferSpace +\n        externalSeqSpace;\n\n    DEBUGLOG(5, \"estimate workspace : %u\", (U32)neededSpace);\n    return neededSpace;\n}\n\nsize_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)\n{\n    ZSTD_compressionParameters const cParams =\n                ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);\n    ldmParams_t ldmParams = params->ldmParams;\n    ZSTD_ParamSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params->useRowMatchFinder,\n                                                                               &cParams);\n\n    RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, \"Estimate CCtx size is supported for single-threaded compression only.\");\n    if (ldmParams.enableLdm == ZSTD_ps_enable) {\n        ZSTD_ldm_adjustParameters(&ldmParams, &cParams);\n    }\n    /* estimateCCtxSize is for one-shot compression. So no buffers should\n     * be needed. However, we still allocate two 0-sized buffers, which can\n     * take space under ASAN. */\n    return ZSTD_estimateCCtxSize_usingCCtxParams_internal(\n        &cParams, &ldmParams, 1, useRowMatchFinder, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN, ZSTD_hasExtSeqProd(params), params->maxBlockSize);\n}\n\nsize_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams)\n{\n    ZSTD_CCtx_params initialParams = ZSTD_makeCCtxParamsFromCParams(cParams);\n    if (ZSTD_rowMatchFinderSupported(cParams.strategy)) {\n        /* Pick bigger of not using and using row-based matchfinder for greedy and lazy strategies */\n        size_t noRowCCtxSize;\n        size_t rowCCtxSize;\n        initialParams.useRowMatchFinder = ZSTD_ps_disable;\n        noRowCCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(&initialParams);\n        initialParams.useRowMatchFinder = ZSTD_ps_enable;\n        rowCCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(&initialParams);\n        return MAX(noRowCCtxSize, rowCCtxSize);\n    } else {\n        return ZSTD_estimateCCtxSize_usingCCtxParams(&initialParams);\n    }\n}\n\nstatic size_t ZSTD_estimateCCtxSize_internal(int compressionLevel)\n{\n    int tier = 0;\n    size_t largestSize = 0;\n    static const unsigned long long srcSizeTiers[4] = {16 KB, 128 KB, 256 KB, ZSTD_CONTENTSIZE_UNKNOWN};\n    for (; tier < 4; ++tier) {\n        /* Choose the set of cParams for a given level across all srcSizes that give the largest cctxSize */\n        ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeTiers[tier], 0, ZSTD_cpm_noAttachDict);\n        largestSize = MAX(ZSTD_estimateCCtxSize_usingCParams(cParams), largestSize);\n    }\n    return largestSize;\n}\n\nsize_t ZSTD_estimateCCtxSize(int compressionLevel)\n{\n    int level;\n    size_t memBudget = 0;\n    for (level=MIN(compressionLevel, 1); level<=compressionLevel; level++) {\n        /* Ensure monotonically increasing memory usage as compression level increases */\n        size_t const newMB = ZSTD_estimateCCtxSize_internal(level);\n        if (newMB > memBudget) memBudget = newMB;\n    }\n    return memBudget;\n}\n\nsize_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)\n{\n    RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, \"Estimate CCtx size is supported for single-threaded compression only.\");\n    {   ZSTD_compressionParameters const cParams =\n                ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);\n        ldmParams_t ldmParams = params->ldmParams;\n        size_t const blockSize = MIN(ZSTD_resolveMaxBlockSize(params->maxBlockSize), (size_t)1 << cParams.windowLog);\n        size_t const inBuffSize = (params->inBufferMode == ZSTD_bm_buffered)\n                ? ((size_t)1 << cParams.windowLog) + blockSize\n                : 0;\n        size_t const outBuffSize = (params->outBufferMode == ZSTD_bm_buffered)\n                ? ZSTD_compressBound(blockSize) + 1\n                : 0;\n        ZSTD_ParamSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params->useRowMatchFinder, &params->cParams);\n\n        if (ldmParams.enableLdm == ZSTD_ps_enable) {\n            ZSTD_ldm_adjustParameters(&ldmParams, &cParams);\n        }\n        return ZSTD_estimateCCtxSize_usingCCtxParams_internal(\n            &cParams, &ldmParams, 1, useRowMatchFinder, inBuffSize, outBuffSize,\n            ZSTD_CONTENTSIZE_UNKNOWN, ZSTD_hasExtSeqProd(params), params->maxBlockSize);\n    }\n}\n\nsize_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams)\n{\n    ZSTD_CCtx_params initialParams = ZSTD_makeCCtxParamsFromCParams(cParams);\n    if (ZSTD_rowMatchFinderSupported(cParams.strategy)) {\n        /* Pick bigger of not using and using row-based matchfinder for greedy and lazy strategies */\n        size_t noRowCCtxSize;\n        size_t rowCCtxSize;\n        initialParams.useRowMatchFinder = ZSTD_ps_disable;\n        noRowCCtxSize = ZSTD_estimateCStreamSize_usingCCtxParams(&initialParams);\n        initialParams.useRowMatchFinder = ZSTD_ps_enable;\n        rowCCtxSize = ZSTD_estimateCStreamSize_usingCCtxParams(&initialParams);\n        return MAX(noRowCCtxSize, rowCCtxSize);\n    } else {\n        return ZSTD_estimateCStreamSize_usingCCtxParams(&initialParams);\n    }\n}\n\nstatic size_t ZSTD_estimateCStreamSize_internal(int compressionLevel)\n{\n    ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);\n    return ZSTD_estimateCStreamSize_usingCParams(cParams);\n}\n\nsize_t ZSTD_estimateCStreamSize(int compressionLevel)\n{\n    int level;\n    size_t memBudget = 0;\n    for (level=MIN(compressionLevel, 1); level<=compressionLevel; level++) {\n        size_t const newMB = ZSTD_estimateCStreamSize_internal(level);\n        if (newMB > memBudget) memBudget = newMB;\n    }\n    return memBudget;\n}\n\n/* ZSTD_getFrameProgression():\n * tells how much data has been consumed (input) and produced (output) for current frame.\n * able to count progression inside worker threads (non-blocking mode).\n */\nZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx)\n{\n#ifdef ZSTD_MULTITHREAD\n    if (cctx->appliedParams.nbWorkers > 0) {\n        return ZSTDMT_getFrameProgression(cctx->mtctx);\n    }\n#endif\n    {   ZSTD_frameProgression fp;\n        size_t const buffered = (cctx->inBuff == NULL) ? 0 :\n                                cctx->inBuffPos - cctx->inToCompress;\n        if (buffered) assert(cctx->inBuffPos >= cctx->inToCompress);\n        assert(buffered <= ZSTD_BLOCKSIZE_MAX);\n        fp.ingested = cctx->consumedSrcSize + buffered;\n        fp.consumed = cctx->consumedSrcSize;\n        fp.produced = cctx->producedCSize;\n        fp.flushed  = cctx->producedCSize;   /* simplified; some data might still be left within streaming output buffer */\n        fp.currentJobID = 0;\n        fp.nbActiveWorkers = 0;\n        return fp;\n}   }\n\n/*! ZSTD_toFlushNow()\n *  Only useful for multithreading scenarios currently (nbWorkers >= 1).\n */\nsize_t ZSTD_toFlushNow(ZSTD_CCtx* cctx)\n{\n#ifdef ZSTD_MULTITHREAD\n    if (cctx->appliedParams.nbWorkers > 0) {\n        return ZSTDMT_toFlushNow(cctx->mtctx);\n    }\n#endif\n    (void)cctx;\n    return 0;   /* over-simplification; could also check if context is currently running in streaming mode, and in which case, report how many bytes are left to be flushed within output buffer */\n}\n\nstatic void ZSTD_assertEqualCParams(ZSTD_compressionParameters cParams1,\n                                    ZSTD_compressionParameters cParams2)\n{\n    (void)cParams1;\n    (void)cParams2;\n    assert(cParams1.windowLog    == cParams2.windowLog);\n    assert(cParams1.chainLog     == cParams2.chainLog);\n    assert(cParams1.hashLog      == cParams2.hashLog);\n    assert(cParams1.searchLog    == cParams2.searchLog);\n    assert(cParams1.minMatch     == cParams2.minMatch);\n    assert(cParams1.targetLength == cParams2.targetLength);\n    assert(cParams1.strategy     == cParams2.strategy);\n}\n\nvoid ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)\n{\n    int i;\n    for (i = 0; i < ZSTD_REP_NUM; ++i)\n        bs->rep[i] = repStartValue[i];\n    bs->entropy.huf.repeatMode = HUF_repeat_none;\n    bs->entropy.fse.offcode_repeatMode = FSE_repeat_none;\n    bs->entropy.fse.matchlength_repeatMode = FSE_repeat_none;\n    bs->entropy.fse.litlength_repeatMode = FSE_repeat_none;\n}\n\n/*! ZSTD_invalidateMatchState()\n *  Invalidate all the matches in the match finder tables.\n *  Requires nextSrc and base to be set (can be NULL).\n */\nstatic void ZSTD_invalidateMatchState(ZSTD_MatchState_t* ms)\n{\n    ZSTD_window_clear(&ms->window);\n\n    ms->nextToUpdate = ms->window.dictLimit;\n    ms->loadedDictEnd = 0;\n    ms->opt.litLengthSum = 0;  /* force reset of btopt stats */\n    ms->dictMatchState = NULL;\n}\n\n/**\n * Controls, for this matchState reset, whether the tables need to be cleared /\n * prepared for the coming compression (ZSTDcrp_makeClean), or whether the\n * tables can be left unclean (ZSTDcrp_leaveDirty), because we know that a\n * subsequent operation will overwrite the table space anyways (e.g., copying\n * the matchState contents in from a CDict).\n */\ntypedef enum {\n    ZSTDcrp_makeClean,\n    ZSTDcrp_leaveDirty\n} ZSTD_compResetPolicy_e;\n\n/**\n * Controls, for this matchState reset, whether indexing can continue where it\n * left off (ZSTDirp_continue), or whether it needs to be restarted from zero\n * (ZSTDirp_reset).\n */\ntypedef enum {\n    ZSTDirp_continue,\n    ZSTDirp_reset\n} ZSTD_indexResetPolicy_e;\n\ntypedef enum {\n    ZSTD_resetTarget_CDict,\n    ZSTD_resetTarget_CCtx\n} ZSTD_resetTarget_e;\n\n/* Mixes bits in a 64 bits in a value, based on XXH3_rrmxmx */\nstatic U64 ZSTD_bitmix(U64 val, U64 len) {\n    val ^= ZSTD_rotateRight_U64(val, 49) ^ ZSTD_rotateRight_U64(val, 24);\n    val *= 0x9FB21C651E98DF25ULL;\n    val ^= (val >> 35) + len ;\n    val *= 0x9FB21C651E98DF25ULL;\n    return val ^ (val >> 28);\n}\n\n/* Mixes in the hashSalt and hashSaltEntropy to create a new hashSalt */\nstatic void ZSTD_advanceHashSalt(ZSTD_MatchState_t* ms) {\n    ms->hashSalt = ZSTD_bitmix(ms->hashSalt, 8) ^ ZSTD_bitmix((U64) ms->hashSaltEntropy, 4);\n}\n\nstatic size_t\nZSTD_reset_matchState(ZSTD_MatchState_t* ms,\n                      ZSTD_cwksp* ws,\n                const ZSTD_compressionParameters* cParams,\n                const ZSTD_ParamSwitch_e useRowMatchFinder,\n                const ZSTD_compResetPolicy_e crp,\n                const ZSTD_indexResetPolicy_e forceResetIndex,\n                const ZSTD_resetTarget_e forWho)\n{\n    /* disable chain table allocation for fast or row-based strategies */\n    size_t const chainSize = ZSTD_allocateChainTable(cParams->strategy, useRowMatchFinder,\n                                                     ms->dedicatedDictSearch && (forWho == ZSTD_resetTarget_CDict))\n                                ? ((size_t)1 << cParams->chainLog)\n                                : 0;\n    size_t const hSize = ((size_t)1) << cParams->hashLog;\n    U32    const hashLog3 = ((forWho == ZSTD_resetTarget_CCtx) && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;\n    size_t const h3Size = hashLog3 ? ((size_t)1) << hashLog3 : 0;\n\n    DEBUGLOG(4, \"reset indices : %u\", forceResetIndex == ZSTDirp_reset);\n    assert(useRowMatchFinder != ZSTD_ps_auto);\n    if (forceResetIndex == ZSTDirp_reset) {\n        ZSTD_window_init(&ms->window);\n        ZSTD_cwksp_mark_tables_dirty(ws);\n    }\n\n    ms->hashLog3 = hashLog3;\n    ms->lazySkipping = 0;\n\n    ZSTD_invalidateMatchState(ms);\n\n    assert(!ZSTD_cwksp_reserve_failed(ws)); /* check that allocation hasn't already failed */\n\n    ZSTD_cwksp_clear_tables(ws);\n\n    DEBUGLOG(5, \"reserving table space\");\n    /* table Space */\n    ms->hashTable = (U32*)ZSTD_cwksp_reserve_table(ws, hSize * sizeof(U32));\n    ms->chainTable = (U32*)ZSTD_cwksp_reserve_table(ws, chainSize * sizeof(U32));\n    ms->hashTable3 = (U32*)ZSTD_cwksp_reserve_table(ws, h3Size * sizeof(U32));\n    RETURN_ERROR_IF(ZSTD_cwksp_reserve_failed(ws), memory_allocation,\n                    \"failed a workspace allocation in ZSTD_reset_matchState\");\n\n    DEBUGLOG(4, \"reset table : %u\", crp!=ZSTDcrp_leaveDirty);\n    if (crp!=ZSTDcrp_leaveDirty) {\n        /* reset tables only */\n        ZSTD_cwksp_clean_tables(ws);\n    }\n\n    if (ZSTD_rowMatchFinderUsed(cParams->strategy, useRowMatchFinder)) {\n        /* Row match finder needs an additional table of hashes (\"tags\") */\n        size_t const tagTableSize = hSize;\n        /* We want to generate a new salt in case we reset a Cctx, but we always want to use\n         * 0 when we reset a Cdict */\n        if(forWho == ZSTD_resetTarget_CCtx) {\n            ms->tagTable = (BYTE*) ZSTD_cwksp_reserve_aligned_init_once(ws, tagTableSize);\n            ZSTD_advanceHashSalt(ms);\n        } else {\n            /* When we are not salting we want to always memset the memory */\n            ms->tagTable = (BYTE*) ZSTD_cwksp_reserve_aligned64(ws, tagTableSize);\n            ZSTD_memset(ms->tagTable, 0, tagTableSize);\n            ms->hashSalt = 0;\n        }\n        {   /* Switch to 32-entry rows if searchLog is 5 (or more) */\n            U32 const rowLog = BOUNDED(4, cParams->searchLog, 6);\n            assert(cParams->hashLog >= rowLog);\n            ms->rowHashLog = cParams->hashLog - rowLog;\n        }\n    }\n\n    /* opt parser space */\n    if ((forWho == ZSTD_resetTarget_CCtx) && (cParams->strategy >= ZSTD_btopt)) {\n        DEBUGLOG(4, \"reserving optimal parser space\");\n        ms->opt.litFreq = (unsigned*)ZSTD_cwksp_reserve_aligned64(ws, (1<<Litbits) * sizeof(unsigned));\n        ms->opt.litLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned64(ws, (MaxLL+1) * sizeof(unsigned));\n        ms->opt.matchLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned64(ws, (MaxML+1) * sizeof(unsigned));\n        ms->opt.offCodeFreq = (unsigned*)ZSTD_cwksp_reserve_aligned64(ws, (MaxOff+1) * sizeof(unsigned));\n        ms->opt.matchTable = (ZSTD_match_t*)ZSTD_cwksp_reserve_aligned64(ws, ZSTD_OPT_SIZE * sizeof(ZSTD_match_t));\n        ms->opt.priceTable = (ZSTD_optimal_t*)ZSTD_cwksp_reserve_aligned64(ws, ZSTD_OPT_SIZE * sizeof(ZSTD_optimal_t));\n    }\n\n    ms->cParams = *cParams;\n\n    RETURN_ERROR_IF(ZSTD_cwksp_reserve_failed(ws), memory_allocation,\n                    \"failed a workspace allocation in ZSTD_reset_matchState\");\n    return 0;\n}\n\n/* ZSTD_indexTooCloseToMax() :\n * minor optimization : prefer memset() rather than reduceIndex()\n * which is measurably slow in some circumstances (reported for Visual Studio).\n * Works when re-using a context for a lot of smallish inputs :\n * if all inputs are smaller than ZSTD_INDEXOVERFLOW_MARGIN,\n * memset() will be triggered before reduceIndex().\n */\n#define ZSTD_INDEXOVERFLOW_MARGIN (16 MB)\nstatic int ZSTD_indexTooCloseToMax(ZSTD_window_t w)\n{\n    return (size_t)(w.nextSrc - w.base) > (ZSTD_CURRENT_MAX - ZSTD_INDEXOVERFLOW_MARGIN);\n}\n\n/** ZSTD_dictTooBig():\n * When dictionaries are larger than ZSTD_CHUNKSIZE_MAX they can't be loaded in\n * one go generically. So we ensure that in that case we reset the tables to zero,\n * so that we can load as much of the dictionary as possible.\n */\nstatic int ZSTD_dictTooBig(size_t const loadedDictSize)\n{\n    return loadedDictSize > ZSTD_CHUNKSIZE_MAX;\n}\n\n/*! ZSTD_resetCCtx_internal() :\n * @param loadedDictSize The size of the dictionary to be loaded\n * into the context, if any. If no dictionary is used, or the\n * dictionary is being attached / copied, then pass 0.\n * note : `params` are assumed fully validated at this stage.\n */\nstatic size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,\n                                      ZSTD_CCtx_params const* params,\n                                      U64 const pledgedSrcSize,\n                                      size_t const loadedDictSize,\n                                      ZSTD_compResetPolicy_e const crp,\n                                      ZSTD_buffered_policy_e const zbuff)\n{\n    ZSTD_cwksp* const ws = &zc->workspace;\n    DEBUGLOG(4, \"ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u, useRowMatchFinder=%d useBlockSplitter=%d\",\n                (U32)pledgedSrcSize, params->cParams.windowLog, (int)params->useRowMatchFinder, (int)params->postBlockSplitter);\n    assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams)));\n\n    zc->isFirstBlock = 1;\n\n    /* Set applied params early so we can modify them for LDM,\n     * and point params at the applied params.\n     */\n    zc->appliedParams = *params;\n    params = &zc->appliedParams;\n\n    assert(params->useRowMatchFinder != ZSTD_ps_auto);\n    assert(params->postBlockSplitter != ZSTD_ps_auto);\n    assert(params->ldmParams.enableLdm != ZSTD_ps_auto);\n    assert(params->maxBlockSize != 0);\n    if (params->ldmParams.enableLdm == ZSTD_ps_enable) {\n        /* Adjust long distance matching parameters */\n        ZSTD_ldm_adjustParameters(&zc->appliedParams.ldmParams, &params->cParams);\n        assert(params->ldmParams.hashLog >= params->ldmParams.bucketSizeLog);\n        assert(params->ldmParams.hashRateLog < 32);\n    }\n\n    {   size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params->cParams.windowLog), pledgedSrcSize));\n        size_t const blockSize = MIN(params->maxBlockSize, windowSize);\n        size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, params->cParams.minMatch, ZSTD_hasExtSeqProd(params));\n        size_t const buffOutSize = (zbuff == ZSTDb_buffered && params->outBufferMode == ZSTD_bm_buffered)\n                ? ZSTD_compressBound(blockSize) + 1\n                : 0;\n        size_t const buffInSize = (zbuff == ZSTDb_buffered && params->inBufferMode == ZSTD_bm_buffered)\n                ? windowSize + blockSize\n                : 0;\n        size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params->ldmParams, blockSize);\n\n        int const indexTooClose = ZSTD_indexTooCloseToMax(zc->blockState.matchState.window);\n        int const dictTooBig = ZSTD_dictTooBig(loadedDictSize);\n        ZSTD_indexResetPolicy_e needsIndexReset =\n            (indexTooClose || dictTooBig || !zc->initialized) ? ZSTDirp_reset : ZSTDirp_continue;\n\n        size_t const neededSpace =\n            ZSTD_estimateCCtxSize_usingCCtxParams_internal(\n                &params->cParams, &params->ldmParams, zc->staticSize != 0, params->useRowMatchFinder,\n                buffInSize, buffOutSize, pledgedSrcSize, ZSTD_hasExtSeqProd(params), params->maxBlockSize);\n\n        FORWARD_IF_ERROR(neededSpace, \"cctx size estimate failed!\");\n\n        if (!zc->staticSize) ZSTD_cwksp_bump_oversized_duration(ws, 0);\n\n        {   /* Check if workspace is large enough, alloc a new one if needed */\n            int const workspaceTooSmall = ZSTD_cwksp_sizeof(ws) < neededSpace;\n            int const workspaceWasteful = ZSTD_cwksp_check_wasteful(ws, neededSpace);\n            int resizeWorkspace = workspaceTooSmall || workspaceWasteful;\n            DEBUGLOG(4, \"Need %zu B workspace\", neededSpace);\n            DEBUGLOG(4, \"windowSize: %zu - blockSize: %zu\", windowSize, blockSize);\n\n            if (resizeWorkspace) {\n                DEBUGLOG(4, \"Resize workspaceSize from %zuKB to %zuKB\",\n                            ZSTD_cwksp_sizeof(ws) >> 10,\n                            neededSpace >> 10);\n\n                RETURN_ERROR_IF(zc->staticSize, memory_allocation, \"static cctx : no resize\");\n\n                needsIndexReset = ZSTDirp_reset;\n\n                ZSTD_cwksp_free(ws, zc->customMem);\n                FORWARD_IF_ERROR(ZSTD_cwksp_create(ws, neededSpace, zc->customMem), \"\");\n\n                DEBUGLOG(5, \"reserving object space\");\n                /* Statically sized space.\n                 * tmpWorkspace never moves,\n                 * though prev/next block swap places */\n                assert(ZSTD_cwksp_check_available(ws, 2 * sizeof(ZSTD_compressedBlockState_t)));\n                zc->blockState.prevCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t));\n                RETURN_ERROR_IF(zc->blockState.prevCBlock == NULL, memory_allocation, \"couldn't allocate prevCBlock\");\n                zc->blockState.nextCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t));\n                RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, \"couldn't allocate nextCBlock\");\n                zc->tmpWorkspace = ZSTD_cwksp_reserve_object(ws, TMP_WORKSPACE_SIZE);\n                RETURN_ERROR_IF(zc->tmpWorkspace == NULL, memory_allocation, \"couldn't allocate tmpWorkspace\");\n                zc->tmpWkspSize = TMP_WORKSPACE_SIZE;\n        }   }\n\n        ZSTD_cwksp_clear(ws);\n\n        /* init params */\n        zc->blockState.matchState.cParams = params->cParams;\n        zc->blockState.matchState.prefetchCDictTables = params->prefetchCDictTables == ZSTD_ps_enable;\n        zc->pledgedSrcSizePlusOne = pledgedSrcSize+1;\n        zc->consumedSrcSize = 0;\n        zc->producedCSize = 0;\n        if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)\n            zc->appliedParams.fParams.contentSizeFlag = 0;\n        DEBUGLOG(4, \"pledged content size : %u ; flag : %u\",\n            (unsigned)pledgedSrcSize, zc->appliedParams.fParams.contentSizeFlag);\n        zc->blockSizeMax = blockSize;\n\n        XXH64_reset(&zc->xxhState, 0);\n        zc->stage = ZSTDcs_init;\n        zc->dictID = 0;\n        zc->dictContentSize = 0;\n\n        ZSTD_reset_compressedBlockState(zc->blockState.prevCBlock);\n\n        FORWARD_IF_ERROR(ZSTD_reset_matchState(\n                &zc->blockState.matchState,\n                ws,\n                &params->cParams,\n                params->useRowMatchFinder,\n                crp,\n                needsIndexReset,\n                ZSTD_resetTarget_CCtx), \"\");\n\n        zc->seqStore.sequencesStart = (SeqDef*)ZSTD_cwksp_reserve_aligned64(ws, maxNbSeq * sizeof(SeqDef));\n\n        /* ldm hash table */\n        if (params->ldmParams.enableLdm == ZSTD_ps_enable) {\n            /* TODO: avoid memset? */\n            size_t const ldmHSize = ((size_t)1) << params->ldmParams.hashLog;\n            zc->ldmState.hashTable = (ldmEntry_t*)ZSTD_cwksp_reserve_aligned64(ws, ldmHSize * sizeof(ldmEntry_t));\n            ZSTD_memset(zc->ldmState.hashTable, 0, ldmHSize * sizeof(ldmEntry_t));\n            zc->ldmSequences = (rawSeq*)ZSTD_cwksp_reserve_aligned64(ws, maxNbLdmSeq * sizeof(rawSeq));\n            zc->maxNbLdmSequences = maxNbLdmSeq;\n\n            ZSTD_window_init(&zc->ldmState.window);\n            zc->ldmState.loadedDictEnd = 0;\n        }\n\n        /* reserve space for block-level external sequences */\n        if (ZSTD_hasExtSeqProd(params)) {\n            size_t const maxNbExternalSeq = ZSTD_sequenceBound(blockSize);\n            zc->extSeqBufCapacity = maxNbExternalSeq;\n            zc->extSeqBuf =\n                (ZSTD_Sequence*)ZSTD_cwksp_reserve_aligned64(ws, maxNbExternalSeq * sizeof(ZSTD_Sequence));\n        }\n\n        /* buffers */\n\n        /* ZSTD_wildcopy() is used to copy into the literals buffer,\n         * so we have to oversize the buffer by WILDCOPY_OVERLENGTH bytes.\n         */\n        zc->seqStore.litStart = ZSTD_cwksp_reserve_buffer(ws, blockSize + WILDCOPY_OVERLENGTH);\n        zc->seqStore.maxNbLit = blockSize;\n\n        zc->bufferedPolicy = zbuff;\n        zc->inBuffSize = buffInSize;\n        zc->inBuff = (char*)ZSTD_cwksp_reserve_buffer(ws, buffInSize);\n        zc->outBuffSize = buffOutSize;\n        zc->outBuff = (char*)ZSTD_cwksp_reserve_buffer(ws, buffOutSize);\n\n        /* ldm bucketOffsets table */\n        if (params->ldmParams.enableLdm == ZSTD_ps_enable) {\n            /* TODO: avoid memset? */\n            size_t const numBuckets =\n                  ((size_t)1) << (params->ldmParams.hashLog -\n                                  params->ldmParams.bucketSizeLog);\n            zc->ldmState.bucketOffsets = ZSTD_cwksp_reserve_buffer(ws, numBuckets);\n            ZSTD_memset(zc->ldmState.bucketOffsets, 0, numBuckets);\n        }\n\n        /* sequences storage */\n        ZSTD_referenceExternalSequences(zc, NULL, 0);\n        zc->seqStore.maxNbSeq = maxNbSeq;\n        zc->seqStore.llCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE));\n        zc->seqStore.mlCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE));\n        zc->seqStore.ofCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE));\n\n        DEBUGLOG(3, \"wksp: finished allocating, %zd bytes remain available\", ZSTD_cwksp_available_space(ws));\n        assert(ZSTD_cwksp_estimated_space_within_bounds(ws, neededSpace));\n\n        zc->initialized = 1;\n\n        return 0;\n    }\n}\n\n/* ZSTD_invalidateRepCodes() :\n * ensures next compression will not use repcodes from previous block.\n * Note : only works with regular variant;\n *        do not use with extDict variant ! */\nvoid ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) {\n    int i;\n    for (i=0; i<ZSTD_REP_NUM; i++) cctx->blockState.prevCBlock->rep[i] = 0;\n    assert(!ZSTD_window_hasExtDict(cctx->blockState.matchState.window));\n}\n\n/* These are the approximate sizes for each strategy past which copying the\n * dictionary tables into the working context is faster than using them\n * in-place.\n */\nstatic const size_t attachDictSizeCutoffs[ZSTD_STRATEGY_MAX+1] = {\n    8 KB,  /* unused */\n    8 KB,  /* ZSTD_fast */\n    16 KB, /* ZSTD_dfast */\n    32 KB, /* ZSTD_greedy */\n    32 KB, /* ZSTD_lazy */\n    32 KB, /* ZSTD_lazy2 */\n    32 KB, /* ZSTD_btlazy2 */\n    32 KB, /* ZSTD_btopt */\n    8 KB,  /* ZSTD_btultra */\n    8 KB   /* ZSTD_btultra2 */\n};\n\nstatic int ZSTD_shouldAttachDict(const ZSTD_CDict* cdict,\n                                 const ZSTD_CCtx_params* params,\n                                 U64 pledgedSrcSize)\n{\n    size_t cutoff = attachDictSizeCutoffs[cdict->matchState.cParams.strategy];\n    int const dedicatedDictSearch = cdict->matchState.dedicatedDictSearch;\n    return dedicatedDictSearch\n        || ( ( pledgedSrcSize <= cutoff\n            || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN\n            || params->attachDictPref == ZSTD_dictForceAttach )\n          && params->attachDictPref != ZSTD_dictForceCopy\n          && !params->forceWindow ); /* dictMatchState isn't correctly\n                                      * handled in _enforceMaxDist */\n}\n\nstatic size_t\nZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx,\n                        const ZSTD_CDict* cdict,\n                        ZSTD_CCtx_params params,\n                        U64 pledgedSrcSize,\n                        ZSTD_buffered_policy_e zbuff)\n{\n    DEBUGLOG(4, \"ZSTD_resetCCtx_byAttachingCDict() pledgedSrcSize=%llu\",\n                (unsigned long long)pledgedSrcSize);\n    {\n        ZSTD_compressionParameters adjusted_cdict_cParams = cdict->matchState.cParams;\n        unsigned const windowLog = params.cParams.windowLog;\n        assert(windowLog != 0);\n        /* Resize working context table params for input only, since the dict\n         * has its own tables. */\n        /* pledgedSrcSize == 0 means 0! */\n\n        if (cdict->matchState.dedicatedDictSearch) {\n            ZSTD_dedicatedDictSearch_revertCParams(&adjusted_cdict_cParams);\n        }\n\n        params.cParams = ZSTD_adjustCParams_internal(adjusted_cdict_cParams, pledgedSrcSize,\n                                                     cdict->dictContentSize, ZSTD_cpm_attachDict,\n                                                     params.useRowMatchFinder);\n        params.cParams.windowLog = windowLog;\n        params.useRowMatchFinder = cdict->useRowMatchFinder;    /* cdict overrides */\n        FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, &params, pledgedSrcSize,\n                                                 /* loadedDictSize */ 0,\n                                                 ZSTDcrp_makeClean, zbuff), \"\");\n        assert(cctx->appliedParams.cParams.strategy == adjusted_cdict_cParams.strategy);\n    }\n\n    {   const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc\n                                  - cdict->matchState.window.base);\n        const U32 cdictLen = cdictEnd - cdict->matchState.window.dictLimit;\n        if (cdictLen == 0) {\n            /* don't even attach dictionaries with no contents */\n            DEBUGLOG(4, \"skipping attaching empty dictionary\");\n        } else {\n            DEBUGLOG(4, \"attaching dictionary into context\");\n            cctx->blockState.matchState.dictMatchState = &cdict->matchState;\n\n            /* prep working match state so dict matches never have negative indices\n             * when they are translated to the working context's index space. */\n            if (cctx->blockState.matchState.window.dictLimit < cdictEnd) {\n                cctx->blockState.matchState.window.nextSrc =\n                    cctx->blockState.matchState.window.base + cdictEnd;\n                ZSTD_window_clear(&cctx->blockState.matchState.window);\n            }\n            /* loadedDictEnd is expressed within the referential of the active context */\n            cctx->blockState.matchState.loadedDictEnd = cctx->blockState.matchState.window.dictLimit;\n    }   }\n\n    cctx->dictID = cdict->dictID;\n    cctx->dictContentSize = cdict->dictContentSize;\n\n    /* copy block state */\n    ZSTD_memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState));\n\n    return 0;\n}\n\nstatic void ZSTD_copyCDictTableIntoCCtx(U32* dst, U32 const* src, size_t tableSize,\n                                        ZSTD_compressionParameters const* cParams) {\n    if (ZSTD_CDictIndicesAreTagged(cParams)){\n        /* Remove tags from the CDict table if they are present.\n         * See docs on \"short cache\" in zstd_compress_internal.h for context. */\n        size_t i;\n        for (i = 0; i < tableSize; i++) {\n            U32 const taggedIndex = src[i];\n            U32 const index = taggedIndex >> ZSTD_SHORT_CACHE_TAG_BITS;\n            dst[i] = index;\n        }\n    } else {\n        ZSTD_memcpy(dst, src, tableSize * sizeof(U32));\n    }\n}\n\nstatic size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,\n                            const ZSTD_CDict* cdict,\n                            ZSTD_CCtx_params params,\n                            U64 pledgedSrcSize,\n                            ZSTD_buffered_policy_e zbuff)\n{\n    const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams;\n\n    assert(!cdict->matchState.dedicatedDictSearch);\n    DEBUGLOG(4, \"ZSTD_resetCCtx_byCopyingCDict() pledgedSrcSize=%llu\",\n                (unsigned long long)pledgedSrcSize);\n\n    {   unsigned const windowLog = params.cParams.windowLog;\n        assert(windowLog != 0);\n        /* Copy only compression parameters related to tables. */\n        params.cParams = *cdict_cParams;\n        params.cParams.windowLog = windowLog;\n        params.useRowMatchFinder = cdict->useRowMatchFinder;\n        FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, &params, pledgedSrcSize,\n                                                 /* loadedDictSize */ 0,\n                                                 ZSTDcrp_leaveDirty, zbuff), \"\");\n        assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy);\n        assert(cctx->appliedParams.cParams.hashLog == cdict_cParams->hashLog);\n        assert(cctx->appliedParams.cParams.chainLog == cdict_cParams->chainLog);\n    }\n\n    ZSTD_cwksp_mark_tables_dirty(&cctx->workspace);\n    assert(params.useRowMatchFinder != ZSTD_ps_auto);\n\n    /* copy tables */\n    {   size_t const chainSize = ZSTD_allocateChainTable(cdict_cParams->strategy, cdict->useRowMatchFinder, 0 /* DDS guaranteed disabled */)\n                                                            ? ((size_t)1 << cdict_cParams->chainLog)\n                                                            : 0;\n        size_t const hSize =  (size_t)1 << cdict_cParams->hashLog;\n\n        ZSTD_copyCDictTableIntoCCtx(cctx->blockState.matchState.hashTable,\n                                cdict->matchState.hashTable,\n                                hSize, cdict_cParams);\n\n        /* Do not copy cdict's chainTable if cctx has parameters such that it would not use chainTable */\n        if (ZSTD_allocateChainTable(cctx->appliedParams.cParams.strategy, cctx->appliedParams.useRowMatchFinder, 0 /* forDDSDict */)) {\n            ZSTD_copyCDictTableIntoCCtx(cctx->blockState.matchState.chainTable,\n                                    cdict->matchState.chainTable,\n                                    chainSize, cdict_cParams);\n        }\n        /* copy tag table */\n        if (ZSTD_rowMatchFinderUsed(cdict_cParams->strategy, cdict->useRowMatchFinder)) {\n            size_t const tagTableSize = hSize;\n            ZSTD_memcpy(cctx->blockState.matchState.tagTable,\n                        cdict->matchState.tagTable,\n                        tagTableSize);\n            cctx->blockState.matchState.hashSalt = cdict->matchState.hashSalt;\n        }\n    }\n\n    /* Zero the hashTable3, since the cdict never fills it */\n    assert(cctx->blockState.matchState.hashLog3 <= 31);\n    {   U32 const h3log = cctx->blockState.matchState.hashLog3;\n        size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0;\n        assert(cdict->matchState.hashLog3 == 0);\n        ZSTD_memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32));\n    }\n\n    ZSTD_cwksp_mark_tables_clean(&cctx->workspace);\n\n    /* copy dictionary offsets */\n    {   ZSTD_MatchState_t const* srcMatchState = &cdict->matchState;\n        ZSTD_MatchState_t* dstMatchState = &cctx->blockState.matchState;\n        dstMatchState->window       = srcMatchState->window;\n        dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;\n        dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;\n    }\n\n    cctx->dictID = cdict->dictID;\n    cctx->dictContentSize = cdict->dictContentSize;\n\n    /* copy block state */\n    ZSTD_memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState));\n\n    return 0;\n}\n\n/* We have a choice between copying the dictionary context into the working\n * context, or referencing the dictionary context from the working context\n * in-place. We decide here which strategy to use. */\nstatic size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,\n                            const ZSTD_CDict* cdict,\n                            const ZSTD_CCtx_params* params,\n                            U64 pledgedSrcSize,\n                            ZSTD_buffered_policy_e zbuff)\n{\n\n    DEBUGLOG(4, \"ZSTD_resetCCtx_usingCDict (pledgedSrcSize=%u)\",\n                (unsigned)pledgedSrcSize);\n\n    if (ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize)) {\n        return ZSTD_resetCCtx_byAttachingCDict(\n            cctx, cdict, *params, pledgedSrcSize, zbuff);\n    } else {\n        return ZSTD_resetCCtx_byCopyingCDict(\n            cctx, cdict, *params, pledgedSrcSize, zbuff);\n    }\n}\n\n/*! ZSTD_copyCCtx_internal() :\n *  Duplicate an existing context `srcCCtx` into another one `dstCCtx`.\n *  Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()).\n *  The \"context\", in this case, refers to the hash and chain tables,\n *  entropy tables, and dictionary references.\n * `windowLog` value is enforced if != 0, otherwise value is copied from srcCCtx.\n * @return : 0, or an error code */\nstatic size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,\n                            const ZSTD_CCtx* srcCCtx,\n                            ZSTD_frameParameters fParams,\n                            U64 pledgedSrcSize,\n                            ZSTD_buffered_policy_e zbuff)\n{\n    RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong,\n                    \"Can't copy a ctx that's not in init stage.\");\n    DEBUGLOG(5, \"ZSTD_copyCCtx_internal\");\n    ZSTD_memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem));\n    {   ZSTD_CCtx_params params = dstCCtx->requestedParams;\n        /* Copy only compression parameters related to tables. */\n        params.cParams = srcCCtx->appliedParams.cParams;\n        assert(srcCCtx->appliedParams.useRowMatchFinder != ZSTD_ps_auto);\n        assert(srcCCtx->appliedParams.postBlockSplitter != ZSTD_ps_auto);\n        assert(srcCCtx->appliedParams.ldmParams.enableLdm != ZSTD_ps_auto);\n        params.useRowMatchFinder = srcCCtx->appliedParams.useRowMatchFinder;\n        params.postBlockSplitter = srcCCtx->appliedParams.postBlockSplitter;\n        params.ldmParams = srcCCtx->appliedParams.ldmParams;\n        params.fParams = fParams;\n        params.maxBlockSize = srcCCtx->appliedParams.maxBlockSize;\n        ZSTD_resetCCtx_internal(dstCCtx, &params, pledgedSrcSize,\n                                /* loadedDictSize */ 0,\n                                ZSTDcrp_leaveDirty, zbuff);\n        assert(dstCCtx->appliedParams.cParams.windowLog == srcCCtx->appliedParams.cParams.windowLog);\n        assert(dstCCtx->appliedParams.cParams.strategy == srcCCtx->appliedParams.cParams.strategy);\n        assert(dstCCtx->appliedParams.cParams.hashLog == srcCCtx->appliedParams.cParams.hashLog);\n        assert(dstCCtx->appliedParams.cParams.chainLog == srcCCtx->appliedParams.cParams.chainLog);\n        assert(dstCCtx->blockState.matchState.hashLog3 == srcCCtx->blockState.matchState.hashLog3);\n    }\n\n    ZSTD_cwksp_mark_tables_dirty(&dstCCtx->workspace);\n\n    /* copy tables */\n    {   size_t const chainSize = ZSTD_allocateChainTable(srcCCtx->appliedParams.cParams.strategy,\n                                                         srcCCtx->appliedParams.useRowMatchFinder,\n                                                         0 /* forDDSDict */)\n                                    ? ((size_t)1 << srcCCtx->appliedParams.cParams.chainLog)\n                                    : 0;\n        size_t const hSize =  (size_t)1 << srcCCtx->appliedParams.cParams.hashLog;\n        U32 const h3log = srcCCtx->blockState.matchState.hashLog3;\n        size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0;\n\n        ZSTD_memcpy(dstCCtx->blockState.matchState.hashTable,\n               srcCCtx->blockState.matchState.hashTable,\n               hSize * sizeof(U32));\n        ZSTD_memcpy(dstCCtx->blockState.matchState.chainTable,\n               srcCCtx->blockState.matchState.chainTable,\n               chainSize * sizeof(U32));\n        ZSTD_memcpy(dstCCtx->blockState.matchState.hashTable3,\n               srcCCtx->blockState.matchState.hashTable3,\n               h3Size * sizeof(U32));\n    }\n\n    ZSTD_cwksp_mark_tables_clean(&dstCCtx->workspace);\n\n    /* copy dictionary offsets */\n    {\n        const ZSTD_MatchState_t* srcMatchState = &srcCCtx->blockState.matchState;\n        ZSTD_MatchState_t* dstMatchState = &dstCCtx->blockState.matchState;\n        dstMatchState->window       = srcMatchState->window;\n        dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;\n        dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;\n    }\n    dstCCtx->dictID = srcCCtx->dictID;\n    dstCCtx->dictContentSize = srcCCtx->dictContentSize;\n\n    /* copy block state */\n    ZSTD_memcpy(dstCCtx->blockState.prevCBlock, srcCCtx->blockState.prevCBlock, sizeof(*srcCCtx->blockState.prevCBlock));\n\n    return 0;\n}\n\n/*! ZSTD_copyCCtx() :\n *  Duplicate an existing context `srcCCtx` into another one `dstCCtx`.\n *  Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()).\n *  pledgedSrcSize==0 means \"unknown\".\n*   @return : 0, or an error code */\nsize_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx, unsigned long long pledgedSrcSize)\n{\n    ZSTD_frameParameters fParams = { 1 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };\n    ZSTD_buffered_policy_e const zbuff = srcCCtx->bufferedPolicy;\n    ZSTD_STATIC_ASSERT((U32)ZSTDb_buffered==1);\n    if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;\n    fParams.contentSizeFlag = (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN);\n\n    return ZSTD_copyCCtx_internal(dstCCtx, srcCCtx,\n                                fParams, pledgedSrcSize,\n                                zbuff);\n}\n\n\n#define ZSTD_ROWSIZE 16\n/*! ZSTD_reduceTable() :\n *  reduce table indexes by `reducerValue`, or squash to zero.\n *  PreserveMark preserves \"unsorted mark\" for btlazy2 strategy.\n *  It must be set to a clear 0/1 value, to remove branch during inlining.\n *  Presume table size is a multiple of ZSTD_ROWSIZE\n *  to help auto-vectorization */\nFORCE_INLINE_TEMPLATE void\nZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerValue, int const preserveMark)\n{\n    int const nbRows = (int)size / ZSTD_ROWSIZE;\n    int cellNb = 0;\n    int rowNb;\n    /* Protect special index values < ZSTD_WINDOW_START_INDEX. */\n    U32 const reducerThreshold = reducerValue + ZSTD_WINDOW_START_INDEX;\n    assert((size & (ZSTD_ROWSIZE-1)) == 0);  /* multiple of ZSTD_ROWSIZE */\n    assert(size < (1U<<31));   /* can be cast to int */\n\n#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)\n    /* To validate that the table reuse logic is sound, and that we don't\n     * access table space that we haven't cleaned, we re-\"poison\" the table\n     * space every time we mark it dirty.\n     *\n     * This function however is intended to operate on those dirty tables and\n     * re-clean them. So when this function is used correctly, we can unpoison\n     * the memory it operated on. This introduces a blind spot though, since\n     * if we now try to operate on __actually__ poisoned memory, we will not\n     * detect that. */\n    __msan_unpoison(table, size * sizeof(U32));\n#endif\n\n    for (rowNb=0 ; rowNb < nbRows ; rowNb++) {\n        int column;\n        for (column=0; column<ZSTD_ROWSIZE; column++) {\n            U32 newVal;\n            if (preserveMark && table[cellNb] == ZSTD_DUBT_UNSORTED_MARK) {\n                /* This write is pointless, but is required(?) for the compiler\n                 * to auto-vectorize the loop. */\n                newVal = ZSTD_DUBT_UNSORTED_MARK;\n            } else if (table[cellNb] < reducerThreshold) {\n                newVal = 0;\n            } else {\n                newVal = table[cellNb] - reducerValue;\n            }\n            table[cellNb] = newVal;\n            cellNb++;\n    }   }\n}\n\nstatic void ZSTD_reduceTable(U32* const table, U32 const size, U32 const reducerValue)\n{\n    ZSTD_reduceTable_internal(table, size, reducerValue, 0);\n}\n\nstatic void ZSTD_reduceTable_btlazy2(U32* const table, U32 const size, U32 const reducerValue)\n{\n    ZSTD_reduceTable_internal(table, size, reducerValue, 1);\n}\n\n/*! ZSTD_reduceIndex() :\n*   rescale all indexes to avoid future overflow (indexes are U32) */\nstatic void ZSTD_reduceIndex (ZSTD_MatchState_t* ms, ZSTD_CCtx_params const* params, const U32 reducerValue)\n{\n    {   U32 const hSize = (U32)1 << params->cParams.hashLog;\n        ZSTD_reduceTable(ms->hashTable, hSize, reducerValue);\n    }\n\n    if (ZSTD_allocateChainTable(params->cParams.strategy, params->useRowMatchFinder, (U32)ms->dedicatedDictSearch)) {\n        U32 const chainSize = (U32)1 << params->cParams.chainLog;\n        if (params->cParams.strategy == ZSTD_btlazy2)\n            ZSTD_reduceTable_btlazy2(ms->chainTable, chainSize, reducerValue);\n        else\n            ZSTD_reduceTable(ms->chainTable, chainSize, reducerValue);\n    }\n\n    if (ms->hashLog3) {\n        U32 const h3Size = (U32)1 << ms->hashLog3;\n        ZSTD_reduceTable(ms->hashTable3, h3Size, reducerValue);\n    }\n}\n\n\n/*-*******************************************************\n*  Block entropic compression\n*********************************************************/\n\n/* See doc/zstd_compression_format.md for detailed format description */\n\nint ZSTD_seqToCodes(const SeqStore_t* seqStorePtr)\n{\n    const SeqDef* const sequences = seqStorePtr->sequencesStart;\n    BYTE* const llCodeTable = seqStorePtr->llCode;\n    BYTE* const ofCodeTable = seqStorePtr->ofCode;\n    BYTE* const mlCodeTable = seqStorePtr->mlCode;\n    U32 const nbSeq = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);\n    U32 u;\n    int longOffsets = 0;\n    assert(nbSeq <= seqStorePtr->maxNbSeq);\n    for (u=0; u<nbSeq; u++) {\n        U32 const llv = sequences[u].litLength;\n        U32 const ofCode = ZSTD_highbit32(sequences[u].offBase);\n        U32 const mlv = sequences[u].mlBase;\n        llCodeTable[u] = (BYTE)ZSTD_LLcode(llv);\n        ofCodeTable[u] = (BYTE)ofCode;\n        mlCodeTable[u] = (BYTE)ZSTD_MLcode(mlv);\n        assert(!(MEM_64bits() && ofCode >= STREAM_ACCUMULATOR_MIN));\n        if (MEM_32bits() && ofCode >= STREAM_ACCUMULATOR_MIN)\n            longOffsets = 1;\n    }\n    if (seqStorePtr->longLengthType==ZSTD_llt_literalLength)\n        llCodeTable[seqStorePtr->longLengthPos] = MaxLL;\n    if (seqStorePtr->longLengthType==ZSTD_llt_matchLength)\n        mlCodeTable[seqStorePtr->longLengthPos] = MaxML;\n    return longOffsets;\n}\n\n/* ZSTD_useTargetCBlockSize():\n * Returns if target compressed block size param is being used.\n * If used, compression will do best effort to make a compressed block size to be around targetCBlockSize.\n * Returns 1 if true, 0 otherwise. */\nstatic int ZSTD_useTargetCBlockSize(const ZSTD_CCtx_params* cctxParams)\n{\n    DEBUGLOG(5, \"ZSTD_useTargetCBlockSize (targetCBlockSize=%zu)\", cctxParams->targetCBlockSize);\n    return (cctxParams->targetCBlockSize != 0);\n}\n\n/* ZSTD_blockSplitterEnabled():\n * Returns if block splitting param is being used\n * If used, compression will do best effort to split a block in order to improve compression ratio.\n * At the time this function is called, the parameter must be finalized.\n * Returns 1 if true, 0 otherwise. */\nstatic int ZSTD_blockSplitterEnabled(ZSTD_CCtx_params* cctxParams)\n{\n    DEBUGLOG(5, \"ZSTD_blockSplitterEnabled (postBlockSplitter=%d)\", cctxParams->postBlockSplitter);\n    assert(cctxParams->postBlockSplitter != ZSTD_ps_auto);\n    return (cctxParams->postBlockSplitter == ZSTD_ps_enable);\n}\n\n/* Type returned by ZSTD_buildSequencesStatistics containing finalized symbol encoding types\n * and size of the sequences statistics\n */\ntypedef struct {\n    U32 LLtype;\n    U32 Offtype;\n    U32 MLtype;\n    size_t size;\n    size_t lastCountSize; /* Accounts for bug in 1.3.4. More detail in ZSTD_entropyCompressSeqStore_internal() */\n    int longOffsets;\n} ZSTD_symbolEncodingTypeStats_t;\n\n/* ZSTD_buildSequencesStatistics():\n * Returns a ZSTD_symbolEncodingTypeStats_t, or a zstd error code in the `size` field.\n * Modifies `nextEntropy` to have the appropriate values as a side effect.\n * nbSeq must be greater than 0.\n *\n * entropyWkspSize must be of size at least ENTROPY_WORKSPACE_SIZE - (MaxSeq + 1)*sizeof(U32)\n */\nstatic ZSTD_symbolEncodingTypeStats_t\nZSTD_buildSequencesStatistics(\n                const SeqStore_t* seqStorePtr, size_t nbSeq,\n                const ZSTD_fseCTables_t* prevEntropy, ZSTD_fseCTables_t* nextEntropy,\n                      BYTE* dst, const BYTE* const dstEnd,\n                      ZSTD_strategy strategy, unsigned* countWorkspace,\n                      void* entropyWorkspace, size_t entropyWkspSize)\n{\n    BYTE* const ostart = dst;\n    const BYTE* const oend = dstEnd;\n    BYTE* op = ostart;\n    FSE_CTable* CTable_LitLength = nextEntropy->litlengthCTable;\n    FSE_CTable* CTable_OffsetBits = nextEntropy->offcodeCTable;\n    FSE_CTable* CTable_MatchLength = nextEntropy->matchlengthCTable;\n    const BYTE* const ofCodeTable = seqStorePtr->ofCode;\n    const BYTE* const llCodeTable = seqStorePtr->llCode;\n    const BYTE* const mlCodeTable = seqStorePtr->mlCode;\n    ZSTD_symbolEncodingTypeStats_t stats;\n\n    stats.lastCountSize = 0;\n    /* convert length/distances into codes */\n    stats.longOffsets = ZSTD_seqToCodes(seqStorePtr);\n    assert(op <= oend);\n    assert(nbSeq != 0); /* ZSTD_selectEncodingType() divides by nbSeq */\n    /* build CTable for Literal Lengths */\n    {   unsigned max = MaxLL;\n        size_t const mostFrequent = HIST_countFast_wksp(countWorkspace, &max, llCodeTable, nbSeq, entropyWorkspace, entropyWkspSize);   /* can't fail */\n        DEBUGLOG(5, \"Building LL table\");\n        nextEntropy->litlength_repeatMode = prevEntropy->litlength_repeatMode;\n        stats.LLtype = ZSTD_selectEncodingType(&nextEntropy->litlength_repeatMode,\n                                        countWorkspace, max, mostFrequent, nbSeq,\n                                        LLFSELog, prevEntropy->litlengthCTable,\n                                        LL_defaultNorm, LL_defaultNormLog,\n                                        ZSTD_defaultAllowed, strategy);\n        assert(set_basic < set_compressed && set_rle < set_compressed);\n        assert(!(stats.LLtype < set_compressed && nextEntropy->litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */\n        {   size_t const countSize = ZSTD_buildCTable(\n                op, (size_t)(oend - op),\n                CTable_LitLength, LLFSELog, (SymbolEncodingType_e)stats.LLtype,\n                countWorkspace, max, llCodeTable, nbSeq,\n                LL_defaultNorm, LL_defaultNormLog, MaxLL,\n                prevEntropy->litlengthCTable,\n                sizeof(prevEntropy->litlengthCTable),\n                entropyWorkspace, entropyWkspSize);\n            if (ZSTD_isError(countSize)) {\n                DEBUGLOG(3, \"ZSTD_buildCTable for LitLens failed\");\n                stats.size = countSize;\n                return stats;\n            }\n            if (stats.LLtype == set_compressed)\n                stats.lastCountSize = countSize;\n            op += countSize;\n            assert(op <= oend);\n    }   }\n    /* build CTable for Offsets */\n    {   unsigned max = MaxOff;\n        size_t const mostFrequent = HIST_countFast_wksp(\n            countWorkspace, &max, ofCodeTable, nbSeq, entropyWorkspace, entropyWkspSize);  /* can't fail */\n        /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */\n        ZSTD_DefaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;\n        DEBUGLOG(5, \"Building OF table\");\n        nextEntropy->offcode_repeatMode = prevEntropy->offcode_repeatMode;\n        stats.Offtype = ZSTD_selectEncodingType(&nextEntropy->offcode_repeatMode,\n                                        countWorkspace, max, mostFrequent, nbSeq,\n                                        OffFSELog, prevEntropy->offcodeCTable,\n                                        OF_defaultNorm, OF_defaultNormLog,\n                                        defaultPolicy, strategy);\n        assert(!(stats.Offtype < set_compressed && nextEntropy->offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */\n        {   size_t const countSize = ZSTD_buildCTable(\n                op, (size_t)(oend - op),\n                CTable_OffsetBits, OffFSELog, (SymbolEncodingType_e)stats.Offtype,\n                countWorkspace, max, ofCodeTable, nbSeq,\n                OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,\n                prevEntropy->offcodeCTable,\n                sizeof(prevEntropy->offcodeCTable),\n                entropyWorkspace, entropyWkspSize);\n            if (ZSTD_isError(countSize)) {\n                DEBUGLOG(3, \"ZSTD_buildCTable for Offsets failed\");\n                stats.size = countSize;\n                return stats;\n            }\n            if (stats.Offtype == set_compressed)\n                stats.lastCountSize = countSize;\n            op += countSize;\n            assert(op <= oend);\n    }   }\n    /* build CTable for MatchLengths */\n    {   unsigned max = MaxML;\n        size_t const mostFrequent = HIST_countFast_wksp(\n            countWorkspace, &max, mlCodeTable, nbSeq, entropyWorkspace, entropyWkspSize);   /* can't fail */\n        DEBUGLOG(5, \"Building ML table (remaining space : %i)\", (int)(oend-op));\n        nextEntropy->matchlength_repeatMode = prevEntropy->matchlength_repeatMode;\n        stats.MLtype = ZSTD_selectEncodingType(&nextEntropy->matchlength_repeatMode,\n                                        countWorkspace, max, mostFrequent, nbSeq,\n                                        MLFSELog, prevEntropy->matchlengthCTable,\n                                        ML_defaultNorm, ML_defaultNormLog,\n                                        ZSTD_defaultAllowed, strategy);\n        assert(!(stats.MLtype < set_compressed && nextEntropy->matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */\n        {   size_t const countSize = ZSTD_buildCTable(\n                op, (size_t)(oend - op),\n                CTable_MatchLength, MLFSELog, (SymbolEncodingType_e)stats.MLtype,\n                countWorkspace, max, mlCodeTable, nbSeq,\n                ML_defaultNorm, ML_defaultNormLog, MaxML,\n                prevEntropy->matchlengthCTable,\n                sizeof(prevEntropy->matchlengthCTable),\n                entropyWorkspace, entropyWkspSize);\n            if (ZSTD_isError(countSize)) {\n                DEBUGLOG(3, \"ZSTD_buildCTable for MatchLengths failed\");\n                stats.size = countSize;\n                return stats;\n            }\n            if (stats.MLtype == set_compressed)\n                stats.lastCountSize = countSize;\n            op += countSize;\n            assert(op <= oend);\n    }   }\n    stats.size = (size_t)(op-ostart);\n    return stats;\n}\n\n/* ZSTD_entropyCompressSeqStore_internal():\n * compresses both literals and sequences\n * Returns compressed size of block, or a zstd error.\n */\n#define SUSPECT_UNCOMPRESSIBLE_LITERAL_RATIO 20\nMEM_STATIC size_t\nZSTD_entropyCompressSeqStore_internal(\n                              void* dst, size_t dstCapacity,\n                        const void* literals, size_t litSize,\n                        const SeqStore_t* seqStorePtr,\n                        const ZSTD_entropyCTables_t* prevEntropy,\n                              ZSTD_entropyCTables_t* nextEntropy,\n                        const ZSTD_CCtx_params* cctxParams,\n                              void* entropyWorkspace, size_t entropyWkspSize,\n                        const int bmi2)\n{\n    ZSTD_strategy const strategy = cctxParams->cParams.strategy;\n    unsigned* count = (unsigned*)entropyWorkspace;\n    FSE_CTable* CTable_LitLength = nextEntropy->fse.litlengthCTable;\n    FSE_CTable* CTable_OffsetBits = nextEntropy->fse.offcodeCTable;\n    FSE_CTable* CTable_MatchLength = nextEntropy->fse.matchlengthCTable;\n    const SeqDef* const sequences = seqStorePtr->sequencesStart;\n    const size_t nbSeq = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart);\n    const BYTE* const ofCodeTable = seqStorePtr->ofCode;\n    const BYTE* const llCodeTable = seqStorePtr->llCode;\n    const BYTE* const mlCodeTable = seqStorePtr->mlCode;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = ostart + dstCapacity;\n    BYTE* op = ostart;\n    size_t lastCountSize;\n    int longOffsets = 0;\n\n    entropyWorkspace = count + (MaxSeq + 1);\n    entropyWkspSize -= (MaxSeq + 1) * sizeof(*count);\n\n    DEBUGLOG(5, \"ZSTD_entropyCompressSeqStore_internal (nbSeq=%zu, dstCapacity=%zu)\", nbSeq, dstCapacity);\n    ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));\n    assert(entropyWkspSize >= HUF_WORKSPACE_SIZE);\n\n    /* Compress literals */\n    {   size_t const numSequences = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart);\n        /* Base suspicion of uncompressibility on ratio of literals to sequences */\n        int const suspectUncompressible = (numSequences == 0) || (litSize / numSequences >= SUSPECT_UNCOMPRESSIBLE_LITERAL_RATIO);\n\n        size_t const cSize = ZSTD_compressLiterals(\n                                    op, dstCapacity,\n                                    literals, litSize,\n                                    entropyWorkspace, entropyWkspSize,\n                                    &prevEntropy->huf, &nextEntropy->huf,\n                                    cctxParams->cParams.strategy,\n                                    ZSTD_literalsCompressionIsDisabled(cctxParams),\n                                    suspectUncompressible, bmi2);\n        FORWARD_IF_ERROR(cSize, \"ZSTD_compressLiterals failed\");\n        assert(cSize <= dstCapacity);\n        op += cSize;\n    }\n\n    /* Sequences Header */\n    RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/,\n                    dstSize_tooSmall, \"Can't fit seq hdr in output buf!\");\n    if (nbSeq < 128) {\n        *op++ = (BYTE)nbSeq;\n    } else if (nbSeq < LONGNBSEQ) {\n        op[0] = (BYTE)((nbSeq>>8) + 0x80);\n        op[1] = (BYTE)nbSeq;\n        op+=2;\n    } else {\n        op[0]=0xFF;\n        MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ));\n        op+=3;\n    }\n    assert(op <= oend);\n    if (nbSeq==0) {\n        /* Copy the old tables over as if we repeated them */\n        ZSTD_memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse));\n        return (size_t)(op - ostart);\n    }\n    {   BYTE* const seqHead = op++;\n        /* build stats for sequences */\n        const ZSTD_symbolEncodingTypeStats_t stats =\n                ZSTD_buildSequencesStatistics(seqStorePtr, nbSeq,\n                                             &prevEntropy->fse, &nextEntropy->fse,\n                                              op, oend,\n                                              strategy, count,\n                                              entropyWorkspace, entropyWkspSize);\n        FORWARD_IF_ERROR(stats.size, \"ZSTD_buildSequencesStatistics failed!\");\n        *seqHead = (BYTE)((stats.LLtype<<6) + (stats.Offtype<<4) + (stats.MLtype<<2));\n        lastCountSize = stats.lastCountSize;\n        op += stats.size;\n        longOffsets = stats.longOffsets;\n    }\n\n    {   size_t const bitstreamSize = ZSTD_encodeSequences(\n                                        op, (size_t)(oend - op),\n                                        CTable_MatchLength, mlCodeTable,\n                                        CTable_OffsetBits, ofCodeTable,\n                                        CTable_LitLength, llCodeTable,\n                                        sequences, nbSeq,\n                                        longOffsets, bmi2);\n        FORWARD_IF_ERROR(bitstreamSize, \"ZSTD_encodeSequences failed\");\n        op += bitstreamSize;\n        assert(op <= oend);\n        /* zstd versions <= 1.3.4 mistakenly report corruption when\n         * FSE_readNCount() receives a buffer < 4 bytes.\n         * Fixed by https://github.com/facebook/zstd/pull/1146.\n         * This can happen when the last set_compressed table present is 2\n         * bytes and the bitstream is only one byte.\n         * In this exceedingly rare case, we will simply emit an uncompressed\n         * block, since it isn't worth optimizing.\n         */\n        if (lastCountSize && (lastCountSize + bitstreamSize) < 4) {\n            /* lastCountSize >= 2 && bitstreamSize > 0 ==> lastCountSize == 3 */\n            assert(lastCountSize + bitstreamSize == 3);\n            DEBUGLOG(5, \"Avoiding bug in zstd decoder in versions <= 1.3.4 by \"\n                        \"emitting an uncompressed block.\");\n            return 0;\n        }\n    }\n\n    DEBUGLOG(5, \"compressed block size : %u\", (unsigned)(op - ostart));\n    return (size_t)(op - ostart);\n}\n\nstatic size_t\nZSTD_entropyCompressSeqStore_wExtLitBuffer(\n                          void* dst, size_t dstCapacity,\n                    const void* literals, size_t litSize,\n                          size_t blockSize,\n                    const SeqStore_t* seqStorePtr,\n                    const ZSTD_entropyCTables_t* prevEntropy,\n                          ZSTD_entropyCTables_t* nextEntropy,\n                    const ZSTD_CCtx_params* cctxParams,\n                          void* entropyWorkspace, size_t entropyWkspSize,\n                          int bmi2)\n{\n    size_t const cSize = ZSTD_entropyCompressSeqStore_internal(\n                            dst, dstCapacity,\n                            literals, litSize,\n                            seqStorePtr, prevEntropy, nextEntropy, cctxParams,\n                            entropyWorkspace, entropyWkspSize, bmi2);\n    if (cSize == 0) return 0;\n    /* When srcSize <= dstCapacity, there is enough space to write a raw uncompressed block.\n     * Since we ran out of space, block must be not compressible, so fall back to raw uncompressed block.\n     */\n    if ((cSize == ERROR(dstSize_tooSmall)) & (blockSize <= dstCapacity)) {\n        DEBUGLOG(4, \"not enough dstCapacity (%zu) for ZSTD_entropyCompressSeqStore_internal()=> do not compress block\", dstCapacity);\n        return 0;  /* block not compressed */\n    }\n    FORWARD_IF_ERROR(cSize, \"ZSTD_entropyCompressSeqStore_internal failed\");\n\n    /* Check compressibility */\n    {   size_t const maxCSize = blockSize - ZSTD_minGain(blockSize, cctxParams->cParams.strategy);\n        if (cSize >= maxCSize) return 0;  /* block not compressed */\n    }\n    DEBUGLOG(5, \"ZSTD_entropyCompressSeqStore() cSize: %zu\", cSize);\n    /* libzstd decoder before  > v1.5.4 is not compatible with compressed blocks of size ZSTD_BLOCKSIZE_MAX exactly.\n     * This restriction is indirectly already fulfilled by respecting ZSTD_minGain() condition above.\n     */\n    assert(cSize < ZSTD_BLOCKSIZE_MAX);\n    return cSize;\n}\n\nstatic size_t\nZSTD_entropyCompressSeqStore(\n                    const SeqStore_t* seqStorePtr,\n                    const ZSTD_entropyCTables_t* prevEntropy,\n                          ZSTD_entropyCTables_t* nextEntropy,\n                    const ZSTD_CCtx_params* cctxParams,\n                          void* dst, size_t dstCapacity,\n                          size_t srcSize,\n                          void* entropyWorkspace, size_t entropyWkspSize,\n                          int bmi2)\n{\n    return ZSTD_entropyCompressSeqStore_wExtLitBuffer(\n                dst, dstCapacity,\n                seqStorePtr->litStart, (size_t)(seqStorePtr->lit - seqStorePtr->litStart),\n                srcSize,\n                seqStorePtr,\n                prevEntropy, nextEntropy,\n                cctxParams,\n                entropyWorkspace, entropyWkspSize,\n                bmi2);\n}\n\n/* ZSTD_selectBlockCompressor() :\n * Not static, but internal use only (used by long distance matcher)\n * assumption : strat is a valid strategy */\nZSTD_BlockCompressor_f ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_ParamSwitch_e useRowMatchFinder, ZSTD_dictMode_e dictMode)\n{\n    static const ZSTD_BlockCompressor_f blockCompressor[4][ZSTD_STRATEGY_MAX+1] = {\n        { ZSTD_compressBlock_fast  /* default for 0 */,\n          ZSTD_compressBlock_fast,\n          ZSTD_COMPRESSBLOCK_DOUBLEFAST,\n          ZSTD_COMPRESSBLOCK_GREEDY,\n          ZSTD_COMPRESSBLOCK_LAZY,\n          ZSTD_COMPRESSBLOCK_LAZY2,\n          ZSTD_COMPRESSBLOCK_BTLAZY2,\n          ZSTD_COMPRESSBLOCK_BTOPT,\n          ZSTD_COMPRESSBLOCK_BTULTRA,\n          ZSTD_COMPRESSBLOCK_BTULTRA2\n        },\n        { ZSTD_compressBlock_fast_extDict  /* default for 0 */,\n          ZSTD_compressBlock_fast_extDict,\n          ZSTD_COMPRESSBLOCK_DOUBLEFAST_EXTDICT,\n          ZSTD_COMPRESSBLOCK_GREEDY_EXTDICT,\n          ZSTD_COMPRESSBLOCK_LAZY_EXTDICT,\n          ZSTD_COMPRESSBLOCK_LAZY2_EXTDICT,\n          ZSTD_COMPRESSBLOCK_BTLAZY2_EXTDICT,\n          ZSTD_COMPRESSBLOCK_BTOPT_EXTDICT,\n          ZSTD_COMPRESSBLOCK_BTULTRA_EXTDICT,\n          ZSTD_COMPRESSBLOCK_BTULTRA_EXTDICT\n        },\n        { ZSTD_compressBlock_fast_dictMatchState  /* default for 0 */,\n          ZSTD_compressBlock_fast_dictMatchState,\n          ZSTD_COMPRESSBLOCK_DOUBLEFAST_DICTMATCHSTATE,\n          ZSTD_COMPRESSBLOCK_GREEDY_DICTMATCHSTATE,\n          ZSTD_COMPRESSBLOCK_LAZY_DICTMATCHSTATE,\n          ZSTD_COMPRESSBLOCK_LAZY2_DICTMATCHSTATE,\n          ZSTD_COMPRESSBLOCK_BTLAZY2_DICTMATCHSTATE,\n          ZSTD_COMPRESSBLOCK_BTOPT_DICTMATCHSTATE,\n          ZSTD_COMPRESSBLOCK_BTULTRA_DICTMATCHSTATE,\n          ZSTD_COMPRESSBLOCK_BTULTRA_DICTMATCHSTATE\n        },\n        { NULL  /* default for 0 */,\n          NULL,\n          NULL,\n          ZSTD_COMPRESSBLOCK_GREEDY_DEDICATEDDICTSEARCH,\n          ZSTD_COMPRESSBLOCK_LAZY_DEDICATEDDICTSEARCH,\n          ZSTD_COMPRESSBLOCK_LAZY2_DEDICATEDDICTSEARCH,\n          NULL,\n          NULL,\n          NULL,\n          NULL }\n    };\n    ZSTD_BlockCompressor_f selectedCompressor;\n    ZSTD_STATIC_ASSERT((unsigned)ZSTD_fast == 1);\n\n    assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, (int)strat));\n    DEBUGLOG(5, \"Selected block compressor: dictMode=%d strat=%d rowMatchfinder=%d\", (int)dictMode, (int)strat, (int)useRowMatchFinder);\n    if (ZSTD_rowMatchFinderUsed(strat, useRowMatchFinder)) {\n        static const ZSTD_BlockCompressor_f rowBasedBlockCompressors[4][3] = {\n            {\n                ZSTD_COMPRESSBLOCK_GREEDY_ROW,\n                ZSTD_COMPRESSBLOCK_LAZY_ROW,\n                ZSTD_COMPRESSBLOCK_LAZY2_ROW\n            },\n            {\n                ZSTD_COMPRESSBLOCK_GREEDY_EXTDICT_ROW,\n                ZSTD_COMPRESSBLOCK_LAZY_EXTDICT_ROW,\n                ZSTD_COMPRESSBLOCK_LAZY2_EXTDICT_ROW\n            },\n            {\n                ZSTD_COMPRESSBLOCK_GREEDY_DICTMATCHSTATE_ROW,\n                ZSTD_COMPRESSBLOCK_LAZY_DICTMATCHSTATE_ROW,\n                ZSTD_COMPRESSBLOCK_LAZY2_DICTMATCHSTATE_ROW\n            },\n            {\n                ZSTD_COMPRESSBLOCK_GREEDY_DEDICATEDDICTSEARCH_ROW,\n                ZSTD_COMPRESSBLOCK_LAZY_DEDICATEDDICTSEARCH_ROW,\n                ZSTD_COMPRESSBLOCK_LAZY2_DEDICATEDDICTSEARCH_ROW\n            }\n        };\n        DEBUGLOG(5, \"Selecting a row-based matchfinder\");\n        assert(useRowMatchFinder != ZSTD_ps_auto);\n        selectedCompressor = rowBasedBlockCompressors[(int)dictMode][(int)strat - (int)ZSTD_greedy];\n    } else {\n        selectedCompressor = blockCompressor[(int)dictMode][(int)strat];\n    }\n    assert(selectedCompressor != NULL);\n    return selectedCompressor;\n}\n\nstatic void ZSTD_storeLastLiterals(SeqStore_t* seqStorePtr,\n                                   const BYTE* anchor, size_t lastLLSize)\n{\n    ZSTD_memcpy(seqStorePtr->lit, anchor, lastLLSize);\n    seqStorePtr->lit += lastLLSize;\n}\n\nvoid ZSTD_resetSeqStore(SeqStore_t* ssPtr)\n{\n    ssPtr->lit = ssPtr->litStart;\n    ssPtr->sequences = ssPtr->sequencesStart;\n    ssPtr->longLengthType = ZSTD_llt_none;\n}\n\n/* ZSTD_postProcessSequenceProducerResult() :\n * Validates and post-processes sequences obtained through the external matchfinder API:\n *   - Checks whether nbExternalSeqs represents an error condition.\n *   - Appends a block delimiter to outSeqs if one is not already present.\n *     See zstd.h for context regarding block delimiters.\n * Returns the number of sequences after post-processing, or an error code. */\nstatic size_t ZSTD_postProcessSequenceProducerResult(\n    ZSTD_Sequence* outSeqs, size_t nbExternalSeqs, size_t outSeqsCapacity, size_t srcSize\n) {\n    RETURN_ERROR_IF(\n        nbExternalSeqs > outSeqsCapacity,\n        sequenceProducer_failed,\n        \"External sequence producer returned error code %lu\",\n        (unsigned long)nbExternalSeqs\n    );\n\n    RETURN_ERROR_IF(\n        nbExternalSeqs == 0 && srcSize > 0,\n        sequenceProducer_failed,\n        \"Got zero sequences from external sequence producer for a non-empty src buffer!\"\n    );\n\n    if (srcSize == 0) {\n        ZSTD_memset(&outSeqs[0], 0, sizeof(ZSTD_Sequence));\n        return 1;\n    }\n\n    {\n        ZSTD_Sequence const lastSeq = outSeqs[nbExternalSeqs - 1];\n\n        /* We can return early if lastSeq is already a block delimiter. */\n        if (lastSeq.offset == 0 && lastSeq.matchLength == 0) {\n            return nbExternalSeqs;\n        }\n\n        /* This error condition is only possible if the external matchfinder\n         * produced an invalid parse, by definition of ZSTD_sequenceBound(). */\n        RETURN_ERROR_IF(\n            nbExternalSeqs == outSeqsCapacity,\n            sequenceProducer_failed,\n            \"nbExternalSeqs == outSeqsCapacity but lastSeq is not a block delimiter!\"\n        );\n\n        /* lastSeq is not a block delimiter, so we need to append one. */\n        ZSTD_memset(&outSeqs[nbExternalSeqs], 0, sizeof(ZSTD_Sequence));\n        return nbExternalSeqs + 1;\n    }\n}\n\n/* ZSTD_fastSequenceLengthSum() :\n * Returns sum(litLen) + sum(matchLen) + lastLits for *seqBuf*.\n * Similar to another function in zstd_compress.c (determine_blockSize),\n * except it doesn't check for a block delimiter to end summation.\n * Removing the early exit allows the compiler to auto-vectorize (https://godbolt.org/z/cY1cajz9P).\n * This function can be deleted and replaced by determine_blockSize after we resolve issue #3456. */\nstatic size_t ZSTD_fastSequenceLengthSum(ZSTD_Sequence const* seqBuf, size_t seqBufSize) {\n    size_t matchLenSum, litLenSum, i;\n    matchLenSum = 0;\n    litLenSum = 0;\n    for (i = 0; i < seqBufSize; i++) {\n        litLenSum += seqBuf[i].litLength;\n        matchLenSum += seqBuf[i].matchLength;\n    }\n    return litLenSum + matchLenSum;\n}\n\n/**\n * Function to validate sequences produced by a block compressor.\n */\nstatic void ZSTD_validateSeqStore(const SeqStore_t* seqStore, const ZSTD_compressionParameters* cParams)\n{\n#if DEBUGLEVEL >= 1\n    const SeqDef* seq = seqStore->sequencesStart;\n    const SeqDef* const seqEnd = seqStore->sequences;\n    size_t const matchLenLowerBound = cParams->minMatch == 3 ? 3 : 4;\n    for (; seq < seqEnd; ++seq) {\n        const ZSTD_SequenceLength seqLength = ZSTD_getSequenceLength(seqStore, seq);\n        assert(seqLength.matchLength >= matchLenLowerBound);\n        (void)seqLength;\n        (void)matchLenLowerBound;\n    }\n#else\n    (void)seqStore;\n    (void)cParams;\n#endif\n}\n\nstatic size_t\nZSTD_transferSequences_wBlockDelim(ZSTD_CCtx* cctx,\n                                   ZSTD_SequencePosition* seqPos,\n                             const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,\n                             const void* src, size_t blockSize,\n                                   ZSTD_ParamSwitch_e externalRepSearch);\n\ntypedef enum { ZSTDbss_compress, ZSTDbss_noCompress } ZSTD_BuildSeqStore_e;\n\nstatic size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)\n{\n    ZSTD_MatchState_t* const ms = &zc->blockState.matchState;\n    DEBUGLOG(5, \"ZSTD_buildSeqStore (srcSize=%zu)\", srcSize);\n    assert(srcSize <= ZSTD_BLOCKSIZE_MAX);\n    /* Assert that we have correctly flushed the ctx params into the ms's copy */\n    ZSTD_assertEqualCParams(zc->appliedParams.cParams, ms->cParams);\n    /* TODO: See 3090. We reduced MIN_CBLOCK_SIZE from 3 to 2 so to compensate we are adding\n     * additional 1. We need to revisit and change this logic to be more consistent */\n    if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1+1) {\n        if (zc->appliedParams.cParams.strategy >= ZSTD_btopt) {\n            ZSTD_ldm_skipRawSeqStoreBytes(&zc->externSeqStore, srcSize);\n        } else {\n            ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.minMatch);\n        }\n        return ZSTDbss_noCompress; /* don't even attempt compression below a certain srcSize */\n    }\n    ZSTD_resetSeqStore(&(zc->seqStore));\n    /* required for optimal parser to read stats from dictionary */\n    ms->opt.symbolCosts = &zc->blockState.prevCBlock->entropy;\n    /* tell the optimal parser how we expect to compress literals */\n    ms->opt.literalCompressionMode = zc->appliedParams.literalCompressionMode;\n    /* a gap between an attached dict and the current window is not safe,\n     * they must remain adjacent,\n     * and when that stops being the case, the dict must be unset */\n    assert(ms->dictMatchState == NULL || ms->loadedDictEnd == ms->window.dictLimit);\n\n    /* limited update after a very long match */\n    {   const BYTE* const base = ms->window.base;\n        const BYTE* const istart = (const BYTE*)src;\n        const U32 curr = (U32)(istart-base);\n        if (sizeof(ptrdiff_t)==8) assert(istart - base < (ptrdiff_t)(U32)(-1));   /* ensure no overflow */\n        if (curr > ms->nextToUpdate + 384)\n            ms->nextToUpdate = curr - MIN(192, (U32)(curr - ms->nextToUpdate - 384));\n    }\n\n    /* select and store sequences */\n    {   ZSTD_dictMode_e const dictMode = ZSTD_matchState_dictMode(ms);\n        size_t lastLLSize;\n        {   int i;\n            for (i = 0; i < ZSTD_REP_NUM; ++i)\n                zc->blockState.nextCBlock->rep[i] = zc->blockState.prevCBlock->rep[i];\n        }\n        if (zc->externSeqStore.pos < zc->externSeqStore.size) {\n            assert(zc->appliedParams.ldmParams.enableLdm == ZSTD_ps_disable);\n\n            /* External matchfinder + LDM is technically possible, just not implemented yet.\n             * We need to revisit soon and implement it. */\n            RETURN_ERROR_IF(\n                ZSTD_hasExtSeqProd(&zc->appliedParams),\n                parameter_combination_unsupported,\n                \"Long-distance matching with external sequence producer enabled is not currently supported.\"\n            );\n\n            /* Updates ldmSeqStore.pos */\n            lastLLSize =\n                ZSTD_ldm_blockCompress(&zc->externSeqStore,\n                                       ms, &zc->seqStore,\n                                       zc->blockState.nextCBlock->rep,\n                                       zc->appliedParams.useRowMatchFinder,\n                                       src, srcSize);\n            assert(zc->externSeqStore.pos <= zc->externSeqStore.size);\n        } else if (zc->appliedParams.ldmParams.enableLdm == ZSTD_ps_enable) {\n            RawSeqStore_t ldmSeqStore = kNullRawSeqStore;\n\n            /* External matchfinder + LDM is technically possible, just not implemented yet.\n             * We need to revisit soon and implement it. */\n            RETURN_ERROR_IF(\n                ZSTD_hasExtSeqProd(&zc->appliedParams),\n                parameter_combination_unsupported,\n                \"Long-distance matching with external sequence producer enabled is not currently supported.\"\n            );\n\n            ldmSeqStore.seq = zc->ldmSequences;\n            ldmSeqStore.capacity = zc->maxNbLdmSequences;\n            /* Updates ldmSeqStore.size */\n            FORWARD_IF_ERROR(ZSTD_ldm_generateSequences(&zc->ldmState, &ldmSeqStore,\n                                               &zc->appliedParams.ldmParams,\n                                               src, srcSize), \"\");\n            /* Updates ldmSeqStore.pos */\n            lastLLSize =\n                ZSTD_ldm_blockCompress(&ldmSeqStore,\n                                       ms, &zc->seqStore,\n                                       zc->blockState.nextCBlock->rep,\n                                       zc->appliedParams.useRowMatchFinder,\n                                       src, srcSize);\n            assert(ldmSeqStore.pos == ldmSeqStore.size);\n        } else if (ZSTD_hasExtSeqProd(&zc->appliedParams)) {\n            assert(\n                zc->extSeqBufCapacity >= ZSTD_sequenceBound(srcSize)\n            );\n            assert(zc->appliedParams.extSeqProdFunc != NULL);\n\n            {   U32 const windowSize = (U32)1 << zc->appliedParams.cParams.windowLog;\n\n                size_t const nbExternalSeqs = (zc->appliedParams.extSeqProdFunc)(\n                    zc->appliedParams.extSeqProdState,\n                    zc->extSeqBuf,\n                    zc->extSeqBufCapacity,\n                    src, srcSize,\n                    NULL, 0,  /* dict and dictSize, currently not supported */\n                    zc->appliedParams.compressionLevel,\n                    windowSize\n                );\n\n                size_t const nbPostProcessedSeqs = ZSTD_postProcessSequenceProducerResult(\n                    zc->extSeqBuf,\n                    nbExternalSeqs,\n                    zc->extSeqBufCapacity,\n                    srcSize\n                );\n\n                /* Return early if there is no error, since we don't need to worry about last literals */\n                if (!ZSTD_isError(nbPostProcessedSeqs)) {\n                    ZSTD_SequencePosition seqPos = {0,0,0};\n                    size_t const seqLenSum = ZSTD_fastSequenceLengthSum(zc->extSeqBuf, nbPostProcessedSeqs);\n                    RETURN_ERROR_IF(seqLenSum > srcSize, externalSequences_invalid, \"External sequences imply too large a block!\");\n                    FORWARD_IF_ERROR(\n                        ZSTD_transferSequences_wBlockDelim(\n                            zc, &seqPos,\n                            zc->extSeqBuf, nbPostProcessedSeqs,\n                            src, srcSize,\n                            zc->appliedParams.searchForExternalRepcodes\n                        ),\n                        \"Failed to copy external sequences to seqStore!\"\n                    );\n                    ms->ldmSeqStore = NULL;\n                    DEBUGLOG(5, \"Copied %lu sequences from external sequence producer to internal seqStore.\", (unsigned long)nbExternalSeqs);\n                    return ZSTDbss_compress;\n                }\n\n                /* Propagate the error if fallback is disabled */\n                if (!zc->appliedParams.enableMatchFinderFallback) {\n                    return nbPostProcessedSeqs;\n                }\n\n                /* Fallback to software matchfinder */\n                {   ZSTD_BlockCompressor_f const blockCompressor =\n                        ZSTD_selectBlockCompressor(\n                            zc->appliedParams.cParams.strategy,\n                            zc->appliedParams.useRowMatchFinder,\n                            dictMode);\n                    ms->ldmSeqStore = NULL;\n                    DEBUGLOG(\n                        5,\n                        \"External sequence producer returned error code %lu. Falling back to internal parser.\",\n                        (unsigned long)nbExternalSeqs\n                    );\n                    lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize);\n            }   }\n        } else {   /* not long range mode and no external matchfinder */\n            ZSTD_BlockCompressor_f const blockCompressor = ZSTD_selectBlockCompressor(\n                    zc->appliedParams.cParams.strategy,\n                    zc->appliedParams.useRowMatchFinder,\n                    dictMode);\n            ms->ldmSeqStore = NULL;\n            lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize);\n        }\n        {   const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize;\n            ZSTD_storeLastLiterals(&zc->seqStore, lastLiterals, lastLLSize);\n    }   }\n    ZSTD_validateSeqStore(&zc->seqStore, &zc->appliedParams.cParams);\n    return ZSTDbss_compress;\n}\n\nstatic size_t ZSTD_copyBlockSequences(SeqCollector* seqCollector, const SeqStore_t* seqStore, const U32 prevRepcodes[ZSTD_REP_NUM])\n{\n    const SeqDef* inSeqs = seqStore->sequencesStart;\n    const size_t nbInSequences = (size_t)(seqStore->sequences - inSeqs);\n    const size_t nbInLiterals = (size_t)(seqStore->lit - seqStore->litStart);\n\n    ZSTD_Sequence* outSeqs = seqCollector->seqIndex == 0 ? seqCollector->seqStart : seqCollector->seqStart + seqCollector->seqIndex;\n    const size_t nbOutSequences = nbInSequences + 1;\n    size_t nbOutLiterals = 0;\n    Repcodes_t repcodes;\n    size_t i;\n\n    /* Bounds check that we have enough space for every input sequence\n     * and the block delimiter\n     */\n    assert(seqCollector->seqIndex <= seqCollector->maxSequences);\n    RETURN_ERROR_IF(\n        nbOutSequences > (size_t)(seqCollector->maxSequences - seqCollector->seqIndex),\n        dstSize_tooSmall,\n        \"Not enough space to copy sequences\");\n\n    ZSTD_memcpy(&repcodes, prevRepcodes, sizeof(repcodes));\n    for (i = 0; i < nbInSequences; ++i) {\n        U32 rawOffset;\n        outSeqs[i].litLength = inSeqs[i].litLength;\n        outSeqs[i].matchLength = inSeqs[i].mlBase + MINMATCH;\n        outSeqs[i].rep = 0;\n\n        /* Handle the possible single length >= 64K\n         * There can only be one because we add MINMATCH to every match length,\n         * and blocks are at most 128K.\n         */\n        if (i == seqStore->longLengthPos) {\n            if (seqStore->longLengthType == ZSTD_llt_literalLength) {\n                outSeqs[i].litLength += 0x10000;\n            } else if (seqStore->longLengthType == ZSTD_llt_matchLength) {\n                outSeqs[i].matchLength += 0x10000;\n            }\n        }\n\n        /* Determine the raw offset given the offBase, which may be a repcode. */\n        if (OFFBASE_IS_REPCODE(inSeqs[i].offBase)) {\n            const U32 repcode = OFFBASE_TO_REPCODE(inSeqs[i].offBase);\n            assert(repcode > 0);\n            outSeqs[i].rep = repcode;\n            if (outSeqs[i].litLength != 0) {\n                rawOffset = repcodes.rep[repcode - 1];\n            } else {\n                if (repcode == 3) {\n                    assert(repcodes.rep[0] > 1);\n                    rawOffset = repcodes.rep[0] - 1;\n                } else {\n                    rawOffset = repcodes.rep[repcode];\n                }\n            }\n        } else {\n            rawOffset = OFFBASE_TO_OFFSET(inSeqs[i].offBase);\n        }\n        outSeqs[i].offset = rawOffset;\n\n        /* Update repcode history for the sequence */\n        ZSTD_updateRep(repcodes.rep,\n                       inSeqs[i].offBase,\n                       inSeqs[i].litLength == 0);\n\n        nbOutLiterals += outSeqs[i].litLength;\n    }\n    /* Insert last literals (if any exist) in the block as a sequence with ml == off == 0.\n     * If there are no last literals, then we'll emit (of: 0, ml: 0, ll: 0), which is a marker\n     * for the block boundary, according to the API.\n     */\n    assert(nbInLiterals >= nbOutLiterals);\n    {\n        const size_t lastLLSize = nbInLiterals - nbOutLiterals;\n        outSeqs[nbInSequences].litLength = (U32)lastLLSize;\n        outSeqs[nbInSequences].matchLength = 0;\n        outSeqs[nbInSequences].offset = 0;\n        assert(nbOutSequences == nbInSequences + 1);\n    }\n    seqCollector->seqIndex += nbOutSequences;\n    assert(seqCollector->seqIndex <= seqCollector->maxSequences);\n\n    return 0;\n}\n\nsize_t ZSTD_sequenceBound(size_t srcSize) {\n    const size_t maxNbSeq = (srcSize / ZSTD_MINMATCH_MIN) + 1;\n    const size_t maxNbDelims = (srcSize / ZSTD_BLOCKSIZE_MAX_MIN) + 1;\n    return maxNbSeq + maxNbDelims;\n}\n\nsize_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,\n                              size_t outSeqsSize, const void* src, size_t srcSize)\n{\n    const size_t dstCapacity = ZSTD_compressBound(srcSize);\n    void* dst; /* Make C90 happy. */\n    SeqCollector seqCollector;\n    {\n        int targetCBlockSize;\n        FORWARD_IF_ERROR(ZSTD_CCtx_getParameter(zc, ZSTD_c_targetCBlockSize, &targetCBlockSize), \"\");\n        RETURN_ERROR_IF(targetCBlockSize != 0, parameter_unsupported, \"targetCBlockSize != 0\");\n    }\n    {\n        int nbWorkers;\n        FORWARD_IF_ERROR(ZSTD_CCtx_getParameter(zc, ZSTD_c_nbWorkers, &nbWorkers), \"\");\n        RETURN_ERROR_IF(nbWorkers != 0, parameter_unsupported, \"nbWorkers != 0\");\n    }\n\n    dst = ZSTD_customMalloc(dstCapacity, ZSTD_defaultCMem);\n    RETURN_ERROR_IF(dst == NULL, memory_allocation, \"NULL pointer!\");\n\n    seqCollector.collectSequences = 1;\n    seqCollector.seqStart = outSeqs;\n    seqCollector.seqIndex = 0;\n    seqCollector.maxSequences = outSeqsSize;\n    zc->seqCollector = seqCollector;\n\n    {\n        const size_t ret = ZSTD_compress2(zc, dst, dstCapacity, src, srcSize);\n        ZSTD_customFree(dst, ZSTD_defaultCMem);\n        FORWARD_IF_ERROR(ret, \"ZSTD_compress2 failed\");\n    }\n    assert(zc->seqCollector.seqIndex <= ZSTD_sequenceBound(srcSize));\n    return zc->seqCollector.seqIndex;\n}\n\nsize_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize) {\n    size_t in = 0;\n    size_t out = 0;\n    for (; in < seqsSize; ++in) {\n        if (sequences[in].offset == 0 && sequences[in].matchLength == 0) {\n            if (in != seqsSize - 1) {\n                sequences[in+1].litLength += sequences[in].litLength;\n            }\n        } else {\n            sequences[out] = sequences[in];\n            ++out;\n        }\n    }\n    return out;\n}\n\n/* Unrolled loop to read four size_ts of input at a time. Returns 1 if is RLE, 0 if not. */\nstatic int ZSTD_isRLE(const BYTE* src, size_t length) {\n    const BYTE* ip = src;\n    const BYTE value = ip[0];\n    const size_t valueST = (size_t)((U64)value * 0x0101010101010101ULL);\n    const size_t unrollSize = sizeof(size_t) * 4;\n    const size_t unrollMask = unrollSize - 1;\n    const size_t prefixLength = length & unrollMask;\n    size_t i;\n    if (length == 1) return 1;\n    /* Check if prefix is RLE first before using unrolled loop */\n    if (prefixLength && ZSTD_count(ip+1, ip, ip+prefixLength) != prefixLength-1) {\n        return 0;\n    }\n    for (i = prefixLength; i != length; i += unrollSize) {\n        size_t u;\n        for (u = 0; u < unrollSize; u += sizeof(size_t)) {\n            if (MEM_readST(ip + i + u) != valueST) {\n                return 0;\n    }   }   }\n    return 1;\n}\n\n/* Returns true if the given block may be RLE.\n * This is just a heuristic based on the compressibility.\n * It may return both false positives and false negatives.\n */\nstatic int ZSTD_maybeRLE(SeqStore_t const* seqStore)\n{\n    size_t const nbSeqs = (size_t)(seqStore->sequences - seqStore->sequencesStart);\n    size_t const nbLits = (size_t)(seqStore->lit - seqStore->litStart);\n\n    return nbSeqs < 4 && nbLits < 10;\n}\n\nstatic void\nZSTD_blockState_confirmRepcodesAndEntropyTables(ZSTD_blockState_t* const bs)\n{\n    ZSTD_compressedBlockState_t* const tmp = bs->prevCBlock;\n    bs->prevCBlock = bs->nextCBlock;\n    bs->nextCBlock = tmp;\n}\n\n/* Writes the block header */\nstatic void\nwriteBlockHeader(void* op, size_t cSize, size_t blockSize, U32 lastBlock)\n{\n    U32 const cBlockHeader = cSize == 1 ?\n                        lastBlock + (((U32)bt_rle)<<1) + (U32)(blockSize << 3) :\n                        lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);\n    MEM_writeLE24(op, cBlockHeader);\n    DEBUGLOG(5, \"writeBlockHeader: cSize: %zu blockSize: %zu lastBlock: %u\", cSize, blockSize, lastBlock);\n}\n\n/** ZSTD_buildBlockEntropyStats_literals() :\n *  Builds entropy for the literals.\n *  Stores literals block type (raw, rle, compressed, repeat) and\n *  huffman description table to hufMetadata.\n *  Requires ENTROPY_WORKSPACE_SIZE workspace\n * @return : size of huffman description table, or an error code\n */\nstatic size_t\nZSTD_buildBlockEntropyStats_literals(void* const src, size_t srcSize,\n                               const ZSTD_hufCTables_t* prevHuf,\n                                     ZSTD_hufCTables_t* nextHuf,\n                                     ZSTD_hufCTablesMetadata_t* hufMetadata,\n                               const int literalsCompressionIsDisabled,\n                                     void* workspace, size_t wkspSize,\n                                     int hufFlags)\n{\n    BYTE* const wkspStart = (BYTE*)workspace;\n    BYTE* const wkspEnd = wkspStart + wkspSize;\n    BYTE* const countWkspStart = wkspStart;\n    unsigned* const countWksp = (unsigned*)workspace;\n    const size_t countWkspSize = (HUF_SYMBOLVALUE_MAX + 1) * sizeof(unsigned);\n    BYTE* const nodeWksp = countWkspStart + countWkspSize;\n    const size_t nodeWkspSize = (size_t)(wkspEnd - nodeWksp);\n    unsigned maxSymbolValue = HUF_SYMBOLVALUE_MAX;\n    unsigned huffLog = LitHufLog;\n    HUF_repeat repeat = prevHuf->repeatMode;\n    DEBUGLOG(5, \"ZSTD_buildBlockEntropyStats_literals (srcSize=%zu)\", srcSize);\n\n    /* Prepare nextEntropy assuming reusing the existing table */\n    ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));\n\n    if (literalsCompressionIsDisabled) {\n        DEBUGLOG(5, \"set_basic - disabled\");\n        hufMetadata->hType = set_basic;\n        return 0;\n    }\n\n    /* small ? don't even attempt compression (speed opt) */\n#ifndef COMPRESS_LITERALS_SIZE_MIN\n# define COMPRESS_LITERALS_SIZE_MIN 63  /* heuristic */\n#endif\n    {   size_t const minLitSize = (prevHuf->repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN;\n        if (srcSize <= minLitSize) {\n            DEBUGLOG(5, \"set_basic - too small\");\n            hufMetadata->hType = set_basic;\n            return 0;\n    }   }\n\n    /* Scan input and build symbol stats */\n    {   size_t const largest =\n            HIST_count_wksp (countWksp, &maxSymbolValue,\n                            (const BYTE*)src, srcSize,\n                            workspace, wkspSize);\n        FORWARD_IF_ERROR(largest, \"HIST_count_wksp failed\");\n        if (largest == srcSize) {\n            /* only one literal symbol */\n            DEBUGLOG(5, \"set_rle\");\n            hufMetadata->hType = set_rle;\n            return 0;\n        }\n        if (largest <= (srcSize >> 7)+4) {\n            /* heuristic: likely not compressible */\n            DEBUGLOG(5, \"set_basic - no gain\");\n            hufMetadata->hType = set_basic;\n            return 0;\n    }   }\n\n    /* Validate the previous Huffman table */\n    if (repeat == HUF_repeat_check\n      && !HUF_validateCTable((HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue)) {\n        repeat = HUF_repeat_none;\n    }\n\n    /* Build Huffman Tree */\n    ZSTD_memset(nextHuf->CTable, 0, sizeof(nextHuf->CTable));\n    huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue, nodeWksp, nodeWkspSize, nextHuf->CTable, countWksp, hufFlags);\n    assert(huffLog <= LitHufLog);\n    {   size_t const maxBits = HUF_buildCTable_wksp((HUF_CElt*)nextHuf->CTable, countWksp,\n                                                    maxSymbolValue, huffLog,\n                                                    nodeWksp, nodeWkspSize);\n        FORWARD_IF_ERROR(maxBits, \"HUF_buildCTable_wksp\");\n        huffLog = (U32)maxBits;\n    }\n    {   /* Build and write the CTable */\n        size_t const newCSize = HUF_estimateCompressedSize(\n                (HUF_CElt*)nextHuf->CTable, countWksp, maxSymbolValue);\n        size_t const hSize = HUF_writeCTable_wksp(\n                hufMetadata->hufDesBuffer, sizeof(hufMetadata->hufDesBuffer),\n                (HUF_CElt*)nextHuf->CTable, maxSymbolValue, huffLog,\n                nodeWksp, nodeWkspSize);\n        /* Check against repeating the previous CTable */\n        if (repeat != HUF_repeat_none) {\n            size_t const oldCSize = HUF_estimateCompressedSize(\n                    (HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue);\n            if (oldCSize < srcSize && (oldCSize <= hSize + newCSize || hSize + 12 >= srcSize)) {\n                DEBUGLOG(5, \"set_repeat - smaller\");\n                ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));\n                hufMetadata->hType = set_repeat;\n                return 0;\n        }   }\n        if (newCSize + hSize >= srcSize) {\n            DEBUGLOG(5, \"set_basic - no gains\");\n            ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));\n            hufMetadata->hType = set_basic;\n            return 0;\n        }\n        DEBUGLOG(5, \"set_compressed (hSize=%u)\", (U32)hSize);\n        hufMetadata->hType = set_compressed;\n        nextHuf->repeatMode = HUF_repeat_check;\n        return hSize;\n    }\n}\n\n\n/* ZSTD_buildDummySequencesStatistics():\n * Returns a ZSTD_symbolEncodingTypeStats_t with all encoding types as set_basic,\n * and updates nextEntropy to the appropriate repeatMode.\n */\nstatic ZSTD_symbolEncodingTypeStats_t\nZSTD_buildDummySequencesStatistics(ZSTD_fseCTables_t* nextEntropy)\n{\n    ZSTD_symbolEncodingTypeStats_t stats = {set_basic, set_basic, set_basic, 0, 0, 0};\n    nextEntropy->litlength_repeatMode = FSE_repeat_none;\n    nextEntropy->offcode_repeatMode = FSE_repeat_none;\n    nextEntropy->matchlength_repeatMode = FSE_repeat_none;\n    return stats;\n}\n\n/** ZSTD_buildBlockEntropyStats_sequences() :\n *  Builds entropy for the sequences.\n *  Stores symbol compression modes and fse table to fseMetadata.\n *  Requires ENTROPY_WORKSPACE_SIZE wksp.\n * @return : size of fse tables or error code */\nstatic size_t\nZSTD_buildBlockEntropyStats_sequences(\n                const SeqStore_t* seqStorePtr,\n                const ZSTD_fseCTables_t* prevEntropy,\n                      ZSTD_fseCTables_t* nextEntropy,\n                const ZSTD_CCtx_params* cctxParams,\n                      ZSTD_fseCTablesMetadata_t* fseMetadata,\n                      void* workspace, size_t wkspSize)\n{\n    ZSTD_strategy const strategy = cctxParams->cParams.strategy;\n    size_t const nbSeq = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart);\n    BYTE* const ostart = fseMetadata->fseTablesBuffer;\n    BYTE* const oend = ostart + sizeof(fseMetadata->fseTablesBuffer);\n    BYTE* op = ostart;\n    unsigned* countWorkspace = (unsigned*)workspace;\n    unsigned* entropyWorkspace = countWorkspace + (MaxSeq + 1);\n    size_t entropyWorkspaceSize = wkspSize - (MaxSeq + 1) * sizeof(*countWorkspace);\n    ZSTD_symbolEncodingTypeStats_t stats;\n\n    DEBUGLOG(5, \"ZSTD_buildBlockEntropyStats_sequences (nbSeq=%zu)\", nbSeq);\n    stats = nbSeq != 0 ? ZSTD_buildSequencesStatistics(seqStorePtr, nbSeq,\n                                          prevEntropy, nextEntropy, op, oend,\n                                          strategy, countWorkspace,\n                                          entropyWorkspace, entropyWorkspaceSize)\n                       : ZSTD_buildDummySequencesStatistics(nextEntropy);\n    FORWARD_IF_ERROR(stats.size, \"ZSTD_buildSequencesStatistics failed!\");\n    fseMetadata->llType = (SymbolEncodingType_e) stats.LLtype;\n    fseMetadata->ofType = (SymbolEncodingType_e) stats.Offtype;\n    fseMetadata->mlType = (SymbolEncodingType_e) stats.MLtype;\n    fseMetadata->lastCountSize = stats.lastCountSize;\n    return stats.size;\n}\n\n\n/** ZSTD_buildBlockEntropyStats() :\n *  Builds entropy for the block.\n *  Requires workspace size ENTROPY_WORKSPACE_SIZE\n * @return : 0 on success, or an error code\n *  Note : also employed in superblock\n */\nsize_t ZSTD_buildBlockEntropyStats(\n            const SeqStore_t* seqStorePtr,\n            const ZSTD_entropyCTables_t* prevEntropy,\n                  ZSTD_entropyCTables_t* nextEntropy,\n            const ZSTD_CCtx_params* cctxParams,\n                  ZSTD_entropyCTablesMetadata_t* entropyMetadata,\n                  void* workspace, size_t wkspSize)\n{\n    size_t const litSize = (size_t)(seqStorePtr->lit - seqStorePtr->litStart);\n    int const huf_useOptDepth = (cctxParams->cParams.strategy >= HUF_OPTIMAL_DEPTH_THRESHOLD);\n    int const hufFlags = huf_useOptDepth ? HUF_flags_optimalDepth : 0;\n\n    entropyMetadata->hufMetadata.hufDesSize =\n        ZSTD_buildBlockEntropyStats_literals(seqStorePtr->litStart, litSize,\n                                            &prevEntropy->huf, &nextEntropy->huf,\n                                            &entropyMetadata->hufMetadata,\n                                            ZSTD_literalsCompressionIsDisabled(cctxParams),\n                                            workspace, wkspSize, hufFlags);\n\n    FORWARD_IF_ERROR(entropyMetadata->hufMetadata.hufDesSize, \"ZSTD_buildBlockEntropyStats_literals failed\");\n    entropyMetadata->fseMetadata.fseTablesSize =\n        ZSTD_buildBlockEntropyStats_sequences(seqStorePtr,\n                                              &prevEntropy->fse, &nextEntropy->fse,\n                                              cctxParams,\n                                              &entropyMetadata->fseMetadata,\n                                              workspace, wkspSize);\n    FORWARD_IF_ERROR(entropyMetadata->fseMetadata.fseTablesSize, \"ZSTD_buildBlockEntropyStats_sequences failed\");\n    return 0;\n}\n\n/* Returns the size estimate for the literals section (header + content) of a block */\nstatic size_t\nZSTD_estimateBlockSize_literal(const BYTE* literals, size_t litSize,\n                               const ZSTD_hufCTables_t* huf,\n                               const ZSTD_hufCTablesMetadata_t* hufMetadata,\n                               void* workspace, size_t wkspSize,\n                               int writeEntropy)\n{\n    unsigned* const countWksp = (unsigned*)workspace;\n    unsigned maxSymbolValue = HUF_SYMBOLVALUE_MAX;\n    size_t literalSectionHeaderSize = 3 + (litSize >= 1 KB) + (litSize >= 16 KB);\n    U32 singleStream = litSize < 256;\n\n    if (hufMetadata->hType == set_basic) return litSize;\n    else if (hufMetadata->hType == set_rle) return 1;\n    else if (hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat) {\n        size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)literals, litSize, workspace, wkspSize);\n        if (ZSTD_isError(largest)) return litSize;\n        {   size_t cLitSizeEstimate = HUF_estimateCompressedSize((const HUF_CElt*)huf->CTable, countWksp, maxSymbolValue);\n            if (writeEntropy) cLitSizeEstimate += hufMetadata->hufDesSize;\n            if (!singleStream) cLitSizeEstimate += 6; /* multi-stream huffman uses 6-byte jump table */\n            return cLitSizeEstimate + literalSectionHeaderSize;\n    }   }\n    assert(0); /* impossible */\n    return 0;\n}\n\n/* Returns the size estimate for the FSE-compressed symbols (of, ml, ll) of a block */\nstatic size_t\nZSTD_estimateBlockSize_symbolType(SymbolEncodingType_e type,\n                    const BYTE* codeTable, size_t nbSeq, unsigned maxCode,\n                    const FSE_CTable* fseCTable,\n                    const U8* additionalBits,\n                    short const* defaultNorm, U32 defaultNormLog, U32 defaultMax,\n                    void* workspace, size_t wkspSize)\n{\n    unsigned* const countWksp = (unsigned*)workspace;\n    const BYTE* ctp = codeTable;\n    const BYTE* const ctStart = ctp;\n    const BYTE* const ctEnd = ctStart + nbSeq;\n    size_t cSymbolTypeSizeEstimateInBits = 0;\n    unsigned max = maxCode;\n\n    HIST_countFast_wksp(countWksp, &max, codeTable, nbSeq, workspace, wkspSize);  /* can't fail */\n    if (type == set_basic) {\n        /* We selected this encoding type, so it must be valid. */\n        assert(max <= defaultMax);\n        (void)defaultMax;\n        cSymbolTypeSizeEstimateInBits = ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, countWksp, max);\n    } else if (type == set_rle) {\n        cSymbolTypeSizeEstimateInBits = 0;\n    } else if (type == set_compressed || type == set_repeat) {\n        cSymbolTypeSizeEstimateInBits = ZSTD_fseBitCost(fseCTable, countWksp, max);\n    }\n    if (ZSTD_isError(cSymbolTypeSizeEstimateInBits)) {\n        return nbSeq * 10;\n    }\n    while (ctp < ctEnd) {\n        if (additionalBits) cSymbolTypeSizeEstimateInBits += additionalBits[*ctp];\n        else cSymbolTypeSizeEstimateInBits += *ctp; /* for offset, offset code is also the number of additional bits */\n        ctp++;\n    }\n    return cSymbolTypeSizeEstimateInBits >> 3;\n}\n\n/* Returns the size estimate for the sequences section (header + content) of a block */\nstatic size_t\nZSTD_estimateBlockSize_sequences(const BYTE* ofCodeTable,\n                                 const BYTE* llCodeTable,\n                                 const BYTE* mlCodeTable,\n                                 size_t nbSeq,\n                                 const ZSTD_fseCTables_t* fseTables,\n                                 const ZSTD_fseCTablesMetadata_t* fseMetadata,\n                                 void* workspace, size_t wkspSize,\n                                 int writeEntropy)\n{\n    size_t sequencesSectionHeaderSize = 1 /* seqHead */ + 1 /* min seqSize size */ + (nbSeq >= 128) + (nbSeq >= LONGNBSEQ);\n    size_t cSeqSizeEstimate = 0;\n    cSeqSizeEstimate += ZSTD_estimateBlockSize_symbolType(fseMetadata->ofType, ofCodeTable, nbSeq, MaxOff,\n                                    fseTables->offcodeCTable, NULL,\n                                    OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,\n                                    workspace, wkspSize);\n    cSeqSizeEstimate += ZSTD_estimateBlockSize_symbolType(fseMetadata->llType, llCodeTable, nbSeq, MaxLL,\n                                    fseTables->litlengthCTable, LL_bits,\n                                    LL_defaultNorm, LL_defaultNormLog, MaxLL,\n                                    workspace, wkspSize);\n    cSeqSizeEstimate += ZSTD_estimateBlockSize_symbolType(fseMetadata->mlType, mlCodeTable, nbSeq, MaxML,\n                                    fseTables->matchlengthCTable, ML_bits,\n                                    ML_defaultNorm, ML_defaultNormLog, MaxML,\n                                    workspace, wkspSize);\n    if (writeEntropy) cSeqSizeEstimate += fseMetadata->fseTablesSize;\n    return cSeqSizeEstimate + sequencesSectionHeaderSize;\n}\n\n/* Returns the size estimate for a given stream of literals, of, ll, ml */\nstatic size_t\nZSTD_estimateBlockSize(const BYTE* literals, size_t litSize,\n                       const BYTE* ofCodeTable,\n                       const BYTE* llCodeTable,\n                       const BYTE* mlCodeTable,\n                       size_t nbSeq,\n                       const ZSTD_entropyCTables_t* entropy,\n                       const ZSTD_entropyCTablesMetadata_t* entropyMetadata,\n                       void* workspace, size_t wkspSize,\n                       int writeLitEntropy, int writeSeqEntropy)\n{\n    size_t const literalsSize = ZSTD_estimateBlockSize_literal(literals, litSize,\n                                    &entropy->huf, &entropyMetadata->hufMetadata,\n                                    workspace, wkspSize, writeLitEntropy);\n    size_t const seqSize = ZSTD_estimateBlockSize_sequences(ofCodeTable, llCodeTable, mlCodeTable,\n                                    nbSeq, &entropy->fse, &entropyMetadata->fseMetadata,\n                                    workspace, wkspSize, writeSeqEntropy);\n    return seqSize + literalsSize + ZSTD_blockHeaderSize;\n}\n\n/* Builds entropy statistics and uses them for blocksize estimation.\n *\n * @return: estimated compressed size of the seqStore, or a zstd error.\n */\nstatic size_t\nZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(SeqStore_t* seqStore, ZSTD_CCtx* zc)\n{\n    ZSTD_entropyCTablesMetadata_t* const entropyMetadata = &zc->blockSplitCtx.entropyMetadata;\n    DEBUGLOG(6, \"ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize()\");\n    FORWARD_IF_ERROR(ZSTD_buildBlockEntropyStats(seqStore,\n                    &zc->blockState.prevCBlock->entropy,\n                    &zc->blockState.nextCBlock->entropy,\n                    &zc->appliedParams,\n                    entropyMetadata,\n                    zc->tmpWorkspace, zc->tmpWkspSize), \"\");\n    return ZSTD_estimateBlockSize(\n                    seqStore->litStart, (size_t)(seqStore->lit - seqStore->litStart),\n                    seqStore->ofCode, seqStore->llCode, seqStore->mlCode,\n                    (size_t)(seqStore->sequences - seqStore->sequencesStart),\n                    &zc->blockState.nextCBlock->entropy,\n                    entropyMetadata,\n                    zc->tmpWorkspace, zc->tmpWkspSize,\n                    (int)(entropyMetadata->hufMetadata.hType == set_compressed), 1);\n}\n\n/* Returns literals bytes represented in a seqStore */\nstatic size_t ZSTD_countSeqStoreLiteralsBytes(const SeqStore_t* const seqStore)\n{\n    size_t literalsBytes = 0;\n    size_t const nbSeqs = (size_t)(seqStore->sequences - seqStore->sequencesStart);\n    size_t i;\n    for (i = 0; i < nbSeqs; ++i) {\n        SeqDef const seq = seqStore->sequencesStart[i];\n        literalsBytes += seq.litLength;\n        if (i == seqStore->longLengthPos && seqStore->longLengthType == ZSTD_llt_literalLength) {\n            literalsBytes += 0x10000;\n    }   }\n    return literalsBytes;\n}\n\n/* Returns match bytes represented in a seqStore */\nstatic size_t ZSTD_countSeqStoreMatchBytes(const SeqStore_t* const seqStore)\n{\n    size_t matchBytes = 0;\n    size_t const nbSeqs = (size_t)(seqStore->sequences - seqStore->sequencesStart);\n    size_t i;\n    for (i = 0; i < nbSeqs; ++i) {\n        SeqDef seq = seqStore->sequencesStart[i];\n        matchBytes += seq.mlBase + MINMATCH;\n        if (i == seqStore->longLengthPos && seqStore->longLengthType == ZSTD_llt_matchLength) {\n            matchBytes += 0x10000;\n    }   }\n    return matchBytes;\n}\n\n/* Derives the seqStore that is a chunk of the originalSeqStore from [startIdx, endIdx).\n * Stores the result in resultSeqStore.\n */\nstatic void ZSTD_deriveSeqStoreChunk(SeqStore_t* resultSeqStore,\n                               const SeqStore_t* originalSeqStore,\n                                     size_t startIdx, size_t endIdx)\n{\n    *resultSeqStore = *originalSeqStore;\n    if (startIdx > 0) {\n        resultSeqStore->sequences = originalSeqStore->sequencesStart + startIdx;\n        resultSeqStore->litStart += ZSTD_countSeqStoreLiteralsBytes(resultSeqStore);\n    }\n\n    /* Move longLengthPos into the correct position if necessary */\n    if (originalSeqStore->longLengthType != ZSTD_llt_none) {\n        if (originalSeqStore->longLengthPos < startIdx || originalSeqStore->longLengthPos > endIdx) {\n            resultSeqStore->longLengthType = ZSTD_llt_none;\n        } else {\n            resultSeqStore->longLengthPos -= (U32)startIdx;\n        }\n    }\n    resultSeqStore->sequencesStart = originalSeqStore->sequencesStart + startIdx;\n    resultSeqStore->sequences = originalSeqStore->sequencesStart + endIdx;\n    if (endIdx == (size_t)(originalSeqStore->sequences - originalSeqStore->sequencesStart)) {\n        /* This accounts for possible last literals if the derived chunk reaches the end of the block */\n        assert(resultSeqStore->lit == originalSeqStore->lit);\n    } else {\n        size_t const literalsBytes = ZSTD_countSeqStoreLiteralsBytes(resultSeqStore);\n        resultSeqStore->lit = resultSeqStore->litStart + literalsBytes;\n    }\n    resultSeqStore->llCode += startIdx;\n    resultSeqStore->mlCode += startIdx;\n    resultSeqStore->ofCode += startIdx;\n}\n\n/**\n * Returns the raw offset represented by the combination of offBase, ll0, and repcode history.\n * offBase must represent a repcode in the numeric representation of ZSTD_storeSeq().\n */\nstatic U32\nZSTD_resolveRepcodeToRawOffset(const U32 rep[ZSTD_REP_NUM], const U32 offBase, const U32 ll0)\n{\n    U32 const adjustedRepCode = OFFBASE_TO_REPCODE(offBase) - 1 + ll0;  /* [ 0 - 3 ] */\n    assert(OFFBASE_IS_REPCODE(offBase));\n    if (adjustedRepCode == ZSTD_REP_NUM) {\n        assert(ll0);\n        /* litlength == 0 and offCode == 2 implies selection of first repcode - 1\n         * This is only valid if it results in a valid offset value, aka > 0.\n         * Note : it may happen that `rep[0]==1` in exceptional circumstances.\n         * In which case this function will return 0, which is an invalid offset.\n         * It's not an issue though, since this value will be\n         * compared and discarded within ZSTD_seqStore_resolveOffCodes().\n         */\n        return rep[0] - 1;\n    }\n    return rep[adjustedRepCode];\n}\n\n/**\n * ZSTD_seqStore_resolveOffCodes() reconciles any possible divergences in offset history that may arise\n * due to emission of RLE/raw blocks that disturb the offset history,\n * and replaces any repcodes within the seqStore that may be invalid.\n *\n * dRepcodes are updated as would be on the decompression side.\n * cRepcodes are updated exactly in accordance with the seqStore.\n *\n * Note : this function assumes seq->offBase respects the following numbering scheme :\n *        0 : invalid\n *        1-3 : repcode 1-3\n *        4+ : real_offset+3\n */\nstatic void\nZSTD_seqStore_resolveOffCodes(Repcodes_t* const dRepcodes, Repcodes_t* const cRepcodes,\n                        const SeqStore_t* const seqStore, U32 const nbSeq)\n{\n    U32 idx = 0;\n    U32 const longLitLenIdx = seqStore->longLengthType == ZSTD_llt_literalLength ? seqStore->longLengthPos : nbSeq;\n    for (; idx < nbSeq; ++idx) {\n        SeqDef* const seq = seqStore->sequencesStart + idx;\n        U32 const ll0 = (seq->litLength == 0) && (idx != longLitLenIdx);\n        U32 const offBase = seq->offBase;\n        assert(offBase > 0);\n        if (OFFBASE_IS_REPCODE(offBase)) {\n            U32 const dRawOffset = ZSTD_resolveRepcodeToRawOffset(dRepcodes->rep, offBase, ll0);\n            U32 const cRawOffset = ZSTD_resolveRepcodeToRawOffset(cRepcodes->rep, offBase, ll0);\n            /* Adjust simulated decompression repcode history if we come across a mismatch. Replace\n             * the repcode with the offset it actually references, determined by the compression\n             * repcode history.\n             */\n            if (dRawOffset != cRawOffset) {\n                seq->offBase = OFFSET_TO_OFFBASE(cRawOffset);\n            }\n        }\n        /* Compression repcode history is always updated with values directly from the unmodified seqStore.\n         * Decompression repcode history may use modified seq->offset value taken from compression repcode history.\n         */\n        ZSTD_updateRep(dRepcodes->rep, seq->offBase, ll0);\n        ZSTD_updateRep(cRepcodes->rep, offBase, ll0);\n    }\n}\n\n/* ZSTD_compressSeqStore_singleBlock():\n * Compresses a seqStore into a block with a block header, into the buffer dst.\n *\n * Returns the total size of that block (including header) or a ZSTD error code.\n */\nstatic size_t\nZSTD_compressSeqStore_singleBlock(ZSTD_CCtx* zc,\n                            const SeqStore_t* const seqStore,\n                                  Repcodes_t* const dRep, Repcodes_t* const cRep,\n                                  void* dst, size_t dstCapacity,\n                            const void* src, size_t srcSize,\n                                  U32 lastBlock, U32 isPartition)\n{\n    const U32 rleMaxLength = 25;\n    BYTE* op = (BYTE*)dst;\n    const BYTE* ip = (const BYTE*)src;\n    size_t cSize;\n    size_t cSeqsSize;\n\n    /* In case of an RLE or raw block, the simulated decompression repcode history must be reset */\n    Repcodes_t const dRepOriginal = *dRep;\n    DEBUGLOG(5, \"ZSTD_compressSeqStore_singleBlock\");\n    if (isPartition)\n        ZSTD_seqStore_resolveOffCodes(dRep, cRep, seqStore, (U32)(seqStore->sequences - seqStore->sequencesStart));\n\n    RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall, \"Block header doesn't fit\");\n    cSeqsSize = ZSTD_entropyCompressSeqStore(seqStore,\n                &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy,\n                &zc->appliedParams,\n                op + ZSTD_blockHeaderSize, dstCapacity - ZSTD_blockHeaderSize,\n                srcSize,\n                zc->tmpWorkspace, zc->tmpWkspSize /* statically allocated in resetCCtx */,\n                zc->bmi2);\n    FORWARD_IF_ERROR(cSeqsSize, \"ZSTD_entropyCompressSeqStore failed!\");\n\n    if (!zc->isFirstBlock &&\n        cSeqsSize < rleMaxLength &&\n        ZSTD_isRLE((BYTE const*)src, srcSize)) {\n        /* We don't want to emit our first block as a RLE even if it qualifies because\n        * doing so will cause the decoder (cli only) to throw a \"should consume all input error.\"\n        * This is only an issue for zstd <= v1.4.3\n        */\n        cSeqsSize = 1;\n    }\n\n    /* Sequence collection not supported when block splitting */\n    if (zc->seqCollector.collectSequences) {\n        FORWARD_IF_ERROR(ZSTD_copyBlockSequences(&zc->seqCollector, seqStore, dRepOriginal.rep), \"copyBlockSequences failed\");\n        ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState);\n        return 0;\n    }\n\n    if (cSeqsSize == 0) {\n        cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, srcSize, lastBlock);\n        FORWARD_IF_ERROR(cSize, \"Nocompress block failed\");\n        DEBUGLOG(5, \"Writing out nocompress block, size: %zu\", cSize);\n        *dRep = dRepOriginal; /* reset simulated decompression repcode history */\n    } else if (cSeqsSize == 1) {\n        cSize = ZSTD_rleCompressBlock(op, dstCapacity, *ip, srcSize, lastBlock);\n        FORWARD_IF_ERROR(cSize, \"RLE compress block failed\");\n        DEBUGLOG(5, \"Writing out RLE block, size: %zu\", cSize);\n        *dRep = dRepOriginal; /* reset simulated decompression repcode history */\n    } else {\n        ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState);\n        writeBlockHeader(op, cSeqsSize, srcSize, lastBlock);\n        cSize = ZSTD_blockHeaderSize + cSeqsSize;\n        DEBUGLOG(5, \"Writing out compressed block, size: %zu\", cSize);\n    }\n\n    if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)\n        zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;\n\n    return cSize;\n}\n\n/* Struct to keep track of where we are in our recursive calls. */\ntypedef struct {\n    U32* splitLocations;    /* Array of split indices */\n    size_t idx;             /* The current index within splitLocations being worked on */\n} seqStoreSplits;\n\n#define MIN_SEQUENCES_BLOCK_SPLITTING 300\n\n/* Helper function to perform the recursive search for block splits.\n * Estimates the cost of seqStore prior to split, and estimates the cost of splitting the sequences in half.\n * If advantageous to split, then we recurse down the two sub-blocks.\n * If not, or if an error occurred in estimation, then we do not recurse.\n *\n * Note: The recursion depth is capped by a heuristic minimum number of sequences,\n * defined by MIN_SEQUENCES_BLOCK_SPLITTING.\n * In theory, this means the absolute largest recursion depth is 10 == log2(maxNbSeqInBlock/MIN_SEQUENCES_BLOCK_SPLITTING).\n * In practice, recursion depth usually doesn't go beyond 4.\n *\n * Furthermore, the number of splits is capped by ZSTD_MAX_NB_BLOCK_SPLITS.\n * At ZSTD_MAX_NB_BLOCK_SPLITS == 196 with the current existing blockSize\n * maximum of 128 KB, this value is actually impossible to reach.\n */\nstatic void\nZSTD_deriveBlockSplitsHelper(seqStoreSplits* splits, size_t startIdx, size_t endIdx,\n                             ZSTD_CCtx* zc, const SeqStore_t* origSeqStore)\n{\n    SeqStore_t* const fullSeqStoreChunk = &zc->blockSplitCtx.fullSeqStoreChunk;\n    SeqStore_t* const firstHalfSeqStore = &zc->blockSplitCtx.firstHalfSeqStore;\n    SeqStore_t* const secondHalfSeqStore = &zc->blockSplitCtx.secondHalfSeqStore;\n    size_t estimatedOriginalSize;\n    size_t estimatedFirstHalfSize;\n    size_t estimatedSecondHalfSize;\n    size_t midIdx = (startIdx + endIdx)/2;\n\n    DEBUGLOG(5, \"ZSTD_deriveBlockSplitsHelper: startIdx=%zu endIdx=%zu\", startIdx, endIdx);\n    assert(endIdx >= startIdx);\n    if (endIdx - startIdx < MIN_SEQUENCES_BLOCK_SPLITTING || splits->idx >= ZSTD_MAX_NB_BLOCK_SPLITS) {\n        DEBUGLOG(6, \"ZSTD_deriveBlockSplitsHelper: Too few sequences (%zu)\", endIdx - startIdx);\n        return;\n    }\n    ZSTD_deriveSeqStoreChunk(fullSeqStoreChunk, origSeqStore, startIdx, endIdx);\n    ZSTD_deriveSeqStoreChunk(firstHalfSeqStore, origSeqStore, startIdx, midIdx);\n    ZSTD_deriveSeqStoreChunk(secondHalfSeqStore, origSeqStore, midIdx, endIdx);\n    estimatedOriginalSize = ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(fullSeqStoreChunk, zc);\n    estimatedFirstHalfSize = ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(firstHalfSeqStore, zc);\n    estimatedSecondHalfSize = ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(secondHalfSeqStore, zc);\n    DEBUGLOG(5, \"Estimated original block size: %zu -- First half split: %zu -- Second half split: %zu\",\n             estimatedOriginalSize, estimatedFirstHalfSize, estimatedSecondHalfSize);\n    if (ZSTD_isError(estimatedOriginalSize) || ZSTD_isError(estimatedFirstHalfSize) || ZSTD_isError(estimatedSecondHalfSize)) {\n        return;\n    }\n    if (estimatedFirstHalfSize + estimatedSecondHalfSize < estimatedOriginalSize) {\n        DEBUGLOG(5, \"split decided at seqNb:%zu\", midIdx);\n        ZSTD_deriveBlockSplitsHelper(splits, startIdx, midIdx, zc, origSeqStore);\n        splits->splitLocations[splits->idx] = (U32)midIdx;\n        splits->idx++;\n        ZSTD_deriveBlockSplitsHelper(splits, midIdx, endIdx, zc, origSeqStore);\n    }\n}\n\n/* Base recursive function.\n * Populates a table with intra-block partition indices that can improve compression ratio.\n *\n * @return: number of splits made (which equals the size of the partition table - 1).\n */\nstatic size_t ZSTD_deriveBlockSplits(ZSTD_CCtx* zc, U32 partitions[], U32 nbSeq)\n{\n    seqStoreSplits splits;\n    splits.splitLocations = partitions;\n    splits.idx = 0;\n    if (nbSeq <= 4) {\n        DEBUGLOG(5, \"ZSTD_deriveBlockSplits: Too few sequences to split (%u <= 4)\", nbSeq);\n        /* Refuse to try and split anything with less than 4 sequences */\n        return 0;\n    }\n    ZSTD_deriveBlockSplitsHelper(&splits, 0, nbSeq, zc, &zc->seqStore);\n    splits.splitLocations[splits.idx] = nbSeq;\n    DEBUGLOG(5, \"ZSTD_deriveBlockSplits: final nb partitions: %zu\", splits.idx+1);\n    return splits.idx;\n}\n\n/* ZSTD_compressBlock_splitBlock():\n * Attempts to split a given block into multiple blocks to improve compression ratio.\n *\n * Returns combined size of all blocks (which includes headers), or a ZSTD error code.\n */\nstatic size_t\nZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc,\n                                    void* dst, size_t dstCapacity,\n                              const void* src, size_t blockSize,\n                                    U32 lastBlock, U32 nbSeq)\n{\n    size_t cSize = 0;\n    const BYTE* ip = (const BYTE*)src;\n    BYTE* op = (BYTE*)dst;\n    size_t i = 0;\n    size_t srcBytesTotal = 0;\n    U32* const partitions = zc->blockSplitCtx.partitions; /* size == ZSTD_MAX_NB_BLOCK_SPLITS */\n    SeqStore_t* const nextSeqStore = &zc->blockSplitCtx.nextSeqStore;\n    SeqStore_t* const currSeqStore = &zc->blockSplitCtx.currSeqStore;\n    size_t const numSplits = ZSTD_deriveBlockSplits(zc, partitions, nbSeq);\n\n    /* If a block is split and some partitions are emitted as RLE/uncompressed, then repcode history\n     * may become invalid. In order to reconcile potentially invalid repcodes, we keep track of two\n     * separate repcode histories that simulate repcode history on compression and decompression side,\n     * and use the histories to determine whether we must replace a particular repcode with its raw offset.\n     *\n     * 1) cRep gets updated for each partition, regardless of whether the block was emitted as uncompressed\n     *    or RLE. This allows us to retrieve the offset value that an invalid repcode references within\n     *    a nocompress/RLE block.\n     * 2) dRep gets updated only for compressed partitions, and when a repcode gets replaced, will use\n     *    the replacement offset value rather than the original repcode to update the repcode history.\n     *    dRep also will be the final repcode history sent to the next block.\n     *\n     * See ZSTD_seqStore_resolveOffCodes() for more details.\n     */\n    Repcodes_t dRep;\n    Repcodes_t cRep;\n    ZSTD_memcpy(dRep.rep, zc->blockState.prevCBlock->rep, sizeof(Repcodes_t));\n    ZSTD_memcpy(cRep.rep, zc->blockState.prevCBlock->rep, sizeof(Repcodes_t));\n    ZSTD_memset(nextSeqStore, 0, sizeof(SeqStore_t));\n\n    DEBUGLOG(5, \"ZSTD_compressBlock_splitBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)\",\n                (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit,\n                (unsigned)zc->blockState.matchState.nextToUpdate);\n\n    if (numSplits == 0) {\n        size_t cSizeSingleBlock =\n            ZSTD_compressSeqStore_singleBlock(zc, &zc->seqStore,\n                                            &dRep, &cRep,\n                                            op, dstCapacity,\n                                            ip, blockSize,\n                                            lastBlock, 0 /* isPartition */);\n        FORWARD_IF_ERROR(cSizeSingleBlock, \"Compressing single block from splitBlock_internal() failed!\");\n        DEBUGLOG(5, \"ZSTD_compressBlock_splitBlock_internal: No splits\");\n        assert(zc->blockSizeMax <= ZSTD_BLOCKSIZE_MAX);\n        assert(cSizeSingleBlock <= zc->blockSizeMax + ZSTD_blockHeaderSize);\n        return cSizeSingleBlock;\n    }\n\n    ZSTD_deriveSeqStoreChunk(currSeqStore, &zc->seqStore, 0, partitions[0]);\n    for (i = 0; i <= numSplits; ++i) {\n        size_t cSizeChunk;\n        U32 const lastPartition = (i == numSplits);\n        U32 lastBlockEntireSrc = 0;\n\n        size_t srcBytes = ZSTD_countSeqStoreLiteralsBytes(currSeqStore) + ZSTD_countSeqStoreMatchBytes(currSeqStore);\n        srcBytesTotal += srcBytes;\n        if (lastPartition) {\n            /* This is the final partition, need to account for possible last literals */\n            srcBytes += blockSize - srcBytesTotal;\n            lastBlockEntireSrc = lastBlock;\n        } else {\n            ZSTD_deriveSeqStoreChunk(nextSeqStore, &zc->seqStore, partitions[i], partitions[i+1]);\n        }\n\n        cSizeChunk = ZSTD_compressSeqStore_singleBlock(zc, currSeqStore,\n                                                      &dRep, &cRep,\n                                                       op, dstCapacity,\n                                                       ip, srcBytes,\n                                                       lastBlockEntireSrc, 1 /* isPartition */);\n        DEBUGLOG(5, \"Estimated size: %zu vs %zu : actual size\",\n                    ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(currSeqStore, zc), cSizeChunk);\n        FORWARD_IF_ERROR(cSizeChunk, \"Compressing chunk failed!\");\n\n        ip += srcBytes;\n        op += cSizeChunk;\n        dstCapacity -= cSizeChunk;\n        cSize += cSizeChunk;\n        *currSeqStore = *nextSeqStore;\n        assert(cSizeChunk <= zc->blockSizeMax + ZSTD_blockHeaderSize);\n    }\n    /* cRep and dRep may have diverged during the compression.\n     * If so, we use the dRep repcodes for the next block.\n     */\n    ZSTD_memcpy(zc->blockState.prevCBlock->rep, dRep.rep, sizeof(Repcodes_t));\n    return cSize;\n}\n\nstatic size_t\nZSTD_compressBlock_splitBlock(ZSTD_CCtx* zc,\n                              void* dst, size_t dstCapacity,\n                              const void* src, size_t srcSize, U32 lastBlock)\n{\n    U32 nbSeq;\n    size_t cSize;\n    DEBUGLOG(5, \"ZSTD_compressBlock_splitBlock\");\n    assert(zc->appliedParams.postBlockSplitter == ZSTD_ps_enable);\n\n    {   const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize);\n        FORWARD_IF_ERROR(bss, \"ZSTD_buildSeqStore failed\");\n        if (bss == ZSTDbss_noCompress) {\n            if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)\n                zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;\n            RETURN_ERROR_IF(zc->seqCollector.collectSequences, sequenceProducer_failed, \"Uncompressible block\");\n            cSize = ZSTD_noCompressBlock(dst, dstCapacity, src, srcSize, lastBlock);\n            FORWARD_IF_ERROR(cSize, \"ZSTD_noCompressBlock failed\");\n            DEBUGLOG(5, \"ZSTD_compressBlock_splitBlock: Nocompress block\");\n            return cSize;\n        }\n        nbSeq = (U32)(zc->seqStore.sequences - zc->seqStore.sequencesStart);\n    }\n\n    cSize = ZSTD_compressBlock_splitBlock_internal(zc, dst, dstCapacity, src, srcSize, lastBlock, nbSeq);\n    FORWARD_IF_ERROR(cSize, \"Splitting blocks failed!\");\n    return cSize;\n}\n\nstatic size_t\nZSTD_compressBlock_internal(ZSTD_CCtx* zc,\n                            void* dst, size_t dstCapacity,\n                            const void* src, size_t srcSize, U32 frame)\n{\n    /* This is an estimated upper bound for the length of an rle block.\n     * This isn't the actual upper bound.\n     * Finding the real threshold needs further investigation.\n     */\n    const U32 rleMaxLength = 25;\n    size_t cSize;\n    const BYTE* ip = (const BYTE*)src;\n    BYTE* op = (BYTE*)dst;\n    DEBUGLOG(5, \"ZSTD_compressBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)\",\n                (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit,\n                (unsigned)zc->blockState.matchState.nextToUpdate);\n\n    {   const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize);\n        FORWARD_IF_ERROR(bss, \"ZSTD_buildSeqStore failed\");\n        if (bss == ZSTDbss_noCompress) {\n            RETURN_ERROR_IF(zc->seqCollector.collectSequences, sequenceProducer_failed, \"Uncompressible block\");\n            cSize = 0;\n            goto out;\n        }\n    }\n\n    if (zc->seqCollector.collectSequences) {\n        FORWARD_IF_ERROR(ZSTD_copyBlockSequences(&zc->seqCollector, ZSTD_getSeqStore(zc), zc->blockState.prevCBlock->rep), \"copyBlockSequences failed\");\n        ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState);\n        return 0;\n    }\n\n    /* encode sequences and literals */\n    cSize = ZSTD_entropyCompressSeqStore(&zc->seqStore,\n            &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy,\n            &zc->appliedParams,\n            dst, dstCapacity,\n            srcSize,\n            zc->tmpWorkspace, zc->tmpWkspSize /* statically allocated in resetCCtx */,\n            zc->bmi2);\n\n    if (frame &&\n        /* We don't want to emit our first block as a RLE even if it qualifies because\n         * doing so will cause the decoder (cli only) to throw a \"should consume all input error.\"\n         * This is only an issue for zstd <= v1.4.3\n         */\n        !zc->isFirstBlock &&\n        cSize < rleMaxLength &&\n        ZSTD_isRLE(ip, srcSize))\n    {\n        cSize = 1;\n        op[0] = ip[0];\n    }\n\nout:\n    if (!ZSTD_isError(cSize) && cSize > 1) {\n        ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState);\n    }\n    /* We check that dictionaries have offset codes available for the first\n     * block. After the first block, the offcode table might not have large\n     * enough codes to represent the offsets in the data.\n     */\n    if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)\n        zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;\n\n    return cSize;\n}\n\nstatic size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc,\n                               void* dst, size_t dstCapacity,\n                               const void* src, size_t srcSize,\n                               const size_t bss, U32 lastBlock)\n{\n    DEBUGLOG(6, \"Attempting ZSTD_compressSuperBlock()\");\n    if (bss == ZSTDbss_compress) {\n        if (/* We don't want to emit our first block as a RLE even if it qualifies because\n            * doing so will cause the decoder (cli only) to throw a \"should consume all input error.\"\n            * This is only an issue for zstd <= v1.4.3\n            */\n            !zc->isFirstBlock &&\n            ZSTD_maybeRLE(&zc->seqStore) &&\n            ZSTD_isRLE((BYTE const*)src, srcSize))\n        {\n            return ZSTD_rleCompressBlock(dst, dstCapacity, *(BYTE const*)src, srcSize, lastBlock);\n        }\n        /* Attempt superblock compression.\n         *\n         * Note that compressed size of ZSTD_compressSuperBlock() is not bound by the\n         * standard ZSTD_compressBound(). This is a problem, because even if we have\n         * space now, taking an extra byte now could cause us to run out of space later\n         * and violate ZSTD_compressBound().\n         *\n         * Define blockBound(blockSize) = blockSize + ZSTD_blockHeaderSize.\n         *\n         * In order to respect ZSTD_compressBound() we must attempt to emit a raw\n         * uncompressed block in these cases:\n         *   * cSize == 0: Return code for an uncompressed block.\n         *   * cSize == dstSize_tooSmall: We may have expanded beyond blockBound(srcSize).\n         *     ZSTD_noCompressBlock() will return dstSize_tooSmall if we are really out of\n         *     output space.\n         *   * cSize >= blockBound(srcSize): We have expanded the block too much so\n         *     emit an uncompressed block.\n         */\n        {   size_t const cSize =\n                ZSTD_compressSuperBlock(zc, dst, dstCapacity, src, srcSize, lastBlock);\n            if (cSize != ERROR(dstSize_tooSmall)) {\n                size_t const maxCSize =\n                    srcSize - ZSTD_minGain(srcSize, zc->appliedParams.cParams.strategy);\n                FORWARD_IF_ERROR(cSize, \"ZSTD_compressSuperBlock failed\");\n                if (cSize != 0 && cSize < maxCSize + ZSTD_blockHeaderSize) {\n                    ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState);\n                    return cSize;\n                }\n            }\n        }\n    } /* if (bss == ZSTDbss_compress)*/\n\n    DEBUGLOG(6, \"Resorting to ZSTD_noCompressBlock()\");\n    /* Superblock compression failed, attempt to emit a single no compress block.\n     * The decoder will be able to stream this block since it is uncompressed.\n     */\n    return ZSTD_noCompressBlock(dst, dstCapacity, src, srcSize, lastBlock);\n}\n\nstatic size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc,\n                               void* dst, size_t dstCapacity,\n                               const void* src, size_t srcSize,\n                               U32 lastBlock)\n{\n    size_t cSize = 0;\n    const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize);\n    DEBUGLOG(5, \"ZSTD_compressBlock_targetCBlockSize (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u, srcSize=%zu)\",\n                (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, (unsigned)zc->blockState.matchState.nextToUpdate, srcSize);\n    FORWARD_IF_ERROR(bss, \"ZSTD_buildSeqStore failed\");\n\n    cSize = ZSTD_compressBlock_targetCBlockSize_body(zc, dst, dstCapacity, src, srcSize, bss, lastBlock);\n    FORWARD_IF_ERROR(cSize, \"ZSTD_compressBlock_targetCBlockSize_body failed\");\n\n    if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)\n        zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;\n\n    return cSize;\n}\n\nstatic void ZSTD_overflowCorrectIfNeeded(ZSTD_MatchState_t* ms,\n                                         ZSTD_cwksp* ws,\n                                         ZSTD_CCtx_params const* params,\n                                         void const* ip,\n                                         void const* iend)\n{\n    U32 const cycleLog = ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy);\n    U32 const maxDist = (U32)1 << params->cParams.windowLog;\n    if (ZSTD_window_needOverflowCorrection(ms->window, cycleLog, maxDist, ms->loadedDictEnd, ip, iend)) {\n        U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip);\n        ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);\n        ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);\n        ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);\n        ZSTD_cwksp_mark_tables_dirty(ws);\n        ZSTD_reduceIndex(ms, params, correction);\n        ZSTD_cwksp_mark_tables_clean(ws);\n        if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;\n        else ms->nextToUpdate -= correction;\n        /* invalidate dictionaries on overflow correction */\n        ms->loadedDictEnd = 0;\n        ms->dictMatchState = NULL;\n    }\n}\n\n#include \"zstd_preSplit.h\"\n\nstatic size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t srcSize, size_t blockSizeMax, int splitLevel, ZSTD_strategy strat, S64 savings)\n{\n    /* split level based on compression strategy, from `fast` to `btultra2` */\n    static const int splitLevels[] = { 0, 0, 1, 2, 2, 3, 3, 4, 4, 4 };\n    /* note: conservatively only split full blocks (128 KB) currently.\n     * While it's possible to go lower, let's keep it simple for a first implementation.\n     * Besides, benefits of splitting are reduced when blocks are already small.\n     */\n    if (srcSize < 128 KB || blockSizeMax < 128 KB)\n        return MIN(srcSize, blockSizeMax);\n    /* do not split incompressible data though:\n     * require verified savings to allow pre-splitting.\n     * Note: as a consequence, the first full block is not split.\n     */\n    if (savings < 3) {\n        DEBUGLOG(6, \"don't attempt splitting: savings (%i) too low\", (int)savings);\n        return 128 KB;\n    }\n    /* apply @splitLevel, or use default value (which depends on @strat).\n     * note that splitting heuristic is still conditioned by @savings >= 3,\n     * so the first block will not reach this code path */\n    if (splitLevel == 1) return 128 KB;\n    if (splitLevel == 0) {\n        assert(ZSTD_fast <= strat && strat <= ZSTD_btultra2);\n        splitLevel = splitLevels[strat];\n    } else {\n        assert(2 <= splitLevel && splitLevel <= 6);\n        splitLevel -= 2;\n    }\n    return ZSTD_splitBlock(src, blockSizeMax, splitLevel, cctx->tmpWorkspace, cctx->tmpWkspSize);\n}\n\n/*! ZSTD_compress_frameChunk() :\n*   Compress a chunk of data into one or multiple blocks.\n*   All blocks will be terminated, all input will be consumed.\n*   Function will issue an error if there is not enough `dstCapacity` to hold the compressed content.\n*   Frame is supposed already started (header already produced)\n*  @return : compressed size, or an error code\n*/\nstatic size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx,\n                                     void* dst, size_t dstCapacity,\n                               const void* src, size_t srcSize,\n                                     U32 lastFrameChunk)\n{\n    size_t blockSizeMax = cctx->blockSizeMax;\n    size_t remaining = srcSize;\n    const BYTE* ip = (const BYTE*)src;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* op = ostart;\n    U32 const maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog;\n    S64 savings = (S64)cctx->consumedSrcSize - (S64)cctx->producedCSize;\n\n    assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX);\n\n    DEBUGLOG(5, \"ZSTD_compress_frameChunk (srcSize=%u, blockSizeMax=%u)\", (unsigned)srcSize, (unsigned)blockSizeMax);\n    if (cctx->appliedParams.fParams.checksumFlag && srcSize)\n        XXH64_update(&cctx->xxhState, src, srcSize);\n\n    while (remaining) {\n        ZSTD_MatchState_t* const ms = &cctx->blockState.matchState;\n        size_t const blockSize = ZSTD_optimalBlockSize(cctx,\n                                ip, remaining,\n                                blockSizeMax,\n                                cctx->appliedParams.preBlockSplitter_level,\n                                cctx->appliedParams.cParams.strategy,\n                                savings);\n        U32 const lastBlock = lastFrameChunk & (blockSize == remaining);\n        assert(blockSize <= remaining);\n\n        /* TODO: See 3090. We reduced MIN_CBLOCK_SIZE from 3 to 2 so to compensate we are adding\n         * additional 1. We need to revisit and change this logic to be more consistent */\n        RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE + 1,\n                        dstSize_tooSmall,\n                        \"not enough space to store compressed block\");\n\n        ZSTD_overflowCorrectIfNeeded(\n            ms, &cctx->workspace, &cctx->appliedParams, ip, ip + blockSize);\n        ZSTD_checkDictValidity(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState);\n        ZSTD_window_enforceMaxDist(&ms->window, ip, maxDist, &ms->loadedDictEnd, &ms->dictMatchState);\n\n        /* Ensure hash/chain table insertion resumes no sooner than lowlimit */\n        if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit;\n\n        {   size_t cSize;\n            if (ZSTD_useTargetCBlockSize(&cctx->appliedParams)) {\n                cSize = ZSTD_compressBlock_targetCBlockSize(cctx, op, dstCapacity, ip, blockSize, lastBlock);\n                FORWARD_IF_ERROR(cSize, \"ZSTD_compressBlock_targetCBlockSize failed\");\n                assert(cSize > 0);\n                assert(cSize <= blockSize + ZSTD_blockHeaderSize);\n            } else if (ZSTD_blockSplitterEnabled(&cctx->appliedParams)) {\n                cSize = ZSTD_compressBlock_splitBlock(cctx, op, dstCapacity, ip, blockSize, lastBlock);\n                FORWARD_IF_ERROR(cSize, \"ZSTD_compressBlock_splitBlock failed\");\n                assert(cSize > 0 || cctx->seqCollector.collectSequences == 1);\n            } else {\n                cSize = ZSTD_compressBlock_internal(cctx,\n                                        op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize,\n                                        ip, blockSize, 1 /* frame */);\n                FORWARD_IF_ERROR(cSize, \"ZSTD_compressBlock_internal failed\");\n\n                if (cSize == 0) {  /* block is not compressible */\n                    cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);\n                    FORWARD_IF_ERROR(cSize, \"ZSTD_noCompressBlock failed\");\n                } else {\n                    U32 const cBlockHeader = cSize == 1 ?\n                        lastBlock + (((U32)bt_rle)<<1) + (U32)(blockSize << 3) :\n                        lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);\n                    MEM_writeLE24(op, cBlockHeader);\n                    cSize += ZSTD_blockHeaderSize;\n                }\n            }  /* if (ZSTD_useTargetCBlockSize(&cctx->appliedParams))*/\n\n            /* @savings is employed to ensure that splitting doesn't worsen expansion of incompressible data.\n             * Without splitting, the maximum expansion is 3 bytes per full block.\n             * An adversarial input could attempt to fudge the split detector,\n             * and make it split incompressible data, resulting in more block headers.\n             * Note that, since ZSTD_COMPRESSBOUND() assumes a worst case scenario of 1KB per block,\n             * and the splitter never creates blocks that small (current lower limit is 8 KB),\n             * there is already no risk to expand beyond ZSTD_COMPRESSBOUND() limit.\n             * But if the goal is to not expand by more than 3-bytes per 128 KB full block,\n             * then yes, it becomes possible to make the block splitter oversplit incompressible data.\n             * Using @savings, we enforce an even more conservative condition,\n             * requiring the presence of enough savings (at least 3 bytes) to authorize splitting,\n             * otherwise only full blocks are used.\n             * But being conservative is fine,\n             * since splitting barely compressible blocks is not fruitful anyway */\n            savings += (S64)blockSize - (S64)cSize;\n\n            ip += blockSize;\n            assert(remaining >= blockSize);\n            remaining -= blockSize;\n            op += cSize;\n            assert(dstCapacity >= cSize);\n            dstCapacity -= cSize;\n            cctx->isFirstBlock = 0;\n            DEBUGLOG(5, \"ZSTD_compress_frameChunk: adding a block of size %u\",\n                        (unsigned)cSize);\n    }   }\n\n    if (lastFrameChunk && (op>ostart)) cctx->stage = ZSTDcs_ending;\n    return (size_t)(op-ostart);\n}\n\n\nstatic size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,\n                                    const ZSTD_CCtx_params* params,\n                                    U64 pledgedSrcSize, U32 dictID)\n{\n    BYTE* const op = (BYTE*)dst;\n    U32   const dictIDSizeCodeLength = (dictID>0) + (dictID>=256) + (dictID>=65536);   /* 0-3 */\n    U32   const dictIDSizeCode = params->fParams.noDictIDFlag ? 0 : dictIDSizeCodeLength;   /* 0-3 */\n    U32   const checksumFlag = params->fParams.checksumFlag>0;\n    U32   const windowSize = (U32)1 << params->cParams.windowLog;\n    U32   const singleSegment = params->fParams.contentSizeFlag && (windowSize >= pledgedSrcSize);\n    BYTE  const windowLogByte = (BYTE)((params->cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);\n    U32   const fcsCode = params->fParams.contentSizeFlag ?\n                     (pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0;  /* 0-3 */\n    BYTE  const frameHeaderDescriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) );\n    size_t pos=0;\n\n    assert(!(params->fParams.contentSizeFlag && pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN));\n    RETURN_ERROR_IF(dstCapacity < ZSTD_FRAMEHEADERSIZE_MAX, dstSize_tooSmall,\n                    \"dst buf is too small to fit worst-case frame header size.\");\n    DEBUGLOG(4, \"ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u\",\n                !params->fParams.noDictIDFlag, (unsigned)dictID, (unsigned)dictIDSizeCode);\n    if (params->format == ZSTD_f_zstd1) {\n        MEM_writeLE32(dst, ZSTD_MAGICNUMBER);\n        pos = 4;\n    }\n    op[pos++] = frameHeaderDescriptionByte;\n    if (!singleSegment) op[pos++] = windowLogByte;\n    switch(dictIDSizeCode)\n    {\n        default:\n            assert(0); /* impossible */\n            ZSTD_FALLTHROUGH;\n        case 0 : break;\n        case 1 : op[pos] = (BYTE)(dictID); pos++; break;\n        case 2 : MEM_writeLE16(op+pos, (U16)dictID); pos+=2; break;\n        case 3 : MEM_writeLE32(op+pos, dictID); pos+=4; break;\n    }\n    switch(fcsCode)\n    {\n        default:\n            assert(0); /* impossible */\n            ZSTD_FALLTHROUGH;\n        case 0 : if (singleSegment) op[pos++] = (BYTE)(pledgedSrcSize); break;\n        case 1 : MEM_writeLE16(op+pos, (U16)(pledgedSrcSize-256)); pos+=2; break;\n        case 2 : MEM_writeLE32(op+pos, (U32)(pledgedSrcSize)); pos+=4; break;\n        case 3 : MEM_writeLE64(op+pos, (U64)(pledgedSrcSize)); pos+=8; break;\n    }\n    return pos;\n}\n\n/* ZSTD_writeSkippableFrame_advanced() :\n * Writes out a skippable frame with the specified magic number variant (16 are supported),\n * from ZSTD_MAGIC_SKIPPABLE_START to ZSTD_MAGIC_SKIPPABLE_START+15, and the desired source data.\n *\n * Returns the total number of bytes written, or a ZSTD error code.\n */\nsize_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity,\n                                const void* src, size_t srcSize, unsigned magicVariant) {\n    BYTE* op = (BYTE*)dst;\n    RETURN_ERROR_IF(dstCapacity < srcSize + ZSTD_SKIPPABLEHEADERSIZE /* Skippable frame overhead */,\n                    dstSize_tooSmall, \"Not enough room for skippable frame\");\n    RETURN_ERROR_IF(srcSize > (unsigned)0xFFFFFFFF, srcSize_wrong, \"Src size too large for skippable frame\");\n    RETURN_ERROR_IF(magicVariant > 15, parameter_outOfBound, \"Skippable frame magic number variant not supported\");\n\n    MEM_writeLE32(op, (U32)(ZSTD_MAGIC_SKIPPABLE_START + magicVariant));\n    MEM_writeLE32(op+4, (U32)srcSize);\n    ZSTD_memcpy(op+8, src, srcSize);\n    return srcSize + ZSTD_SKIPPABLEHEADERSIZE;\n}\n\n/* ZSTD_writeLastEmptyBlock() :\n * output an empty Block with end-of-frame mark to complete a frame\n * @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))\n *           or an error code if `dstCapacity` is too small (<ZSTD_blockHeaderSize)\n */\nsize_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity)\n{\n    RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall,\n                    \"dst buf is too small to write frame trailer empty block.\");\n    {   U32 const cBlockHeader24 = 1 /*lastBlock*/ + (((U32)bt_raw)<<1);  /* 0 size */\n        MEM_writeLE24(dst, cBlockHeader24);\n        return ZSTD_blockHeaderSize;\n    }\n}\n\nvoid ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq)\n{\n    assert(cctx->stage == ZSTDcs_init);\n    assert(nbSeq == 0 || cctx->appliedParams.ldmParams.enableLdm != ZSTD_ps_enable);\n    cctx->externSeqStore.seq = seq;\n    cctx->externSeqStore.size = nbSeq;\n    cctx->externSeqStore.capacity = nbSeq;\n    cctx->externSeqStore.pos = 0;\n    cctx->externSeqStore.posInSequence = 0;\n}\n\n\nstatic size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,\n                              void* dst, size_t dstCapacity,\n                        const void* src, size_t srcSize,\n                               U32 frame, U32 lastFrameChunk)\n{\n    ZSTD_MatchState_t* const ms = &cctx->blockState.matchState;\n    size_t fhSize = 0;\n\n    DEBUGLOG(5, \"ZSTD_compressContinue_internal, stage: %u, srcSize: %u\",\n                cctx->stage, (unsigned)srcSize);\n    RETURN_ERROR_IF(cctx->stage==ZSTDcs_created, stage_wrong,\n                    \"missing init (ZSTD_compressBegin)\");\n\n    if (frame && (cctx->stage==ZSTDcs_init)) {\n        fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams,\n                                       cctx->pledgedSrcSizePlusOne-1, cctx->dictID);\n        FORWARD_IF_ERROR(fhSize, \"ZSTD_writeFrameHeader failed\");\n        assert(fhSize <= dstCapacity);\n        dstCapacity -= fhSize;\n        dst = (char*)dst + fhSize;\n        cctx->stage = ZSTDcs_ongoing;\n    }\n\n    if (!srcSize) return fhSize;  /* do not generate an empty block if no input */\n\n    if (!ZSTD_window_update(&ms->window, src, srcSize, ms->forceNonContiguous)) {\n        ms->forceNonContiguous = 0;\n        ms->nextToUpdate = ms->window.dictLimit;\n    }\n    if (cctx->appliedParams.ldmParams.enableLdm == ZSTD_ps_enable) {\n        ZSTD_window_update(&cctx->ldmState.window, src, srcSize, /* forceNonContiguous */ 0);\n    }\n\n    if (!frame) {\n        /* overflow check and correction for block mode */\n        ZSTD_overflowCorrectIfNeeded(\n            ms, &cctx->workspace, &cctx->appliedParams,\n            src, (BYTE const*)src + srcSize);\n    }\n\n    DEBUGLOG(5, \"ZSTD_compressContinue_internal (blockSize=%u)\", (unsigned)cctx->blockSizeMax);\n    {   size_t const cSize = frame ?\n                             ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :\n                             ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize, 0 /* frame */);\n        FORWARD_IF_ERROR(cSize, \"%s\", frame ? \"ZSTD_compress_frameChunk failed\" : \"ZSTD_compressBlock_internal failed\");\n        cctx->consumedSrcSize += srcSize;\n        cctx->producedCSize += (cSize + fhSize);\n        assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));\n        if (cctx->pledgedSrcSizePlusOne != 0) {  /* control src size */\n            ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);\n            RETURN_ERROR_IF(\n                cctx->consumedSrcSize+1 > cctx->pledgedSrcSizePlusOne,\n                srcSize_wrong,\n                \"error : pledgedSrcSize = %u, while realSrcSize >= %u\",\n                (unsigned)cctx->pledgedSrcSizePlusOne-1,\n                (unsigned)cctx->consumedSrcSize);\n        }\n        return cSize + fhSize;\n    }\n}\n\nsize_t ZSTD_compressContinue_public(ZSTD_CCtx* cctx,\n                                        void* dst, size_t dstCapacity,\n                                  const void* src, size_t srcSize)\n{\n    DEBUGLOG(5, \"ZSTD_compressContinue (srcSize=%u)\", (unsigned)srcSize);\n    return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1 /* frame mode */, 0 /* last chunk */);\n}\n\n/* NOTE: Must just wrap ZSTD_compressContinue_public() */\nsize_t ZSTD_compressContinue(ZSTD_CCtx* cctx,\n                             void* dst, size_t dstCapacity,\n                       const void* src, size_t srcSize)\n{\n    return ZSTD_compressContinue_public(cctx, dst, dstCapacity, src, srcSize);\n}\n\nstatic size_t ZSTD_getBlockSize_deprecated(const ZSTD_CCtx* cctx)\n{\n    ZSTD_compressionParameters const cParams = cctx->appliedParams.cParams;\n    assert(!ZSTD_checkCParams(cParams));\n    return MIN(cctx->appliedParams.maxBlockSize, (size_t)1 << cParams.windowLog);\n}\n\n/* NOTE: Must just wrap ZSTD_getBlockSize_deprecated() */\nsize_t ZSTD_getBlockSize(const ZSTD_CCtx* cctx)\n{\n    return ZSTD_getBlockSize_deprecated(cctx);\n}\n\n/* NOTE: Must just wrap ZSTD_compressBlock_deprecated() */\nsize_t ZSTD_compressBlock_deprecated(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    DEBUGLOG(5, \"ZSTD_compressBlock: srcSize = %u\", (unsigned)srcSize);\n    { size_t const blockSizeMax = ZSTD_getBlockSize_deprecated(cctx);\n      RETURN_ERROR_IF(srcSize > blockSizeMax, srcSize_wrong, \"input is larger than a block\"); }\n\n    return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 /* frame mode */, 0 /* last chunk */);\n}\n\n/* NOTE: Must just wrap ZSTD_compressBlock_deprecated() */\nsize_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_deprecated(cctx, dst, dstCapacity, src, srcSize);\n}\n\n/*! ZSTD_loadDictionaryContent() :\n *  @return : 0, or an error code\n */\nstatic size_t\nZSTD_loadDictionaryContent(ZSTD_MatchState_t* ms,\n                        ldmState_t* ls,\n                        ZSTD_cwksp* ws,\n                        ZSTD_CCtx_params const* params,\n                        const void* src, size_t srcSize,\n                        ZSTD_dictTableLoadMethod_e dtlm,\n                        ZSTD_tableFillPurpose_e tfp)\n{\n    const BYTE* ip = (const BYTE*) src;\n    const BYTE* const iend = ip + srcSize;\n    int const loadLdmDict = params->ldmParams.enableLdm == ZSTD_ps_enable && ls != NULL;\n\n    /* Assert that the ms params match the params we're being given */\n    ZSTD_assertEqualCParams(params->cParams, ms->cParams);\n\n    {   /* Ensure large dictionaries can't cause index overflow */\n\n        /* Allow the dictionary to set indices up to exactly ZSTD_CURRENT_MAX.\n         * Dictionaries right at the edge will immediately trigger overflow\n         * correction, but I don't want to insert extra constraints here.\n         */\n        U32 maxDictSize = ZSTD_CURRENT_MAX - ZSTD_WINDOW_START_INDEX;\n\n        int const CDictTaggedIndices = ZSTD_CDictIndicesAreTagged(&params->cParams);\n        if (CDictTaggedIndices && tfp == ZSTD_tfp_forCDict) {\n            /* Some dictionary matchfinders in zstd use \"short cache\",\n             * which treats the lower ZSTD_SHORT_CACHE_TAG_BITS of each\n             * CDict hashtable entry as a tag rather than as part of an index.\n             * When short cache is used, we need to truncate the dictionary\n             * so that its indices don't overlap with the tag. */\n            U32 const shortCacheMaxDictSize = (1u << (32 - ZSTD_SHORT_CACHE_TAG_BITS)) - ZSTD_WINDOW_START_INDEX;\n            maxDictSize = MIN(maxDictSize, shortCacheMaxDictSize);\n            assert(!loadLdmDict);\n        }\n\n        /* If the dictionary is too large, only load the suffix of the dictionary. */\n        if (srcSize > maxDictSize) {\n            ip = iend - maxDictSize;\n            src = ip;\n            srcSize = maxDictSize;\n        }\n    }\n\n    if (srcSize > ZSTD_CHUNKSIZE_MAX) {\n        /* We must have cleared our windows when our source is this large. */\n        assert(ZSTD_window_isEmpty(ms->window));\n        if (loadLdmDict) assert(ZSTD_window_isEmpty(ls->window));\n    }\n    ZSTD_window_update(&ms->window, src, srcSize, /* forceNonContiguous */ 0);\n\n    DEBUGLOG(4, \"ZSTD_loadDictionaryContent: useRowMatchFinder=%d\", (int)params->useRowMatchFinder);\n\n    if (loadLdmDict) { /* Load the entire dict into LDM matchfinders. */\n        DEBUGLOG(4, \"ZSTD_loadDictionaryContent: Trigger loadLdmDict\");\n        ZSTD_window_update(&ls->window, src, srcSize, /* forceNonContiguous */ 0);\n        ls->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ls->window.base);\n        ZSTD_ldm_fillHashTable(ls, ip, iend, &params->ldmParams);\n        DEBUGLOG(4, \"ZSTD_loadDictionaryContent: ZSTD_ldm_fillHashTable completes\");\n    }\n\n    /* If the dict is larger than we can reasonably index in our tables, only load the suffix. */\n    {   U32 maxDictSize = 1U << MIN(MAX(params->cParams.hashLog + 3, params->cParams.chainLog + 1), 31);\n        if (srcSize > maxDictSize) {\n            ip = iend - maxDictSize;\n            src = ip;\n            srcSize = maxDictSize;\n        }\n    }\n\n    ms->nextToUpdate = (U32)(ip - ms->window.base);\n    ms->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ms->window.base);\n    ms->forceNonContiguous = params->deterministicRefPrefix;\n\n    if (srcSize <= HASH_READ_SIZE) return 0;\n\n    ZSTD_overflowCorrectIfNeeded(ms, ws, params, ip, iend);\n\n    switch(params->cParams.strategy)\n    {\n    case ZSTD_fast:\n        ZSTD_fillHashTable(ms, iend, dtlm, tfp);\n        break;\n    case ZSTD_dfast:\n#ifndef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR\n        ZSTD_fillDoubleHashTable(ms, iend, dtlm, tfp);\n#else\n        assert(0); /* shouldn't be called: cparams should've been adjusted. */\n#endif\n        break;\n\n    case ZSTD_greedy:\n    case ZSTD_lazy:\n    case ZSTD_lazy2:\n#if !defined(ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR)\n        assert(srcSize >= HASH_READ_SIZE);\n        if (ms->dedicatedDictSearch) {\n            assert(ms->chainTable != NULL);\n            ZSTD_dedicatedDictSearch_lazy_loadDictionary(ms, iend-HASH_READ_SIZE);\n        } else {\n            assert(params->useRowMatchFinder != ZSTD_ps_auto);\n            if (params->useRowMatchFinder == ZSTD_ps_enable) {\n                size_t const tagTableSize = ((size_t)1 << params->cParams.hashLog);\n                ZSTD_memset(ms->tagTable, 0, tagTableSize);\n                ZSTD_row_update(ms, iend-HASH_READ_SIZE);\n                DEBUGLOG(4, \"Using row-based hash table for lazy dict\");\n            } else {\n                ZSTD_insertAndFindFirstIndex(ms, iend-HASH_READ_SIZE);\n                DEBUGLOG(4, \"Using chain-based hash table for lazy dict\");\n            }\n        }\n#else\n        assert(0); /* shouldn't be called: cparams should've been adjusted. */\n#endif\n        break;\n\n    case ZSTD_btlazy2:   /* we want the dictionary table fully sorted */\n    case ZSTD_btopt:\n    case ZSTD_btultra:\n    case ZSTD_btultra2:\n#if !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR)\n        assert(srcSize >= HASH_READ_SIZE);\n        DEBUGLOG(4, \"Fill %u bytes into the Binary Tree\", (unsigned)srcSize);\n        ZSTD_updateTree(ms, iend-HASH_READ_SIZE, iend);\n#else\n        assert(0); /* shouldn't be called: cparams should've been adjusted. */\n#endif\n        break;\n\n    default:\n        assert(0);  /* not possible : not a valid strategy id */\n    }\n\n    ms->nextToUpdate = (U32)(iend - ms->window.base);\n    return 0;\n}\n\n\n/* Dictionaries that assign zero probability to symbols that show up causes problems\n * when FSE encoding. Mark dictionaries with zero probability symbols as FSE_repeat_check\n * and only dictionaries with 100% valid symbols can be assumed valid.\n */\nstatic FSE_repeat ZSTD_dictNCountRepeat(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue)\n{\n    U32 s;\n    if (dictMaxSymbolValue < maxSymbolValue) {\n        return FSE_repeat_check;\n    }\n    for (s = 0; s <= maxSymbolValue; ++s) {\n        if (normalizedCounter[s] == 0) {\n            return FSE_repeat_check;\n        }\n    }\n    return FSE_repeat_valid;\n}\n\nsize_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,\n                         const void* const dict, size_t dictSize)\n{\n    short offcodeNCount[MaxOff+1];\n    unsigned offcodeMaxValue = MaxOff;\n    const BYTE* dictPtr = (const BYTE*)dict;    /* skip magic num and dict ID */\n    const BYTE* const dictEnd = dictPtr + dictSize;\n    dictPtr += 8;\n    bs->entropy.huf.repeatMode = HUF_repeat_check;\n\n    {   unsigned maxSymbolValue = 255;\n        unsigned hasZeroWeights = 1;\n        size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr,\n            (size_t)(dictEnd-dictPtr), &hasZeroWeights);\n\n        /* We only set the loaded table as valid if it contains all non-zero\n         * weights. Otherwise, we set it to check */\n        if (!hasZeroWeights && maxSymbolValue == 255)\n            bs->entropy.huf.repeatMode = HUF_repeat_valid;\n\n        RETURN_ERROR_IF(HUF_isError(hufHeaderSize), dictionary_corrupted, \"\");\n        dictPtr += hufHeaderSize;\n    }\n\n    {   unsigned offcodeLog;\n        size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, (size_t)(dictEnd-dictPtr));\n        RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, \"\");\n        RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, \"\");\n        /* fill all offset symbols to avoid garbage at end of table */\n        RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(\n                bs->entropy.fse.offcodeCTable,\n                offcodeNCount, MaxOff, offcodeLog,\n                workspace, HUF_WORKSPACE_SIZE)),\n            dictionary_corrupted, \"\");\n        /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */\n        dictPtr += offcodeHeaderSize;\n    }\n\n    {   short matchlengthNCount[MaxML+1];\n        unsigned matchlengthMaxValue = MaxML, matchlengthLog;\n        size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));\n        RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, \"\");\n        RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, \"\");\n        RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(\n                bs->entropy.fse.matchlengthCTable,\n                matchlengthNCount, matchlengthMaxValue, matchlengthLog,\n                workspace, HUF_WORKSPACE_SIZE)),\n            dictionary_corrupted, \"\");\n        bs->entropy.fse.matchlength_repeatMode = ZSTD_dictNCountRepeat(matchlengthNCount, matchlengthMaxValue, MaxML);\n        dictPtr += matchlengthHeaderSize;\n    }\n\n    {   short litlengthNCount[MaxLL+1];\n        unsigned litlengthMaxValue = MaxLL, litlengthLog;\n        size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));\n        RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, \"\");\n        RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, \"\");\n        RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(\n                bs->entropy.fse.litlengthCTable,\n                litlengthNCount, litlengthMaxValue, litlengthLog,\n                workspace, HUF_WORKSPACE_SIZE)),\n            dictionary_corrupted, \"\");\n        bs->entropy.fse.litlength_repeatMode = ZSTD_dictNCountRepeat(litlengthNCount, litlengthMaxValue, MaxLL);\n        dictPtr += litlengthHeaderSize;\n    }\n\n    RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, \"\");\n    bs->rep[0] = MEM_readLE32(dictPtr+0);\n    bs->rep[1] = MEM_readLE32(dictPtr+4);\n    bs->rep[2] = MEM_readLE32(dictPtr+8);\n    dictPtr += 12;\n\n    {   size_t const dictContentSize = (size_t)(dictEnd - dictPtr);\n        U32 offcodeMax = MaxOff;\n        if (dictContentSize <= ((U32)-1) - 128 KB) {\n            U32 const maxOffset = (U32)dictContentSize + 128 KB; /* The maximum offset that must be supported */\n            offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */\n        }\n        /* All offset values <= dictContentSize + 128 KB must be representable for a valid table */\n        bs->entropy.fse.offcode_repeatMode = ZSTD_dictNCountRepeat(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff));\n\n        /* All repCodes must be <= dictContentSize and != 0 */\n        {   U32 u;\n            for (u=0; u<3; u++) {\n                RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted, \"\");\n                RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted, \"\");\n    }   }   }\n\n    return (size_t)(dictPtr - (const BYTE*)dict);\n}\n\n/* Dictionary format :\n * See :\n * https://github.com/facebook/zstd/blob/release/doc/zstd_compression_format.md#dictionary-format\n */\n/*! ZSTD_loadZstdDictionary() :\n * @return : dictID, or an error code\n *  assumptions : magic number supposed already checked\n *                dictSize supposed >= 8\n */\nstatic size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,\n                                      ZSTD_MatchState_t* ms,\n                                      ZSTD_cwksp* ws,\n                                      ZSTD_CCtx_params const* params,\n                                      const void* dict, size_t dictSize,\n                                      ZSTD_dictTableLoadMethod_e dtlm,\n                                      ZSTD_tableFillPurpose_e tfp,\n                                      void* workspace)\n{\n    const BYTE* dictPtr = (const BYTE*)dict;\n    const BYTE* const dictEnd = dictPtr + dictSize;\n    size_t dictID;\n    size_t eSize;\n    ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));\n    assert(dictSize >= 8);\n    assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY);\n\n    dictID = params->fParams.noDictIDFlag ? 0 :  MEM_readLE32(dictPtr + 4 /* skip magic number */ );\n    eSize = ZSTD_loadCEntropy(bs, workspace, dict, dictSize);\n    FORWARD_IF_ERROR(eSize, \"ZSTD_loadCEntropy failed\");\n    dictPtr += eSize;\n\n    {\n        size_t const dictContentSize = (size_t)(dictEnd - dictPtr);\n        FORWARD_IF_ERROR(ZSTD_loadDictionaryContent(\n            ms, NULL, ws, params, dictPtr, dictContentSize, dtlm, tfp), \"\");\n    }\n    return dictID;\n}\n\n/** ZSTD_compress_insertDictionary() :\n*   @return : dictID, or an error code */\nstatic size_t\nZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs,\n                               ZSTD_MatchState_t* ms,\n                               ldmState_t* ls,\n                               ZSTD_cwksp* ws,\n                         const ZSTD_CCtx_params* params,\n                         const void* dict, size_t dictSize,\n                               ZSTD_dictContentType_e dictContentType,\n                               ZSTD_dictTableLoadMethod_e dtlm,\n                               ZSTD_tableFillPurpose_e tfp,\n                               void* workspace)\n{\n    DEBUGLOG(4, \"ZSTD_compress_insertDictionary (dictSize=%u)\", (U32)dictSize);\n    if ((dict==NULL) || (dictSize<8)) {\n        RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong, \"\");\n        return 0;\n    }\n\n    ZSTD_reset_compressedBlockState(bs);\n\n    /* dict restricted modes */\n    if (dictContentType == ZSTD_dct_rawContent)\n        return ZSTD_loadDictionaryContent(ms, ls, ws, params, dict, dictSize, dtlm, tfp);\n\n    if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) {\n        if (dictContentType == ZSTD_dct_auto) {\n            DEBUGLOG(4, \"raw content dictionary detected\");\n            return ZSTD_loadDictionaryContent(\n                ms, ls, ws, params, dict, dictSize, dtlm, tfp);\n        }\n        RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong, \"\");\n        assert(0);   /* impossible */\n    }\n\n    /* dict as full zstd dictionary */\n    return ZSTD_loadZstdDictionary(\n        bs, ms, ws, params, dict, dictSize, dtlm, tfp, workspace);\n}\n\n#define ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF (128 KB)\n#define ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER (6ULL)\n\n/*! ZSTD_compressBegin_internal() :\n * Assumption : either @dict OR @cdict (or none) is non-NULL, never both\n * @return : 0, or an error code */\nstatic size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,\n                                    const void* dict, size_t dictSize,\n                                    ZSTD_dictContentType_e dictContentType,\n                                    ZSTD_dictTableLoadMethod_e dtlm,\n                                    const ZSTD_CDict* cdict,\n                                    const ZSTD_CCtx_params* params, U64 pledgedSrcSize,\n                                    ZSTD_buffered_policy_e zbuff)\n{\n    size_t const dictContentSize = cdict ? cdict->dictContentSize : dictSize;\n#if ZSTD_TRACE\n    cctx->traceCtx = (ZSTD_trace_compress_begin != NULL) ? ZSTD_trace_compress_begin(cctx) : 0;\n#endif\n    DEBUGLOG(4, \"ZSTD_compressBegin_internal: wlog=%u\", params->cParams.windowLog);\n    /* params are supposed to be fully validated at this point */\n    assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams)));\n    assert(!((dict) && (cdict)));  /* either dict or cdict, not both */\n    if ( (cdict)\n      && (cdict->dictContentSize > 0)\n      && ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF\n        || pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER\n        || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN\n        || cdict->compressionLevel == 0)\n      && (params->attachDictPref != ZSTD_dictForceLoad) ) {\n        return ZSTD_resetCCtx_usingCDict(cctx, cdict, params, pledgedSrcSize, zbuff);\n    }\n\n    FORWARD_IF_ERROR( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,\n                                     dictContentSize,\n                                     ZSTDcrp_makeClean, zbuff) , \"\");\n    {   size_t const dictID = cdict ?\n                ZSTD_compress_insertDictionary(\n                        cctx->blockState.prevCBlock, &cctx->blockState.matchState,\n                        &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, cdict->dictContent,\n                        cdict->dictContentSize, cdict->dictContentType, dtlm,\n                        ZSTD_tfp_forCCtx, cctx->tmpWorkspace)\n              : ZSTD_compress_insertDictionary(\n                        cctx->blockState.prevCBlock, &cctx->blockState.matchState,\n                        &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, dict, dictSize,\n                        dictContentType, dtlm, ZSTD_tfp_forCCtx, cctx->tmpWorkspace);\n        FORWARD_IF_ERROR(dictID, \"ZSTD_compress_insertDictionary failed\");\n        assert(dictID <= UINT_MAX);\n        cctx->dictID = (U32)dictID;\n        cctx->dictContentSize = dictContentSize;\n    }\n    return 0;\n}\n\nsize_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,\n                                    const void* dict, size_t dictSize,\n                                    ZSTD_dictContentType_e dictContentType,\n                                    ZSTD_dictTableLoadMethod_e dtlm,\n                                    const ZSTD_CDict* cdict,\n                                    const ZSTD_CCtx_params* params,\n                                    unsigned long long pledgedSrcSize)\n{\n    DEBUGLOG(4, \"ZSTD_compressBegin_advanced_internal: wlog=%u\", params->cParams.windowLog);\n    /* compression parameters verification and optimization */\n    FORWARD_IF_ERROR( ZSTD_checkCParams(params->cParams) , \"\");\n    return ZSTD_compressBegin_internal(cctx,\n                                       dict, dictSize, dictContentType, dtlm,\n                                       cdict,\n                                       params, pledgedSrcSize,\n                                       ZSTDb_not_buffered);\n}\n\n/*! ZSTD_compressBegin_advanced() :\n*   @return : 0, or an error code */\nsize_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,\n                             const void* dict, size_t dictSize,\n                                   ZSTD_parameters params, unsigned long long pledgedSrcSize)\n{\n    ZSTD_CCtx_params cctxParams;\n    ZSTD_CCtxParams_init_internal(&cctxParams, &params, ZSTD_NO_CLEVEL);\n    return ZSTD_compressBegin_advanced_internal(cctx,\n                                            dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast,\n                                            NULL /*cdict*/,\n                                            &cctxParams, pledgedSrcSize);\n}\n\nstatic size_t\nZSTD_compressBegin_usingDict_deprecated(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel)\n{\n    ZSTD_CCtx_params cctxParams;\n    {   ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_noAttachDict);\n        ZSTD_CCtxParams_init_internal(&cctxParams, &params, (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel);\n    }\n    DEBUGLOG(4, \"ZSTD_compressBegin_usingDict (dictSize=%u)\", (unsigned)dictSize);\n    return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,\n                                       &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered);\n}\n\nsize_t\nZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel)\n{\n    return ZSTD_compressBegin_usingDict_deprecated(cctx, dict, dictSize, compressionLevel);\n}\n\nsize_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel)\n{\n    return ZSTD_compressBegin_usingDict_deprecated(cctx, NULL, 0, compressionLevel);\n}\n\n\n/*! ZSTD_writeEpilogue() :\n*   Ends a frame.\n*   @return : nb of bytes written into dst (or an error code) */\nstatic size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)\n{\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* op = ostart;\n\n    DEBUGLOG(4, \"ZSTD_writeEpilogue\");\n    RETURN_ERROR_IF(cctx->stage == ZSTDcs_created, stage_wrong, \"init missing\");\n\n    /* special case : empty frame */\n    if (cctx->stage == ZSTDcs_init) {\n        size_t fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams, 0, 0);\n        FORWARD_IF_ERROR(fhSize, \"ZSTD_writeFrameHeader failed\");\n        dstCapacity -= fhSize;\n        op += fhSize;\n        cctx->stage = ZSTDcs_ongoing;\n    }\n\n    if (cctx->stage != ZSTDcs_ending) {\n        /* write one last empty block, make it the \"last\" block */\n        U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1) + 0;\n        ZSTD_STATIC_ASSERT(ZSTD_BLOCKHEADERSIZE == 3);\n        RETURN_ERROR_IF(dstCapacity<3, dstSize_tooSmall, \"no room for epilogue\");\n        MEM_writeLE24(op, cBlockHeader24);\n        op += ZSTD_blockHeaderSize;\n        dstCapacity -= ZSTD_blockHeaderSize;\n    }\n\n    if (cctx->appliedParams.fParams.checksumFlag) {\n        U32 const checksum = (U32) XXH64_digest(&cctx->xxhState);\n        RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, \"no room for checksum\");\n        DEBUGLOG(4, \"ZSTD_writeEpilogue: write checksum : %08X\", (unsigned)checksum);\n        MEM_writeLE32(op, checksum);\n        op += 4;\n    }\n\n    cctx->stage = ZSTDcs_created;  /* return to \"created but no init\" status */\n    return (size_t)(op-ostart);\n}\n\nvoid ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize)\n{\n#if ZSTD_TRACE\n    if (cctx->traceCtx && ZSTD_trace_compress_end != NULL) {\n        int const streaming = cctx->inBuffSize > 0 || cctx->outBuffSize > 0 || cctx->appliedParams.nbWorkers > 0;\n        ZSTD_Trace trace;\n        ZSTD_memset(&trace, 0, sizeof(trace));\n        trace.version = ZSTD_VERSION_NUMBER;\n        trace.streaming = streaming;\n        trace.dictionaryID = cctx->dictID;\n        trace.dictionarySize = cctx->dictContentSize;\n        trace.uncompressedSize = cctx->consumedSrcSize;\n        trace.compressedSize = cctx->producedCSize + extraCSize;\n        trace.params = &cctx->appliedParams;\n        trace.cctx = cctx;\n        ZSTD_trace_compress_end(cctx->traceCtx, &trace);\n    }\n    cctx->traceCtx = 0;\n#else\n    (void)cctx;\n    (void)extraCSize;\n#endif\n}\n\nsize_t ZSTD_compressEnd_public(ZSTD_CCtx* cctx,\n                               void* dst, size_t dstCapacity,\n                         const void* src, size_t srcSize)\n{\n    size_t endResult;\n    size_t const cSize = ZSTD_compressContinue_internal(cctx,\n                                dst, dstCapacity, src, srcSize,\n                                1 /* frame mode */, 1 /* last chunk */);\n    FORWARD_IF_ERROR(cSize, \"ZSTD_compressContinue_internal failed\");\n    endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize);\n    FORWARD_IF_ERROR(endResult, \"ZSTD_writeEpilogue failed\");\n    assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));\n    if (cctx->pledgedSrcSizePlusOne != 0) {  /* control src size */\n        ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);\n        DEBUGLOG(4, \"end of frame : controlling src size\");\n        RETURN_ERROR_IF(\n            cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1,\n            srcSize_wrong,\n             \"error : pledgedSrcSize = %u, while realSrcSize = %u\",\n            (unsigned)cctx->pledgedSrcSizePlusOne-1,\n            (unsigned)cctx->consumedSrcSize);\n    }\n    ZSTD_CCtx_trace(cctx, endResult);\n    return cSize + endResult;\n}\n\n/* NOTE: Must just wrap ZSTD_compressEnd_public() */\nsize_t ZSTD_compressEnd(ZSTD_CCtx* cctx,\n                        void* dst, size_t dstCapacity,\n                  const void* src, size_t srcSize)\n{\n    return ZSTD_compressEnd_public(cctx, dst, dstCapacity, src, srcSize);\n}\n\nsize_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,\n                               void* dst, size_t dstCapacity,\n                         const void* src, size_t srcSize,\n                         const void* dict,size_t dictSize,\n                               ZSTD_parameters params)\n{\n    DEBUGLOG(4, \"ZSTD_compress_advanced\");\n    FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams), \"\");\n    ZSTD_CCtxParams_init_internal(&cctx->simpleApiParams, &params, ZSTD_NO_CLEVEL);\n    return ZSTD_compress_advanced_internal(cctx,\n                                           dst, dstCapacity,\n                                           src, srcSize,\n                                           dict, dictSize,\n                                           &cctx->simpleApiParams);\n}\n\n/* Internal */\nsize_t ZSTD_compress_advanced_internal(\n        ZSTD_CCtx* cctx,\n        void* dst, size_t dstCapacity,\n        const void* src, size_t srcSize,\n        const void* dict,size_t dictSize,\n        const ZSTD_CCtx_params* params)\n{\n    DEBUGLOG(4, \"ZSTD_compress_advanced_internal (srcSize:%u)\", (unsigned)srcSize);\n    FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,\n                         dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,\n                         params, srcSize, ZSTDb_not_buffered) , \"\");\n    return ZSTD_compressEnd_public(cctx, dst, dstCapacity, src, srcSize);\n}\n\nsize_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx,\n                               void* dst, size_t dstCapacity,\n                         const void* src, size_t srcSize,\n                         const void* dict, size_t dictSize,\n                               int compressionLevel)\n{\n    {\n        ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, srcSize, dict ? dictSize : 0, ZSTD_cpm_noAttachDict);\n        assert(params.fParams.contentSizeFlag == 1);\n        ZSTD_CCtxParams_init_internal(&cctx->simpleApiParams, &params, (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT: compressionLevel);\n    }\n    DEBUGLOG(4, \"ZSTD_compress_usingDict (srcSize=%u)\", (unsigned)srcSize);\n    return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, &cctx->simpleApiParams);\n}\n\nsize_t ZSTD_compressCCtx(ZSTD_CCtx* cctx,\n                         void* dst, size_t dstCapacity,\n                   const void* src, size_t srcSize,\n                         int compressionLevel)\n{\n    DEBUGLOG(4, \"ZSTD_compressCCtx (srcSize=%u)\", (unsigned)srcSize);\n    assert(cctx != NULL);\n    return ZSTD_compress_usingDict(cctx, dst, dstCapacity, src, srcSize, NULL, 0, compressionLevel);\n}\n\nsize_t ZSTD_compress(void* dst, size_t dstCapacity,\n               const void* src, size_t srcSize,\n                     int compressionLevel)\n{\n    size_t result;\n#if ZSTD_COMPRESS_HEAPMODE\n    ZSTD_CCtx* cctx = ZSTD_createCCtx();\n    RETURN_ERROR_IF(!cctx, memory_allocation, \"ZSTD_createCCtx failed\");\n    result = ZSTD_compressCCtx(cctx, dst, dstCapacity, src, srcSize, compressionLevel);\n    ZSTD_freeCCtx(cctx);\n#else\n    ZSTD_CCtx ctxBody;\n    ZSTD_initCCtx(&ctxBody, ZSTD_defaultCMem);\n    result = ZSTD_compressCCtx(&ctxBody, dst, dstCapacity, src, srcSize, compressionLevel);\n    ZSTD_freeCCtxContent(&ctxBody);   /* can't free ctxBody itself, as it's on stack; free only heap content */\n#endif\n    return result;\n}\n\n\n/* =====  Dictionary API  ===== */\n\n/*! ZSTD_estimateCDictSize_advanced() :\n *  Estimate amount of memory that will be needed to create a dictionary with following arguments */\nsize_t ZSTD_estimateCDictSize_advanced(\n        size_t dictSize, ZSTD_compressionParameters cParams,\n        ZSTD_dictLoadMethod_e dictLoadMethod)\n{\n    DEBUGLOG(5, \"sizeof(ZSTD_CDict) : %u\", (unsigned)sizeof(ZSTD_CDict));\n    return ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict))\n         + ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE)\n         /* enableDedicatedDictSearch == 1 ensures that CDict estimation will not be too small\n          * in case we are using DDS with row-hash. */\n         + ZSTD_sizeof_matchState(&cParams, ZSTD_resolveRowMatchFinderMode(ZSTD_ps_auto, &cParams),\n                                  /* enableDedicatedDictSearch */ 1, /* forCCtx */ 0)\n         + (dictLoadMethod == ZSTD_dlm_byRef ? 0\n            : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void *))));\n}\n\nsize_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel)\n{\n    ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);\n    return ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy);\n}\n\nsize_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)\n{\n    if (cdict==NULL) return 0;   /* support sizeof on NULL */\n    DEBUGLOG(5, \"sizeof(*cdict) : %u\", (unsigned)sizeof(*cdict));\n    /* cdict may be in the workspace */\n    return (cdict->workspace.workspace == cdict ? 0 : sizeof(*cdict))\n        + ZSTD_cwksp_sizeof(&cdict->workspace);\n}\n\nstatic size_t ZSTD_initCDict_internal(\n                    ZSTD_CDict* cdict,\n              const void* dictBuffer, size_t dictSize,\n                    ZSTD_dictLoadMethod_e dictLoadMethod,\n                    ZSTD_dictContentType_e dictContentType,\n                    ZSTD_CCtx_params params)\n{\n    DEBUGLOG(3, \"ZSTD_initCDict_internal (dictContentType:%u)\", (unsigned)dictContentType);\n    assert(!ZSTD_checkCParams(params.cParams));\n    cdict->matchState.cParams = params.cParams;\n    cdict->matchState.dedicatedDictSearch = params.enableDedicatedDictSearch;\n    if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) {\n        cdict->dictContent = dictBuffer;\n    } else {\n         void *internalBuffer = ZSTD_cwksp_reserve_object(&cdict->workspace, ZSTD_cwksp_align(dictSize, sizeof(void*)));\n        RETURN_ERROR_IF(!internalBuffer, memory_allocation, \"NULL pointer!\");\n        cdict->dictContent = internalBuffer;\n        ZSTD_memcpy(internalBuffer, dictBuffer, dictSize);\n    }\n    cdict->dictContentSize = dictSize;\n    cdict->dictContentType = dictContentType;\n\n    cdict->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cdict->workspace, HUF_WORKSPACE_SIZE);\n\n\n    /* Reset the state to no dictionary */\n    ZSTD_reset_compressedBlockState(&cdict->cBlockState);\n    FORWARD_IF_ERROR(ZSTD_reset_matchState(\n        &cdict->matchState,\n        &cdict->workspace,\n        &params.cParams,\n        params.useRowMatchFinder,\n        ZSTDcrp_makeClean,\n        ZSTDirp_reset,\n        ZSTD_resetTarget_CDict), \"\");\n    /* (Maybe) load the dictionary\n     * Skips loading the dictionary if it is < 8 bytes.\n     */\n    {   params.compressionLevel = ZSTD_CLEVEL_DEFAULT;\n        params.fParams.contentSizeFlag = 1;\n        {   size_t const dictID = ZSTD_compress_insertDictionary(\n                    &cdict->cBlockState, &cdict->matchState, NULL, &cdict->workspace,\n                    &params, cdict->dictContent, cdict->dictContentSize,\n                    dictContentType, ZSTD_dtlm_full, ZSTD_tfp_forCDict, cdict->entropyWorkspace);\n            FORWARD_IF_ERROR(dictID, \"ZSTD_compress_insertDictionary failed\");\n            assert(dictID <= (size_t)(U32)-1);\n            cdict->dictID = (U32)dictID;\n        }\n    }\n\n    return 0;\n}\n\nstatic ZSTD_CDict*\nZSTD_createCDict_advanced_internal(size_t dictSize,\n                                ZSTD_dictLoadMethod_e dictLoadMethod,\n                                ZSTD_compressionParameters cParams,\n                                ZSTD_ParamSwitch_e useRowMatchFinder,\n                                int enableDedicatedDictSearch,\n                                ZSTD_customMem customMem)\n{\n    if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;\n    DEBUGLOG(3, \"ZSTD_createCDict_advanced_internal (dictSize=%u)\", (unsigned)dictSize);\n\n    {   size_t const workspaceSize =\n            ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict)) +\n            ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE) +\n            ZSTD_sizeof_matchState(&cParams, useRowMatchFinder, enableDedicatedDictSearch, /* forCCtx */ 0) +\n            (dictLoadMethod == ZSTD_dlm_byRef ? 0\n             : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void*))));\n        void* const workspace = ZSTD_customMalloc(workspaceSize, customMem);\n        ZSTD_cwksp ws;\n        ZSTD_CDict* cdict;\n\n        if (!workspace) {\n            ZSTD_customFree(workspace, customMem);\n            return NULL;\n        }\n\n        ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_dynamic_alloc);\n\n        cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict));\n        assert(cdict != NULL);\n        ZSTD_cwksp_move(&cdict->workspace, &ws);\n        cdict->customMem = customMem;\n        cdict->compressionLevel = ZSTD_NO_CLEVEL; /* signals advanced API usage */\n        cdict->useRowMatchFinder = useRowMatchFinder;\n        return cdict;\n    }\n}\n\nZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,\n                                      ZSTD_dictLoadMethod_e dictLoadMethod,\n                                      ZSTD_dictContentType_e dictContentType,\n                                      ZSTD_compressionParameters cParams,\n                                      ZSTD_customMem customMem)\n{\n    ZSTD_CCtx_params cctxParams;\n    ZSTD_memset(&cctxParams, 0, sizeof(cctxParams));\n    DEBUGLOG(3, \"ZSTD_createCDict_advanced, dictSize=%u, mode=%u\", (unsigned)dictSize, (unsigned)dictContentType);\n    ZSTD_CCtxParams_init(&cctxParams, 0);\n    cctxParams.cParams = cParams;\n    cctxParams.customMem = customMem;\n    return ZSTD_createCDict_advanced2(\n        dictBuffer, dictSize,\n        dictLoadMethod, dictContentType,\n        &cctxParams, customMem);\n}\n\nZSTD_CDict* ZSTD_createCDict_advanced2(\n        const void* dict, size_t dictSize,\n        ZSTD_dictLoadMethod_e dictLoadMethod,\n        ZSTD_dictContentType_e dictContentType,\n        const ZSTD_CCtx_params* originalCctxParams,\n        ZSTD_customMem customMem)\n{\n    ZSTD_CCtx_params cctxParams = *originalCctxParams;\n    ZSTD_compressionParameters cParams;\n    ZSTD_CDict* cdict;\n\n    DEBUGLOG(3, \"ZSTD_createCDict_advanced2, dictSize=%u, mode=%u\", (unsigned)dictSize, (unsigned)dictContentType);\n    if (!customMem.customAlloc ^ !customMem.customFree) return NULL;\n\n    if (cctxParams.enableDedicatedDictSearch) {\n        cParams = ZSTD_dedicatedDictSearch_getCParams(\n            cctxParams.compressionLevel, dictSize);\n        ZSTD_overrideCParams(&cParams, &cctxParams.cParams);\n    } else {\n        cParams = ZSTD_getCParamsFromCCtxParams(\n            &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);\n    }\n\n    if (!ZSTD_dedicatedDictSearch_isSupported(&cParams)) {\n        /* Fall back to non-DDSS params */\n        cctxParams.enableDedicatedDictSearch = 0;\n        cParams = ZSTD_getCParamsFromCCtxParams(\n            &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);\n    }\n\n    DEBUGLOG(3, \"ZSTD_createCDict_advanced2: DedicatedDictSearch=%u\", cctxParams.enableDedicatedDictSearch);\n    cctxParams.cParams = cParams;\n    cctxParams.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams.useRowMatchFinder, &cParams);\n\n    cdict = ZSTD_createCDict_advanced_internal(dictSize,\n                        dictLoadMethod, cctxParams.cParams,\n                        cctxParams.useRowMatchFinder, cctxParams.enableDedicatedDictSearch,\n                        customMem);\n\n    if (!cdict || ZSTD_isError( ZSTD_initCDict_internal(cdict,\n                                    dict, dictSize,\n                                    dictLoadMethod, dictContentType,\n                                    cctxParams) )) {\n        ZSTD_freeCDict(cdict);\n        return NULL;\n    }\n\n    return cdict;\n}\n\nZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel)\n{\n    ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);\n    ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dict, dictSize,\n                                                  ZSTD_dlm_byCopy, ZSTD_dct_auto,\n                                                  cParams, ZSTD_defaultCMem);\n    if (cdict)\n        cdict->compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel;\n    return cdict;\n}\n\nZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel)\n{\n    ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);\n    ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dict, dictSize,\n                                     ZSTD_dlm_byRef, ZSTD_dct_auto,\n                                     cParams, ZSTD_defaultCMem);\n    if (cdict)\n        cdict->compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel;\n    return cdict;\n}\n\nsize_t ZSTD_freeCDict(ZSTD_CDict* cdict)\n{\n    if (cdict==NULL) return 0;   /* support free on NULL */\n    {   ZSTD_customMem const cMem = cdict->customMem;\n        int cdictInWorkspace = ZSTD_cwksp_owns_buffer(&cdict->workspace, cdict);\n        ZSTD_cwksp_free(&cdict->workspace, cMem);\n        if (!cdictInWorkspace) {\n            ZSTD_customFree(cdict, cMem);\n        }\n        return 0;\n    }\n}\n\n/*! ZSTD_initStaticCDict_advanced() :\n *  Generate a digested dictionary in provided memory area.\n *  workspace: The memory area to emplace the dictionary into.\n *             Provided pointer must 8-bytes aligned.\n *             It must outlive dictionary usage.\n *  workspaceSize: Use ZSTD_estimateCDictSize()\n *                 to determine how large workspace must be.\n *  cParams : use ZSTD_getCParams() to transform a compression level\n *            into its relevant cParams.\n * @return : pointer to ZSTD_CDict*, or NULL if error (size too small)\n *  Note : there is no corresponding \"free\" function.\n *         Since workspace was allocated externally, it must be freed externally.\n */\nconst ZSTD_CDict* ZSTD_initStaticCDict(\n                                 void* workspace, size_t workspaceSize,\n                           const void* dict, size_t dictSize,\n                                 ZSTD_dictLoadMethod_e dictLoadMethod,\n                                 ZSTD_dictContentType_e dictContentType,\n                                 ZSTD_compressionParameters cParams)\n{\n    ZSTD_ParamSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(ZSTD_ps_auto, &cParams);\n    /* enableDedicatedDictSearch == 1 ensures matchstate is not too small in case this CDict will be used for DDS + row hash */\n    size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, useRowMatchFinder, /* enableDedicatedDictSearch */ 1, /* forCCtx */ 0);\n    size_t const neededSize = ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict))\n                            + (dictLoadMethod == ZSTD_dlm_byRef ? 0\n                               : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void*))))\n                            + ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE)\n                            + matchStateSize;\n    ZSTD_CDict* cdict;\n    ZSTD_CCtx_params params;\n\n    DEBUGLOG(4, \"ZSTD_initStaticCDict (dictSize==%u)\", (unsigned)dictSize);\n    if ((size_t)workspace & 7) return NULL;  /* 8-aligned */\n\n    {\n        ZSTD_cwksp ws;\n        ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_static_alloc);\n        cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict));\n        if (cdict == NULL) return NULL;\n        ZSTD_cwksp_move(&cdict->workspace, &ws);\n    }\n\n    if (workspaceSize < neededSize) return NULL;\n\n    ZSTD_CCtxParams_init(&params, 0);\n    params.cParams = cParams;\n    params.useRowMatchFinder = useRowMatchFinder;\n    cdict->useRowMatchFinder = useRowMatchFinder;\n    cdict->compressionLevel = ZSTD_NO_CLEVEL;\n\n    if (ZSTD_isError( ZSTD_initCDict_internal(cdict,\n                                              dict, dictSize,\n                                              dictLoadMethod, dictContentType,\n                                              params) ))\n        return NULL;\n\n    return cdict;\n}\n\nZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict)\n{\n    assert(cdict != NULL);\n    return cdict->matchState.cParams;\n}\n\n/*! ZSTD_getDictID_fromCDict() :\n *  Provides the dictID of the dictionary loaded into `cdict`.\n *  If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.\n *  Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */\nunsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* cdict)\n{\n    if (cdict==NULL) return 0;\n    return cdict->dictID;\n}\n\n/* ZSTD_compressBegin_usingCDict_internal() :\n * Implementation of various ZSTD_compressBegin_usingCDict* functions.\n */\nstatic size_t ZSTD_compressBegin_usingCDict_internal(\n    ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict,\n    ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)\n{\n    ZSTD_CCtx_params cctxParams;\n    DEBUGLOG(4, \"ZSTD_compressBegin_usingCDict_internal\");\n    RETURN_ERROR_IF(cdict==NULL, dictionary_wrong, \"NULL pointer!\");\n    /* Initialize the cctxParams from the cdict */\n    {\n        ZSTD_parameters params;\n        params.fParams = fParams;\n        params.cParams = ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF\n                        || pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER\n                        || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN\n                        || cdict->compressionLevel == 0 ) ?\n                ZSTD_getCParamsFromCDict(cdict)\n              : ZSTD_getCParams(cdict->compressionLevel,\n                                pledgedSrcSize,\n                                cdict->dictContentSize);\n        ZSTD_CCtxParams_init_internal(&cctxParams, &params, cdict->compressionLevel);\n    }\n    /* Increase window log to fit the entire dictionary and source if the\n     * source size is known. Limit the increase to 19, which is the\n     * window log for compression level 1 with the largest source size.\n     */\n    if (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN) {\n        U32 const limitedSrcSize = (U32)MIN(pledgedSrcSize, 1U << 19);\n        U32 const limitedSrcLog = limitedSrcSize > 1 ? ZSTD_highbit32(limitedSrcSize - 1) + 1 : 1;\n        cctxParams.cParams.windowLog = MAX(cctxParams.cParams.windowLog, limitedSrcLog);\n    }\n    return ZSTD_compressBegin_internal(cctx,\n                                        NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast,\n                                        cdict,\n                                        &cctxParams, pledgedSrcSize,\n                                        ZSTDb_not_buffered);\n}\n\n\n/* ZSTD_compressBegin_usingCDict_advanced() :\n * This function is DEPRECATED.\n * cdict must be != NULL */\nsize_t ZSTD_compressBegin_usingCDict_advanced(\n    ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict,\n    ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)\n{\n    return ZSTD_compressBegin_usingCDict_internal(cctx, cdict, fParams, pledgedSrcSize);\n}\n\n/* ZSTD_compressBegin_usingCDict() :\n * cdict must be != NULL */\nsize_t ZSTD_compressBegin_usingCDict_deprecated(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)\n{\n    ZSTD_frameParameters const fParams = { 0 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };\n    return ZSTD_compressBegin_usingCDict_internal(cctx, cdict, fParams, ZSTD_CONTENTSIZE_UNKNOWN);\n}\n\nsize_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)\n{\n    return ZSTD_compressBegin_usingCDict_deprecated(cctx, cdict);\n}\n\n/*! ZSTD_compress_usingCDict_internal():\n * Implementation of various ZSTD_compress_usingCDict* functions.\n */\nstatic size_t ZSTD_compress_usingCDict_internal(ZSTD_CCtx* cctx,\n                                void* dst, size_t dstCapacity,\n                                const void* src, size_t srcSize,\n                                const ZSTD_CDict* cdict, ZSTD_frameParameters fParams)\n{\n    FORWARD_IF_ERROR(ZSTD_compressBegin_usingCDict_internal(cctx, cdict, fParams, srcSize), \"\"); /* will check if cdict != NULL */\n    return ZSTD_compressEnd_public(cctx, dst, dstCapacity, src, srcSize);\n}\n\n/*! ZSTD_compress_usingCDict_advanced():\n * This function is DEPRECATED.\n */\nsize_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,\n                                void* dst, size_t dstCapacity,\n                                const void* src, size_t srcSize,\n                                const ZSTD_CDict* cdict, ZSTD_frameParameters fParams)\n{\n    return ZSTD_compress_usingCDict_internal(cctx, dst, dstCapacity, src, srcSize, cdict, fParams);\n}\n\n/*! ZSTD_compress_usingCDict() :\n *  Compression using a digested Dictionary.\n *  Faster startup than ZSTD_compress_usingDict(), recommended when same dictionary is used multiple times.\n *  Note that compression parameters are decided at CDict creation time\n *  while frame parameters are hardcoded */\nsize_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,\n                                void* dst, size_t dstCapacity,\n                                const void* src, size_t srcSize,\n                                const ZSTD_CDict* cdict)\n{\n    ZSTD_frameParameters const fParams = { 1 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };\n    return ZSTD_compress_usingCDict_internal(cctx, dst, dstCapacity, src, srcSize, cdict, fParams);\n}\n\n\n\n/* ******************************************************************\n*  Streaming\n********************************************************************/\n\nZSTD_CStream* ZSTD_createCStream(void)\n{\n    DEBUGLOG(3, \"ZSTD_createCStream\");\n    return ZSTD_createCStream_advanced(ZSTD_defaultCMem);\n}\n\nZSTD_CStream* ZSTD_initStaticCStream(void *workspace, size_t workspaceSize)\n{\n    return ZSTD_initStaticCCtx(workspace, workspaceSize);\n}\n\nZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem)\n{   /* CStream and CCtx are now same object */\n    return ZSTD_createCCtx_advanced(customMem);\n}\n\nsize_t ZSTD_freeCStream(ZSTD_CStream* zcs)\n{\n    return ZSTD_freeCCtx(zcs);   /* same object */\n}\n\n\n\n/*======   Initialization   ======*/\n\nsize_t ZSTD_CStreamInSize(void)  { return ZSTD_BLOCKSIZE_MAX; }\n\nsize_t ZSTD_CStreamOutSize(void)\n{\n    return ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */ ;\n}\n\nstatic ZSTD_CParamMode_e ZSTD_getCParamMode(ZSTD_CDict const* cdict, ZSTD_CCtx_params const* params, U64 pledgedSrcSize)\n{\n    if (cdict != NULL && ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize))\n        return ZSTD_cpm_attachDict;\n    else\n        return ZSTD_cpm_noAttachDict;\n}\n\n/* ZSTD_resetCStream():\n * pledgedSrcSize == 0 means \"unknown\" */\nsize_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pss)\n{\n    /* temporary : 0 interpreted as \"unknown\" during transition period.\n     * Users willing to specify \"unknown\" **must** use ZSTD_CONTENTSIZE_UNKNOWN.\n     * 0 will be interpreted as \"empty\" in the future.\n     */\n    U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;\n    DEBUGLOG(4, \"ZSTD_resetCStream: pledgedSrcSize = %u\", (unsigned)pledgedSrcSize);\n    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , \"\");\n    return 0;\n}\n\n/*! ZSTD_initCStream_internal() :\n *  Note : for lib/compress only. Used by zstdmt_compress.c.\n *  Assumption 1 : params are valid\n *  Assumption 2 : either dict, or cdict, is defined, not both */\nsize_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,\n                    const void* dict, size_t dictSize, const ZSTD_CDict* cdict,\n                    const ZSTD_CCtx_params* params,\n                    unsigned long long pledgedSrcSize)\n{\n    DEBUGLOG(4, \"ZSTD_initCStream_internal\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , \"\");\n    assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams)));\n    zcs->requestedParams = *params;\n    assert(!((dict) && (cdict)));  /* either dict or cdict, not both */\n    if (dict) {\n        FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , \"\");\n    } else {\n        /* Dictionary is cleared if !cdict */\n        FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , \"\");\n    }\n    return 0;\n}\n\n/* ZSTD_initCStream_usingCDict_advanced() :\n * same as ZSTD_initCStream_usingCDict(), with control over frame parameters */\nsize_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,\n                                            const ZSTD_CDict* cdict,\n                                            ZSTD_frameParameters fParams,\n                                            unsigned long long pledgedSrcSize)\n{\n    DEBUGLOG(4, \"ZSTD_initCStream_usingCDict_advanced\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , \"\");\n    zcs->requestedParams.fParams = fParams;\n    FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , \"\");\n    return 0;\n}\n\n/* note : cdict must outlive compression session */\nsize_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)\n{\n    DEBUGLOG(4, \"ZSTD_initCStream_usingCDict\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , \"\");\n    return 0;\n}\n\n\n/* ZSTD_initCStream_advanced() :\n * pledgedSrcSize must be exact.\n * if srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN.\n * dict is loaded with default parameters ZSTD_dct_auto and ZSTD_dlm_byCopy. */\nsize_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,\n                                 const void* dict, size_t dictSize,\n                                 ZSTD_parameters params, unsigned long long pss)\n{\n    /* for compatibility with older programs relying on this behavior.\n     * Users should now specify ZSTD_CONTENTSIZE_UNKNOWN.\n     * This line will be removed in the future.\n     */\n    U64 const pledgedSrcSize = (pss==0 && params.fParams.contentSizeFlag==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;\n    DEBUGLOG(4, \"ZSTD_initCStream_advanced\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , \"\");\n    FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , \"\");\n    ZSTD_CCtxParams_setZstdParams(&zcs->requestedParams, &params);\n    FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , \"\");\n    return 0;\n}\n\nsize_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)\n{\n    DEBUGLOG(4, \"ZSTD_initCStream_usingDict\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , \"\");\n    return 0;\n}\n\nsize_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pss)\n{\n    /* temporary : 0 interpreted as \"unknown\" during transition period.\n     * Users willing to specify \"unknown\" **must** use ZSTD_CONTENTSIZE_UNKNOWN.\n     * 0 will be interpreted as \"empty\" in the future.\n     */\n    U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;\n    DEBUGLOG(4, \"ZSTD_initCStream_srcSize\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , \"\");\n    return 0;\n}\n\nsize_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)\n{\n    DEBUGLOG(4, \"ZSTD_initCStream\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , \"\");\n    return 0;\n}\n\n/*======   Compression   ======*/\n\nstatic size_t ZSTD_nextInputSizeHint(const ZSTD_CCtx* cctx)\n{\n    if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) {\n        return cctx->blockSizeMax - cctx->stableIn_notConsumed;\n    }\n    assert(cctx->appliedParams.inBufferMode == ZSTD_bm_buffered);\n    {   size_t hintInSize = cctx->inBuffTarget - cctx->inBuffPos;\n        if (hintInSize==0) hintInSize = cctx->blockSizeMax;\n        return hintInSize;\n    }\n}\n\n/** ZSTD_compressStream_generic():\n *  internal function for all *compressStream*() variants\n * @return : hint size for next input to complete ongoing block */\nstatic size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,\n                                          ZSTD_outBuffer* output,\n                                          ZSTD_inBuffer* input,\n                                          ZSTD_EndDirective const flushMode)\n{\n    const char* const istart = (assert(input != NULL), (const char*)input->src);\n    const char* const iend = (istart != NULL) ? istart + input->size : istart;\n    const char* ip = (istart != NULL) ? istart + input->pos : istart;\n    char* const ostart = (assert(output != NULL), (char*)output->dst);\n    char* const oend = (ostart != NULL) ? ostart + output->size : ostart;\n    char* op = (ostart != NULL) ? ostart + output->pos : ostart;\n    U32 someMoreWork = 1;\n\n    /* check expectations */\n    DEBUGLOG(5, \"ZSTD_compressStream_generic, flush=%i, srcSize = %zu\", (int)flushMode, input->size - input->pos);\n    assert(zcs != NULL);\n    if (zcs->appliedParams.inBufferMode == ZSTD_bm_stable) {\n        assert(input->pos >= zcs->stableIn_notConsumed);\n        input->pos -= zcs->stableIn_notConsumed;\n        if (ip) ip -= zcs->stableIn_notConsumed;\n        zcs->stableIn_notConsumed = 0;\n    }\n    if (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered) {\n        assert(zcs->inBuff != NULL);\n        assert(zcs->inBuffSize > 0);\n    }\n    if (zcs->appliedParams.outBufferMode == ZSTD_bm_buffered) {\n        assert(zcs->outBuff !=  NULL);\n        assert(zcs->outBuffSize > 0);\n    }\n    if (input->src == NULL) assert(input->size == 0);\n    assert(input->pos <= input->size);\n    if (output->dst == NULL) assert(output->size == 0);\n    assert(output->pos <= output->size);\n    assert((U32)flushMode <= (U32)ZSTD_e_end);\n\n    while (someMoreWork) {\n        switch(zcs->streamStage)\n        {\n        case zcss_init:\n            RETURN_ERROR(init_missing, \"call ZSTD_initCStream() first!\");\n\n        case zcss_load:\n            if ( (flushMode == ZSTD_e_end)\n              && ( (size_t)(oend-op) >= ZSTD_compressBound((size_t)(iend-ip))     /* Enough output space */\n                || zcs->appliedParams.outBufferMode == ZSTD_bm_stable)  /* OR we are allowed to return dstSizeTooSmall */\n              && (zcs->inBuffPos == 0) ) {\n                /* shortcut to compression pass directly into output buffer */\n                size_t const cSize = ZSTD_compressEnd_public(zcs,\n                                                op, (size_t)(oend-op),\n                                                ip, (size_t)(iend-ip));\n                DEBUGLOG(4, \"ZSTD_compressEnd : cSize=%u\", (unsigned)cSize);\n                FORWARD_IF_ERROR(cSize, \"ZSTD_compressEnd failed\");\n                ip = iend;\n                op += cSize;\n                zcs->frameEnded = 1;\n                ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n                someMoreWork = 0; break;\n            }\n            /* complete loading into inBuffer in buffered mode */\n            if (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered) {\n                size_t const toLoad = zcs->inBuffTarget - zcs->inBuffPos;\n                size_t const loaded = ZSTD_limitCopy(\n                                        zcs->inBuff + zcs->inBuffPos, toLoad,\n                                        ip, (size_t)(iend-ip));\n                zcs->inBuffPos += loaded;\n                if (ip) ip += loaded;\n                if ( (flushMode == ZSTD_e_continue)\n                  && (zcs->inBuffPos < zcs->inBuffTarget) ) {\n                    /* not enough input to fill full block : stop here */\n                    someMoreWork = 0; break;\n                }\n                if ( (flushMode == ZSTD_e_flush)\n                  && (zcs->inBuffPos == zcs->inToCompress) ) {\n                    /* empty */\n                    someMoreWork = 0; break;\n                }\n            } else {\n                assert(zcs->appliedParams.inBufferMode == ZSTD_bm_stable);\n                if ( (flushMode == ZSTD_e_continue)\n                  && ( (size_t)(iend - ip) < zcs->blockSizeMax) ) {\n                    /* can't compress a full block : stop here */\n                    zcs->stableIn_notConsumed = (size_t)(iend - ip);\n                    ip = iend;  /* pretend to have consumed input */\n                    someMoreWork = 0; break;\n                }\n                if ( (flushMode == ZSTD_e_flush)\n                  && (ip == iend) ) {\n                    /* empty */\n                    someMoreWork = 0; break;\n                }\n            }\n            /* compress current block (note : this stage cannot be stopped in the middle) */\n            DEBUGLOG(5, \"stream compression stage (flushMode==%u)\", flushMode);\n            {   int const inputBuffered = (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered);\n                void* cDst;\n                size_t cSize;\n                size_t oSize = (size_t)(oend-op);\n                size_t const iSize = inputBuffered ? zcs->inBuffPos - zcs->inToCompress\n                                                   : MIN((size_t)(iend - ip), zcs->blockSizeMax);\n                if (oSize >= ZSTD_compressBound(iSize) || zcs->appliedParams.outBufferMode == ZSTD_bm_stable)\n                    cDst = op;   /* compress into output buffer, to skip flush stage */\n                else\n                    cDst = zcs->outBuff, oSize = zcs->outBuffSize;\n                if (inputBuffered) {\n                    unsigned const lastBlock = (flushMode == ZSTD_e_end) && (ip==iend);\n                    cSize = lastBlock ?\n                            ZSTD_compressEnd_public(zcs, cDst, oSize,\n                                        zcs->inBuff + zcs->inToCompress, iSize) :\n                            ZSTD_compressContinue_public(zcs, cDst, oSize,\n                                        zcs->inBuff + zcs->inToCompress, iSize);\n                    FORWARD_IF_ERROR(cSize, \"%s\", lastBlock ? \"ZSTD_compressEnd failed\" : \"ZSTD_compressContinue failed\");\n                    zcs->frameEnded = lastBlock;\n                    /* prepare next block */\n                    zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSizeMax;\n                    if (zcs->inBuffTarget > zcs->inBuffSize)\n                        zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSizeMax;\n                    DEBUGLOG(5, \"inBuffTarget:%u / inBuffSize:%u\",\n                            (unsigned)zcs->inBuffTarget, (unsigned)zcs->inBuffSize);\n                    if (!lastBlock)\n                        assert(zcs->inBuffTarget <= zcs->inBuffSize);\n                    zcs->inToCompress = zcs->inBuffPos;\n                } else { /* !inputBuffered, hence ZSTD_bm_stable */\n                    unsigned const lastBlock = (flushMode == ZSTD_e_end) && (ip + iSize == iend);\n                    cSize = lastBlock ?\n                            ZSTD_compressEnd_public(zcs, cDst, oSize, ip, iSize) :\n                            ZSTD_compressContinue_public(zcs, cDst, oSize, ip, iSize);\n                    /* Consume the input prior to error checking to mirror buffered mode. */\n                    if (ip) ip += iSize;\n                    FORWARD_IF_ERROR(cSize, \"%s\", lastBlock ? \"ZSTD_compressEnd failed\" : \"ZSTD_compressContinue failed\");\n                    zcs->frameEnded = lastBlock;\n                    if (lastBlock) assert(ip == iend);\n                }\n                if (cDst == op) {  /* no need to flush */\n                    op += cSize;\n                    if (zcs->frameEnded) {\n                        DEBUGLOG(5, \"Frame completed directly in outBuffer\");\n                        someMoreWork = 0;\n                        ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n                    }\n                    break;\n                }\n                zcs->outBuffContentSize = cSize;\n                zcs->outBuffFlushedSize = 0;\n                zcs->streamStage = zcss_flush; /* pass-through to flush stage */\n            }\n\t    ZSTD_FALLTHROUGH;\n        case zcss_flush:\n            DEBUGLOG(5, \"flush stage\");\n            assert(zcs->appliedParams.outBufferMode == ZSTD_bm_buffered);\n            {   size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize;\n                size_t const flushed = ZSTD_limitCopy(op, (size_t)(oend-op),\n                            zcs->outBuff + zcs->outBuffFlushedSize, toFlush);\n                DEBUGLOG(5, \"toFlush: %u into %u ==> flushed: %u\",\n                            (unsigned)toFlush, (unsigned)(oend-op), (unsigned)flushed);\n                if (flushed)\n                    op += flushed;\n                zcs->outBuffFlushedSize += flushed;\n                if (toFlush!=flushed) {\n                    /* flush not fully completed, presumably because dst is too small */\n                    assert(op==oend);\n                    someMoreWork = 0;\n                    break;\n                }\n                zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0;\n                if (zcs->frameEnded) {\n                    DEBUGLOG(5, \"Frame completed on flush\");\n                    someMoreWork = 0;\n                    ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n                    break;\n                }\n                zcs->streamStage = zcss_load;\n                break;\n            }\n\n        default: /* impossible */\n            assert(0);\n        }\n    }\n\n    input->pos = (size_t)(ip - istart);\n    output->pos = (size_t)(op - ostart);\n    if (zcs->frameEnded) return 0;\n    return ZSTD_nextInputSizeHint(zcs);\n}\n\nstatic size_t ZSTD_nextInputSizeHint_MTorST(const ZSTD_CCtx* cctx)\n{\n#ifdef ZSTD_MULTITHREAD\n    if (cctx->appliedParams.nbWorkers >= 1) {\n        assert(cctx->mtctx != NULL);\n        return ZSTDMT_nextInputSizeHint(cctx->mtctx);\n    }\n#endif\n    return ZSTD_nextInputSizeHint(cctx);\n\n}\n\nsize_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input)\n{\n    FORWARD_IF_ERROR( ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue) , \"\");\n    return ZSTD_nextInputSizeHint_MTorST(zcs);\n}\n\n/* After a compression call set the expected input/output buffer.\n * This is validated at the start of the next compression call.\n */\nstatic void\nZSTD_setBufferExpectations(ZSTD_CCtx* cctx, const ZSTD_outBuffer* output, const ZSTD_inBuffer* input)\n{\n    DEBUGLOG(5, \"ZSTD_setBufferExpectations (for advanced stable in/out modes)\");\n    if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) {\n        cctx->expectedInBuffer = *input;\n    }\n    if (cctx->appliedParams.outBufferMode == ZSTD_bm_stable) {\n        cctx->expectedOutBufferSize = output->size - output->pos;\n    }\n}\n\n/* Validate that the input/output buffers match the expectations set by\n * ZSTD_setBufferExpectations.\n */\nstatic size_t ZSTD_checkBufferStability(ZSTD_CCtx const* cctx,\n                                        ZSTD_outBuffer const* output,\n                                        ZSTD_inBuffer const* input,\n                                        ZSTD_EndDirective endOp)\n{\n    if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) {\n        ZSTD_inBuffer const expect = cctx->expectedInBuffer;\n        if (expect.src != input->src || expect.pos != input->pos)\n            RETURN_ERROR(stabilityCondition_notRespected, \"ZSTD_c_stableInBuffer enabled but input differs!\");\n    }\n    (void)endOp;\n    if (cctx->appliedParams.outBufferMode == ZSTD_bm_stable) {\n        size_t const outBufferSize = output->size - output->pos;\n        if (cctx->expectedOutBufferSize != outBufferSize)\n            RETURN_ERROR(stabilityCondition_notRespected, \"ZSTD_c_stableOutBuffer enabled but output size differs!\");\n    }\n    return 0;\n}\n\n/*\n * If @endOp == ZSTD_e_end, @inSize becomes pledgedSrcSize.\n * Otherwise, it's ignored.\n * @return: 0 on success, or a ZSTD_error code otherwise.\n */\nstatic size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx,\n                                             ZSTD_EndDirective endOp,\n                                             size_t inSize)\n{\n    ZSTD_CCtx_params params = cctx->requestedParams;\n    ZSTD_prefixDict const prefixDict = cctx->prefixDict;\n    FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) , \"\"); /* Init the local dict if present. */\n    ZSTD_memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict));   /* single usage */\n    assert(prefixDict.dict==NULL || cctx->cdict==NULL);    /* only one can be set */\n    if (cctx->cdict && !cctx->localDict.cdict) {\n        /* Let the cdict's compression level take priority over the requested params.\n         * But do not take the cdict's compression level if the \"cdict\" is actually a localDict\n         * generated from ZSTD_initLocalDict().\n         */\n        params.compressionLevel = cctx->cdict->compressionLevel;\n    }\n    DEBUGLOG(4, \"ZSTD_CCtx_init_compressStream2 : transparent init stage\");\n    if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = inSize + 1;  /* auto-determine pledgedSrcSize */\n\n    {   size_t const dictSize = prefixDict.dict\n                ? prefixDict.dictSize\n                : (cctx->cdict ? cctx->cdict->dictContentSize : 0);\n        ZSTD_CParamMode_e const mode = ZSTD_getCParamMode(cctx->cdict, &params, cctx->pledgedSrcSizePlusOne - 1);\n        params.cParams = ZSTD_getCParamsFromCCtxParams(\n                &params, cctx->pledgedSrcSizePlusOne-1,\n                dictSize, mode);\n    }\n\n    params.postBlockSplitter = ZSTD_resolveBlockSplitterMode(params.postBlockSplitter, &params.cParams);\n    params.ldmParams.enableLdm = ZSTD_resolveEnableLdm(params.ldmParams.enableLdm, &params.cParams);\n    params.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params.useRowMatchFinder, &params.cParams);\n    params.validateSequences = ZSTD_resolveExternalSequenceValidation(params.validateSequences);\n    params.maxBlockSize = ZSTD_resolveMaxBlockSize(params.maxBlockSize);\n    params.searchForExternalRepcodes = ZSTD_resolveExternalRepcodeSearch(params.searchForExternalRepcodes, params.compressionLevel);\n\n#ifdef ZSTD_MULTITHREAD\n    /* If external matchfinder is enabled, make sure to fail before checking job size (for consistency) */\n    RETURN_ERROR_IF(\n        ZSTD_hasExtSeqProd(&params) && params.nbWorkers >= 1,\n        parameter_combination_unsupported,\n        \"External sequence producer isn't supported with nbWorkers >= 1\"\n    );\n\n    if ((cctx->pledgedSrcSizePlusOne-1) <= ZSTDMT_JOBSIZE_MIN) {\n        params.nbWorkers = 0; /* do not invoke multi-threading when src size is too small */\n    }\n    if (params.nbWorkers > 0) {\n# if ZSTD_TRACE\n        cctx->traceCtx = (ZSTD_trace_compress_begin != NULL) ? ZSTD_trace_compress_begin(cctx) : 0;\n# endif\n        /* mt context creation */\n        if (cctx->mtctx == NULL) {\n            DEBUGLOG(4, \"ZSTD_compressStream2: creating new mtctx for nbWorkers=%u\",\n                        params.nbWorkers);\n            cctx->mtctx = ZSTDMT_createCCtx_advanced((U32)params.nbWorkers, cctx->customMem, cctx->pool);\n            RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation, \"NULL pointer!\");\n        }\n        /* mt compression */\n        DEBUGLOG(4, \"call ZSTDMT_initCStream_internal as nbWorkers=%u\", params.nbWorkers);\n        FORWARD_IF_ERROR( ZSTDMT_initCStream_internal(\n                    cctx->mtctx,\n                    prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType,\n                    cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) , \"\");\n        cctx->dictID = cctx->cdict ? cctx->cdict->dictID : 0;\n        cctx->dictContentSize = cctx->cdict ? cctx->cdict->dictContentSize : prefixDict.dictSize;\n        cctx->consumedSrcSize = 0;\n        cctx->producedCSize = 0;\n        cctx->streamStage = zcss_load;\n        cctx->appliedParams = params;\n    } else\n#endif  /* ZSTD_MULTITHREAD */\n    {   U64 const pledgedSrcSize = cctx->pledgedSrcSizePlusOne - 1;\n        assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));\n        FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,\n                prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, ZSTD_dtlm_fast,\n                cctx->cdict,\n                &params, pledgedSrcSize,\n                ZSTDb_buffered) , \"\");\n        assert(cctx->appliedParams.nbWorkers == 0);\n        cctx->inToCompress = 0;\n        cctx->inBuffPos = 0;\n        if (cctx->appliedParams.inBufferMode == ZSTD_bm_buffered) {\n            /* for small input: avoid automatic flush on reaching end of block, since\n            * it would require to add a 3-bytes null block to end frame\n            */\n            cctx->inBuffTarget = cctx->blockSizeMax + (cctx->blockSizeMax == pledgedSrcSize);\n        } else {\n            cctx->inBuffTarget = 0;\n        }\n        cctx->outBuffContentSize = cctx->outBuffFlushedSize = 0;\n        cctx->streamStage = zcss_load;\n        cctx->frameEnded = 0;\n    }\n    return 0;\n}\n\n/* @return provides a minimum amount of data remaining to be flushed from internal buffers\n */\nsize_t ZSTD_compressStream2( ZSTD_CCtx* cctx,\n                             ZSTD_outBuffer* output,\n                             ZSTD_inBuffer* input,\n                             ZSTD_EndDirective endOp)\n{\n    DEBUGLOG(5, \"ZSTD_compressStream2, endOp=%u \", (unsigned)endOp);\n    /* check conditions */\n    RETURN_ERROR_IF(output->pos > output->size, dstSize_tooSmall, \"invalid output buffer\");\n    RETURN_ERROR_IF(input->pos  > input->size, srcSize_wrong, \"invalid input buffer\");\n    RETURN_ERROR_IF((U32)endOp > (U32)ZSTD_e_end, parameter_outOfBound, \"invalid endDirective\");\n    assert(cctx != NULL);\n\n    /* transparent initialization stage */\n    if (cctx->streamStage == zcss_init) {\n        size_t const inputSize = input->size - input->pos;  /* no obligation to start from pos==0 */\n        size_t const totalInputSize = inputSize + cctx->stableIn_notConsumed;\n        if ( (cctx->requestedParams.inBufferMode == ZSTD_bm_stable) /* input is presumed stable, across invocations */\n          && (endOp == ZSTD_e_continue)                             /* no flush requested, more input to come */\n          && (totalInputSize < ZSTD_BLOCKSIZE_MAX) ) {              /* not even reached one block yet */\n            if (cctx->stableIn_notConsumed) {  /* not the first time */\n                /* check stable source guarantees */\n                RETURN_ERROR_IF(input->src != cctx->expectedInBuffer.src, stabilityCondition_notRespected, \"stableInBuffer condition not respected: wrong src pointer\");\n                RETURN_ERROR_IF(input->pos != cctx->expectedInBuffer.size, stabilityCondition_notRespected, \"stableInBuffer condition not respected: externally modified pos\");\n            }\n            /* pretend input was consumed, to give a sense forward progress */\n            input->pos = input->size;\n            /* save stable inBuffer, for later control, and flush/end */\n            cctx->expectedInBuffer = *input;\n            /* but actually input wasn't consumed, so keep track of position from where compression shall resume */\n            cctx->stableIn_notConsumed += inputSize;\n            /* don't initialize yet, wait for the first block of flush() order, for better parameters adaptation */\n            return ZSTD_FRAMEHEADERSIZE_MIN(cctx->requestedParams.format);  /* at least some header to produce */\n        }\n        FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, endOp, totalInputSize), \"compressStream2 initialization failed\");\n        ZSTD_setBufferExpectations(cctx, output, input);   /* Set initial buffer expectations now that we've initialized */\n    }\n    /* end of transparent initialization stage */\n\n    FORWARD_IF_ERROR(ZSTD_checkBufferStability(cctx, output, input, endOp), \"invalid buffers\");\n    /* compression stage */\n#ifdef ZSTD_MULTITHREAD\n    if (cctx->appliedParams.nbWorkers > 0) {\n        size_t flushMin;\n        if (cctx->cParamsChanged) {\n            ZSTDMT_updateCParams_whileCompressing(cctx->mtctx, &cctx->requestedParams);\n            cctx->cParamsChanged = 0;\n        }\n        if (cctx->stableIn_notConsumed) {\n            assert(cctx->appliedParams.inBufferMode == ZSTD_bm_stable);\n            /* some early data was skipped - make it available for consumption */\n            assert(input->pos >= cctx->stableIn_notConsumed);\n            input->pos -= cctx->stableIn_notConsumed;\n            cctx->stableIn_notConsumed = 0;\n        }\n        for (;;) {\n            size_t const ipos = input->pos;\n            size_t const opos = output->pos;\n            flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);\n            cctx->consumedSrcSize += (U64)(input->pos - ipos);\n            cctx->producedCSize += (U64)(output->pos - opos);\n            if ( ZSTD_isError(flushMin)\n              || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */\n                if (flushMin == 0)\n                    ZSTD_CCtx_trace(cctx, 0);\n                ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);\n            }\n            FORWARD_IF_ERROR(flushMin, \"ZSTDMT_compressStream_generic failed\");\n\n            if (endOp == ZSTD_e_continue) {\n                /* We only require some progress with ZSTD_e_continue, not maximal progress.\n                 * We're done if we've consumed or produced any bytes, or either buffer is\n                 * full.\n                 */\n                if (input->pos != ipos || output->pos != opos || input->pos == input->size || output->pos == output->size)\n                    break;\n            } else {\n                assert(endOp == ZSTD_e_flush || endOp == ZSTD_e_end);\n                /* We require maximal progress. We're done when the flush is complete or the\n                 * output buffer is full.\n                 */\n                if (flushMin == 0 || output->pos == output->size)\n                    break;\n            }\n        }\n        DEBUGLOG(5, \"completed ZSTD_compressStream2 delegating to ZSTDMT_compressStream_generic\");\n        /* Either we don't require maximum forward progress, we've finished the\n         * flush, or we are out of output space.\n         */\n        assert(endOp == ZSTD_e_continue || flushMin == 0 || output->pos == output->size);\n        ZSTD_setBufferExpectations(cctx, output, input);\n        return flushMin;\n    }\n#endif /* ZSTD_MULTITHREAD */\n    FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) , \"\");\n    DEBUGLOG(5, \"completed ZSTD_compressStream2\");\n    ZSTD_setBufferExpectations(cctx, output, input);\n    return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */\n}\n\nsize_t ZSTD_compressStream2_simpleArgs (\n                            ZSTD_CCtx* cctx,\n                            void* dst, size_t dstCapacity, size_t* dstPos,\n                      const void* src, size_t srcSize, size_t* srcPos,\n                            ZSTD_EndDirective endOp)\n{\n    ZSTD_outBuffer output;\n    ZSTD_inBuffer  input;\n    output.dst = dst;\n    output.size = dstCapacity;\n    output.pos = *dstPos;\n    input.src = src;\n    input.size = srcSize;\n    input.pos = *srcPos;\n    /* ZSTD_compressStream2() will check validity of dstPos and srcPos */\n    {   size_t const cErr = ZSTD_compressStream2(cctx, &output, &input, endOp);\n        *dstPos = output.pos;\n        *srcPos = input.pos;\n        return cErr;\n    }\n}\n\nsize_t ZSTD_compress2(ZSTD_CCtx* cctx,\n                      void* dst, size_t dstCapacity,\n                      const void* src, size_t srcSize)\n{\n    ZSTD_bufferMode_e const originalInBufferMode = cctx->requestedParams.inBufferMode;\n    ZSTD_bufferMode_e const originalOutBufferMode = cctx->requestedParams.outBufferMode;\n    DEBUGLOG(4, \"ZSTD_compress2 (srcSize=%u)\", (unsigned)srcSize);\n    ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);\n    /* Enable stable input/output buffers. */\n    cctx->requestedParams.inBufferMode = ZSTD_bm_stable;\n    cctx->requestedParams.outBufferMode = ZSTD_bm_stable;\n    {   size_t oPos = 0;\n        size_t iPos = 0;\n        size_t const result = ZSTD_compressStream2_simpleArgs(cctx,\n                                        dst, dstCapacity, &oPos,\n                                        src, srcSize, &iPos,\n                                        ZSTD_e_end);\n        /* Reset to the original values. */\n        cctx->requestedParams.inBufferMode = originalInBufferMode;\n        cctx->requestedParams.outBufferMode = originalOutBufferMode;\n\n        FORWARD_IF_ERROR(result, \"ZSTD_compressStream2_simpleArgs failed\");\n        if (result != 0) {  /* compression not completed, due to lack of output space */\n            assert(oPos == dstCapacity);\n            RETURN_ERROR(dstSize_tooSmall, \"\");\n        }\n        assert(iPos == srcSize);   /* all input is expected consumed */\n        return oPos;\n    }\n}\n\n/* ZSTD_validateSequence() :\n * @offBase : must use the format required by ZSTD_storeSeq()\n * @returns a ZSTD error code if sequence is not valid\n */\nstatic size_t\nZSTD_validateSequence(U32 offBase, U32 matchLength, U32 minMatch,\n                      size_t posInSrc, U32 windowLog, size_t dictSize, int useSequenceProducer)\n{\n    U32 const windowSize = 1u << windowLog;\n    /* posInSrc represents the amount of data the decoder would decode up to this point.\n     * As long as the amount of data decoded is less than or equal to window size, offsets may be\n     * larger than the total length of output decoded in order to reference the dict, even larger than\n     * window size. After output surpasses windowSize, we're limited to windowSize offsets again.\n     */\n    size_t const offsetBound = posInSrc > windowSize ? (size_t)windowSize : posInSrc + (size_t)dictSize;\n    size_t const matchLenLowerBound = (minMatch == 3 || useSequenceProducer) ? 3 : 4;\n    RETURN_ERROR_IF(offBase > OFFSET_TO_OFFBASE(offsetBound), externalSequences_invalid, \"Offset too large!\");\n    /* Validate maxNbSeq is large enough for the given matchLength and minMatch */\n    RETURN_ERROR_IF(matchLength < matchLenLowerBound, externalSequences_invalid, \"Matchlength too small for the minMatch\");\n    return 0;\n}\n\n/* Returns an offset code, given a sequence's raw offset, the ongoing repcode array, and whether litLength == 0 */\nstatic U32 ZSTD_finalizeOffBase(U32 rawOffset, const U32 rep[ZSTD_REP_NUM], U32 ll0)\n{\n    U32 offBase = OFFSET_TO_OFFBASE(rawOffset);\n\n    if (!ll0 && rawOffset == rep[0]) {\n        offBase = REPCODE1_TO_OFFBASE;\n    } else if (rawOffset == rep[1]) {\n        offBase = REPCODE_TO_OFFBASE(2 - ll0);\n    } else if (rawOffset == rep[2]) {\n        offBase = REPCODE_TO_OFFBASE(3 - ll0);\n    } else if (ll0 && rawOffset == rep[0] - 1) {\n        offBase = REPCODE3_TO_OFFBASE;\n    }\n    return offBase;\n}\n\n/* This function scans through an array of ZSTD_Sequence,\n * storing the sequences it reads, until it reaches a block delimiter.\n * Note that the block delimiter includes the last literals of the block.\n * @blockSize must be == sum(sequence_lengths).\n * @returns @blockSize on success, and a ZSTD_error otherwise.\n */\nstatic size_t\nZSTD_transferSequences_wBlockDelim(ZSTD_CCtx* cctx,\n                                   ZSTD_SequencePosition* seqPos,\n                             const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,\n                             const void* src, size_t blockSize,\n                                   ZSTD_ParamSwitch_e externalRepSearch)\n{\n    U32 idx = seqPos->idx;\n    U32 const startIdx = idx;\n    BYTE const* ip = (BYTE const*)(src);\n    const BYTE* const iend = ip + blockSize;\n    Repcodes_t updatedRepcodes;\n    U32 dictSize;\n\n    DEBUGLOG(5, \"ZSTD_transferSequences_wBlockDelim (blockSize = %zu)\", blockSize);\n\n    if (cctx->cdict) {\n        dictSize = (U32)cctx->cdict->dictContentSize;\n    } else if (cctx->prefixDict.dict) {\n        dictSize = (U32)cctx->prefixDict.dictSize;\n    } else {\n        dictSize = 0;\n    }\n    ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(Repcodes_t));\n    for (; idx < inSeqsSize && (inSeqs[idx].matchLength != 0 || inSeqs[idx].offset != 0); ++idx) {\n        U32 const litLength = inSeqs[idx].litLength;\n        U32 const matchLength = inSeqs[idx].matchLength;\n        U32 offBase;\n\n        if (externalRepSearch == ZSTD_ps_disable) {\n            offBase = OFFSET_TO_OFFBASE(inSeqs[idx].offset);\n        } else {\n            U32 const ll0 = (litLength == 0);\n            offBase = ZSTD_finalizeOffBase(inSeqs[idx].offset, updatedRepcodes.rep, ll0);\n            ZSTD_updateRep(updatedRepcodes.rep, offBase, ll0);\n        }\n\n        DEBUGLOG(6, \"Storing sequence: (of: %u, ml: %u, ll: %u)\", offBase, matchLength, litLength);\n        if (cctx->appliedParams.validateSequences) {\n            seqPos->posInSrc += litLength + matchLength;\n            FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, cctx->appliedParams.cParams.minMatch,\n                                                seqPos->posInSrc,\n                                                cctx->appliedParams.cParams.windowLog, dictSize,\n                                                ZSTD_hasExtSeqProd(&cctx->appliedParams)),\n                                                \"Sequence validation failed\");\n        }\n        RETURN_ERROR_IF(idx - seqPos->idx >= cctx->seqStore.maxNbSeq, externalSequences_invalid,\n                        \"Not enough memory allocated. Try adjusting ZSTD_c_minMatch.\");\n        ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offBase, matchLength);\n        ip += matchLength + litLength;\n    }\n    RETURN_ERROR_IF(idx == inSeqsSize, externalSequences_invalid, \"Block delimiter not found.\");\n\n    /* If we skipped repcode search while parsing, we need to update repcodes now */\n    assert(externalRepSearch != ZSTD_ps_auto);\n    assert(idx >= startIdx);\n    if (externalRepSearch == ZSTD_ps_disable && idx != startIdx) {\n        U32* const rep = updatedRepcodes.rep;\n        U32 lastSeqIdx = idx - 1; /* index of last non-block-delimiter sequence */\n\n        if (lastSeqIdx >= startIdx + 2) {\n            rep[2] = inSeqs[lastSeqIdx - 2].offset;\n            rep[1] = inSeqs[lastSeqIdx - 1].offset;\n            rep[0] = inSeqs[lastSeqIdx].offset;\n        } else if (lastSeqIdx == startIdx + 1) {\n            rep[2] = rep[0];\n            rep[1] = inSeqs[lastSeqIdx - 1].offset;\n            rep[0] = inSeqs[lastSeqIdx].offset;\n        } else {\n            assert(lastSeqIdx == startIdx);\n            rep[2] = rep[1];\n            rep[1] = rep[0];\n            rep[0] = inSeqs[lastSeqIdx].offset;\n        }\n    }\n\n    ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(Repcodes_t));\n\n    if (inSeqs[idx].litLength) {\n        DEBUGLOG(6, \"Storing last literals of size: %u\", inSeqs[idx].litLength);\n        ZSTD_storeLastLiterals(&cctx->seqStore, ip, inSeqs[idx].litLength);\n        ip += inSeqs[idx].litLength;\n        seqPos->posInSrc += inSeqs[idx].litLength;\n    }\n    RETURN_ERROR_IF(ip != iend, externalSequences_invalid, \"Blocksize doesn't agree with block delimiter!\");\n    seqPos->idx = idx+1;\n    return blockSize;\n}\n\n/*\n * This function attempts to scan through @blockSize bytes in @src\n * represented by the sequences in @inSeqs,\n * storing any (partial) sequences.\n *\n * Occasionally, we may want to reduce the actual number of bytes consumed from @src\n * to avoid splitting a match, notably if it would produce a match smaller than MINMATCH.\n *\n * @returns the number of bytes consumed from @src, necessarily <= @blockSize.\n * Otherwise, it may return a ZSTD error if something went wrong.\n */\nstatic size_t\nZSTD_transferSequences_noDelim(ZSTD_CCtx* cctx,\n                               ZSTD_SequencePosition* seqPos,\n                         const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,\n                         const void* src, size_t blockSize,\n                               ZSTD_ParamSwitch_e externalRepSearch)\n{\n    U32 idx = seqPos->idx;\n    U32 startPosInSequence = seqPos->posInSequence;\n    U32 endPosInSequence = seqPos->posInSequence + (U32)blockSize;\n    size_t dictSize;\n    const BYTE* const istart = (const BYTE*)(src);\n    const BYTE* ip = istart;\n    const BYTE* iend = istart + blockSize;  /* May be adjusted if we decide to process fewer than blockSize bytes */\n    Repcodes_t updatedRepcodes;\n    U32 bytesAdjustment = 0;\n    U32 finalMatchSplit = 0;\n\n    /* TODO(embg) support fast parsing mode in noBlockDelim mode */\n    (void)externalRepSearch;\n\n    if (cctx->cdict) {\n        dictSize = cctx->cdict->dictContentSize;\n    } else if (cctx->prefixDict.dict) {\n        dictSize = cctx->prefixDict.dictSize;\n    } else {\n        dictSize = 0;\n    }\n    DEBUGLOG(5, \"ZSTD_transferSequences_noDelim: idx: %u PIS: %u blockSize: %zu\", idx, startPosInSequence, blockSize);\n    DEBUGLOG(5, \"Start seq: idx: %u (of: %u ml: %u ll: %u)\", idx, inSeqs[idx].offset, inSeqs[idx].matchLength, inSeqs[idx].litLength);\n    ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(Repcodes_t));\n    while (endPosInSequence && idx < inSeqsSize && !finalMatchSplit) {\n        const ZSTD_Sequence currSeq = inSeqs[idx];\n        U32 litLength = currSeq.litLength;\n        U32 matchLength = currSeq.matchLength;\n        U32 const rawOffset = currSeq.offset;\n        U32 offBase;\n\n        /* Modify the sequence depending on where endPosInSequence lies */\n        if (endPosInSequence >= currSeq.litLength + currSeq.matchLength) {\n            if (startPosInSequence >= litLength) {\n                startPosInSequence -= litLength;\n                litLength = 0;\n                matchLength -= startPosInSequence;\n            } else {\n                litLength -= startPosInSequence;\n            }\n            /* Move to the next sequence */\n            endPosInSequence -= currSeq.litLength + currSeq.matchLength;\n            startPosInSequence = 0;\n        } else {\n            /* This is the final (partial) sequence we're adding from inSeqs, and endPosInSequence\n               does not reach the end of the match. So, we have to split the sequence */\n            DEBUGLOG(6, \"Require a split: diff: %u, idx: %u PIS: %u\",\n                     currSeq.litLength + currSeq.matchLength - endPosInSequence, idx, endPosInSequence);\n            if (endPosInSequence > litLength) {\n                U32 firstHalfMatchLength;\n                litLength = startPosInSequence >= litLength ? 0 : litLength - startPosInSequence;\n                firstHalfMatchLength = endPosInSequence - startPosInSequence - litLength;\n                if (matchLength > blockSize && firstHalfMatchLength >= cctx->appliedParams.cParams.minMatch) {\n                    /* Only ever split the match if it is larger than the block size */\n                    U32 secondHalfMatchLength = currSeq.matchLength + currSeq.litLength - endPosInSequence;\n                    if (secondHalfMatchLength < cctx->appliedParams.cParams.minMatch) {\n                        /* Move the endPosInSequence backward so that it creates match of minMatch length */\n                        endPosInSequence -= cctx->appliedParams.cParams.minMatch - secondHalfMatchLength;\n                        bytesAdjustment = cctx->appliedParams.cParams.minMatch - secondHalfMatchLength;\n                        firstHalfMatchLength -= bytesAdjustment;\n                    }\n                    matchLength = firstHalfMatchLength;\n                    /* Flag that we split the last match - after storing the sequence, exit the loop,\n                       but keep the value of endPosInSequence */\n                    finalMatchSplit = 1;\n                } else {\n                    /* Move the position in sequence backwards so that we don't split match, and break to store\n                     * the last literals. We use the original currSeq.litLength as a marker for where endPosInSequence\n                     * should go. We prefer to do this whenever it is not necessary to split the match, or if doing so\n                     * would cause the first half of the match to be too small\n                     */\n                    bytesAdjustment = endPosInSequence - currSeq.litLength;\n                    endPosInSequence = currSeq.litLength;\n                    break;\n                }\n            } else {\n                /* This sequence ends inside the literals, break to store the last literals */\n                break;\n            }\n        }\n        /* Check if this offset can be represented with a repcode */\n        {   U32 const ll0 = (litLength == 0);\n            offBase = ZSTD_finalizeOffBase(rawOffset, updatedRepcodes.rep, ll0);\n            ZSTD_updateRep(updatedRepcodes.rep, offBase, ll0);\n        }\n\n        if (cctx->appliedParams.validateSequences) {\n            seqPos->posInSrc += litLength + matchLength;\n            FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, cctx->appliedParams.cParams.minMatch, seqPos->posInSrc,\n                                                   cctx->appliedParams.cParams.windowLog, dictSize, ZSTD_hasExtSeqProd(&cctx->appliedParams)),\n                                                   \"Sequence validation failed\");\n        }\n        DEBUGLOG(6, \"Storing sequence: (of: %u, ml: %u, ll: %u)\", offBase, matchLength, litLength);\n        RETURN_ERROR_IF(idx - seqPos->idx >= cctx->seqStore.maxNbSeq, externalSequences_invalid,\n                        \"Not enough memory allocated. Try adjusting ZSTD_c_minMatch.\");\n        ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offBase, matchLength);\n        ip += matchLength + litLength;\n        if (!finalMatchSplit)\n            idx++; /* Next Sequence */\n    }\n    DEBUGLOG(5, \"Ending seq: idx: %u (of: %u ml: %u ll: %u)\", idx, inSeqs[idx].offset, inSeqs[idx].matchLength, inSeqs[idx].litLength);\n    assert(idx == inSeqsSize || endPosInSequence <= inSeqs[idx].litLength + inSeqs[idx].matchLength);\n    seqPos->idx = idx;\n    seqPos->posInSequence = endPosInSequence;\n    ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(Repcodes_t));\n\n    iend -= bytesAdjustment;\n    if (ip != iend) {\n        /* Store any last literals */\n        U32 const lastLLSize = (U32)(iend - ip);\n        assert(ip <= iend);\n        DEBUGLOG(6, \"Storing last literals of size: %u\", lastLLSize);\n        ZSTD_storeLastLiterals(&cctx->seqStore, ip, lastLLSize);\n        seqPos->posInSrc += lastLLSize;\n    }\n\n    return (size_t)(iend-istart);\n}\n\n/* @seqPos represents a position within @inSeqs,\n * it is read and updated by this function,\n * once the goal to produce a block of size @blockSize is reached.\n * @return: nb of bytes consumed from @src, necessarily <= @blockSize.\n */\ntypedef size_t (*ZSTD_SequenceCopier_f)(ZSTD_CCtx* cctx,\n                                        ZSTD_SequencePosition* seqPos,\n                                  const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,\n                                  const void* src, size_t blockSize,\n                                        ZSTD_ParamSwitch_e externalRepSearch);\n\nstatic ZSTD_SequenceCopier_f ZSTD_selectSequenceCopier(ZSTD_SequenceFormat_e mode)\n{\n    assert(ZSTD_cParam_withinBounds(ZSTD_c_blockDelimiters, (int)mode));\n    if (mode == ZSTD_sf_explicitBlockDelimiters) {\n        return ZSTD_transferSequences_wBlockDelim;\n    }\n    assert(mode == ZSTD_sf_noBlockDelimiters);\n    return ZSTD_transferSequences_noDelim;\n}\n\n/* Discover the size of next block by searching for the delimiter.\n * Note that a block delimiter **must** exist in this mode,\n * otherwise it's an input error.\n * The block size retrieved will be later compared to ensure it remains within bounds */\nstatic size_t\nblockSize_explicitDelimiter(const ZSTD_Sequence* inSeqs, size_t inSeqsSize, ZSTD_SequencePosition seqPos)\n{\n    int end = 0;\n    size_t blockSize = 0;\n    size_t spos = seqPos.idx;\n    DEBUGLOG(6, \"blockSize_explicitDelimiter : seq %zu / %zu\", spos, inSeqsSize);\n    assert(spos <= inSeqsSize);\n    while (spos < inSeqsSize) {\n        end = (inSeqs[spos].offset == 0);\n        blockSize += inSeqs[spos].litLength + inSeqs[spos].matchLength;\n        if (end) {\n            if (inSeqs[spos].matchLength != 0)\n                RETURN_ERROR(externalSequences_invalid, \"delimiter format error : both matchlength and offset must be == 0\");\n            break;\n        }\n        spos++;\n    }\n    if (!end)\n        RETURN_ERROR(externalSequences_invalid, \"Reached end of sequences without finding a block delimiter\");\n    return blockSize;\n}\n\nstatic size_t determine_blockSize(ZSTD_SequenceFormat_e mode,\n                           size_t blockSize, size_t remaining,\n                     const ZSTD_Sequence* inSeqs, size_t inSeqsSize,\n                           ZSTD_SequencePosition seqPos)\n{\n    DEBUGLOG(6, \"determine_blockSize : remainingSize = %zu\", remaining);\n    if (mode == ZSTD_sf_noBlockDelimiters) {\n        /* Note: more a \"target\" block size */\n        return MIN(remaining, blockSize);\n    }\n    assert(mode == ZSTD_sf_explicitBlockDelimiters);\n    {   size_t const explicitBlockSize = blockSize_explicitDelimiter(inSeqs, inSeqsSize, seqPos);\n        FORWARD_IF_ERROR(explicitBlockSize, \"Error while determining block size with explicit delimiters\");\n        if (explicitBlockSize > blockSize)\n            RETURN_ERROR(externalSequences_invalid, \"sequences incorrectly define a too large block\");\n        if (explicitBlockSize > remaining)\n            RETURN_ERROR(externalSequences_invalid, \"sequences define a frame longer than source\");\n        return explicitBlockSize;\n    }\n}\n\n/* Compress all provided sequences, block-by-block.\n *\n * Returns the cumulative size of all compressed blocks (including their headers),\n * otherwise a ZSTD error.\n */\nstatic size_t\nZSTD_compressSequences_internal(ZSTD_CCtx* cctx,\n                                void* dst, size_t dstCapacity,\n                          const ZSTD_Sequence* inSeqs, size_t inSeqsSize,\n                          const void* src, size_t srcSize)\n{\n    size_t cSize = 0;\n    size_t remaining = srcSize;\n    ZSTD_SequencePosition seqPos = {0, 0, 0};\n\n    const BYTE* ip = (BYTE const*)src;\n    BYTE* op = (BYTE*)dst;\n    ZSTD_SequenceCopier_f const sequenceCopier = ZSTD_selectSequenceCopier(cctx->appliedParams.blockDelimiters);\n\n    DEBUGLOG(4, \"ZSTD_compressSequences_internal srcSize: %zu, inSeqsSize: %zu\", srcSize, inSeqsSize);\n    /* Special case: empty frame */\n    if (remaining == 0) {\n        U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1);\n        RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, \"No room for empty frame block header\");\n        MEM_writeLE32(op, cBlockHeader24);\n        op += ZSTD_blockHeaderSize;\n        dstCapacity -= ZSTD_blockHeaderSize;\n        cSize += ZSTD_blockHeaderSize;\n    }\n\n    while (remaining) {\n        size_t compressedSeqsSize;\n        size_t cBlockSize;\n        size_t blockSize = determine_blockSize(cctx->appliedParams.blockDelimiters,\n                                        cctx->blockSizeMax, remaining,\n                                        inSeqs, inSeqsSize, seqPos);\n        U32 const lastBlock = (blockSize == remaining);\n        FORWARD_IF_ERROR(blockSize, \"Error while trying to determine block size\");\n        assert(blockSize <= remaining);\n        ZSTD_resetSeqStore(&cctx->seqStore);\n\n        blockSize = sequenceCopier(cctx,\n                                   &seqPos, inSeqs, inSeqsSize,\n                                   ip, blockSize,\n                                   cctx->appliedParams.searchForExternalRepcodes);\n        FORWARD_IF_ERROR(blockSize, \"Bad sequence copy\");\n\n        /* If blocks are too small, emit as a nocompress block */\n        /* TODO: See 3090. We reduced MIN_CBLOCK_SIZE from 3 to 2 so to compensate we are adding\n         * additional 1. We need to revisit and change this logic to be more consistent */\n        if (blockSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1+1) {\n            cBlockSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);\n            FORWARD_IF_ERROR(cBlockSize, \"Nocompress block failed\");\n            DEBUGLOG(5, \"Block too small (%zu): data remains uncompressed: cSize=%zu\", blockSize, cBlockSize);\n            cSize += cBlockSize;\n            ip += blockSize;\n            op += cBlockSize;\n            remaining -= blockSize;\n            dstCapacity -= cBlockSize;\n            continue;\n        }\n\n        RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall, \"not enough dstCapacity to write a new compressed block\");\n        compressedSeqsSize = ZSTD_entropyCompressSeqStore(&cctx->seqStore,\n                                &cctx->blockState.prevCBlock->entropy, &cctx->blockState.nextCBlock->entropy,\n                                &cctx->appliedParams,\n                                op + ZSTD_blockHeaderSize /* Leave space for block header */, dstCapacity - ZSTD_blockHeaderSize,\n                                blockSize,\n                                cctx->tmpWorkspace, cctx->tmpWkspSize /* statically allocated in resetCCtx */,\n                                cctx->bmi2);\n        FORWARD_IF_ERROR(compressedSeqsSize, \"Compressing sequences of block failed\");\n        DEBUGLOG(5, \"Compressed sequences size: %zu\", compressedSeqsSize);\n\n        if (!cctx->isFirstBlock &&\n            ZSTD_maybeRLE(&cctx->seqStore) &&\n            ZSTD_isRLE(ip, blockSize)) {\n            /* Note: don't emit the first block as RLE even if it qualifies because\n             * doing so will cause the decoder (cli <= v1.4.3 only) to throw an (invalid) error\n             * \"should consume all input error.\"\n             */\n            compressedSeqsSize = 1;\n        }\n\n        if (compressedSeqsSize == 0) {\n            /* ZSTD_noCompressBlock writes the block header as well */\n            cBlockSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);\n            FORWARD_IF_ERROR(cBlockSize, \"ZSTD_noCompressBlock failed\");\n            DEBUGLOG(5, \"Writing out nocompress block, size: %zu\", cBlockSize);\n        } else if (compressedSeqsSize == 1) {\n            cBlockSize = ZSTD_rleCompressBlock(op, dstCapacity, *ip, blockSize, lastBlock);\n            FORWARD_IF_ERROR(cBlockSize, \"ZSTD_rleCompressBlock failed\");\n            DEBUGLOG(5, \"Writing out RLE block, size: %zu\", cBlockSize);\n        } else {\n            U32 cBlockHeader;\n            /* Error checking and repcodes update */\n            ZSTD_blockState_confirmRepcodesAndEntropyTables(&cctx->blockState);\n            if (cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)\n                cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;\n\n            /* Write block header into beginning of block*/\n            cBlockHeader = lastBlock + (((U32)bt_compressed)<<1) + (U32)(compressedSeqsSize << 3);\n            MEM_writeLE24(op, cBlockHeader);\n            cBlockSize = ZSTD_blockHeaderSize + compressedSeqsSize;\n            DEBUGLOG(5, \"Writing out compressed block, size: %zu\", cBlockSize);\n        }\n\n        cSize += cBlockSize;\n\n        if (lastBlock) {\n            break;\n        } else {\n            ip += blockSize;\n            op += cBlockSize;\n            remaining -= blockSize;\n            dstCapacity -= cBlockSize;\n            cctx->isFirstBlock = 0;\n        }\n        DEBUGLOG(5, \"cSize running total: %zu (remaining dstCapacity=%zu)\", cSize, dstCapacity);\n    }\n\n    DEBUGLOG(4, \"cSize final total: %zu\", cSize);\n    return cSize;\n}\n\nsize_t ZSTD_compressSequences(ZSTD_CCtx* cctx,\n                              void* dst, size_t dstCapacity,\n                              const ZSTD_Sequence* inSeqs, size_t inSeqsSize,\n                              const void* src, size_t srcSize)\n{\n    BYTE* op = (BYTE*)dst;\n    size_t cSize = 0;\n\n    /* Transparent initialization stage, same as compressStream2() */\n    DEBUGLOG(4, \"ZSTD_compressSequences (nbSeqs=%zu,dstCapacity=%zu)\", inSeqsSize, dstCapacity);\n    assert(cctx != NULL);\n    FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, ZSTD_e_end, srcSize), \"CCtx initialization failed\");\n\n    /* Begin writing output, starting with frame header */\n    {   size_t const frameHeaderSize = ZSTD_writeFrameHeader(op, dstCapacity,\n                    &cctx->appliedParams, srcSize, cctx->dictID);\n        op += frameHeaderSize;\n        assert(frameHeaderSize <= dstCapacity);\n        dstCapacity -= frameHeaderSize;\n        cSize += frameHeaderSize;\n    }\n    if (cctx->appliedParams.fParams.checksumFlag && srcSize) {\n        XXH64_update(&cctx->xxhState, src, srcSize);\n    }\n\n    /* Now generate compressed blocks */\n    {   size_t const cBlocksSize = ZSTD_compressSequences_internal(cctx,\n                                                           op, dstCapacity,\n                                                           inSeqs, inSeqsSize,\n                                                           src, srcSize);\n        FORWARD_IF_ERROR(cBlocksSize, \"Compressing blocks failed!\");\n        cSize += cBlocksSize;\n        assert(cBlocksSize <= dstCapacity);\n        dstCapacity -= cBlocksSize;\n    }\n\n    /* Complete with frame checksum, if needed */\n    if (cctx->appliedParams.fParams.checksumFlag) {\n        U32 const checksum = (U32) XXH64_digest(&cctx->xxhState);\n        RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, \"no room for checksum\");\n        DEBUGLOG(4, \"Write checksum : %08X\", (unsigned)checksum);\n        MEM_writeLE32((char*)dst + cSize, checksum);\n        cSize += 4;\n    }\n\n    DEBUGLOG(4, \"Final compressed size: %zu\", cSize);\n    return cSize;\n}\n\n\n#if defined(ZSTD_ARCH_X86_AVX2)\n\n#include <immintrin.h>  /* AVX2 intrinsics */\n\n/*\n * Convert 2 sequences per iteration, using AVX2 intrinsics:\n *   - offset -> offBase = offset + 2\n *   - litLength -> (U16) litLength\n *   - matchLength -> (U16)(matchLength - 3)\n *   - rep is ignored\n * Store only 8 bytes per SeqDef (offBase[4], litLength[2], mlBase[2]).\n *\n * At the end, instead of extracting two __m128i,\n * we use _mm256_permute4x64_epi64(..., 0xE8) to move lane2 into lane1,\n * then store the lower 16 bytes in one go.\n *\n * @returns 0 on succes, with no long length detected\n * @returns > 0 if there is one long length (> 65535),\n * indicating the position, and type.\n */\nsize_t convertSequences_noRepcodes(\n    SeqDef* dstSeqs,\n    const ZSTD_Sequence* inSeqs,\n    size_t nbSequences)\n{\n    /*\n     * addition:\n     *   For each 128-bit half: (offset+2, litLength+0, matchLength-3, rep+0)\n     */\n    const __m256i addition = _mm256_setr_epi32(\n        ZSTD_REP_NUM, 0, -MINMATCH, 0,    /* for sequence i */\n        ZSTD_REP_NUM, 0, -MINMATCH, 0     /* for sequence i+1 */\n    );\n\n    /* limit: check if there is a long length */\n    const __m256i limit = _mm256_set1_epi32(65535);\n\n    /*\n     * shuffle mask for byte-level rearrangement in each 128-bit half:\n     *\n     * Input layout (after addition) per 128-bit half:\n     *   [ offset+2 (4 bytes) | litLength (4 bytes) | matchLength (4 bytes) | rep (4 bytes) ]\n     * We only need:\n     *   offBase (4 bytes) = offset+2\n     *   litLength (2 bytes) = low 2 bytes of litLength\n     *   mlBase (2 bytes) = low 2 bytes of (matchLength)\n     * => Bytes [0..3, 4..5, 8..9], zero the rest.\n     */\n    const __m256i mask = _mm256_setr_epi8(\n        /* For the lower 128 bits => sequence i */\n         0, 1, 2, 3,       /* offset+2 */\n         4, 5,             /* litLength (16 bits) */\n         8, 9,             /* matchLength (16 bits) */\n         (BYTE)0x80, (BYTE)0x80, (BYTE)0x80, (BYTE)0x80,\n         (BYTE)0x80, (BYTE)0x80, (BYTE)0x80, (BYTE)0x80,\n\n        /* For the upper 128 bits => sequence i+1 */\n        16,17,18,19,       /* offset+2 */\n        20,21,             /* litLength */\n        24,25,             /* matchLength */\n        (BYTE)0x80, (BYTE)0x80, (BYTE)0x80, (BYTE)0x80,\n        (BYTE)0x80, (BYTE)0x80, (BYTE)0x80, (BYTE)0x80\n    );\n\n    /*\n     * Next, we'll use _mm256_permute4x64_epi64(vshf, 0xE8).\n     * Explanation of 0xE8 = 11101000b => [lane0, lane2, lane2, lane3].\n     * So the lower 128 bits become [lane0, lane2] => combining seq0 and seq1.\n     */\n#define PERM_LANE_0X_E8 0xE8  /* [0,2,2,3] in lane indices */\n\n    size_t longLen = 0, i = 0;\n\n    /* AVX permutation depends on the specific definition of target structures */\n    ZSTD_STATIC_ASSERT(sizeof(ZSTD_Sequence) == 16);\n    ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, offset) == 0);\n    ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, litLength) == 4);\n    ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, matchLength) == 8);\n    ZSTD_STATIC_ASSERT(sizeof(SeqDef) == 8);\n    ZSTD_STATIC_ASSERT(offsetof(SeqDef, offBase) == 0);\n    ZSTD_STATIC_ASSERT(offsetof(SeqDef, litLength) == 4);\n    ZSTD_STATIC_ASSERT(offsetof(SeqDef, mlBase) == 6);\n\n    /* Process 2 sequences per loop iteration */\n    for (; i + 1 < nbSequences; i += 2) {\n        /* Load 2 ZSTD_Sequence (32 bytes) */\n        __m256i vin  = _mm256_loadu_si256((const __m256i*)(const void*)&inSeqs[i]);\n\n        /* Add {2, 0, -3, 0} in each 128-bit half */\n        __m256i vadd = _mm256_add_epi32(vin, addition);\n\n        /* Check for long length */\n        __m256i ll_cmp  = _mm256_cmpgt_epi32(vadd, limit);  /* 0xFFFFFFFF for element > 65535 */\n        int ll_res  = _mm256_movemask_epi8(ll_cmp);\n\n        /* Shuffle bytes so each half gives us the 8 bytes we need */\n        __m256i vshf = _mm256_shuffle_epi8(vadd, mask);\n        /*\n         * Now:\n         *   Lane0 = seq0's 8 bytes\n         *   Lane1 = 0\n         *   Lane2 = seq1's 8 bytes\n         *   Lane3 = 0\n         */\n\n        /* Permute 64-bit lanes => move Lane2 down into Lane1. */\n        __m256i vperm = _mm256_permute4x64_epi64(vshf, PERM_LANE_0X_E8);\n        /*\n         * Now the lower 16 bytes (Lane0+Lane1) = [seq0, seq1].\n         * The upper 16 bytes are [Lane2, Lane3] = [seq1, 0], but we won't use them.\n         */\n\n        /* Store only the lower 16 bytes => 2 SeqDef (8 bytes each) */\n        _mm_storeu_si128((__m128i *)(void*)&dstSeqs[i], _mm256_castsi256_si128(vperm));\n        /*\n         * This writes out 16 bytes total:\n         *   - offset 0..7  => seq0 (offBase, litLength, mlBase)\n         *   - offset 8..15 => seq1 (offBase, litLength, mlBase)\n         */\n\n        /* check (unlikely) long lengths > 65535\n         * indices for lengths correspond to bits [4..7], [8..11], [20..23], [24..27]\n         * => combined mask = 0x0FF00FF0\n         */\n        if (UNLIKELY((ll_res & 0x0FF00FF0) != 0)) {\n            /* long length detected: let's figure out which one*/\n            if (inSeqs[i].matchLength > 65535+MINMATCH) {\n                assert(longLen == 0);\n                longLen = i + 1;\n            }\n            if (inSeqs[i].litLength > 65535) {\n                assert(longLen == 0);\n                longLen = i + nbSequences + 1;\n            }\n            if (inSeqs[i+1].matchLength > 65535+MINMATCH) {\n                assert(longLen == 0);\n                longLen = i + 1 + 1;\n            }\n            if (inSeqs[i+1].litLength > 65535) {\n                assert(longLen == 0);\n                longLen = i + 1 + nbSequences + 1;\n            }\n        }\n    }\n\n    /* Handle leftover if @nbSequences is odd */\n    if (i < nbSequences) {\n        /* process last sequence */\n        assert(i == nbSequences - 1);\n        dstSeqs[i].offBase = OFFSET_TO_OFFBASE(inSeqs[i].offset);\n        dstSeqs[i].litLength = (U16)inSeqs[i].litLength;\n        dstSeqs[i].mlBase = (U16)(inSeqs[i].matchLength - MINMATCH);\n        /* check (unlikely) long lengths > 65535 */\n        if (UNLIKELY(inSeqs[i].matchLength > 65535+MINMATCH)) {\n            assert(longLen == 0);\n            longLen = i + 1;\n        }\n        if (UNLIKELY(inSeqs[i].litLength > 65535)) {\n            assert(longLen == 0);\n            longLen = i + nbSequences + 1;\n        }\n    }\n\n    return longLen;\n}\n\n#elif defined (ZSTD_ARCH_RISCV_RVV)\n#include <riscv_vector.h>\n/*\n * Convert `vl` sequences per iteration, using RVV intrinsics:\n *   - offset -> offBase = offset + 2\n *   - litLength -> (U16) litLength\n *   - matchLength -> (U16)(matchLength - 3)\n *   - rep is ignored\n * Store only 8 bytes per SeqDef (offBase[4], litLength[2], mlBase[2]).\n *\n * @returns 0 on succes, with no long length detected\n * @returns > 0 if there is one long length (> 65535),\n * indicating the position, and type.\n */\nsize_t convertSequences_noRepcodes(SeqDef* dstSeqs, const ZSTD_Sequence* inSeqs, size_t nbSequences) {\n    size_t longLen = 0;\n    size_t vl = 0;\n    typedef uint32_t __attribute__((may_alias)) aliased_u32;\n    /* RVV depends on the specific definition of target structures */\n    ZSTD_STATIC_ASSERT(sizeof(ZSTD_Sequence) == 16);\n    ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, offset) == 0);\n    ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, litLength) == 4);\n    ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, matchLength) == 8);\n    ZSTD_STATIC_ASSERT(sizeof(SeqDef) == 8);\n    ZSTD_STATIC_ASSERT(offsetof(SeqDef, offBase) == 0);\n    ZSTD_STATIC_ASSERT(offsetof(SeqDef, litLength) == 4);\n    ZSTD_STATIC_ASSERT(offsetof(SeqDef, mlBase) == 6);\n    \n    for (size_t i = 0; i < nbSequences; i += vl) {\n\n        vl = __riscv_vsetvl_e32m2(nbSequences-i);       \n        {\n            // Loading structure member variables\n            vuint32m2x4_t v_tuple = __riscv_vlseg4e32_v_u32m2x4(\n                (const aliased_u32*)((const void*)&inSeqs[i]), \n                vl\n            );\n            vuint32m2_t v_offset = __riscv_vget_v_u32m2x4_u32m2(v_tuple, 0);\n            vuint32m2_t v_lit = __riscv_vget_v_u32m2x4_u32m2(v_tuple, 1);\n            vuint32m2_t v_match = __riscv_vget_v_u32m2x4_u32m2(v_tuple, 2);\n            // offset + ZSTD_REP_NUM\n            vuint32m2_t v_offBase = __riscv_vadd_vx_u32m2(v_offset, ZSTD_REP_NUM, vl); \n            // Check for integer overflow\n            // Cast to a 16-bit variable\n            vbool16_t lit_overflow = __riscv_vmsgtu_vx_u32m2_b16(v_lit, 65535, vl);\n            vuint16m1_t v_lit_clamped = __riscv_vncvt_x_x_w_u16m1(v_lit, vl);\n\n            vbool16_t ml_overflow = __riscv_vmsgtu_vx_u32m2_b16(v_match, 65535+MINMATCH, vl);\n            vuint16m1_t v_ml_clamped = __riscv_vncvt_x_x_w_u16m1(__riscv_vsub_vx_u32m2(v_match, MINMATCH, vl), vl);\n\n            // Pack two 16-bit fields into a 32-bit value (little-endian)\n            // The lower 16 bits contain litLength, and the upper 16 bits contain mlBase\n            vuint32m2_t v_lit_ml_combined = __riscv_vsll_vx_u32m2(\n                __riscv_vwcvtu_x_x_v_u32m2(v_ml_clamped, vl), // Convert matchLength to 32-bit\n                16, \n                vl\n            );\n            v_lit_ml_combined = __riscv_vor_vv_u32m2(\n                v_lit_ml_combined,\n                __riscv_vwcvtu_x_x_v_u32m2(v_lit_clamped, vl),\n                vl\n            );\n            {\n                // Create a vector of SeqDef structures\n                // Store the offBase, litLength, and mlBase in a vector of SeqDef\n                vuint32m2x2_t store_data = __riscv_vcreate_v_u32m2x2(\n                    v_offBase,          \n                    v_lit_ml_combined   \n                );\n                __riscv_vsseg2e32_v_u32m2x2(\n                    (aliased_u32*)((void*)&dstSeqs[i]), \n                    store_data,             \n                    vl                      \n                );\n            }\n            {\n                // Find the first index where an overflow occurs\n                int first_ml = __riscv_vfirst_m_b16(ml_overflow, vl);\n                int first_lit = __riscv_vfirst_m_b16(lit_overflow, vl);\n\n                if (UNLIKELY(first_ml != -1)) {\n                    assert(longLen == 0);\n                    longLen = i + first_ml + 1;\n                }\n                if (UNLIKELY(first_lit != -1)) {\n                    assert(longLen == 0);\n                    longLen = i + first_lit + 1 + nbSequences;\n                }\n            }\n        }\n    }\n    return longLen;\n}\n\n/* the vector implementation could also be ported to SSSE3,\n * but since this implementation is targeting modern systems (>= Sapphire Rapid),\n * it's not useful to develop and maintain code for older pre-AVX2 platforms */\n\n#elif defined(ZSTD_ARCH_ARM_SVE2)\n\n/*\n * Checks if any active element in a signed 8-bit integer vector is greater\n * than zero.\n *\n * @param g Governing predicate selecting active lanes.\n * @param a Input vector of signed 8-bit integers.\n *\n * @return True if any active element in `a` is > 0, false otherwise.\n */\nFORCE_INLINE_TEMPLATE int cmpgtz_any_s8(svbool_t g, svint8_t a)\n{\n    svbool_t ptest = svcmpgt_n_s8(g, a, 0);\n    return svptest_any(ptest, ptest);\n}\n\nsize_t convertSequences_noRepcodes(\n    SeqDef* dstSeqs,\n    const ZSTD_Sequence* inSeqs,\n    size_t nbSequences)\n{\n    /* Process the input with `8 * VL / element` lanes. */\n    const size_t lanes = 8 * svcntb() / sizeof(ZSTD_Sequence);\n    size_t longLen = 0;\n    size_t n = 0;\n\n    /* SVE permutation depends on the specific definition of target structures. */\n    ZSTD_STATIC_ASSERT(sizeof(ZSTD_Sequence) == 16);\n    ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, offset) == 0);\n    ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, litLength) == 4);\n    ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, matchLength) == 8);\n    ZSTD_STATIC_ASSERT(sizeof(SeqDef) == 8);\n    ZSTD_STATIC_ASSERT(offsetof(SeqDef, offBase) == 0);\n    ZSTD_STATIC_ASSERT(offsetof(SeqDef, litLength) == 4);\n    ZSTD_STATIC_ASSERT(offsetof(SeqDef, mlBase) == 6);\n\n    if (nbSequences >= lanes) {\n        const svbool_t ptrue = svptrue_b8();\n        /* 16-bit of {ZSTD_REP_NUM, 0, -MINMATCH, 0} extended to 32-bit lanes. */\n        const svuint32_t vaddition = svreinterpret_u32(\n            svunpklo_s32(svreinterpret_s16(svdup_n_u64(ZSTD_REP_NUM | (((U64)(U16)-MINMATCH) << 32)))));\n        /* For permutation of 16-bit units: 0, 1, 2, 4, 8, 9, 10, 12, ... */\n        const svuint16_t vmask = svreinterpret_u16(\n            svindex_u64(0x0004000200010000, 0x0008000800080008));\n        /* Upper bytes of `litLength` and `matchLength` will be packed into the\n         * middle of overflow check vector. */\n        const svbool_t pmid = svcmpne_n_u8(\n            ptrue, svreinterpret_u8(svdup_n_u64(0x0000FFFFFFFF0000)), 0);\n\n        do {\n            /* Load `lanes` number of `ZSTD_Sequence` into 8 vectors. */\n            const svuint32_t vin0 = svld1_vnum_u32(ptrue, &inSeqs[n].offset, 0);\n            const svuint32_t vin1 = svld1_vnum_u32(ptrue, &inSeqs[n].offset, 1);\n            const svuint32_t vin2 = svld1_vnum_u32(ptrue, &inSeqs[n].offset, 2);\n            const svuint32_t vin3 = svld1_vnum_u32(ptrue, &inSeqs[n].offset, 3);\n            const svuint32_t vin4 = svld1_vnum_u32(ptrue, &inSeqs[n].offset, 4);\n            const svuint32_t vin5 = svld1_vnum_u32(ptrue, &inSeqs[n].offset, 5);\n            const svuint32_t vin6 = svld1_vnum_u32(ptrue, &inSeqs[n].offset, 6);\n            const svuint32_t vin7 = svld1_vnum_u32(ptrue, &inSeqs[n].offset, 7);\n\n            /* Add {ZSTD_REP_NUM, 0, -MINMATCH, 0} to each structures. */\n            const svuint16x2_t vadd01 = svcreate2_u16(\n                svreinterpret_u16(svadd_u32_x(ptrue, vin0, vaddition)),\n                svreinterpret_u16(svadd_u32_x(ptrue, vin1, vaddition)));\n            const svuint16x2_t vadd23 = svcreate2_u16(\n                svreinterpret_u16(svadd_u32_x(ptrue, vin2, vaddition)),\n                svreinterpret_u16(svadd_u32_x(ptrue, vin3, vaddition)));\n            const svuint16x2_t vadd45 = svcreate2_u16(\n                svreinterpret_u16(svadd_u32_x(ptrue, vin4, vaddition)),\n                svreinterpret_u16(svadd_u32_x(ptrue, vin5, vaddition)));\n            const svuint16x2_t vadd67 = svcreate2_u16(\n                svreinterpret_u16(svadd_u32_x(ptrue, vin6, vaddition)),\n                svreinterpret_u16(svadd_u32_x(ptrue, vin7, vaddition)));\n\n            /* Shuffle and pack bytes so each vector contains SeqDef structures. */\n            const svuint16_t vout01 = svtbl2_u16(vadd01, vmask);\n            const svuint16_t vout23 = svtbl2_u16(vadd23, vmask);\n            const svuint16_t vout45 = svtbl2_u16(vadd45, vmask);\n            const svuint16_t vout67 = svtbl2_u16(vadd67, vmask);\n\n            /* Pack the upper 16-bits of 32-bit lanes for overflow check. */\n            const svuint16_t voverflow01 = svuzp2_u16(svget2_u16(vadd01, 0),\n                                                      svget2_u16(vadd01, 1));\n            const svuint16_t voverflow23 = svuzp2_u16(svget2_u16(vadd23, 0),\n                                                      svget2_u16(vadd23, 1));\n            const svuint16_t voverflow45 = svuzp2_u16(svget2_u16(vadd45, 0),\n                                                      svget2_u16(vadd45, 1));\n            const svuint16_t voverflow67 = svuzp2_u16(svget2_u16(vadd67, 0),\n                                                      svget2_u16(vadd67, 1));\n\n            /* We don't need the whole 16 bits of the overflow part. Only 1 bit\n             * is needed, so we pack tightly and merge multiple vectors to be\n             * able to use a single comparison to handle the overflow case.\n             * However, we also need to handle the possible negative values of\n             * matchLength parts, so we use signed comparison later. */\n            const svint8_t voverflow =\n                svmax_s8_x(pmid,\n                           svtrn1_s8(svreinterpret_s8(voverflow01),\n                                     svreinterpret_s8(voverflow23)),\n                           svtrn1_s8(svreinterpret_s8(voverflow45),\n                                     svreinterpret_s8(voverflow67)));\n\n            /* Store `lanes` number of `SeqDef` structures from 4 vectors. */\n            svst1_vnum_u32(ptrue, &dstSeqs[n].offBase, 0, svreinterpret_u32(vout01));\n            svst1_vnum_u32(ptrue, &dstSeqs[n].offBase, 1, svreinterpret_u32(vout23));\n            svst1_vnum_u32(ptrue, &dstSeqs[n].offBase, 2, svreinterpret_u32(vout45));\n            svst1_vnum_u32(ptrue, &dstSeqs[n].offBase, 3, svreinterpret_u32(vout67));\n\n            /* Check if any enabled lanes of the overflow vector is larger than\n             * zero, only one such may happen. */\n            if (UNLIKELY(cmpgtz_any_s8(pmid, voverflow))) {\n                /* Scalar search for long match is needed because we merged\n                 * multiple overflow bytes with `max`. */\n                size_t i;\n                for (i = n; i < n + lanes; i++) {\n                    if (inSeqs[i].matchLength > 65535 + MINMATCH) {\n                        assert(longLen == 0);\n                        longLen = i + 1;\n                    }\n                    if (inSeqs[i].litLength > 65535) {\n                        assert(longLen == 0);\n                        longLen = i + nbSequences + 1;\n                    }\n                }\n            }\n\n            n += lanes;\n        } while(n <= nbSequences - lanes);\n    }\n\n    /* Handle remaining elements. */\n    for (; n < nbSequences; n++) {\n        dstSeqs[n].offBase = OFFSET_TO_OFFBASE(inSeqs[n].offset);\n        dstSeqs[n].litLength = (U16)inSeqs[n].litLength;\n        dstSeqs[n].mlBase = (U16)(inSeqs[n].matchLength - MINMATCH);\n        /* Check for long length > 65535. */\n        if (UNLIKELY(inSeqs[n].matchLength > 65535 + MINMATCH)) {\n            assert(longLen == 0);\n            longLen = n + 1;\n        }\n        if (UNLIKELY(inSeqs[n].litLength > 65535)) {\n            assert(longLen == 0);\n            longLen = n + nbSequences + 1;\n        }\n    }\n    return longLen;\n}\n\n#elif defined(ZSTD_ARCH_ARM_NEON) && (defined(__aarch64__) || defined(_M_ARM64))\n\nsize_t convertSequences_noRepcodes(\n    SeqDef* dstSeqs,\n    const ZSTD_Sequence* inSeqs,\n    size_t nbSequences)\n{\n    size_t longLen = 0;\n    size_t n = 0;\n\n    /* Neon permutation depends on the specific definition of target structures. */\n    ZSTD_STATIC_ASSERT(sizeof(ZSTD_Sequence) == 16);\n    ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, offset) == 0);\n    ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, litLength) == 4);\n    ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, matchLength) == 8);\n    ZSTD_STATIC_ASSERT(sizeof(SeqDef) == 8);\n    ZSTD_STATIC_ASSERT(offsetof(SeqDef, offBase) == 0);\n    ZSTD_STATIC_ASSERT(offsetof(SeqDef, litLength) == 4);\n    ZSTD_STATIC_ASSERT(offsetof(SeqDef, mlBase) == 6);\n\n    if (nbSequences > 3) {\n        static const ZSTD_ALIGNED(16) U32 constAddition[4] = {\n            ZSTD_REP_NUM, 0, -MINMATCH, 0\n        };\n        static const ZSTD_ALIGNED(16) U8 constMask[16] = {\n            0, 1, 2, 3, 4, 5, 8, 9, 16, 17, 18, 19, 20, 21, 24, 25\n        };\n        static const ZSTD_ALIGNED(16) U16 constCounter[8] = {\n            1, 1, 1, 1, 2, 2, 2, 2\n        };\n\n        const uint32x4_t vaddition = vld1q_u32(constAddition);\n        const uint8x16_t vmask = vld1q_u8(constMask);\n        uint16x8_t vcounter = vld1q_u16(constCounter);\n        uint16x8_t vindex01 = vdupq_n_u16(0);\n        uint16x8_t vindex23 = vdupq_n_u16(0);\n\n        do {\n            /* Load 4 ZSTD_Sequence (64 bytes). */\n            const uint32x4_t vin0 = vld1q_u32(&inSeqs[n + 0].offset);\n            const uint32x4_t vin1 = vld1q_u32(&inSeqs[n + 1].offset);\n            const uint32x4_t vin2 = vld1q_u32(&inSeqs[n + 2].offset);\n            const uint32x4_t vin3 = vld1q_u32(&inSeqs[n + 3].offset);\n\n            /* Add {ZSTD_REP_NUM, 0, -MINMATCH, 0} to each vector. */\n            const uint8x16x2_t vadd01 = { {\n                vreinterpretq_u8_u32(vaddq_u32(vin0, vaddition)),\n                vreinterpretq_u8_u32(vaddq_u32(vin1, vaddition)),\n            } };\n            const uint8x16x2_t vadd23 = { {\n                vreinterpretq_u8_u32(vaddq_u32(vin2, vaddition)),\n                vreinterpretq_u8_u32(vaddq_u32(vin3, vaddition)),\n            } };\n\n            /* Shuffle and pack bytes so each vector contains 2 SeqDef structures. */\n            const uint8x16_t vout01 = vqtbl2q_u8(vadd01, vmask);\n            const uint8x16_t vout23 = vqtbl2q_u8(vadd23, vmask);\n\n            /* Pack the upper 16-bits of 32-bit lanes for overflow check. */\n            uint16x8_t voverflow01 = vuzp2q_u16(vreinterpretq_u16_u8(vadd01.val[0]),\n                                                vreinterpretq_u16_u8(vadd01.val[1]));\n            uint16x8_t voverflow23 = vuzp2q_u16(vreinterpretq_u16_u8(vadd23.val[0]),\n                                                vreinterpretq_u16_u8(vadd23.val[1]));\n\n            /* Store 4 SeqDef structures. */\n            vst1q_u32(&dstSeqs[n + 0].offBase, vreinterpretq_u32_u8(vout01));\n            vst1q_u32(&dstSeqs[n + 2].offBase, vreinterpretq_u32_u8(vout23));\n\n            /* Create masks in case of overflow. */\n            voverflow01 = vcgtzq_s16(vreinterpretq_s16_u16(voverflow01));\n            voverflow23 = vcgtzq_s16(vreinterpretq_s16_u16(voverflow23));\n\n            /* Update overflow indices. */\n            vindex01 = vbslq_u16(voverflow01, vcounter, vindex01);\n            vindex23 = vbslq_u16(voverflow23, vcounter, vindex23);\n\n            /* Update counter for overflow check. */\n            vcounter = vaddq_u16(vcounter, vdupq_n_u16(4));\n\n            n += 4;\n        } while(n < nbSequences - 3);\n\n        /* Fixup indices in the second vector, we saved an additional counter\n           in the loop to update the second overflow index, we need to add 2\n           here when the indices are not 0. */\n        {   uint16x8_t nonzero = vtstq_u16(vindex23, vindex23);\n            vindex23 = vsubq_u16(vindex23, nonzero);\n            vindex23 = vsubq_u16(vindex23, nonzero);\n        }\n\n        /* Merge indices in the vectors, maximums are needed. */\n        vindex01 = vmaxq_u16(vindex01, vindex23);\n        vindex01 = vmaxq_u16(vindex01, vextq_u16(vindex01, vindex01, 4));\n\n        /* Compute `longLen`, maximums of matchLength and litLength\n           with a preference on litLength. */\n        {   U64 maxLitMatchIndices = vgetq_lane_u64(vreinterpretq_u64_u16(vindex01), 0);\n            size_t maxLitIndex = (maxLitMatchIndices >> 16) & 0xFFFF;\n            size_t maxMatchIndex = (maxLitMatchIndices >> 32) & 0xFFFF;\n            longLen = maxLitIndex > maxMatchIndex ? maxLitIndex + nbSequences\n                                                  : maxMatchIndex;\n        }\n    }\n\n    /* Handle remaining elements. */\n    for (; n < nbSequences; n++) {\n        dstSeqs[n].offBase = OFFSET_TO_OFFBASE(inSeqs[n].offset);\n        dstSeqs[n].litLength = (U16)inSeqs[n].litLength;\n        dstSeqs[n].mlBase = (U16)(inSeqs[n].matchLength - MINMATCH);\n        /* Check for long length > 65535. */\n        if (UNLIKELY(inSeqs[n].matchLength > 65535 + MINMATCH)) {\n            assert(longLen == 0);\n            longLen = n + 1;\n        }\n        if (UNLIKELY(inSeqs[n].litLength > 65535)) {\n            assert(longLen == 0);\n            longLen = n + nbSequences + 1;\n        }\n    }\n    return longLen;\n}\n\n#else /* No vectorization. */\n\nsize_t convertSequences_noRepcodes(\n    SeqDef* dstSeqs,\n    const ZSTD_Sequence* inSeqs,\n    size_t nbSequences)\n{\n    size_t longLen = 0;\n    size_t n;\n    for (n=0; n<nbSequences; n++) {\n        dstSeqs[n].offBase = OFFSET_TO_OFFBASE(inSeqs[n].offset);\n        dstSeqs[n].litLength = (U16)inSeqs[n].litLength;\n        dstSeqs[n].mlBase = (U16)(inSeqs[n].matchLength - MINMATCH);\n        /* Check for long length > 65535. */\n        if (UNLIKELY(inSeqs[n].matchLength > 65535+MINMATCH)) {\n            assert(longLen == 0);\n            longLen = n + 1;\n        }\n        if (UNLIKELY(inSeqs[n].litLength > 65535)) {\n            assert(longLen == 0);\n            longLen = n + nbSequences + 1;\n        }\n    }\n    return longLen;\n}\n\n#endif\n\n/*\n * Precondition: Sequences must end on an explicit Block Delimiter\n * @return: 0 on success, or an error code.\n * Note: Sequence validation functionality has been disabled (removed).\n * This is helpful to generate a lean main pipeline, improving performance.\n * It may be re-inserted later.\n */\nsize_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx,\n                const ZSTD_Sequence* const inSeqs, size_t nbSequences,\n                int repcodeResolution)\n{\n    Repcodes_t updatedRepcodes;\n    size_t seqNb = 0;\n\n    DEBUGLOG(5, \"ZSTD_convertBlockSequences (nbSequences = %zu)\", nbSequences);\n\n    RETURN_ERROR_IF(nbSequences >= cctx->seqStore.maxNbSeq, externalSequences_invalid,\n                    \"Not enough memory allocated. Try adjusting ZSTD_c_minMatch.\");\n\n    ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(Repcodes_t));\n\n    /* check end condition */\n    assert(nbSequences >= 1);\n    assert(inSeqs[nbSequences-1].matchLength == 0);\n    assert(inSeqs[nbSequences-1].offset == 0);\n\n    /* Convert Sequences from public format to internal format */\n    if (!repcodeResolution) {\n        size_t const longl = convertSequences_noRepcodes(cctx->seqStore.sequencesStart, inSeqs, nbSequences-1);\n        cctx->seqStore.sequences = cctx->seqStore.sequencesStart + nbSequences-1;\n        if (longl) {\n            DEBUGLOG(5, \"long length\");\n            assert(cctx->seqStore.longLengthType == ZSTD_llt_none);\n            if (longl <= nbSequences-1) {\n                DEBUGLOG(5, \"long match length detected at pos %zu\", longl-1);\n                cctx->seqStore.longLengthType = ZSTD_llt_matchLength;\n                cctx->seqStore.longLengthPos = (U32)(longl-1);\n            } else {\n                DEBUGLOG(5, \"long literals length detected at pos %zu\", longl-nbSequences);\n                assert(longl <= 2* (nbSequences-1));\n                cctx->seqStore.longLengthType = ZSTD_llt_literalLength;\n                cctx->seqStore.longLengthPos = (U32)(longl-(nbSequences-1)-1);\n            }\n        }\n    } else {\n        for (seqNb = 0; seqNb < nbSequences - 1 ; seqNb++) {\n            U32 const litLength = inSeqs[seqNb].litLength;\n            U32 const matchLength = inSeqs[seqNb].matchLength;\n            U32 const ll0 = (litLength == 0);\n            U32 const offBase = ZSTD_finalizeOffBase(inSeqs[seqNb].offset, updatedRepcodes.rep, ll0);\n\n            DEBUGLOG(6, \"Storing sequence: (of: %u, ml: %u, ll: %u)\", offBase, matchLength, litLength);\n            ZSTD_storeSeqOnly(&cctx->seqStore, litLength, offBase, matchLength);\n            ZSTD_updateRep(updatedRepcodes.rep, offBase, ll0);\n        }\n    }\n\n    /* If we skipped repcode search while parsing, we need to update repcodes now */\n    if (!repcodeResolution && nbSequences > 1) {\n        U32* const rep = updatedRepcodes.rep;\n\n        if (nbSequences >= 4) {\n            U32 lastSeqIdx = (U32)nbSequences - 2; /* index of last full sequence */\n            rep[2] = inSeqs[lastSeqIdx - 2].offset;\n            rep[1] = inSeqs[lastSeqIdx - 1].offset;\n            rep[0] = inSeqs[lastSeqIdx].offset;\n        } else if (nbSequences == 3) {\n            rep[2] = rep[0];\n            rep[1] = inSeqs[0].offset;\n            rep[0] = inSeqs[1].offset;\n        } else {\n            assert(nbSequences == 2);\n            rep[2] = rep[1];\n            rep[1] = rep[0];\n            rep[0] = inSeqs[0].offset;\n        }\n    }\n\n    ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(Repcodes_t));\n\n    return 0;\n}\n\n#if defined(ZSTD_ARCH_X86_AVX2)\n\nBlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs)\n{\n    size_t i;\n    __m256i const zeroVec = _mm256_setzero_si256();\n    __m256i sumVec = zeroVec;  /* accumulates match+lit in 32-bit lanes */\n    ZSTD_ALIGNED(32) U32 tmp[8];      /* temporary buffer for reduction */\n    size_t mSum = 0, lSum = 0;\n    ZSTD_STATIC_ASSERT(sizeof(ZSTD_Sequence) == 16);\n\n    /* Process 2 structs (32 bytes) at a time */\n    for (i = 0; i + 2 <= nbSeqs; i += 2) {\n        /* Load two consecutive ZSTD_Sequence (8×4 = 32 bytes) */\n        __m256i data     = _mm256_loadu_si256((const __m256i*)(const void*)&seqs[i]);\n        /* check end of block signal */\n        __m256i cmp      = _mm256_cmpeq_epi32(data, zeroVec);\n        int cmp_res      = _mm256_movemask_epi8(cmp);\n        /* indices for match lengths correspond to bits [8..11], [24..27]\n         * => combined mask = 0x0F000F00 */\n        ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, matchLength) == 8);\n        if (cmp_res & 0x0F000F00) break;\n        /* Accumulate in sumVec */\n        sumVec           = _mm256_add_epi32(sumVec, data);\n    }\n\n    /* Horizontal reduction */\n    _mm256_store_si256((__m256i*)tmp, sumVec);\n    lSum = tmp[1] + tmp[5];\n    mSum = tmp[2] + tmp[6];\n\n    /* Handle the leftover */\n    for (; i < nbSeqs; i++) {\n        lSum += seqs[i].litLength;\n        mSum += seqs[i].matchLength;\n        if (seqs[i].matchLength == 0) break; /* end of block */\n    }\n\n    if (i==nbSeqs) {\n        /* reaching end of sequences: end of block signal was not present */\n        BlockSummary bs;\n        bs.nbSequences = ERROR(externalSequences_invalid);\n        return bs;\n    }\n    {   BlockSummary bs;\n        bs.nbSequences = i+1;\n        bs.blockSize = lSum + mSum;\n        bs.litSize = lSum;\n        return bs;\n    }\n}\n\n#elif defined (ZSTD_ARCH_RISCV_RVV)\n\nBlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs)\n{\n    size_t totalMatchSize = 0;\n    size_t litSize = 0;\n    size_t i = 0;\n    int found_terminator = 0; \n    size_t vl_max = __riscv_vsetvlmax_e32m1();\n    typedef uint32_t __attribute__((may_alias)) aliased_u32;\n    vuint32m1_t v_lit_sum = __riscv_vmv_v_x_u32m1(0, vl_max);\n    vuint32m1_t v_match_sum = __riscv_vmv_v_x_u32m1(0, vl_max);\n\n    for (; i  < nbSeqs; ) {\n        size_t vl = __riscv_vsetvl_e32m2(nbSeqs - i); \n\n        vuint32m2x4_t v_tuple = __riscv_vlseg4e32_v_u32m2x4(\n            (const aliased_u32*)((const void*)&seqs[i]), \n            vl\n        );\n        vuint32m2_t v_lit = __riscv_vget_v_u32m2x4_u32m2(v_tuple, 1);\n        vuint32m2_t v_match = __riscv_vget_v_u32m2x4_u32m2(v_tuple, 2);\n\n        // Check if any element has a matchLength of 0\n        vbool16_t mask = __riscv_vmseq_vx_u32m2_b16(v_match, 0, vl);\n        int first_zero = __riscv_vfirst_m_b16(mask, vl);\n\n        if (first_zero >= 0) {\n            // Find the first zero byte and set the effective length to that index + 1 to \n            // recompute the cumulative vector length of literals and matches\n            vl = first_zero + 1;\n            \n            // recompute the cumulative vector length of literals and matches\n            v_lit_sum = __riscv_vredsum_vs_u32m2_u32m1(__riscv_vslidedown_vx_u32m2(v_lit, 0, vl), v_lit_sum, vl);\n            v_match_sum = __riscv_vredsum_vs_u32m2_u32m1(__riscv_vslidedown_vx_u32m2(v_match, 0, vl), v_match_sum, vl);\n\n            i += vl;\n            found_terminator = 1; \n            assert(seqs[i - 1].offset == 0);\n            break;\n        } else {\n\n            v_lit_sum = __riscv_vredsum_vs_u32m2_u32m1(v_lit, v_lit_sum, vl);\n            v_match_sum = __riscv_vredsum_vs_u32m2_u32m1(v_match, v_match_sum, vl);\n            i += vl;\n        }\n    }\n    litSize = __riscv_vmv_x_s_u32m1_u32(v_lit_sum);\n    totalMatchSize = __riscv_vmv_x_s_u32m1_u32(v_match_sum);\n\n    if (!found_terminator && i==nbSeqs) {\n        BlockSummary bs;\n        bs.nbSequences = ERROR(externalSequences_invalid);\n        return bs;\n    }\n    {   BlockSummary bs;\n        bs.nbSequences = i;\n        bs.blockSize = litSize + totalMatchSize;\n        bs.litSize = litSize;\n        return bs;\n    }\n}\n\n#else\n\n/*\n * The function assumes `litMatchLength` is a packed 64-bit value where the\n * lower 32 bits represent the match length. The check varies based on the\n * system's endianness:\n * - On little-endian systems, it verifies if the entire 64-bit value is at most\n * 0xFFFFFFFF, indicating the match length (lower 32 bits) is zero.\n * - On big-endian systems, it directly checks if the lower 32 bits are zero.\n *\n * @returns 1 if the match length is zero, 0 otherwise.\n */\nFORCE_INLINE_TEMPLATE int matchLengthHalfIsZero(U64 litMatchLength)\n{\n    if (MEM_isLittleEndian()) {\n        return litMatchLength <= 0xFFFFFFFFULL;\n    } else {\n        return (U32)litMatchLength == 0;\n    }\n}\n\nBlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs)\n{\n    /* Use multiple accumulators for efficient use of wide out-of-order machines. */\n    U64 litMatchSize0 = 0;\n    U64 litMatchSize1 = 0;\n    U64 litMatchSize2 = 0;\n    U64 litMatchSize3 = 0;\n    size_t n = 0;\n\n    ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, litLength) + 4 == offsetof(ZSTD_Sequence, matchLength));\n    ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, matchLength) + 4 == offsetof(ZSTD_Sequence, rep));\n    assert(seqs);\n\n    if (nbSeqs > 3) {\n        /* Process the input in 4 independent streams to reach high throughput. */\n        do {\n            /* Load `litLength` and `matchLength` as a packed `U64`. It is safe\n             * to use 64-bit unsigned arithmetic here because the sum of `litLength`\n             * and `matchLength` cannot exceed the block size, so the 32-bit\n             * subparts will never overflow. */\n            U64 litMatchLength = MEM_read64(&seqs[n].litLength);\n            litMatchSize0 += litMatchLength;\n            if (matchLengthHalfIsZero(litMatchLength)) {\n                assert(seqs[n].offset == 0);\n                goto _out;\n            }\n\n            litMatchLength = MEM_read64(&seqs[n + 1].litLength);\n            litMatchSize1 += litMatchLength;\n            if (matchLengthHalfIsZero(litMatchLength)) {\n                n += 1;\n                assert(seqs[n].offset == 0);\n                goto _out;\n            }\n\n            litMatchLength = MEM_read64(&seqs[n + 2].litLength);\n            litMatchSize2 += litMatchLength;\n            if (matchLengthHalfIsZero(litMatchLength)) {\n                n += 2;\n                assert(seqs[n].offset == 0);\n                goto _out;\n            }\n\n            litMatchLength = MEM_read64(&seqs[n + 3].litLength);\n            litMatchSize3 += litMatchLength;\n            if (matchLengthHalfIsZero(litMatchLength)) {\n                n += 3;\n                assert(seqs[n].offset == 0);\n                goto _out;\n            }\n\n            n += 4;\n        } while(n < nbSeqs - 3);\n    }\n\n    for (; n < nbSeqs; n++) {\n        U64 litMatchLength = MEM_read64(&seqs[n].litLength);\n        litMatchSize0 += litMatchLength;\n        if (matchLengthHalfIsZero(litMatchLength)) {\n            assert(seqs[n].offset == 0);\n            goto _out;\n        }\n    }\n    /* At this point n == nbSeqs, so no end terminator. */\n    {   BlockSummary bs;\n        bs.nbSequences = ERROR(externalSequences_invalid);\n        return bs;\n    }\n_out:\n    litMatchSize0 += litMatchSize1 + litMatchSize2 + litMatchSize3;\n    {   BlockSummary bs;\n        bs.nbSequences = n + 1;\n        if (MEM_isLittleEndian()) {\n            bs.litSize = (U32)litMatchSize0;\n            bs.blockSize = bs.litSize + (litMatchSize0 >> 32);\n        } else {\n            bs.litSize = litMatchSize0 >> 32;\n            bs.blockSize = bs.litSize + (U32)litMatchSize0;\n        }\n        return bs;\n    }\n}\n#endif\n\n\nstatic size_t\nZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx,\n                                void* dst, size_t dstCapacity,\n                          const ZSTD_Sequence* inSeqs, size_t nbSequences,\n                          const void* literals, size_t litSize, size_t srcSize)\n{\n    size_t remaining = srcSize;\n    size_t cSize = 0;\n    BYTE* op = (BYTE*)dst;\n    int const repcodeResolution = (cctx->appliedParams.searchForExternalRepcodes == ZSTD_ps_enable);\n    assert(cctx->appliedParams.searchForExternalRepcodes != ZSTD_ps_auto);\n\n    DEBUGLOG(4, \"ZSTD_compressSequencesAndLiterals_internal: nbSeqs=%zu, litSize=%zu\", nbSequences, litSize);\n    RETURN_ERROR_IF(nbSequences == 0, externalSequences_invalid, \"Requires at least 1 end-of-block\");\n\n    /* Special case: empty frame */\n    if ((nbSequences == 1) && (inSeqs[0].litLength == 0)) {\n        U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1);\n        RETURN_ERROR_IF(dstCapacity<3, dstSize_tooSmall, \"No room for empty frame block header\");\n        MEM_writeLE24(op, cBlockHeader24);\n        op += ZSTD_blockHeaderSize;\n        dstCapacity -= ZSTD_blockHeaderSize;\n        cSize += ZSTD_blockHeaderSize;\n    }\n\n    while (nbSequences) {\n        size_t compressedSeqsSize, cBlockSize, conversionStatus;\n        BlockSummary const block = ZSTD_get1BlockSummary(inSeqs, nbSequences);\n        U32 const lastBlock = (block.nbSequences == nbSequences);\n        FORWARD_IF_ERROR(block.nbSequences, \"Error while trying to determine nb of sequences for a block\");\n        assert(block.nbSequences <= nbSequences);\n        RETURN_ERROR_IF(block.litSize > litSize, externalSequences_invalid, \"discrepancy: Sequences require more literals than present in buffer\");\n        ZSTD_resetSeqStore(&cctx->seqStore);\n\n        conversionStatus = ZSTD_convertBlockSequences(cctx,\n                            inSeqs, block.nbSequences,\n                            repcodeResolution);\n        FORWARD_IF_ERROR(conversionStatus, \"Bad sequence conversion\");\n        inSeqs += block.nbSequences;\n        nbSequences -= block.nbSequences;\n        remaining -= block.blockSize;\n\n        /* Note: when blockSize is very small, other variant send it uncompressed.\n         * Here, we still send the sequences, because we don't have the original source to send it uncompressed.\n         * One could imagine in theory reproducing the source from the sequences,\n         * but that's complex and costly memory intensive, and goes against the objectives of this variant. */\n\n        RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall, \"not enough dstCapacity to write a new compressed block\");\n\n        compressedSeqsSize = ZSTD_entropyCompressSeqStore_internal(\n                                op + ZSTD_blockHeaderSize /* Leave space for block header */, dstCapacity - ZSTD_blockHeaderSize,\n                                literals, block.litSize,\n                                &cctx->seqStore,\n                                &cctx->blockState.prevCBlock->entropy, &cctx->blockState.nextCBlock->entropy,\n                                &cctx->appliedParams,\n                                cctx->tmpWorkspace, cctx->tmpWkspSize /* statically allocated in resetCCtx */,\n                                cctx->bmi2);\n        FORWARD_IF_ERROR(compressedSeqsSize, \"Compressing sequences of block failed\");\n        /* note: the spec forbids for any compressed block to be larger than maximum block size */\n        if (compressedSeqsSize > cctx->blockSizeMax) compressedSeqsSize = 0;\n        DEBUGLOG(5, \"Compressed sequences size: %zu\", compressedSeqsSize);\n        litSize -= block.litSize;\n        literals = (const char*)literals + block.litSize;\n\n        /* Note: difficult to check source for RLE block when only Literals are provided,\n         * but it could be considered from analyzing the sequence directly */\n\n        if (compressedSeqsSize == 0) {\n            /* Sending uncompressed blocks is out of reach, because the source is not provided.\n             * In theory, one could use the sequences to regenerate the source, like a decompressor,\n             * but it's complex, and memory hungry, killing the purpose of this variant.\n             * Current outcome: generate an error code.\n             */\n            RETURN_ERROR(cannotProduce_uncompressedBlock, \"ZSTD_compressSequencesAndLiterals cannot generate an uncompressed block\");\n        } else {\n            U32 cBlockHeader;\n            assert(compressedSeqsSize > 1); /* no RLE */\n            /* Error checking and repcodes update */\n            ZSTD_blockState_confirmRepcodesAndEntropyTables(&cctx->blockState);\n            if (cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)\n                cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;\n\n            /* Write block header into beginning of block*/\n            cBlockHeader = lastBlock + (((U32)bt_compressed)<<1) + (U32)(compressedSeqsSize << 3);\n            MEM_writeLE24(op, cBlockHeader);\n            cBlockSize = ZSTD_blockHeaderSize + compressedSeqsSize;\n            DEBUGLOG(5, \"Writing out compressed block, size: %zu\", cBlockSize);\n        }\n\n        cSize += cBlockSize;\n        op += cBlockSize;\n        dstCapacity -= cBlockSize;\n        cctx->isFirstBlock = 0;\n        DEBUGLOG(5, \"cSize running total: %zu (remaining dstCapacity=%zu)\", cSize, dstCapacity);\n\n        if (lastBlock) {\n            assert(nbSequences == 0);\n            break;\n        }\n    }\n\n    RETURN_ERROR_IF(litSize != 0, externalSequences_invalid, \"literals must be entirely and exactly consumed\");\n    RETURN_ERROR_IF(remaining != 0, externalSequences_invalid, \"Sequences must represent a total of exactly srcSize=%zu\", srcSize);\n    DEBUGLOG(4, \"cSize final total: %zu\", cSize);\n    return cSize;\n}\n\nsize_t\nZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx,\n                    void* dst, size_t dstCapacity,\n                    const ZSTD_Sequence* inSeqs, size_t inSeqsSize,\n                    const void* literals, size_t litSize, size_t litCapacity,\n                    size_t decompressedSize)\n{\n    BYTE* op = (BYTE*)dst;\n    size_t cSize = 0;\n\n    /* Transparent initialization stage, same as compressStream2() */\n    DEBUGLOG(4, \"ZSTD_compressSequencesAndLiterals (dstCapacity=%zu)\", dstCapacity);\n    assert(cctx != NULL);\n    if (litCapacity < litSize) {\n        RETURN_ERROR(workSpace_tooSmall, \"literals buffer is not large enough: must be at least 8 bytes larger than litSize (risk of read out-of-bound)\");\n    }\n    FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, ZSTD_e_end, decompressedSize), \"CCtx initialization failed\");\n\n    if (cctx->appliedParams.blockDelimiters == ZSTD_sf_noBlockDelimiters) {\n        RETURN_ERROR(frameParameter_unsupported, \"This mode is only compatible with explicit delimiters\");\n    }\n    if (cctx->appliedParams.validateSequences) {\n        RETURN_ERROR(parameter_unsupported, \"This mode is not compatible with Sequence validation\");\n    }\n    if (cctx->appliedParams.fParams.checksumFlag) {\n        RETURN_ERROR(frameParameter_unsupported, \"this mode is not compatible with frame checksum\");\n    }\n\n    /* Begin writing output, starting with frame header */\n    {   size_t const frameHeaderSize = ZSTD_writeFrameHeader(op, dstCapacity,\n                    &cctx->appliedParams, decompressedSize, cctx->dictID);\n        op += frameHeaderSize;\n        assert(frameHeaderSize <= dstCapacity);\n        dstCapacity -= frameHeaderSize;\n        cSize += frameHeaderSize;\n    }\n\n    /* Now generate compressed blocks */\n    {   size_t const cBlocksSize = ZSTD_compressSequencesAndLiterals_internal(cctx,\n                                            op, dstCapacity,\n                                            inSeqs, inSeqsSize,\n                                            literals, litSize, decompressedSize);\n        FORWARD_IF_ERROR(cBlocksSize, \"Compressing blocks failed!\");\n        cSize += cBlocksSize;\n        assert(cBlocksSize <= dstCapacity);\n        dstCapacity -= cBlocksSize;\n    }\n\n    DEBUGLOG(4, \"Final compressed size: %zu\", cSize);\n    return cSize;\n}\n\n/*======   Finalize   ======*/\n\nstatic ZSTD_inBuffer inBuffer_forEndFlush(const ZSTD_CStream* zcs)\n{\n    const ZSTD_inBuffer nullInput = { NULL, 0, 0 };\n    const int stableInput = (zcs->appliedParams.inBufferMode == ZSTD_bm_stable);\n    return stableInput ? zcs->expectedInBuffer : nullInput;\n}\n\n/*! ZSTD_flushStream() :\n * @return : amount of data remaining to flush */\nsize_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)\n{\n    ZSTD_inBuffer input = inBuffer_forEndFlush(zcs);\n    input.size = input.pos; /* do not ingest more input during flush */\n    return ZSTD_compressStream2(zcs, output, &input, ZSTD_e_flush);\n}\n\nsize_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)\n{\n    ZSTD_inBuffer input = inBuffer_forEndFlush(zcs);\n    size_t const remainingToFlush = ZSTD_compressStream2(zcs, output, &input, ZSTD_e_end);\n    FORWARD_IF_ERROR(remainingToFlush , \"ZSTD_compressStream2(,,ZSTD_e_end) failed\");\n    if (zcs->appliedParams.nbWorkers > 0) return remainingToFlush;   /* minimal estimation */\n    /* single thread mode : attempt to calculate remaining to flush more precisely */\n    {   size_t const lastBlockSize = zcs->frameEnded ? 0 : ZSTD_BLOCKHEADERSIZE;\n        size_t const checksumSize = (size_t)(zcs->frameEnded ? 0 : zcs->appliedParams.fParams.checksumFlag * 4);\n        size_t const toFlush = remainingToFlush + lastBlockSize + checksumSize;\n        DEBUGLOG(4, \"ZSTD_endStream : remaining to flush : %u\", (unsigned)toFlush);\n        return toFlush;\n    }\n}\n\n\n/*-=====  Pre-defined compression levels  =====-*/\n#include \"clevels.h\"\n\nint ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }\nint ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; }\nint ZSTD_defaultCLevel(void) { return ZSTD_CLEVEL_DEFAULT; }\n\nstatic ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams(int const compressionLevel, size_t const dictSize)\n{\n    ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, 0, dictSize, ZSTD_cpm_createCDict);\n    switch (cParams.strategy) {\n        case ZSTD_fast:\n        case ZSTD_dfast:\n            break;\n        case ZSTD_greedy:\n        case ZSTD_lazy:\n        case ZSTD_lazy2:\n            cParams.hashLog += ZSTD_LAZY_DDSS_BUCKET_LOG;\n            break;\n        case ZSTD_btlazy2:\n        case ZSTD_btopt:\n        case ZSTD_btultra:\n        case ZSTD_btultra2:\n            break;\n    }\n    return cParams;\n}\n\nstatic int ZSTD_dedicatedDictSearch_isSupported(\n        ZSTD_compressionParameters const* cParams)\n{\n    return (cParams->strategy >= ZSTD_greedy)\n        && (cParams->strategy <= ZSTD_lazy2)\n        && (cParams->hashLog > cParams->chainLog)\n        && (cParams->chainLog <= 24);\n}\n\n/**\n * Reverses the adjustment applied to cparams when enabling dedicated dict\n * search. This is used to recover the params set to be used in the working\n * context. (Otherwise, those tables would also grow.)\n */\nstatic void ZSTD_dedicatedDictSearch_revertCParams(\n        ZSTD_compressionParameters* cParams) {\n    switch (cParams->strategy) {\n        case ZSTD_fast:\n        case ZSTD_dfast:\n            break;\n        case ZSTD_greedy:\n        case ZSTD_lazy:\n        case ZSTD_lazy2:\n            cParams->hashLog -= ZSTD_LAZY_DDSS_BUCKET_LOG;\n            if (cParams->hashLog < ZSTD_HASHLOG_MIN) {\n                cParams->hashLog = ZSTD_HASHLOG_MIN;\n            }\n            break;\n        case ZSTD_btlazy2:\n        case ZSTD_btopt:\n        case ZSTD_btultra:\n        case ZSTD_btultra2:\n            break;\n    }\n}\n\nstatic U64 ZSTD_getCParamRowSize(U64 srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode)\n{\n    switch (mode) {\n    case ZSTD_cpm_unknown:\n    case ZSTD_cpm_noAttachDict:\n    case ZSTD_cpm_createCDict:\n        break;\n    case ZSTD_cpm_attachDict:\n        dictSize = 0;\n        break;\n    default:\n        assert(0);\n        break;\n    }\n    {   int const unknown = srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN;\n        size_t const addedSize = unknown && dictSize > 0 ? 500 : 0;\n        return unknown && dictSize == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : srcSizeHint+dictSize+addedSize;\n    }\n}\n\n/*! ZSTD_getCParams_internal() :\n * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.\n *  Note: srcSizeHint 0 means 0, use ZSTD_CONTENTSIZE_UNKNOWN for unknown.\n *        Use dictSize == 0 for unknown or unused.\n *  Note: `mode` controls how we treat the `dictSize`. See docs for `ZSTD_CParamMode_e`. */\nstatic ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode)\n{\n    U64 const rSize = ZSTD_getCParamRowSize(srcSizeHint, dictSize, mode);\n    U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB);\n    int row;\n    DEBUGLOG(5, \"ZSTD_getCParams_internal (cLevel=%i)\", compressionLevel);\n\n    /* row */\n    if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT;   /* 0 == default */\n    else if (compressionLevel < 0) row = 0;   /* entry 0 is baseline for fast mode */\n    else if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL;\n    else row = compressionLevel;\n\n    {   ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row];\n        DEBUGLOG(5, \"ZSTD_getCParams_internal selected tableID: %u row: %u strat: %u\", tableID, row, (U32)cp.strategy);\n        /* acceleration factor */\n        if (compressionLevel < 0) {\n            int const clampedCompressionLevel = MAX(ZSTD_minCLevel(), compressionLevel);\n            cp.targetLength = (unsigned)(-clampedCompressionLevel);\n        }\n        /* refine parameters based on srcSize & dictSize */\n        return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize, mode, ZSTD_ps_auto);\n    }\n}\n\n/*! ZSTD_getCParams() :\n * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.\n *  Size values are optional, provide 0 if not known or unused */\nZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)\n{\n    if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN;\n    return ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown);\n}\n\n/*! ZSTD_getParams() :\n *  same idea as ZSTD_getCParams()\n * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`).\n *  Fields of `ZSTD_frameParameters` are set to default values */\nstatic ZSTD_parameters\nZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode)\n{\n    ZSTD_parameters params;\n    ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, mode);\n    DEBUGLOG(5, \"ZSTD_getParams (cLevel=%i)\", compressionLevel);\n    ZSTD_memset(&params, 0, sizeof(params));\n    params.cParams = cParams;\n    params.fParams.contentSizeFlag = 1;\n    return params;\n}\n\n/*! ZSTD_getParams() :\n *  same idea as ZSTD_getCParams()\n * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`).\n *  Fields of `ZSTD_frameParameters` are set to default values */\nZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)\n{\n    if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN;\n    return ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown);\n}\n\nvoid ZSTD_registerSequenceProducer(\n    ZSTD_CCtx* zc,\n    void* extSeqProdState,\n    ZSTD_sequenceProducer_F extSeqProdFunc)\n{\n    assert(zc != NULL);\n    ZSTD_CCtxParams_registerSequenceProducer(\n        &zc->requestedParams, extSeqProdState, extSeqProdFunc\n    );\n}\n\nvoid ZSTD_CCtxParams_registerSequenceProducer(\n  ZSTD_CCtx_params* params,\n  void* extSeqProdState,\n  ZSTD_sequenceProducer_F extSeqProdFunc)\n{\n    assert(params != NULL);\n    if (extSeqProdFunc != NULL) {\n        params->extSeqProdFunc = extSeqProdFunc;\n        params->extSeqProdState = extSeqProdState;\n    } else {\n        params->extSeqProdFunc = NULL;\n        params->extSeqProdState = NULL;\n    }\n}\n"
  },
  {
    "path": "lib/compress/zstd_compress_internal.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* This header contains definitions\n * that shall **only** be used by modules within lib/compress.\n */\n\n#ifndef ZSTD_COMPRESS_H\n#define ZSTD_COMPRESS_H\n\n/*-*************************************\n*  Dependencies\n***************************************/\n#include \"../common/zstd_internal.h\"\n#include \"zstd_cwksp.h\"\n#ifdef ZSTD_MULTITHREAD\n#  include \"zstdmt_compress.h\"\n#endif\n#include \"../common/bits.h\" /* ZSTD_highbit32, ZSTD_NbCommonBytes */\n#include \"zstd_preSplit.h\" /* ZSTD_SLIPBLOCK_WORKSPACESIZE */\n\n/*-*************************************\n*  Constants\n***************************************/\n#define kSearchStrength      8\n#define HASH_READ_SIZE       8\n#define ZSTD_DUBT_UNSORTED_MARK 1   /* For btlazy2 strategy, index ZSTD_DUBT_UNSORTED_MARK==1 means \"unsorted\".\n                                       It could be confused for a real successor at index \"1\", if sorted as larger than its predecessor.\n                                       It's not a big deal though : candidate will just be sorted again.\n                                       Additionally, candidate position 1 will be lost.\n                                       But candidate 1 cannot hide a large tree of candidates, so it's a minimal loss.\n                                       The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be mishandled after table reuse with a different strategy.\n                                       This constant is required by ZSTD_compressBlock_btlazy2() and ZSTD_reduceTable_internal() */\n\n\n/*-*************************************\n*  Context memory management\n***************************************/\ntypedef enum { ZSTDcs_created=0, ZSTDcs_init, ZSTDcs_ongoing, ZSTDcs_ending } ZSTD_compressionStage_e;\ntypedef enum { zcss_init=0, zcss_load, zcss_flush } ZSTD_cStreamStage;\n\ntypedef struct ZSTD_prefixDict_s {\n    const void* dict;\n    size_t dictSize;\n    ZSTD_dictContentType_e dictContentType;\n} ZSTD_prefixDict;\n\ntypedef struct {\n    void* dictBuffer;\n    void const* dict;\n    size_t dictSize;\n    ZSTD_dictContentType_e dictContentType;\n    ZSTD_CDict* cdict;\n} ZSTD_localDict;\n\ntypedef struct {\n    HUF_CElt CTable[HUF_CTABLE_SIZE_ST(255)];\n    HUF_repeat repeatMode;\n} ZSTD_hufCTables_t;\n\ntypedef struct {\n    FSE_CTable offcodeCTable[FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)];\n    FSE_CTable matchlengthCTable[FSE_CTABLE_SIZE_U32(MLFSELog, MaxML)];\n    FSE_CTable litlengthCTable[FSE_CTABLE_SIZE_U32(LLFSELog, MaxLL)];\n    FSE_repeat offcode_repeatMode;\n    FSE_repeat matchlength_repeatMode;\n    FSE_repeat litlength_repeatMode;\n} ZSTD_fseCTables_t;\n\ntypedef struct {\n    ZSTD_hufCTables_t huf;\n    ZSTD_fseCTables_t fse;\n} ZSTD_entropyCTables_t;\n\n/***********************************************\n*  Sequences *\n***********************************************/\ntypedef struct SeqDef_s {\n    U32 offBase;   /* offBase == Offset + ZSTD_REP_NUM, or repcode 1,2,3 */\n    U16 litLength;\n    U16 mlBase;    /* mlBase == matchLength - MINMATCH */\n} SeqDef;\n\n/* Controls whether seqStore has a single \"long\" litLength or matchLength. See SeqStore_t. */\ntypedef enum {\n    ZSTD_llt_none = 0,             /* no longLengthType */\n    ZSTD_llt_literalLength = 1,    /* represents a long literal */\n    ZSTD_llt_matchLength = 2       /* represents a long match */\n} ZSTD_longLengthType_e;\n\ntypedef struct {\n    SeqDef* sequencesStart;\n    SeqDef* sequences;      /* ptr to end of sequences */\n    BYTE*  litStart;\n    BYTE*  lit;             /* ptr to end of literals */\n    BYTE*  llCode;\n    BYTE*  mlCode;\n    BYTE*  ofCode;\n    size_t maxNbSeq;\n    size_t maxNbLit;\n\n    /* longLengthPos and longLengthType to allow us to represent either a single litLength or matchLength\n     * in the seqStore that has a value larger than U16 (if it exists). To do so, we increment\n     * the existing value of the litLength or matchLength by 0x10000.\n     */\n    ZSTD_longLengthType_e longLengthType;\n    U32                   longLengthPos;  /* Index of the sequence to apply long length modification to */\n} SeqStore_t;\n\ntypedef struct {\n    U32 litLength;\n    U32 matchLength;\n} ZSTD_SequenceLength;\n\n/**\n * Returns the ZSTD_SequenceLength for the given sequences. It handles the decoding of long sequences\n * indicated by longLengthPos and longLengthType, and adds MINMATCH back to matchLength.\n */\nMEM_STATIC ZSTD_SequenceLength ZSTD_getSequenceLength(SeqStore_t const* seqStore, SeqDef const* seq)\n{\n    ZSTD_SequenceLength seqLen;\n    seqLen.litLength = seq->litLength;\n    seqLen.matchLength = seq->mlBase + MINMATCH;\n    if (seqStore->longLengthPos == (U32)(seq - seqStore->sequencesStart)) {\n        if (seqStore->longLengthType == ZSTD_llt_literalLength) {\n            seqLen.litLength += 0x10000;\n        }\n        if (seqStore->longLengthType == ZSTD_llt_matchLength) {\n            seqLen.matchLength += 0x10000;\n        }\n    }\n    return seqLen;\n}\n\nconst SeqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx);   /* compress & dictBuilder */\nint ZSTD_seqToCodes(const SeqStore_t* seqStorePtr);   /* compress, dictBuilder, decodeCorpus (shouldn't get its definition from here) */\n\n\n/***********************************************\n*  Entropy buffer statistics structs and funcs *\n***********************************************/\n/** ZSTD_hufCTablesMetadata_t :\n *  Stores Literals Block Type for a super-block in hType, and\n *  huffman tree description in hufDesBuffer.\n *  hufDesSize refers to the size of huffman tree description in bytes.\n *  This metadata is populated in ZSTD_buildBlockEntropyStats_literals() */\ntypedef struct {\n    SymbolEncodingType_e hType;\n    BYTE hufDesBuffer[ZSTD_MAX_HUF_HEADER_SIZE];\n    size_t hufDesSize;\n} ZSTD_hufCTablesMetadata_t;\n\n/** ZSTD_fseCTablesMetadata_t :\n *  Stores symbol compression modes for a super-block in {ll, ol, ml}Type, and\n *  fse tables in fseTablesBuffer.\n *  fseTablesSize refers to the size of fse tables in bytes.\n *  This metadata is populated in ZSTD_buildBlockEntropyStats_sequences() */\ntypedef struct {\n    SymbolEncodingType_e llType;\n    SymbolEncodingType_e ofType;\n    SymbolEncodingType_e mlType;\n    BYTE fseTablesBuffer[ZSTD_MAX_FSE_HEADERS_SIZE];\n    size_t fseTablesSize;\n    size_t lastCountSize; /* This is to account for bug in 1.3.4. More detail in ZSTD_entropyCompressSeqStore_internal() */\n} ZSTD_fseCTablesMetadata_t;\n\ntypedef struct {\n    ZSTD_hufCTablesMetadata_t hufMetadata;\n    ZSTD_fseCTablesMetadata_t fseMetadata;\n} ZSTD_entropyCTablesMetadata_t;\n\n/** ZSTD_buildBlockEntropyStats() :\n *  Builds entropy for the block.\n *  @return : 0 on success or error code */\nsize_t ZSTD_buildBlockEntropyStats(\n                    const SeqStore_t* seqStorePtr,\n                    const ZSTD_entropyCTables_t* prevEntropy,\n                          ZSTD_entropyCTables_t* nextEntropy,\n                    const ZSTD_CCtx_params* cctxParams,\n                          ZSTD_entropyCTablesMetadata_t* entropyMetadata,\n                          void* workspace, size_t wkspSize);\n\n/*********************************\n*  Compression internals structs *\n*********************************/\n\ntypedef struct {\n    U32 off;            /* Offset sumtype code for the match, using ZSTD_storeSeq() format */\n    U32 len;            /* Raw length of match */\n} ZSTD_match_t;\n\ntypedef struct {\n    U32 offset;         /* Offset of sequence */\n    U32 litLength;      /* Length of literals prior to match */\n    U32 matchLength;    /* Raw length of match */\n} rawSeq;\n\ntypedef struct {\n  rawSeq* seq;          /* The start of the sequences */\n  size_t pos;           /* The index in seq where reading stopped. pos <= size. */\n  size_t posInSequence; /* The position within the sequence at seq[pos] where reading\n                           stopped. posInSequence <= seq[pos].litLength + seq[pos].matchLength */\n  size_t size;          /* The number of sequences. <= capacity. */\n  size_t capacity;      /* The capacity starting from `seq` pointer */\n} RawSeqStore_t;\n\nUNUSED_ATTR static const RawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0, 0};\n\ntypedef struct {\n    int price;  /* price from beginning of segment to this position */\n    U32 off;    /* offset of previous match */\n    U32 mlen;   /* length of previous match */\n    U32 litlen; /* nb of literals since previous match */\n    U32 rep[ZSTD_REP_NUM];  /* offset history after previous match */\n} ZSTD_optimal_t;\n\ntypedef enum { zop_dynamic=0, zop_predef } ZSTD_OptPrice_e;\n\n#define ZSTD_OPT_SIZE (ZSTD_OPT_NUM+3)\ntypedef struct {\n    /* All tables are allocated inside cctx->workspace by ZSTD_resetCCtx_internal() */\n    unsigned* litFreq;           /* table of literals statistics, of size 256 */\n    unsigned* litLengthFreq;     /* table of litLength statistics, of size (MaxLL+1) */\n    unsigned* matchLengthFreq;   /* table of matchLength statistics, of size (MaxML+1) */\n    unsigned* offCodeFreq;       /* table of offCode statistics, of size (MaxOff+1) */\n    ZSTD_match_t* matchTable;    /* list of found matches, of size ZSTD_OPT_SIZE */\n    ZSTD_optimal_t* priceTable;  /* All positions tracked by optimal parser, of size ZSTD_OPT_SIZE */\n\n    U32  litSum;                 /* nb of literals */\n    U32  litLengthSum;           /* nb of litLength codes */\n    U32  matchLengthSum;         /* nb of matchLength codes */\n    U32  offCodeSum;             /* nb of offset codes */\n    U32  litSumBasePrice;        /* to compare to log2(litfreq) */\n    U32  litLengthSumBasePrice;  /* to compare to log2(llfreq)  */\n    U32  matchLengthSumBasePrice;/* to compare to log2(mlfreq)  */\n    U32  offCodeSumBasePrice;    /* to compare to log2(offreq)  */\n    ZSTD_OptPrice_e priceType;   /* prices can be determined dynamically, or follow a pre-defined cost structure */\n    const ZSTD_entropyCTables_t* symbolCosts;  /* pre-calculated dictionary statistics */\n    ZSTD_ParamSwitch_e literalCompressionMode;\n} optState_t;\n\ntypedef struct {\n  ZSTD_entropyCTables_t entropy;\n  U32 rep[ZSTD_REP_NUM];\n} ZSTD_compressedBlockState_t;\n\ntypedef struct {\n    BYTE const* nextSrc;       /* next block here to continue on current prefix */\n    BYTE const* base;          /* All regular indexes relative to this position */\n    BYTE const* dictBase;      /* extDict indexes relative to this position */\n    U32 dictLimit;             /* below that point, need extDict */\n    U32 lowLimit;              /* below that point, no more valid data */\n    U32 nbOverflowCorrections; /* Number of times overflow correction has run since\n                                * ZSTD_window_init(). Useful for debugging coredumps\n                                * and for ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY.\n                                */\n} ZSTD_window_t;\n\n#define ZSTD_WINDOW_START_INDEX 2\n\ntypedef struct ZSTD_MatchState_t ZSTD_MatchState_t;\n\n#define ZSTD_ROW_HASH_CACHE_SIZE 8       /* Size of prefetching hash cache for row-based matchfinder */\n\nstruct ZSTD_MatchState_t {\n    ZSTD_window_t window;   /* State for window round buffer management */\n    U32 loadedDictEnd;      /* index of end of dictionary, within context's referential.\n                             * When loadedDictEnd != 0, a dictionary is in use, and still valid.\n                             * This relies on a mechanism to set loadedDictEnd=0 when dictionary is no longer within distance.\n                             * Such mechanism is provided within ZSTD_window_enforceMaxDist() and ZSTD_checkDictValidity().\n                             * When dict referential is copied into active context (i.e. not attached),\n                             * loadedDictEnd == dictSize, since referential starts from zero.\n                             */\n    U32 nextToUpdate;       /* index from which to continue table update */\n    U32 hashLog3;           /* dispatch table for matches of len==3 : larger == faster, more memory */\n\n    U32 rowHashLog;                          /* For row-based matchfinder: Hashlog based on nb of rows in the hashTable.*/\n    BYTE* tagTable;                          /* For row-based matchFinder: A row-based table containing the hashes and head index. */\n    U32 hashCache[ZSTD_ROW_HASH_CACHE_SIZE]; /* For row-based matchFinder: a cache of hashes to improve speed */\n    U64 hashSalt;                            /* For row-based matchFinder: salts the hash for reuse of tag table */\n    U32 hashSaltEntropy;                     /* For row-based matchFinder: collects entropy for salt generation */\n\n    U32* hashTable;\n    U32* hashTable3;\n    U32* chainTable;\n\n    int forceNonContiguous; /* Non-zero if we should force non-contiguous load for the next window update. */\n\n    int dedicatedDictSearch;  /* Indicates whether this matchState is using the\n                               * dedicated dictionary search structure.\n                               */\n    optState_t opt;         /* optimal parser state */\n    const ZSTD_MatchState_t* dictMatchState;\n    ZSTD_compressionParameters cParams;\n    const RawSeqStore_t* ldmSeqStore;\n\n    /* Controls prefetching in some dictMatchState matchfinders.\n     * This behavior is controlled from the cctx ms.\n     * This parameter has no effect in the cdict ms. */\n    int prefetchCDictTables;\n\n    /* When == 0, lazy match finders insert every position.\n     * When != 0, lazy match finders only insert positions they search.\n     * This allows them to skip much faster over incompressible data,\n     * at a small cost to compression ratio.\n     */\n    int lazySkipping;\n};\n\ntypedef struct {\n    ZSTD_compressedBlockState_t* prevCBlock;\n    ZSTD_compressedBlockState_t* nextCBlock;\n    ZSTD_MatchState_t matchState;\n} ZSTD_blockState_t;\n\ntypedef struct {\n    U32 offset;\n    U32 checksum;\n} ldmEntry_t;\n\ntypedef struct {\n    BYTE const* split;\n    U32 hash;\n    U32 checksum;\n    ldmEntry_t* bucket;\n} ldmMatchCandidate_t;\n\n#define LDM_BATCH_SIZE 64\n\ntypedef struct {\n    ZSTD_window_t window;   /* State for the window round buffer management */\n    ldmEntry_t* hashTable;\n    U32 loadedDictEnd;\n    BYTE* bucketOffsets;    /* Next position in bucket to insert entry */\n    size_t splitIndices[LDM_BATCH_SIZE];\n    ldmMatchCandidate_t matchCandidates[LDM_BATCH_SIZE];\n} ldmState_t;\n\ntypedef struct {\n    ZSTD_ParamSwitch_e enableLdm; /* ZSTD_ps_enable to enable LDM. ZSTD_ps_auto by default */\n    U32 hashLog;            /* Log size of hashTable */\n    U32 bucketSizeLog;      /* Log bucket size for collision resolution, at most 8 */\n    U32 minMatchLength;     /* Minimum match length */\n    U32 hashRateLog;       /* Log number of entries to skip */\n    U32 windowLog;          /* Window log for the LDM */\n} ldmParams_t;\n\ntypedef struct {\n    int collectSequences;\n    ZSTD_Sequence* seqStart;\n    size_t seqIndex;\n    size_t maxSequences;\n} SeqCollector;\n\nstruct ZSTD_CCtx_params_s {\n    ZSTD_format_e format;\n    ZSTD_compressionParameters cParams;\n    ZSTD_frameParameters fParams;\n\n    int compressionLevel;\n    int forceWindow;           /* force back-references to respect limit of\n                                * 1<<wLog, even for dictionary */\n    size_t targetCBlockSize;   /* Tries to fit compressed block size to be around targetCBlockSize.\n                                * No target when targetCBlockSize == 0.\n                                * There is no guarantee on compressed block size */\n    int srcSizeHint;           /* User's best guess of source size.\n                                * Hint is not valid when srcSizeHint == 0.\n                                * There is no guarantee that hint is close to actual source size */\n\n    ZSTD_dictAttachPref_e attachDictPref;\n    ZSTD_ParamSwitch_e literalCompressionMode;\n\n    /* Multithreading: used to pass parameters to mtctx */\n    int nbWorkers;\n    size_t jobSize;\n    int overlapLog;\n    int rsyncable;\n\n    /* Long distance matching parameters */\n    ldmParams_t ldmParams;\n\n    /* Dedicated dict search algorithm trigger */\n    int enableDedicatedDictSearch;\n\n    /* Input/output buffer modes */\n    ZSTD_bufferMode_e inBufferMode;\n    ZSTD_bufferMode_e outBufferMode;\n\n    /* Sequence compression API */\n    ZSTD_SequenceFormat_e blockDelimiters;\n    int validateSequences;\n\n    /* Block splitting\n     * @postBlockSplitter executes split analysis after sequences are produced,\n     * it's more accurate but consumes more resources.\n     * @preBlockSplitter_level splits before knowing sequences,\n     * it's more approximative but also cheaper.\n     * Valid @preBlockSplitter_level values range from 0 to 6 (included).\n     * 0 means auto, 1 means do not split,\n     * then levels are sorted in increasing cpu budget, from 2 (fastest) to 6 (slowest).\n     * Highest @preBlockSplitter_level combines well with @postBlockSplitter.\n     */\n    ZSTD_ParamSwitch_e postBlockSplitter;\n    int preBlockSplitter_level;\n\n    /* Adjust the max block size*/\n    size_t maxBlockSize;\n\n    /* Param for deciding whether to use row-based matchfinder */\n    ZSTD_ParamSwitch_e useRowMatchFinder;\n\n    /* Always load a dictionary in ext-dict mode (not prefix mode)? */\n    int deterministicRefPrefix;\n\n    /* Internal use, for createCCtxParams() and freeCCtxParams() only */\n    ZSTD_customMem customMem;\n\n    /* Controls prefetching in some dictMatchState matchfinders */\n    ZSTD_ParamSwitch_e prefetchCDictTables;\n\n    /* Controls whether zstd will fall back to an internal matchfinder\n     * if the external matchfinder returns an error code. */\n    int enableMatchFinderFallback;\n\n    /* Parameters for the external sequence producer API.\n     * Users set these parameters through ZSTD_registerSequenceProducer().\n     * It is not possible to set these parameters individually through the public API. */\n    void* extSeqProdState;\n    ZSTD_sequenceProducer_F extSeqProdFunc;\n\n    /* Controls repcode search in external sequence parsing */\n    ZSTD_ParamSwitch_e searchForExternalRepcodes;\n};  /* typedef'd to ZSTD_CCtx_params within \"zstd.h\" */\n\n#define COMPRESS_SEQUENCES_WORKSPACE_SIZE (sizeof(unsigned) * (MaxSeq + 2))\n#define ENTROPY_WORKSPACE_SIZE (HUF_WORKSPACE_SIZE + COMPRESS_SEQUENCES_WORKSPACE_SIZE)\n#define TMP_WORKSPACE_SIZE (MAX(ENTROPY_WORKSPACE_SIZE, ZSTD_SLIPBLOCK_WORKSPACESIZE))\n\n/**\n * Indicates whether this compression proceeds directly from user-provided\n * source buffer to user-provided destination buffer (ZSTDb_not_buffered), or\n * whether the context needs to buffer the input/output (ZSTDb_buffered).\n */\ntypedef enum {\n    ZSTDb_not_buffered,\n    ZSTDb_buffered\n} ZSTD_buffered_policy_e;\n\n/**\n * Struct that contains all elements of block splitter that should be allocated\n * in a wksp.\n */\n#define ZSTD_MAX_NB_BLOCK_SPLITS 196\ntypedef struct {\n    SeqStore_t fullSeqStoreChunk;\n    SeqStore_t firstHalfSeqStore;\n    SeqStore_t secondHalfSeqStore;\n    SeqStore_t currSeqStore;\n    SeqStore_t nextSeqStore;\n\n    U32 partitions[ZSTD_MAX_NB_BLOCK_SPLITS];\n    ZSTD_entropyCTablesMetadata_t entropyMetadata;\n} ZSTD_blockSplitCtx;\n\nstruct ZSTD_CCtx_s {\n    ZSTD_compressionStage_e stage;\n    int cParamsChanged;                  /* == 1 if cParams(except wlog) or compression level are changed in requestedParams. Triggers transmission of new params to ZSTDMT (if available) then reset to 0. */\n    int bmi2;                            /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */\n    ZSTD_CCtx_params requestedParams;\n    ZSTD_CCtx_params appliedParams;\n    ZSTD_CCtx_params simpleApiParams;    /* Param storage used by the simple API - not sticky. Must only be used in top-level simple API functions for storage. */\n    U32   dictID;\n    size_t dictContentSize;\n\n    ZSTD_cwksp workspace; /* manages buffer for dynamic allocations */\n    size_t blockSizeMax;\n    unsigned long long pledgedSrcSizePlusOne;  /* this way, 0 (default) == unknown */\n    unsigned long long consumedSrcSize;\n    unsigned long long producedCSize;\n    XXH64_state_t xxhState;\n    ZSTD_customMem customMem;\n    ZSTD_threadPool* pool;\n    size_t staticSize;\n    SeqCollector seqCollector;\n    int isFirstBlock;\n    int initialized;\n\n    SeqStore_t seqStore;      /* sequences storage ptrs */\n    ldmState_t ldmState;      /* long distance matching state */\n    rawSeq* ldmSequences;     /* Storage for the ldm output sequences */\n    size_t maxNbLdmSequences;\n    RawSeqStore_t externSeqStore; /* Mutable reference to external sequences */\n    ZSTD_blockState_t blockState;\n    void* tmpWorkspace;  /* used as substitute of stack space - must be aligned for S64 type */\n    size_t tmpWkspSize;\n\n    /* Whether we are streaming or not */\n    ZSTD_buffered_policy_e bufferedPolicy;\n\n    /* streaming */\n    char*  inBuff;\n    size_t inBuffSize;\n    size_t inToCompress;\n    size_t inBuffPos;\n    size_t inBuffTarget;\n    char*  outBuff;\n    size_t outBuffSize;\n    size_t outBuffContentSize;\n    size_t outBuffFlushedSize;\n    ZSTD_cStreamStage streamStage;\n    U32    frameEnded;\n\n    /* Stable in/out buffer verification */\n    ZSTD_inBuffer expectedInBuffer;\n    size_t stableIn_notConsumed; /* nb bytes within stable input buffer that are said to be consumed but are not */\n    size_t expectedOutBufferSize;\n\n    /* Dictionary */\n    ZSTD_localDict localDict;\n    const ZSTD_CDict* cdict;\n    ZSTD_prefixDict prefixDict;   /* single-usage dictionary */\n\n    /* Multi-threading */\n#ifdef ZSTD_MULTITHREAD\n    ZSTDMT_CCtx* mtctx;\n#endif\n\n    /* Tracing */\n#if ZSTD_TRACE\n    ZSTD_TraceCtx traceCtx;\n#endif\n\n    /* Workspace for block splitter */\n    ZSTD_blockSplitCtx blockSplitCtx;\n\n    /* Buffer for output from external sequence producer */\n    ZSTD_Sequence* extSeqBuf;\n    size_t extSeqBufCapacity;\n};\n\ntypedef enum { ZSTD_dtlm_fast, ZSTD_dtlm_full } ZSTD_dictTableLoadMethod_e;\ntypedef enum { ZSTD_tfp_forCCtx, ZSTD_tfp_forCDict } ZSTD_tableFillPurpose_e;\n\ntypedef enum {\n    ZSTD_noDict = 0,\n    ZSTD_extDict = 1,\n    ZSTD_dictMatchState = 2,\n    ZSTD_dedicatedDictSearch = 3\n} ZSTD_dictMode_e;\n\ntypedef enum {\n    ZSTD_cpm_noAttachDict = 0,  /* Compression with ZSTD_noDict or ZSTD_extDict.\n                                 * In this mode we use both the srcSize and the dictSize\n                                 * when selecting and adjusting parameters.\n                                 */\n    ZSTD_cpm_attachDict = 1,    /* Compression with ZSTD_dictMatchState or ZSTD_dedicatedDictSearch.\n                                 * In this mode we only take the srcSize into account when selecting\n                                 * and adjusting parameters.\n                                 */\n    ZSTD_cpm_createCDict = 2,   /* Creating a CDict.\n                                 * In this mode we take both the source size and the dictionary size\n                                 * into account when selecting and adjusting the parameters.\n                                 */\n    ZSTD_cpm_unknown = 3        /* ZSTD_getCParams, ZSTD_getParams, ZSTD_adjustParams.\n                                 * We don't know what these parameters are for. We default to the legacy\n                                 * behavior of taking both the source size and the dict size into account\n                                 * when selecting and adjusting parameters.\n                                 */\n} ZSTD_CParamMode_e;\n\ntypedef size_t (*ZSTD_BlockCompressor_f) (\n        ZSTD_MatchState_t* bs, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nZSTD_BlockCompressor_f ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_ParamSwitch_e rowMatchfinderMode, ZSTD_dictMode_e dictMode);\n\n\nMEM_STATIC U32 ZSTD_LLcode(U32 litLength)\n{\n    static const BYTE LL_Code[64] = {  0,  1,  2,  3,  4,  5,  6,  7,\n                                       8,  9, 10, 11, 12, 13, 14, 15,\n                                      16, 16, 17, 17, 18, 18, 19, 19,\n                                      20, 20, 20, 20, 21, 21, 21, 21,\n                                      22, 22, 22, 22, 22, 22, 22, 22,\n                                      23, 23, 23, 23, 23, 23, 23, 23,\n                                      24, 24, 24, 24, 24, 24, 24, 24,\n                                      24, 24, 24, 24, 24, 24, 24, 24 };\n    static const U32 LL_deltaCode = 19;\n    return (litLength > 63) ? ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength];\n}\n\n/* ZSTD_MLcode() :\n * note : mlBase = matchLength - MINMATCH;\n *        because it's the format it's stored in seqStore->sequences */\nMEM_STATIC U32 ZSTD_MLcode(U32 mlBase)\n{\n    static const BYTE ML_Code[128] = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,\n                                      16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n                                      32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37,\n                                      38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39,\n                                      40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,\n                                      41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,\n                                      42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,\n                                      42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 };\n    static const U32 ML_deltaCode = 36;\n    return (mlBase > 127) ? ZSTD_highbit32(mlBase) + ML_deltaCode : ML_Code[mlBase];\n}\n\n/* ZSTD_cParam_withinBounds:\n * @return 1 if value is within cParam bounds,\n * 0 otherwise */\nMEM_STATIC int ZSTD_cParam_withinBounds(ZSTD_cParameter cParam, int value)\n{\n    ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam);\n    if (ZSTD_isError(bounds.error)) return 0;\n    if (value < bounds.lowerBound) return 0;\n    if (value > bounds.upperBound) return 0;\n    return 1;\n}\n\n/* ZSTD_selectAddr:\n * @return index >= lowLimit ? candidate : backup,\n * tries to force branchless codegen. */\nMEM_STATIC const BYTE*\nZSTD_selectAddr(U32 index, U32 lowLimit, const BYTE* candidate, const BYTE* backup)\n{\n#if defined(__GNUC__) && defined(__x86_64__)\n    __asm__ (\n        \"cmp %1, %2\\n\"\n        \"cmova %3, %0\\n\"\n        : \"+r\"(candidate)\n        : \"r\"(index), \"r\"(lowLimit), \"r\"(backup)\n        );\n    return candidate;\n#else\n    return index >= lowLimit ? candidate : backup;\n#endif\n}\n\n/* ZSTD_noCompressBlock() :\n * Writes uncompressed block to dst buffer from given src.\n * Returns the size of the block */\nMEM_STATIC size_t\nZSTD_noCompressBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock)\n{\n    U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(srcSize << 3);\n    DEBUGLOG(5, \"ZSTD_noCompressBlock (srcSize=%zu, dstCapacity=%zu)\", srcSize, dstCapacity);\n    RETURN_ERROR_IF(srcSize + ZSTD_blockHeaderSize > dstCapacity,\n                    dstSize_tooSmall, \"dst buf too small for uncompressed block\");\n    MEM_writeLE24(dst, cBlockHeader24);\n    ZSTD_memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize);\n    return ZSTD_blockHeaderSize + srcSize;\n}\n\nMEM_STATIC size_t\nZSTD_rleCompressBlock(void* dst, size_t dstCapacity, BYTE src, size_t srcSize, U32 lastBlock)\n{\n    BYTE* const op = (BYTE*)dst;\n    U32 const cBlockHeader = lastBlock + (((U32)bt_rle)<<1) + (U32)(srcSize << 3);\n    RETURN_ERROR_IF(dstCapacity < 4, dstSize_tooSmall, \"\");\n    MEM_writeLE24(op, cBlockHeader);\n    op[3] = src;\n    return 4;\n}\n\n\n/* ZSTD_minGain() :\n * minimum compression required\n * to generate a compress block or a compressed literals section.\n * note : use same formula for both situations */\nMEM_STATIC size_t ZSTD_minGain(size_t srcSize, ZSTD_strategy strat)\n{\n    U32 const minlog = (strat>=ZSTD_btultra) ? (U32)(strat) - 1 : 6;\n    ZSTD_STATIC_ASSERT(ZSTD_btultra == 8);\n    assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, (int)strat));\n    return (srcSize >> minlog) + 2;\n}\n\nMEM_STATIC int ZSTD_literalsCompressionIsDisabled(const ZSTD_CCtx_params* cctxParams)\n{\n    switch (cctxParams->literalCompressionMode) {\n    case ZSTD_ps_enable:\n        return 0;\n    case ZSTD_ps_disable:\n        return 1;\n    default:\n        assert(0 /* impossible: pre-validated */);\n        ZSTD_FALLTHROUGH;\n    case ZSTD_ps_auto:\n        return (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0);\n    }\n}\n\n/*! ZSTD_safecopyLiterals() :\n *  memcpy() function that won't read beyond more than WILDCOPY_OVERLENGTH bytes past ilimit_w.\n *  Only called when the sequence ends past ilimit_w, so it only needs to be optimized for single\n *  large copies.\n */\nstatic void\nZSTD_safecopyLiterals(BYTE* op, BYTE const* ip, BYTE const* const iend, BYTE const* ilimit_w)\n{\n    assert(iend > ilimit_w);\n    if (ip <= ilimit_w) {\n        ZSTD_wildcopy(op, ip, (size_t)(ilimit_w - ip), ZSTD_no_overlap);\n        op += ilimit_w - ip;\n        ip = ilimit_w;\n    }\n    while (ip < iend) *op++ = *ip++;\n}\n\n\n#define REPCODE1_TO_OFFBASE REPCODE_TO_OFFBASE(1)\n#define REPCODE2_TO_OFFBASE REPCODE_TO_OFFBASE(2)\n#define REPCODE3_TO_OFFBASE REPCODE_TO_OFFBASE(3)\n#define REPCODE_TO_OFFBASE(r) (assert((r)>=1), assert((r)<=ZSTD_REP_NUM), (r)) /* accepts IDs 1,2,3 */\n#define OFFSET_TO_OFFBASE(o)  (assert((o)>0), o + ZSTD_REP_NUM)\n#define OFFBASE_IS_OFFSET(o)  ((o) > ZSTD_REP_NUM)\n#define OFFBASE_IS_REPCODE(o) ( 1 <= (o) && (o) <= ZSTD_REP_NUM)\n#define OFFBASE_TO_OFFSET(o)  (assert(OFFBASE_IS_OFFSET(o)), (o) - ZSTD_REP_NUM)\n#define OFFBASE_TO_REPCODE(o) (assert(OFFBASE_IS_REPCODE(o)), (o))  /* returns ID 1,2,3 */\n\n/*! ZSTD_storeSeqOnly() :\n *  Store a sequence (litlen, litPtr, offBase and matchLength) into SeqStore_t.\n *  Literals themselves are not copied, but @litPtr is updated.\n *  @offBase : Users should employ macros REPCODE_TO_OFFBASE() and OFFSET_TO_OFFBASE().\n *  @matchLength : must be >= MINMATCH\n*/\nHINT_INLINE UNUSED_ATTR void\nZSTD_storeSeqOnly(SeqStore_t* seqStorePtr,\n              size_t litLength,\n              U32 offBase,\n              size_t matchLength)\n{\n    assert((size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart) < seqStorePtr->maxNbSeq);\n\n    /* literal Length */\n    assert(litLength <= ZSTD_BLOCKSIZE_MAX);\n    if (UNLIKELY(litLength>0xFFFF)) {\n        assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */\n        seqStorePtr->longLengthType = ZSTD_llt_literalLength;\n        seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);\n    }\n    seqStorePtr->sequences[0].litLength = (U16)litLength;\n\n    /* match offset */\n    seqStorePtr->sequences[0].offBase = offBase;\n\n    /* match Length */\n    assert(matchLength <= ZSTD_BLOCKSIZE_MAX);\n    assert(matchLength >= MINMATCH);\n    {   size_t const mlBase = matchLength - MINMATCH;\n        if (UNLIKELY(mlBase>0xFFFF)) {\n            assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */\n            seqStorePtr->longLengthType = ZSTD_llt_matchLength;\n            seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);\n        }\n        seqStorePtr->sequences[0].mlBase = (U16)mlBase;\n    }\n\n    seqStorePtr->sequences++;\n}\n\n/*! ZSTD_storeSeq() :\n *  Store a sequence (litlen, litPtr, offBase and matchLength) into SeqStore_t.\n *  @offBase : Users should employ macros REPCODE_TO_OFFBASE() and OFFSET_TO_OFFBASE().\n *  @matchLength : must be >= MINMATCH\n *  Allowed to over-read literals up to litLimit.\n*/\nHINT_INLINE UNUSED_ATTR void\nZSTD_storeSeq(SeqStore_t* seqStorePtr,\n              size_t litLength, const BYTE* literals, const BYTE* litLimit,\n              U32 offBase,\n              size_t matchLength)\n{\n    BYTE const* const litLimit_w = litLimit - WILDCOPY_OVERLENGTH;\n    BYTE const* const litEnd = literals + litLength;\n#if defined(DEBUGLEVEL) && (DEBUGLEVEL >= 6)\n    static const BYTE* g_start = NULL;\n    if (g_start==NULL) g_start = (const BYTE*)literals;  /* note : index only works for compression within a single segment */\n    {   U32 const pos = (U32)((const BYTE*)literals - g_start);\n        DEBUGLOG(6, \"Cpos%7u :%3u literals, match%4u bytes at offBase%7u\",\n               pos, (U32)litLength, (U32)matchLength, (U32)offBase);\n    }\n#endif\n    assert((size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart) < seqStorePtr->maxNbSeq);\n    /* copy Literals */\n    assert(seqStorePtr->maxNbLit <= 128 KB);\n    assert(seqStorePtr->lit + litLength <= seqStorePtr->litStart + seqStorePtr->maxNbLit);\n    assert(literals + litLength <= litLimit);\n    if (litEnd <= litLimit_w) {\n        /* Common case we can use wildcopy.\n         * First copy 16 bytes, because literals are likely short.\n         */\n        ZSTD_STATIC_ASSERT(WILDCOPY_OVERLENGTH >= 16);\n        ZSTD_copy16(seqStorePtr->lit, literals);\n        if (litLength > 16) {\n            ZSTD_wildcopy(seqStorePtr->lit+16, literals+16, litLength-16, ZSTD_no_overlap);\n        }\n    } else {\n        ZSTD_safecopyLiterals(seqStorePtr->lit, literals, litEnd, litLimit_w);\n    }\n    seqStorePtr->lit += litLength;\n\n    ZSTD_storeSeqOnly(seqStorePtr, litLength, offBase, matchLength);\n}\n\n/* ZSTD_updateRep() :\n * updates in-place @rep (array of repeat offsets)\n * @offBase : sum-type, using numeric representation of ZSTD_storeSeq()\n */\nMEM_STATIC void\nZSTD_updateRep(U32 rep[ZSTD_REP_NUM], U32 const offBase, U32 const ll0)\n{\n    if (OFFBASE_IS_OFFSET(offBase)) {  /* full offset */\n        rep[2] = rep[1];\n        rep[1] = rep[0];\n        rep[0] = OFFBASE_TO_OFFSET(offBase);\n    } else {   /* repcode */\n        U32 const repCode = OFFBASE_TO_REPCODE(offBase) - 1 + ll0;\n        if (repCode > 0) {  /* note : if repCode==0, no change */\n            U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];\n            rep[2] = (repCode >= 2) ? rep[1] : rep[2];\n            rep[1] = rep[0];\n            rep[0] = currentOffset;\n        } else {   /* repCode == 0 */\n            /* nothing to do */\n        }\n    }\n}\n\ntypedef struct repcodes_s {\n    U32 rep[3];\n} Repcodes_t;\n\nMEM_STATIC Repcodes_t\nZSTD_newRep(U32 const rep[ZSTD_REP_NUM], U32 const offBase, U32 const ll0)\n{\n    Repcodes_t newReps;\n    ZSTD_memcpy(&newReps, rep, sizeof(newReps));\n    ZSTD_updateRep(newReps.rep, offBase, ll0);\n    return newReps;\n}\n\n\n/*-*************************************\n*  Match length counter\n***************************************/\nMEM_STATIC size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* const pInLimit)\n{\n    const BYTE* const pStart = pIn;\n    const BYTE* const pInLoopLimit = pInLimit - (sizeof(size_t)-1);\n\n    if (pIn < pInLoopLimit) {\n        { size_t const diff = MEM_readST(pMatch) ^ MEM_readST(pIn);\n          if (diff) return ZSTD_NbCommonBytes(diff); }\n        pIn+=sizeof(size_t); pMatch+=sizeof(size_t);\n        while (pIn < pInLoopLimit) {\n            size_t const diff = MEM_readST(pMatch) ^ MEM_readST(pIn);\n            if (!diff) { pIn+=sizeof(size_t); pMatch+=sizeof(size_t); continue; }\n            pIn += ZSTD_NbCommonBytes(diff);\n            return (size_t)(pIn - pStart);\n    }   }\n    if (MEM_64bits() && (pIn<(pInLimit-3)) && (MEM_read32(pMatch) == MEM_read32(pIn))) { pIn+=4; pMatch+=4; }\n    if ((pIn<(pInLimit-1)) && (MEM_read16(pMatch) == MEM_read16(pIn))) { pIn+=2; pMatch+=2; }\n    if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;\n    return (size_t)(pIn - pStart);\n}\n\n/** ZSTD_count_2segments() :\n *  can count match length with `ip` & `match` in 2 different segments.\n *  convention : on reaching mEnd, match count continue starting from iStart\n */\nMEM_STATIC size_t\nZSTD_count_2segments(const BYTE* ip, const BYTE* match,\n                     const BYTE* iEnd, const BYTE* mEnd, const BYTE* iStart)\n{\n    const BYTE* const vEnd = MIN( ip + (mEnd - match), iEnd);\n    size_t const matchLength = ZSTD_count(ip, match, vEnd);\n    if (match + matchLength != mEnd) return matchLength;\n    DEBUGLOG(7, \"ZSTD_count_2segments: found a 2-parts match (current length==%zu)\", matchLength);\n    DEBUGLOG(7, \"distance from match beginning to end dictionary = %i\", (int)(mEnd - match));\n    DEBUGLOG(7, \"distance from current pos to end buffer = %i\", (int)(iEnd - ip));\n    DEBUGLOG(7, \"next byte : ip==%02X, istart==%02X\", ip[matchLength], *iStart);\n    DEBUGLOG(7, \"final match length = %zu\", matchLength + ZSTD_count(ip+matchLength, iStart, iEnd));\n    return matchLength + ZSTD_count(ip+matchLength, iStart, iEnd);\n}\n\n\n/*-*************************************\n *  Hashes\n ***************************************/\nstatic const U32 prime3bytes = 506832829U;\nstatic U32    ZSTD_hash3(U32 u, U32 h, U32 s) { assert(h <= 32); return (((u << (32-24)) * prime3bytes) ^ s)  >> (32-h) ; }\nMEM_STATIC size_t ZSTD_hash3Ptr(const void* ptr, U32 h) { return ZSTD_hash3(MEM_readLE32(ptr), h, 0); } /* only in zstd_opt.h */\nMEM_STATIC size_t ZSTD_hash3PtrS(const void* ptr, U32 h, U32 s) { return ZSTD_hash3(MEM_readLE32(ptr), h, s); }\n\nstatic const U32 prime4bytes = 2654435761U;\nstatic U32    ZSTD_hash4(U32 u, U32 h, U32 s) { assert(h <= 32); return ((u * prime4bytes) ^ s) >> (32-h) ; }\nstatic size_t ZSTD_hash4Ptr(const void* ptr, U32 h) { return ZSTD_hash4(MEM_readLE32(ptr), h, 0); }\nstatic size_t ZSTD_hash4PtrS(const void* ptr, U32 h, U32 s) { return ZSTD_hash4(MEM_readLE32(ptr), h, s); }\n\nstatic const U64 prime5bytes = 889523592379ULL;\nstatic size_t ZSTD_hash5(U64 u, U32 h, U64 s) { assert(h <= 64); return (size_t)((((u  << (64-40)) * prime5bytes) ^ s) >> (64-h)) ; }\nstatic size_t ZSTD_hash5Ptr(const void* p, U32 h) { return ZSTD_hash5(MEM_readLE64(p), h, 0); }\nstatic size_t ZSTD_hash5PtrS(const void* p, U32 h, U64 s) { return ZSTD_hash5(MEM_readLE64(p), h, s); }\n\nstatic const U64 prime6bytes = 227718039650203ULL;\nstatic size_t ZSTD_hash6(U64 u, U32 h, U64 s) { assert(h <= 64); return (size_t)((((u  << (64-48)) * prime6bytes) ^ s) >> (64-h)) ; }\nstatic size_t ZSTD_hash6Ptr(const void* p, U32 h) { return ZSTD_hash6(MEM_readLE64(p), h, 0); }\nstatic size_t ZSTD_hash6PtrS(const void* p, U32 h, U64 s) { return ZSTD_hash6(MEM_readLE64(p), h, s); }\n\nstatic const U64 prime7bytes = 58295818150454627ULL;\nstatic size_t ZSTD_hash7(U64 u, U32 h, U64 s) { assert(h <= 64); return (size_t)((((u  << (64-56)) * prime7bytes) ^ s) >> (64-h)) ; }\nstatic size_t ZSTD_hash7Ptr(const void* p, U32 h) { return ZSTD_hash7(MEM_readLE64(p), h, 0); }\nstatic size_t ZSTD_hash7PtrS(const void* p, U32 h, U64 s) { return ZSTD_hash7(MEM_readLE64(p), h, s); }\n\nstatic const U64 prime8bytes = 0xCF1BBCDCB7A56463ULL;\nstatic size_t ZSTD_hash8(U64 u, U32 h, U64 s) { assert(h <= 64); return (size_t)((((u) * prime8bytes)  ^ s) >> (64-h)) ; }\nstatic size_t ZSTD_hash8Ptr(const void* p, U32 h) { return ZSTD_hash8(MEM_readLE64(p), h, 0); }\nstatic size_t ZSTD_hash8PtrS(const void* p, U32 h, U64 s) { return ZSTD_hash8(MEM_readLE64(p), h, s); }\n\n\nMEM_STATIC FORCE_INLINE_ATTR\nsize_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)\n{\n    /* Although some of these hashes do support hBits up to 64, some do not.\n     * To be on the safe side, always avoid hBits > 32. */\n    assert(hBits <= 32);\n\n    switch(mls)\n    {\n    default:\n    case 4: return ZSTD_hash4Ptr(p, hBits);\n    case 5: return ZSTD_hash5Ptr(p, hBits);\n    case 6: return ZSTD_hash6Ptr(p, hBits);\n    case 7: return ZSTD_hash7Ptr(p, hBits);\n    case 8: return ZSTD_hash8Ptr(p, hBits);\n    }\n}\n\nMEM_STATIC FORCE_INLINE_ATTR\nsize_t ZSTD_hashPtrSalted(const void* p, U32 hBits, U32 mls, const U64 hashSalt) {\n    /* Although some of these hashes do support hBits up to 64, some do not.\n     * To be on the safe side, always avoid hBits > 32. */\n    assert(hBits <= 32);\n\n    switch(mls)\n    {\n        default:\n        case 4: return ZSTD_hash4PtrS(p, hBits, (U32)hashSalt);\n        case 5: return ZSTD_hash5PtrS(p, hBits, hashSalt);\n        case 6: return ZSTD_hash6PtrS(p, hBits, hashSalt);\n        case 7: return ZSTD_hash7PtrS(p, hBits, hashSalt);\n        case 8: return ZSTD_hash8PtrS(p, hBits, hashSalt);\n    }\n}\n\n\n/** ZSTD_ipow() :\n * Return base^exponent.\n */\nstatic U64 ZSTD_ipow(U64 base, U64 exponent)\n{\n    U64 power = 1;\n    while (exponent) {\n      if (exponent & 1) power *= base;\n      exponent >>= 1;\n      base *= base;\n    }\n    return power;\n}\n\n#define ZSTD_ROLL_HASH_CHAR_OFFSET 10\n\n/** ZSTD_rollingHash_append() :\n * Add the buffer to the hash value.\n */\nstatic U64 ZSTD_rollingHash_append(U64 hash, void const* buf, size_t size)\n{\n    BYTE const* istart = (BYTE const*)buf;\n    size_t pos;\n    for (pos = 0; pos < size; ++pos) {\n        hash *= prime8bytes;\n        hash += istart[pos] + ZSTD_ROLL_HASH_CHAR_OFFSET;\n    }\n    return hash;\n}\n\n/** ZSTD_rollingHash_compute() :\n * Compute the rolling hash value of the buffer.\n */\nMEM_STATIC U64 ZSTD_rollingHash_compute(void const* buf, size_t size)\n{\n    return ZSTD_rollingHash_append(0, buf, size);\n}\n\n/** ZSTD_rollingHash_primePower() :\n * Compute the primePower to be passed to ZSTD_rollingHash_rotate() for a hash\n * over a window of length bytes.\n */\nMEM_STATIC U64 ZSTD_rollingHash_primePower(U32 length)\n{\n    return ZSTD_ipow(prime8bytes, length - 1);\n}\n\n/** ZSTD_rollingHash_rotate() :\n * Rotate the rolling hash by one byte.\n */\nMEM_STATIC U64 ZSTD_rollingHash_rotate(U64 hash, BYTE toRemove, BYTE toAdd, U64 primePower)\n{\n    hash -= (toRemove + ZSTD_ROLL_HASH_CHAR_OFFSET) * primePower;\n    hash *= prime8bytes;\n    hash += toAdd + ZSTD_ROLL_HASH_CHAR_OFFSET;\n    return hash;\n}\n\n/*-*************************************\n*  Round buffer management\n***************************************/\n/* Max @current value allowed:\n * In 32-bit mode: we want to avoid crossing the 2 GB limit,\n *                 reducing risks of side effects in case of signed operations on indexes.\n * In 64-bit mode: we want to ensure that adding the maximum job size (512 MB)\n *                 doesn't overflow U32 index capacity (4 GB) */\n#define ZSTD_CURRENT_MAX (MEM_64bits() ? 3500U MB : 2000U MB)\n/* Maximum chunk size before overflow correction needs to be called again */\n#define ZSTD_CHUNKSIZE_MAX                                                     \\\n    ( ((U32)-1)                  /* Maximum ending current index */            \\\n    - ZSTD_CURRENT_MAX)          /* Maximum beginning lowLimit */\n\n/**\n * ZSTD_window_clear():\n * Clears the window containing the history by simply setting it to empty.\n */\nMEM_STATIC void ZSTD_window_clear(ZSTD_window_t* window)\n{\n    size_t const endT = (size_t)(window->nextSrc - window->base);\n    U32 const end = (U32)endT;\n\n    window->lowLimit = end;\n    window->dictLimit = end;\n}\n\nMEM_STATIC U32 ZSTD_window_isEmpty(ZSTD_window_t const window)\n{\n    return window.dictLimit == ZSTD_WINDOW_START_INDEX &&\n           window.lowLimit == ZSTD_WINDOW_START_INDEX &&\n           (window.nextSrc - window.base) == ZSTD_WINDOW_START_INDEX;\n}\n\n/**\n * ZSTD_window_hasExtDict():\n * Returns non-zero if the window has a non-empty extDict.\n */\nMEM_STATIC U32 ZSTD_window_hasExtDict(ZSTD_window_t const window)\n{\n    return window.lowLimit < window.dictLimit;\n}\n\n/**\n * ZSTD_matchState_dictMode():\n * Inspects the provided matchState and figures out what dictMode should be\n * passed to the compressor.\n */\nMEM_STATIC ZSTD_dictMode_e ZSTD_matchState_dictMode(const ZSTD_MatchState_t *ms)\n{\n    return ZSTD_window_hasExtDict(ms->window) ?\n        ZSTD_extDict :\n        ms->dictMatchState != NULL ?\n            (ms->dictMatchState->dedicatedDictSearch ? ZSTD_dedicatedDictSearch : ZSTD_dictMatchState) :\n            ZSTD_noDict;\n}\n\n/* Defining this macro to non-zero tells zstd to run the overflow correction\n * code much more frequently. This is very inefficient, and should only be\n * used for tests and fuzzers.\n */\n#ifndef ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY\n#  ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION\n#    define ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY 1\n#  else\n#    define ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY 0\n#  endif\n#endif\n\n/**\n * ZSTD_window_canOverflowCorrect():\n * Returns non-zero if the indices are large enough for overflow correction\n * to work correctly without impacting compression ratio.\n */\nMEM_STATIC U32 ZSTD_window_canOverflowCorrect(ZSTD_window_t const window,\n                                              U32 cycleLog,\n                                              U32 maxDist,\n                                              U32 loadedDictEnd,\n                                              void const* src)\n{\n    U32 const cycleSize = 1u << cycleLog;\n    U32 const curr = (U32)((BYTE const*)src - window.base);\n    U32 const minIndexToOverflowCorrect = cycleSize\n                                        + MAX(maxDist, cycleSize)\n                                        + ZSTD_WINDOW_START_INDEX;\n\n    /* Adjust the min index to backoff the overflow correction frequency,\n     * so we don't waste too much CPU in overflow correction. If this\n     * computation overflows we don't really care, we just need to make\n     * sure it is at least minIndexToOverflowCorrect.\n     */\n    U32 const adjustment = window.nbOverflowCorrections + 1;\n    U32 const adjustedIndex = MAX(minIndexToOverflowCorrect * adjustment,\n                                  minIndexToOverflowCorrect);\n    U32 const indexLargeEnough = curr > adjustedIndex;\n\n    /* Only overflow correct early if the dictionary is invalidated already,\n     * so we don't hurt compression ratio.\n     */\n    U32 const dictionaryInvalidated = curr > maxDist + loadedDictEnd;\n\n    return indexLargeEnough && dictionaryInvalidated;\n}\n\n/**\n * ZSTD_window_needOverflowCorrection():\n * Returns non-zero if the indices are getting too large and need overflow\n * protection.\n */\nMEM_STATIC U32 ZSTD_window_needOverflowCorrection(ZSTD_window_t const window,\n                                                  U32 cycleLog,\n                                                  U32 maxDist,\n                                                  U32 loadedDictEnd,\n                                                  void const* src,\n                                                  void const* srcEnd)\n{\n    U32 const curr = (U32)((BYTE const*)srcEnd - window.base);\n    if (ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY) {\n        if (ZSTD_window_canOverflowCorrect(window, cycleLog, maxDist, loadedDictEnd, src)) {\n            return 1;\n        }\n    }\n    return curr > ZSTD_CURRENT_MAX;\n}\n\n/**\n * ZSTD_window_correctOverflow():\n * Reduces the indices to protect from index overflow.\n * Returns the correction made to the indices, which must be applied to every\n * stored index.\n *\n * The least significant cycleLog bits of the indices must remain the same,\n * which may be 0. Every index up to maxDist in the past must be valid.\n */\nMEM_STATIC\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nU32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,\n                                           U32 maxDist, void const* src)\n{\n    /* preemptive overflow correction:\n     * 1. correction is large enough:\n     *    lowLimit > (3<<29) ==> current > 3<<29 + 1<<windowLog\n     *    1<<windowLog <= newCurrent < 1<<chainLog + 1<<windowLog\n     *\n     *    current - newCurrent\n     *    > (3<<29 + 1<<windowLog) - (1<<windowLog + 1<<chainLog)\n     *    > (3<<29) - (1<<chainLog)\n     *    > (3<<29) - (1<<30)             (NOTE: chainLog <= 30)\n     *    > 1<<29\n     *\n     * 2. (ip+ZSTD_CHUNKSIZE_MAX - cctx->base) doesn't overflow:\n     *    After correction, current is less than (1<<chainLog + 1<<windowLog).\n     *    In 64-bit mode we are safe, because we have 64-bit ptrdiff_t.\n     *    In 32-bit mode we are safe, because (chainLog <= 29), so\n     *    ip+ZSTD_CHUNKSIZE_MAX - cctx->base < 1<<32.\n     * 3. (cctx->lowLimit + 1<<windowLog) < 1<<32:\n     *    windowLog <= 31 ==> 3<<29 + 1<<windowLog < 7<<29 < 1<<32.\n     */\n    U32 const cycleSize = 1u << cycleLog;\n    U32 const cycleMask = cycleSize - 1;\n    U32 const curr = (U32)((BYTE const*)src - window->base);\n    U32 const currentCycle = curr & cycleMask;\n    /* Ensure newCurrent - maxDist >= ZSTD_WINDOW_START_INDEX. */\n    U32 const currentCycleCorrection = currentCycle < ZSTD_WINDOW_START_INDEX\n                                     ? MAX(cycleSize, ZSTD_WINDOW_START_INDEX)\n                                     : 0;\n    U32 const newCurrent = currentCycle\n                         + currentCycleCorrection\n                         + MAX(maxDist, cycleSize);\n    U32 const correction = curr - newCurrent;\n    /* maxDist must be a power of two so that:\n     *   (newCurrent & cycleMask) == (curr & cycleMask)\n     * This is required to not corrupt the chains / binary tree.\n     */\n    assert((maxDist & (maxDist - 1)) == 0);\n    assert((curr & cycleMask) == (newCurrent & cycleMask));\n    assert(curr > newCurrent);\n    if (!ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY) {\n        /* Loose bound, should be around 1<<29 (see above) */\n        assert(correction > 1<<28);\n    }\n\n    window->base += correction;\n    window->dictBase += correction;\n    if (window->lowLimit < correction + ZSTD_WINDOW_START_INDEX) {\n        window->lowLimit = ZSTD_WINDOW_START_INDEX;\n    } else {\n        window->lowLimit -= correction;\n    }\n    if (window->dictLimit < correction + ZSTD_WINDOW_START_INDEX) {\n        window->dictLimit = ZSTD_WINDOW_START_INDEX;\n    } else {\n        window->dictLimit -= correction;\n    }\n\n    /* Ensure we can still reference the full window. */\n    assert(newCurrent >= maxDist);\n    assert(newCurrent - maxDist >= ZSTD_WINDOW_START_INDEX);\n    /* Ensure that lowLimit and dictLimit didn't underflow. */\n    assert(window->lowLimit <= newCurrent);\n    assert(window->dictLimit <= newCurrent);\n\n    ++window->nbOverflowCorrections;\n\n    DEBUGLOG(4, \"Correction of 0x%x bytes to lowLimit=0x%x\", correction,\n             window->lowLimit);\n    return correction;\n}\n\n/**\n * ZSTD_window_enforceMaxDist():\n * Updates lowLimit so that:\n *    (srcEnd - base) - lowLimit == maxDist + loadedDictEnd\n *\n * It ensures index is valid as long as index >= lowLimit.\n * This must be called before a block compression call.\n *\n * loadedDictEnd is only defined if a dictionary is in use for current compression.\n * As the name implies, loadedDictEnd represents the index at end of dictionary.\n * The value lies within context's referential, it can be directly compared to blockEndIdx.\n *\n * If loadedDictEndPtr is NULL, no dictionary is in use, and we use loadedDictEnd == 0.\n * If loadedDictEndPtr is not NULL, we set it to zero after updating lowLimit.\n * This is because dictionaries are allowed to be referenced fully\n * as long as the last byte of the dictionary is in the window.\n * Once input has progressed beyond window size, dictionary cannot be referenced anymore.\n *\n * In normal dict mode, the dictionary lies between lowLimit and dictLimit.\n * In dictMatchState mode, lowLimit and dictLimit are the same,\n * and the dictionary is below them.\n * forceWindow and dictMatchState are therefore incompatible.\n */\nMEM_STATIC void\nZSTD_window_enforceMaxDist(ZSTD_window_t* window,\n                     const void* blockEnd,\n                           U32   maxDist,\n                           U32*  loadedDictEndPtr,\n                     const ZSTD_MatchState_t** dictMatchStatePtr)\n{\n    U32 const blockEndIdx = (U32)((BYTE const*)blockEnd - window->base);\n    U32 const loadedDictEnd = (loadedDictEndPtr != NULL) ? *loadedDictEndPtr : 0;\n    DEBUGLOG(5, \"ZSTD_window_enforceMaxDist: blockEndIdx=%u, maxDist=%u, loadedDictEnd=%u\",\n                (unsigned)blockEndIdx, (unsigned)maxDist, (unsigned)loadedDictEnd);\n\n    /* - When there is no dictionary : loadedDictEnd == 0.\n         In which case, the test (blockEndIdx > maxDist) is merely to avoid\n         overflowing next operation `newLowLimit = blockEndIdx - maxDist`.\n       - When there is a standard dictionary :\n         Index referential is copied from the dictionary,\n         which means it starts from 0.\n         In which case, loadedDictEnd == dictSize,\n         and it makes sense to compare `blockEndIdx > maxDist + dictSize`\n         since `blockEndIdx` also starts from zero.\n       - When there is an attached dictionary :\n         loadedDictEnd is expressed within the referential of the context,\n         so it can be directly compared against blockEndIdx.\n    */\n    if (blockEndIdx > maxDist + loadedDictEnd) {\n        U32 const newLowLimit = blockEndIdx - maxDist;\n        if (window->lowLimit < newLowLimit) window->lowLimit = newLowLimit;\n        if (window->dictLimit < window->lowLimit) {\n            DEBUGLOG(5, \"Update dictLimit to match lowLimit, from %u to %u\",\n                        (unsigned)window->dictLimit, (unsigned)window->lowLimit);\n            window->dictLimit = window->lowLimit;\n        }\n        /* On reaching window size, dictionaries are invalidated */\n        if (loadedDictEndPtr) *loadedDictEndPtr = 0;\n        if (dictMatchStatePtr) *dictMatchStatePtr = NULL;\n    }\n}\n\n/* Similar to ZSTD_window_enforceMaxDist(),\n * but only invalidates dictionary\n * when input progresses beyond window size.\n * assumption : loadedDictEndPtr and dictMatchStatePtr are valid (non NULL)\n *              loadedDictEnd uses same referential as window->base\n *              maxDist is the window size */\nMEM_STATIC void\nZSTD_checkDictValidity(const ZSTD_window_t* window,\n                       const void* blockEnd,\n                             U32   maxDist,\n                             U32*  loadedDictEndPtr,\n                       const ZSTD_MatchState_t** dictMatchStatePtr)\n{\n    assert(loadedDictEndPtr != NULL);\n    assert(dictMatchStatePtr != NULL);\n    {   U32 const blockEndIdx = (U32)((BYTE const*)blockEnd - window->base);\n        U32 const loadedDictEnd = *loadedDictEndPtr;\n        DEBUGLOG(5, \"ZSTD_checkDictValidity: blockEndIdx=%u, maxDist=%u, loadedDictEnd=%u\",\n                    (unsigned)blockEndIdx, (unsigned)maxDist, (unsigned)loadedDictEnd);\n        assert(blockEndIdx >= loadedDictEnd);\n\n        if (blockEndIdx > loadedDictEnd + maxDist || loadedDictEnd != window->dictLimit) {\n            /* On reaching window size, dictionaries are invalidated.\n             * For simplification, if window size is reached anywhere within next block,\n             * the dictionary is invalidated for the full block.\n             *\n             * We also have to invalidate the dictionary if ZSTD_window_update() has detected\n             * non-contiguous segments, which means that loadedDictEnd != window->dictLimit.\n             * loadedDictEnd may be 0, if forceWindow is true, but in that case we never use\n             * dictMatchState, so setting it to NULL is not a problem.\n             */\n            DEBUGLOG(6, \"invalidating dictionary for current block (distance > windowSize)\");\n            *loadedDictEndPtr = 0;\n            *dictMatchStatePtr = NULL;\n        } else {\n            if (*loadedDictEndPtr != 0) {\n                DEBUGLOG(6, \"dictionary considered valid for current block\");\n    }   }   }\n}\n\nMEM_STATIC void ZSTD_window_init(ZSTD_window_t* window) {\n    ZSTD_memset(window, 0, sizeof(*window));\n    window->base = (BYTE const*)\" \";\n    window->dictBase = (BYTE const*)\" \";\n    ZSTD_STATIC_ASSERT(ZSTD_DUBT_UNSORTED_MARK < ZSTD_WINDOW_START_INDEX); /* Start above ZSTD_DUBT_UNSORTED_MARK */\n    window->dictLimit = ZSTD_WINDOW_START_INDEX;    /* start from >0, so that 1st position is valid */\n    window->lowLimit = ZSTD_WINDOW_START_INDEX;     /* it ensures first and later CCtx usages compress the same */\n    window->nextSrc = window->base + ZSTD_WINDOW_START_INDEX;   /* see issue #1241 */\n    window->nbOverflowCorrections = 0;\n}\n\n/**\n * ZSTD_window_update():\n * Updates the window by appending [src, src + srcSize) to the window.\n * If it is not contiguous, the current prefix becomes the extDict, and we\n * forget about the extDict. Handles overlap of the prefix and extDict.\n * Returns non-zero if the segment is contiguous.\n */\nMEM_STATIC\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nU32 ZSTD_window_update(ZSTD_window_t* window,\n                 const void* src, size_t srcSize,\n                       int forceNonContiguous)\n{\n    BYTE const* const ip = (BYTE const*)src;\n    U32 contiguous = 1;\n    DEBUGLOG(5, \"ZSTD_window_update\");\n    if (srcSize == 0)\n        return contiguous;\n    assert(window->base != NULL);\n    assert(window->dictBase != NULL);\n    /* Check if blocks follow each other */\n    if (src != window->nextSrc || forceNonContiguous) {\n        /* not contiguous */\n        size_t const distanceFromBase = (size_t)(window->nextSrc - window->base);\n        DEBUGLOG(5, \"Non contiguous blocks, new segment starts at %u\", window->dictLimit);\n        window->lowLimit = window->dictLimit;\n        assert(distanceFromBase == (size_t)(U32)distanceFromBase);  /* should never overflow */\n        window->dictLimit = (U32)distanceFromBase;\n        window->dictBase = window->base;\n        window->base = ip - distanceFromBase;\n        /* ms->nextToUpdate = window->dictLimit; */\n        if (window->dictLimit - window->lowLimit < HASH_READ_SIZE) window->lowLimit = window->dictLimit;   /* too small extDict */\n        contiguous = 0;\n    }\n    window->nextSrc = ip + srcSize;\n    /* if input and dictionary overlap : reduce dictionary (area presumed modified by input) */\n    if ( (ip+srcSize > window->dictBase + window->lowLimit)\n       & (ip < window->dictBase + window->dictLimit)) {\n        size_t const highInputIdx = (size_t)((ip + srcSize) - window->dictBase);\n        U32 const lowLimitMax = (highInputIdx > (size_t)window->dictLimit) ? window->dictLimit : (U32)highInputIdx;\n        assert(highInputIdx < UINT_MAX);\n        window->lowLimit = lowLimitMax;\n        DEBUGLOG(5, \"Overlapping extDict and input : new lowLimit = %u\", window->lowLimit);\n    }\n    return contiguous;\n}\n\n/**\n * Returns the lowest allowed match index. It may either be in the ext-dict or the prefix.\n */\nMEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_MatchState_t* ms, U32 curr, unsigned windowLog)\n{\n    U32 const maxDistance = 1U << windowLog;\n    U32 const lowestValid = ms->window.lowLimit;\n    U32 const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid;\n    U32 const isDictionary = (ms->loadedDictEnd != 0);\n    /* When using a dictionary the entire dictionary is valid if a single byte of the dictionary\n     * is within the window. We invalidate the dictionary (and set loadedDictEnd to 0) when it isn't\n     * valid for the entire block. So this check is sufficient to find the lowest valid match index.\n     */\n    U32 const matchLowest = isDictionary ? lowestValid : withinWindow;\n    return matchLowest;\n}\n\n/**\n * Returns the lowest allowed match index in the prefix.\n */\nMEM_STATIC U32 ZSTD_getLowestPrefixIndex(const ZSTD_MatchState_t* ms, U32 curr, unsigned windowLog)\n{\n    U32    const maxDistance = 1U << windowLog;\n    U32    const lowestValid = ms->window.dictLimit;\n    U32    const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid;\n    U32    const isDictionary = (ms->loadedDictEnd != 0);\n    /* When computing the lowest prefix index we need to take the dictionary into account to handle\n     * the edge case where the dictionary and the source are contiguous in memory.\n     */\n    U32    const matchLowest = isDictionary ? lowestValid : withinWindow;\n    return matchLowest;\n}\n\n/* index_safety_check:\n * intentional underflow : ensure repIndex isn't overlapping dict + prefix\n * @return 1 if values are not overlapping,\n * 0 otherwise */\nMEM_STATIC int ZSTD_index_overlap_check(const U32 prefixLowestIndex, const U32 repIndex) {\n    return ((U32)((prefixLowestIndex-1)  - repIndex) >= 3);\n}\n\n\n/* debug functions */\n#if (DEBUGLEVEL>=2)\n\nMEM_STATIC double ZSTD_fWeight(U32 rawStat)\n{\n    U32 const fp_accuracy = 8;\n    U32 const fp_multiplier = (1 << fp_accuracy);\n    U32 const newStat = rawStat + 1;\n    U32 const hb = ZSTD_highbit32(newStat);\n    U32 const BWeight = hb * fp_multiplier;\n    U32 const FWeight = (newStat << fp_accuracy) >> hb;\n    U32 const weight = BWeight + FWeight;\n    assert(hb + fp_accuracy < 31);\n    return (double)weight / fp_multiplier;\n}\n\n/* display a table content,\n * listing each element, its frequency, and its predicted bit cost */\nMEM_STATIC void ZSTD_debugTable(const U32* table, U32 max)\n{\n    unsigned u, sum;\n    for (u=0, sum=0; u<=max; u++) sum += table[u];\n    DEBUGLOG(2, \"total nb elts: %u\", sum);\n    for (u=0; u<=max; u++) {\n        DEBUGLOG(2, \"%2u: %5u  (%.2f)\",\n                u, table[u], ZSTD_fWeight(sum) - ZSTD_fWeight(table[u]) );\n    }\n}\n\n#endif\n\n/* Short Cache */\n\n/* Normally, zstd matchfinders follow this flow:\n *     1. Compute hash at ip\n *     2. Load index from hashTable[hash]\n *     3. Check if *ip == *(base + index)\n * In dictionary compression, loading *(base + index) is often an L2 or even L3 miss.\n *\n * Short cache is an optimization which allows us to avoid step 3 most of the time\n * when the data doesn't actually match. With short cache, the flow becomes:\n *     1. Compute (hash, currentTag) at ip. currentTag is an 8-bit independent hash at ip.\n *     2. Load (index, matchTag) from hashTable[hash]. See ZSTD_writeTaggedIndex to understand how this works.\n *     3. Only if currentTag == matchTag, check *ip == *(base + index). Otherwise, continue.\n *\n * Currently, short cache is only implemented in CDict hashtables. Thus, its use is limited to\n * dictMatchState matchfinders.\n */\n#define ZSTD_SHORT_CACHE_TAG_BITS 8\n#define ZSTD_SHORT_CACHE_TAG_MASK ((1u << ZSTD_SHORT_CACHE_TAG_BITS) - 1)\n\n/* Helper function for ZSTD_fillHashTable and ZSTD_fillDoubleHashTable.\n * Unpacks hashAndTag into (hash, tag), then packs (index, tag) into hashTable[hash]. */\nMEM_STATIC void ZSTD_writeTaggedIndex(U32* const hashTable, size_t hashAndTag, U32 index) {\n    size_t const hash = hashAndTag >> ZSTD_SHORT_CACHE_TAG_BITS;\n    U32 const tag = (U32)(hashAndTag & ZSTD_SHORT_CACHE_TAG_MASK);\n    assert(index >> (32 - ZSTD_SHORT_CACHE_TAG_BITS) == 0);\n    hashTable[hash] = (index << ZSTD_SHORT_CACHE_TAG_BITS) | tag;\n}\n\n/* Helper function for short cache matchfinders.\n * Unpacks tag1 and tag2 from lower bits of packedTag1 and packedTag2, then checks if the tags match. */\nMEM_STATIC int ZSTD_comparePackedTags(size_t packedTag1, size_t packedTag2) {\n    U32 const tag1 = packedTag1 & ZSTD_SHORT_CACHE_TAG_MASK;\n    U32 const tag2 = packedTag2 & ZSTD_SHORT_CACHE_TAG_MASK;\n    return tag1 == tag2;\n}\n\n/* ===============================================================\n * Shared internal declarations\n * These prototypes may be called from sources not in lib/compress\n * =============================================================== */\n\n/* ZSTD_loadCEntropy() :\n * dict : must point at beginning of a valid zstd dictionary.\n * return : size of dictionary header (size of magic number + dict ID + entropy tables)\n * assumptions : magic number supposed already checked\n *               and dictSize >= 8 */\nsize_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,\n                         const void* const dict, size_t dictSize);\n\nvoid ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs);\n\ntypedef struct {\n    U32 idx;            /* Index in array of ZSTD_Sequence */\n    U32 posInSequence;  /* Position within sequence at idx */\n    size_t posInSrc;    /* Number of bytes given by sequences provided so far */\n} ZSTD_SequencePosition;\n\n/* for benchmark */\nsize_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx,\n                        const ZSTD_Sequence* const inSeqs, size_t nbSequences,\n                        int repcodeResolution);\n\ntypedef struct {\n    size_t nbSequences;\n    size_t blockSize;\n    size_t litSize;\n} BlockSummary;\n\nBlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs);\n\n/* ==============================================================\n * Private declarations\n * These prototypes shall only be called from within lib/compress\n * ============================================================== */\n\n/* ZSTD_getCParamsFromCCtxParams() :\n * cParams are built depending on compressionLevel, src size hints,\n * LDM and manually set compression parameters.\n * Note: srcSizeHint == 0 means 0!\n */\nZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(\n        const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode);\n\n/*! ZSTD_initCStream_internal() :\n *  Private use only. Init streaming operation.\n *  expects params to be valid.\n *  must receive dict, or cdict, or none, but not both.\n *  @return : 0, or an error code */\nsize_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,\n                     const void* dict, size_t dictSize,\n                     const ZSTD_CDict* cdict,\n                     const ZSTD_CCtx_params* params, unsigned long long pledgedSrcSize);\n\nvoid ZSTD_resetSeqStore(SeqStore_t* ssPtr);\n\n/*! ZSTD_getCParamsFromCDict() :\n *  as the name implies */\nZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict);\n\n/* ZSTD_compressBegin_advanced_internal() :\n * Private use only. To be called from zstdmt_compress.c. */\nsize_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,\n                                    const void* dict, size_t dictSize,\n                                    ZSTD_dictContentType_e dictContentType,\n                                    ZSTD_dictTableLoadMethod_e dtlm,\n                                    const ZSTD_CDict* cdict,\n                                    const ZSTD_CCtx_params* params,\n                                    unsigned long long pledgedSrcSize);\n\n/* ZSTD_compress_advanced_internal() :\n * Private use only. To be called from zstdmt_compress.c. */\nsize_t ZSTD_compress_advanced_internal(ZSTD_CCtx* cctx,\n                                       void* dst, size_t dstCapacity,\n                                 const void* src, size_t srcSize,\n                                 const void* dict,size_t dictSize,\n                                 const ZSTD_CCtx_params* params);\n\n\n/* ZSTD_writeLastEmptyBlock() :\n * output an empty Block with end-of-frame mark to complete a frame\n * @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))\n *           or an error code if `dstCapacity` is too small (<ZSTD_blockHeaderSize)\n */\nsize_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity);\n\n\n/* ZSTD_referenceExternalSequences() :\n * Must be called before starting a compression operation.\n * seqs must parse a prefix of the source.\n * This cannot be used when long range matching is enabled.\n * Zstd will use these sequences, and pass the literals to a secondary block\n * compressor.\n * NOTE: seqs are not verified! Invalid sequences can cause out-of-bounds memory\n * access and data corruption.\n */\nvoid ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq);\n\n/** ZSTD_cycleLog() :\n *  condition for correct operation : hashLog > 1 */\nU32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat);\n\n/** ZSTD_CCtx_trace() :\n *  Trace the end of a compression call.\n */\nvoid ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize);\n\n/* Returns 1 if an external sequence producer is registered, otherwise returns 0. */\nMEM_STATIC int ZSTD_hasExtSeqProd(const ZSTD_CCtx_params* params) {\n    return params->extSeqProdFunc != NULL;\n}\n\n/* ===============================================================\n * Deprecated definitions that are still used internally to avoid\n * deprecation warnings. These functions are exactly equivalent to\n * their public variants, but avoid the deprecation warnings.\n * =============================================================== */\n\nsize_t ZSTD_compressBegin_usingCDict_deprecated(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);\n\nsize_t ZSTD_compressContinue_public(ZSTD_CCtx* cctx,\n                                    void* dst, size_t dstCapacity,\n                              const void* src, size_t srcSize);\n\nsize_t ZSTD_compressEnd_public(ZSTD_CCtx* cctx,\n                               void* dst, size_t dstCapacity,\n                         const void* src, size_t srcSize);\n\nsize_t ZSTD_compressBlock_deprecated(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n\n#endif /* ZSTD_COMPRESS_H */\n"
  },
  {
    "path": "lib/compress/zstd_compress_literals.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n /*-*************************************\n *  Dependencies\n ***************************************/\n#include \"zstd_compress_literals.h\"\n\n\n/* **************************************************************\n*  Debug Traces\n****************************************************************/\n#if DEBUGLEVEL >= 2\n\nstatic size_t showHexa(const void* src, size_t srcSize)\n{\n    const BYTE* const ip = (const BYTE*)src;\n    size_t u;\n    for (u=0; u<srcSize; u++) {\n        RAWLOG(5, \" %02X\", ip[u]); (void)ip;\n    }\n    RAWLOG(5, \" \\n\");\n    return srcSize;\n}\n\n#endif\n\n\n/* **************************************************************\n*  Literals compression - special cases\n****************************************************************/\nsize_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    BYTE* const ostart = (BYTE*)dst;\n    U32   const flSize = 1 + (srcSize>31) + (srcSize>4095);\n\n    DEBUGLOG(5, \"ZSTD_noCompressLiterals: srcSize=%zu, dstCapacity=%zu\", srcSize, dstCapacity);\n\n    RETURN_ERROR_IF(srcSize + flSize > dstCapacity, dstSize_tooSmall, \"\");\n\n    switch(flSize)\n    {\n        case 1: /* 2 - 1 - 5 */\n            ostart[0] = (BYTE)((U32)set_basic + (srcSize<<3));\n            break;\n        case 2: /* 2 - 2 - 12 */\n            MEM_writeLE16(ostart, (U16)((U32)set_basic + (1<<2) + (srcSize<<4)));\n            break;\n        case 3: /* 2 - 2 - 20 */\n            MEM_writeLE32(ostart, (U32)((U32)set_basic + (3<<2) + (srcSize<<4)));\n            break;\n        default:   /* not necessary : flSize is {1,2,3} */\n            assert(0);\n    }\n\n    ZSTD_memcpy(ostart + flSize, src, srcSize);\n    DEBUGLOG(5, \"Raw (uncompressed) literals: %u -> %u\", (U32)srcSize, (U32)(srcSize + flSize));\n    return srcSize + flSize;\n}\n\nstatic int allBytesIdentical(const void* src, size_t srcSize)\n{\n    assert(srcSize >= 1);\n    assert(src != NULL);\n    {   const BYTE b = ((const BYTE*)src)[0];\n        size_t p;\n        for (p=1; p<srcSize; p++) {\n            if (((const BYTE*)src)[p] != b) return 0;\n        }\n        return 1;\n    }\n}\n\nsize_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    BYTE* const ostart = (BYTE*)dst;\n    U32   const flSize = 1 + (srcSize>31) + (srcSize>4095);\n\n    assert(dstCapacity >= 4); (void)dstCapacity;\n    assert(allBytesIdentical(src, srcSize));\n\n    switch(flSize)\n    {\n        case 1: /* 2 - 1 - 5 */\n            ostart[0] = (BYTE)((U32)set_rle + (srcSize<<3));\n            break;\n        case 2: /* 2 - 2 - 12 */\n            MEM_writeLE16(ostart, (U16)((U32)set_rle + (1<<2) + (srcSize<<4)));\n            break;\n        case 3: /* 2 - 2 - 20 */\n            MEM_writeLE32(ostart, (U32)((U32)set_rle + (3<<2) + (srcSize<<4)));\n            break;\n        default:   /* not necessary : flSize is {1,2,3} */\n            assert(0);\n    }\n\n    ostart[flSize] = *(const BYTE*)src;\n    DEBUGLOG(5, \"RLE : Repeated Literal (%02X: %u times) -> %u bytes encoded\", ((const BYTE*)src)[0], (U32)srcSize, (U32)flSize + 1);\n    return flSize+1;\n}\n\n/* ZSTD_minLiteralsToCompress() :\n * returns minimal amount of literals\n * for literal compression to even be attempted.\n * Minimum is made tighter as compression strategy increases.\n */\nstatic size_t\nZSTD_minLiteralsToCompress(ZSTD_strategy strategy, HUF_repeat huf_repeat)\n{\n    assert((int)strategy >= 0);\n    assert((int)strategy <= 9);\n    /* btultra2 : min 8 bytes;\n     * then 2x larger for each successive compression strategy\n     * max threshold 64 bytes */\n    {   int const shift = MIN(9-(int)strategy, 3);\n        size_t const mintc = (huf_repeat == HUF_repeat_valid) ? 6 : (size_t)8 << shift;\n        DEBUGLOG(7, \"minLiteralsToCompress = %zu\", mintc);\n        return mintc;\n    }\n}\n\nsize_t ZSTD_compressLiterals (\n                  void* dst, size_t dstCapacity,\n            const void* src, size_t srcSize,\n                  void* entropyWorkspace, size_t entropyWorkspaceSize,\n            const ZSTD_hufCTables_t* prevHuf,\n                  ZSTD_hufCTables_t* nextHuf,\n                  ZSTD_strategy strategy,\n                  int disableLiteralCompression,\n                  int suspectUncompressible,\n                  int bmi2)\n{\n    size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB);\n    BYTE*  const ostart = (BYTE*)dst;\n    U32 singleStream = srcSize < 256;\n    SymbolEncodingType_e hType = set_compressed;\n    size_t cLitSize;\n\n    DEBUGLOG(5,\"ZSTD_compressLiterals (disableLiteralCompression=%i, srcSize=%u, dstCapacity=%zu)\",\n                disableLiteralCompression, (U32)srcSize, dstCapacity);\n\n    DEBUGLOG(6, \"Completed literals listing (%zu bytes)\", showHexa(src, srcSize));\n\n    /* Prepare nextEntropy assuming reusing the existing table */\n    ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));\n\n    if (disableLiteralCompression)\n        return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);\n\n    /* if too small, don't even attempt compression (speed opt) */\n    if (srcSize < ZSTD_minLiteralsToCompress(strategy, prevHuf->repeatMode))\n        return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);\n\n    RETURN_ERROR_IF(dstCapacity < lhSize+1, dstSize_tooSmall, \"not enough space for compression\");\n    {   HUF_repeat repeat = prevHuf->repeatMode;\n        int const flags = 0\n            | (bmi2 ? HUF_flags_bmi2 : 0)\n            | (strategy < ZSTD_lazy && srcSize <= 1024 ? HUF_flags_preferRepeat : 0)\n            | (strategy >= HUF_OPTIMAL_DEPTH_THRESHOLD ? HUF_flags_optimalDepth : 0)\n            | (suspectUncompressible ? HUF_flags_suspectUncompressible : 0);\n\n        typedef size_t (*huf_compress_f)(void*, size_t, const void*, size_t, unsigned, unsigned, void*, size_t, HUF_CElt*, HUF_repeat*, int);\n        huf_compress_f huf_compress;\n        if (repeat == HUF_repeat_valid && lhSize == 3) singleStream = 1;\n        huf_compress = singleStream ? HUF_compress1X_repeat : HUF_compress4X_repeat;\n        cLitSize = huf_compress(ostart+lhSize, dstCapacity-lhSize,\n                                src, srcSize,\n                                HUF_SYMBOLVALUE_MAX, LitHufLog,\n                                entropyWorkspace, entropyWorkspaceSize,\n                                (HUF_CElt*)nextHuf->CTable,\n                                &repeat, flags);\n        DEBUGLOG(5, \"%zu literals compressed into %zu bytes (before header)\", srcSize, cLitSize);\n        if (repeat != HUF_repeat_none) {\n            /* reused the existing table */\n            DEBUGLOG(5, \"reusing statistics from previous huffman block\");\n            hType = set_repeat;\n        }\n    }\n\n    {   size_t const minGain = ZSTD_minGain(srcSize, strategy);\n        if ((cLitSize==0) || (cLitSize >= srcSize - minGain) || ERR_isError(cLitSize)) {\n            ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));\n            return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);\n    }   }\n    if (cLitSize==1) {\n        /* A return value of 1 signals that the alphabet consists of a single symbol.\n         * However, in some rare circumstances, it could be the compressed size (a single byte).\n         * For that outcome to have a chance to happen, it's necessary that `srcSize < 8`.\n         * (it's also necessary to not generate statistics).\n         * Therefore, in such a case, actively check that all bytes are identical. */\n        if ((srcSize >= 8) || allBytesIdentical(src, srcSize)) {\n            ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));\n            return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize);\n    }   }\n\n    if (hType == set_compressed) {\n        /* using a newly constructed table */\n        nextHuf->repeatMode = HUF_repeat_check;\n    }\n\n    /* Build header */\n    switch(lhSize)\n    {\n    case 3: /* 2 - 2 - 10 - 10 */\n        if (!singleStream) assert(srcSize >= MIN_LITERALS_FOR_4_STREAMS);\n        {   U32 const lhc = hType + ((U32)(!singleStream) << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<14);\n            MEM_writeLE24(ostart, lhc);\n            break;\n        }\n    case 4: /* 2 - 2 - 14 - 14 */\n        assert(srcSize >= MIN_LITERALS_FOR_4_STREAMS);\n        {   U32 const lhc = hType + (2 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<18);\n            MEM_writeLE32(ostart, lhc);\n            break;\n        }\n    case 5: /* 2 - 2 - 18 - 18 */\n        assert(srcSize >= MIN_LITERALS_FOR_4_STREAMS);\n        {   U32 const lhc = hType + (3 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<22);\n            MEM_writeLE32(ostart, lhc);\n            ostart[4] = (BYTE)(cLitSize >> 10);\n            break;\n        }\n    default:  /* not possible : lhSize is {3,4,5} */\n        assert(0);\n    }\n    DEBUGLOG(5, \"Compressed literals: %u -> %u\", (U32)srcSize, (U32)(lhSize+cLitSize));\n    return lhSize+cLitSize;\n}\n"
  },
  {
    "path": "lib/compress/zstd_compress_literals.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_COMPRESS_LITERALS_H\n#define ZSTD_COMPRESS_LITERALS_H\n\n#include \"zstd_compress_internal.h\" /* ZSTD_hufCTables_t, ZSTD_minGain() */\n\n\nsize_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n/* ZSTD_compressRleLiteralsBlock() :\n * Conditions :\n * - All bytes in @src are identical\n * - dstCapacity >= 4 */\nsize_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n/* ZSTD_compressLiterals():\n * @entropyWorkspace: must be aligned on 4-bytes boundaries\n * @entropyWorkspaceSize : must be >= HUF_WORKSPACE_SIZE\n * @suspectUncompressible: sampling checks, to potentially skip huffman coding\n */\nsize_t ZSTD_compressLiterals (void* dst, size_t dstCapacity,\n                        const void* src, size_t srcSize,\n                              void* entropyWorkspace, size_t entropyWorkspaceSize,\n                        const ZSTD_hufCTables_t* prevHuf,\n                              ZSTD_hufCTables_t* nextHuf,\n                              ZSTD_strategy strategy, int disableLiteralCompression,\n                              int suspectUncompressible,\n                              int bmi2);\n\n#endif /* ZSTD_COMPRESS_LITERALS_H */\n"
  },
  {
    "path": "lib/compress/zstd_compress_sequences.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n /*-*************************************\n *  Dependencies\n ***************************************/\n#include \"zstd_compress_sequences.h\"\n\n/**\n * -log2(x / 256) lookup table for x in [0, 256).\n * If x == 0: Return 0\n * Else: Return floor(-log2(x / 256) * 256)\n */\nstatic unsigned const kInverseProbabilityLog256[256] = {\n    0,    2048, 1792, 1642, 1536, 1453, 1386, 1329, 1280, 1236, 1197, 1162,\n    1130, 1100, 1073, 1047, 1024, 1001, 980,  960,  941,  923,  906,  889,\n    874,  859,  844,  830,  817,  804,  791,  779,  768,  756,  745,  734,\n    724,  714,  704,  694,  685,  676,  667,  658,  650,  642,  633,  626,\n    618,  610,  603,  595,  588,  581,  574,  567,  561,  554,  548,  542,\n    535,  529,  523,  517,  512,  506,  500,  495,  489,  484,  478,  473,\n    468,  463,  458,  453,  448,  443,  438,  434,  429,  424,  420,  415,\n    411,  407,  402,  398,  394,  390,  386,  382,  377,  373,  370,  366,\n    362,  358,  354,  350,  347,  343,  339,  336,  332,  329,  325,  322,\n    318,  315,  311,  308,  305,  302,  298,  295,  292,  289,  286,  282,\n    279,  276,  273,  270,  267,  264,  261,  258,  256,  253,  250,  247,\n    244,  241,  239,  236,  233,  230,  228,  225,  222,  220,  217,  215,\n    212,  209,  207,  204,  202,  199,  197,  194,  192,  190,  187,  185,\n    182,  180,  178,  175,  173,  171,  168,  166,  164,  162,  159,  157,\n    155,  153,  151,  149,  146,  144,  142,  140,  138,  136,  134,  132,\n    130,  128,  126,  123,  121,  119,  117,  115,  114,  112,  110,  108,\n    106,  104,  102,  100,  98,   96,   94,   93,   91,   89,   87,   85,\n    83,   82,   80,   78,   76,   74,   73,   71,   69,   67,   66,   64,\n    62,   61,   59,   57,   55,   54,   52,   50,   49,   47,   46,   44,\n    42,   41,   39,   37,   36,   34,   33,   31,   30,   28,   26,   25,\n    23,   22,   20,   19,   17,   16,   14,   13,   11,   10,   8,    7,\n    5,    4,    2,    1,\n};\n\nstatic unsigned ZSTD_getFSEMaxSymbolValue(FSE_CTable const* ctable) {\n  void const* ptr = ctable;\n  U16 const* u16ptr = (U16 const*)ptr;\n  U32 const maxSymbolValue = MEM_read16(u16ptr + 1);\n  return maxSymbolValue;\n}\n\n/**\n * Returns true if we should use ncount=-1 else we should\n * use ncount=1 for low probability symbols instead.\n */\nstatic unsigned ZSTD_useLowProbCount(size_t const nbSeq)\n{\n    /* Heuristic: This should cover most blocks <= 16K and\n     * start to fade out after 16K to about 32K depending on\n     * compressibility.\n     */\n    return nbSeq >= 2048;\n}\n\n/**\n * Returns the cost in bytes of encoding the normalized count header.\n * Returns an error if any of the helper functions return an error.\n */\nstatic size_t ZSTD_NCountCost(unsigned const* count, unsigned const max,\n                              size_t const nbSeq, unsigned const FSELog)\n{\n    BYTE wksp[FSE_NCOUNTBOUND];\n    S16 norm[MaxSeq + 1];\n    const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);\n    FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq, max, ZSTD_useLowProbCount(nbSeq)), \"\");\n    return FSE_writeNCount(wksp, sizeof(wksp), norm, max, tableLog);\n}\n\n/**\n * Returns the cost in bits of encoding the distribution described by count\n * using the entropy bound.\n */\nstatic size_t ZSTD_entropyCost(unsigned const* count, unsigned const max, size_t const total)\n{\n    unsigned cost = 0;\n    unsigned s;\n\n    assert(total > 0);\n    for (s = 0; s <= max; ++s) {\n        unsigned norm = (unsigned)((256 * count[s]) / total);\n        if (count[s] != 0 && norm == 0)\n            norm = 1;\n        assert(count[s] < total);\n        cost += count[s] * kInverseProbabilityLog256[norm];\n    }\n    return cost >> 8;\n}\n\n/**\n * Returns the cost in bits of encoding the distribution in count using ctable.\n * Returns an error if ctable cannot represent all the symbols in count.\n */\nsize_t ZSTD_fseBitCost(\n    FSE_CTable const* ctable,\n    unsigned const* count,\n    unsigned const max)\n{\n    unsigned const kAccuracyLog = 8;\n    size_t cost = 0;\n    unsigned s;\n    FSE_CState_t cstate;\n    FSE_initCState(&cstate, ctable);\n    if (ZSTD_getFSEMaxSymbolValue(ctable) < max) {\n        DEBUGLOG(5, \"Repeat FSE_CTable has maxSymbolValue %u < %u\",\n                    ZSTD_getFSEMaxSymbolValue(ctable), max);\n        return ERROR(GENERIC);\n    }\n    for (s = 0; s <= max; ++s) {\n        unsigned const tableLog = cstate.stateLog;\n        unsigned const badCost = (tableLog + 1) << kAccuracyLog;\n        unsigned const bitCost = FSE_bitCost(cstate.symbolTT, tableLog, s, kAccuracyLog);\n        if (count[s] == 0)\n            continue;\n        if (bitCost >= badCost) {\n            DEBUGLOG(5, \"Repeat FSE_CTable has Prob[%u] == 0\", s);\n            return ERROR(GENERIC);\n        }\n        cost += (size_t)count[s] * bitCost;\n    }\n    return cost >> kAccuracyLog;\n}\n\n/**\n * Returns the cost in bits of encoding the distribution in count using the\n * table described by norm. The max symbol support by norm is assumed >= max.\n * norm must be valid for every symbol with non-zero probability in count.\n */\nsize_t ZSTD_crossEntropyCost(short const* norm, unsigned accuracyLog,\n                             unsigned const* count, unsigned const max)\n{\n    unsigned const shift = 8 - accuracyLog;\n    size_t cost = 0;\n    unsigned s;\n    assert(accuracyLog <= 8);\n    for (s = 0; s <= max; ++s) {\n        unsigned const normAcc = (norm[s] != -1) ? (unsigned)norm[s] : 1;\n        unsigned const norm256 = normAcc << shift;\n        assert(norm256 > 0);\n        assert(norm256 < 256);\n        cost += count[s] * kInverseProbabilityLog256[norm256];\n    }\n    return cost >> 8;\n}\n\nSymbolEncodingType_e\nZSTD_selectEncodingType(\n        FSE_repeat* repeatMode, unsigned const* count, unsigned const max,\n        size_t const mostFrequent, size_t nbSeq, unsigned const FSELog,\n        FSE_CTable const* prevCTable,\n        short const* defaultNorm, U32 defaultNormLog,\n        ZSTD_DefaultPolicy_e const isDefaultAllowed,\n        ZSTD_strategy const strategy)\n{\n    ZSTD_STATIC_ASSERT(ZSTD_defaultDisallowed == 0 && ZSTD_defaultAllowed != 0);\n    if (mostFrequent == nbSeq) {\n        *repeatMode = FSE_repeat_none;\n        if (isDefaultAllowed && nbSeq <= 2) {\n            /* Prefer set_basic over set_rle when there are 2 or fewer symbols,\n             * since RLE uses 1 byte, but set_basic uses 5-6 bits per symbol.\n             * If basic encoding isn't possible, always choose RLE.\n             */\n            DEBUGLOG(5, \"Selected set_basic\");\n            return set_basic;\n        }\n        DEBUGLOG(5, \"Selected set_rle\");\n        return set_rle;\n    }\n    if (strategy < ZSTD_lazy) {\n        if (isDefaultAllowed) {\n            size_t const staticFse_nbSeq_max = 1000;\n            size_t const mult = 10 - strategy;\n            size_t const baseLog = 3;\n            size_t const dynamicFse_nbSeq_min = (((size_t)1 << defaultNormLog) * mult) >> baseLog;  /* 28-36 for offset, 56-72 for lengths */\n            assert(defaultNormLog >= 5 && defaultNormLog <= 6);  /* xx_DEFAULTNORMLOG */\n            assert(mult <= 9 && mult >= 7);\n            if ( (*repeatMode == FSE_repeat_valid)\n              && (nbSeq < staticFse_nbSeq_max) ) {\n                DEBUGLOG(5, \"Selected set_repeat\");\n                return set_repeat;\n            }\n            if ( (nbSeq < dynamicFse_nbSeq_min)\n              || (mostFrequent < (nbSeq >> (defaultNormLog-1))) ) {\n                DEBUGLOG(5, \"Selected set_basic\");\n                /* The format allows default tables to be repeated, but it isn't useful.\n                 * When using simple heuristics to select encoding type, we don't want\n                 * to confuse these tables with dictionaries. When running more careful\n                 * analysis, we don't need to waste time checking both repeating tables\n                 * and default tables.\n                 */\n                *repeatMode = FSE_repeat_none;\n                return set_basic;\n            }\n        }\n    } else {\n        size_t const basicCost = isDefaultAllowed ? ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, count, max) : ERROR(GENERIC);\n        size_t const repeatCost = *repeatMode != FSE_repeat_none ? ZSTD_fseBitCost(prevCTable, count, max) : ERROR(GENERIC);\n        size_t const NCountCost = ZSTD_NCountCost(count, max, nbSeq, FSELog);\n        size_t const compressedCost = (NCountCost << 3) + ZSTD_entropyCost(count, max, nbSeq);\n\n        if (isDefaultAllowed) {\n            assert(!ZSTD_isError(basicCost));\n            assert(!(*repeatMode == FSE_repeat_valid && ZSTD_isError(repeatCost)));\n        }\n        assert(!ZSTD_isError(NCountCost));\n        assert(compressedCost < ERROR(maxCode));\n        DEBUGLOG(5, \"Estimated bit costs: basic=%u\\trepeat=%u\\tcompressed=%u\",\n                    (unsigned)basicCost, (unsigned)repeatCost, (unsigned)compressedCost);\n        if (basicCost <= repeatCost && basicCost <= compressedCost) {\n            DEBUGLOG(5, \"Selected set_basic\");\n            assert(isDefaultAllowed);\n            *repeatMode = FSE_repeat_none;\n            return set_basic;\n        }\n        if (repeatCost <= compressedCost) {\n            DEBUGLOG(5, \"Selected set_repeat\");\n            assert(!ZSTD_isError(repeatCost));\n            return set_repeat;\n        }\n        assert(compressedCost < basicCost && compressedCost < repeatCost);\n    }\n    DEBUGLOG(5, \"Selected set_compressed\");\n    *repeatMode = FSE_repeat_check;\n    return set_compressed;\n}\n\ntypedef struct {\n    S16 norm[MaxSeq + 1];\n    U32 wksp[FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(MaxSeq, MaxFSELog)];\n} ZSTD_BuildCTableWksp;\n\nsize_t\nZSTD_buildCTable(void* dst, size_t dstCapacity,\n                FSE_CTable* nextCTable, U32 FSELog, SymbolEncodingType_e type,\n                unsigned* count, U32 max,\n                const BYTE* codeTable, size_t nbSeq,\n                const S16* defaultNorm, U32 defaultNormLog, U32 defaultMax,\n                const FSE_CTable* prevCTable, size_t prevCTableSize,\n                void* entropyWorkspace, size_t entropyWorkspaceSize)\n{\n    BYTE* op = (BYTE*)dst;\n    const BYTE* const oend = op + dstCapacity;\n    DEBUGLOG(6, \"ZSTD_buildCTable (dstCapacity=%u)\", (unsigned)dstCapacity);\n\n    switch (type) {\n    case set_rle:\n        FORWARD_IF_ERROR(FSE_buildCTable_rle(nextCTable, (BYTE)max), \"\");\n        RETURN_ERROR_IF(dstCapacity==0, dstSize_tooSmall, \"not enough space\");\n        *op = codeTable[0];\n        return 1;\n    case set_repeat:\n        ZSTD_memcpy(nextCTable, prevCTable, prevCTableSize);\n        return 0;\n    case set_basic:\n        FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, entropyWorkspace, entropyWorkspaceSize), \"\");  /* note : could be pre-calculated */\n        return 0;\n    case set_compressed: {\n        ZSTD_BuildCTableWksp* wksp = (ZSTD_BuildCTableWksp*)entropyWorkspace;\n        size_t nbSeq_1 = nbSeq;\n        const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);\n        if (count[codeTable[nbSeq-1]] > 1) {\n            count[codeTable[nbSeq-1]]--;\n            nbSeq_1--;\n        }\n        assert(nbSeq_1 > 1);\n        assert(entropyWorkspaceSize >= sizeof(ZSTD_BuildCTableWksp));\n        (void)entropyWorkspaceSize;\n        FORWARD_IF_ERROR(FSE_normalizeCount(wksp->norm, tableLog, count, nbSeq_1, max, ZSTD_useLowProbCount(nbSeq_1)), \"FSE_normalizeCount failed\");\n        assert(oend >= op);\n        {   size_t const NCountSize = FSE_writeNCount(op, (size_t)(oend - op), wksp->norm, max, tableLog);   /* overflow protected */\n            FORWARD_IF_ERROR(NCountSize, \"FSE_writeNCount failed\");\n            FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, wksp->norm, max, tableLog, wksp->wksp, sizeof(wksp->wksp)), \"FSE_buildCTable_wksp failed\");\n            return NCountSize;\n        }\n    }\n    default: assert(0); RETURN_ERROR(GENERIC, \"impossible to reach\");\n    }\n}\n\nFORCE_INLINE_TEMPLATE size_t\nZSTD_encodeSequences_body(\n            void* dst, size_t dstCapacity,\n            FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,\n            FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,\n            FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,\n            SeqDef const* sequences, size_t nbSeq, int longOffsets)\n{\n    BIT_CStream_t blockStream;\n    FSE_CState_t  stateMatchLength;\n    FSE_CState_t  stateOffsetBits;\n    FSE_CState_t  stateLitLength;\n\n    RETURN_ERROR_IF(\n        ERR_isError(BIT_initCStream(&blockStream, dst, dstCapacity)),\n        dstSize_tooSmall, \"not enough space remaining\");\n    DEBUGLOG(6, \"available space for bitstream : %i  (dstCapacity=%u)\",\n                (int)(blockStream.endPtr - blockStream.startPtr),\n                (unsigned)dstCapacity);\n\n    /* first symbols */\n    FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]);\n    FSE_initCState2(&stateOffsetBits,  CTable_OffsetBits,  ofCodeTable[nbSeq-1]);\n    FSE_initCState2(&stateLitLength,   CTable_LitLength,   llCodeTable[nbSeq-1]);\n    BIT_addBits(&blockStream, sequences[nbSeq-1].litLength, LL_bits[llCodeTable[nbSeq-1]]);\n    if (MEM_32bits()) BIT_flushBits(&blockStream);\n    BIT_addBits(&blockStream, sequences[nbSeq-1].mlBase, ML_bits[mlCodeTable[nbSeq-1]]);\n    if (MEM_32bits()) BIT_flushBits(&blockStream);\n    if (longOffsets) {\n        U32 const ofBits = ofCodeTable[nbSeq-1];\n        unsigned const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);\n        if (extraBits) {\n            BIT_addBits(&blockStream, sequences[nbSeq-1].offBase, extraBits);\n            BIT_flushBits(&blockStream);\n        }\n        BIT_addBits(&blockStream, sequences[nbSeq-1].offBase >> extraBits,\n                    ofBits - extraBits);\n    } else {\n        BIT_addBits(&blockStream, sequences[nbSeq-1].offBase, ofCodeTable[nbSeq-1]);\n    }\n    BIT_flushBits(&blockStream);\n\n    {   size_t n;\n        for (n=nbSeq-2 ; n<nbSeq ; n--) {      /* intentional underflow */\n            BYTE const llCode = llCodeTable[n];\n            BYTE const ofCode = ofCodeTable[n];\n            BYTE const mlCode = mlCodeTable[n];\n            U32  const llBits = LL_bits[llCode];\n            U32  const ofBits = ofCode;\n            U32  const mlBits = ML_bits[mlCode];\n            DEBUGLOG(6, \"encoding: litlen:%2u - matchlen:%2u - offCode:%7u\",\n                        (unsigned)sequences[n].litLength,\n                        (unsigned)sequences[n].mlBase + MINMATCH,\n                        (unsigned)sequences[n].offBase);\n                                                                            /* 32b*/  /* 64b*/\n                                                                            /* (7)*/  /* (7)*/\n            FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode);       /* 15 */  /* 15 */\n            FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode);      /* 24 */  /* 24 */\n            if (MEM_32bits()) BIT_flushBits(&blockStream);                  /* (7)*/\n            FSE_encodeSymbol(&blockStream, &stateLitLength, llCode);        /* 16 */  /* 33 */\n            if (MEM_32bits() || (ofBits+mlBits+llBits >= 64-7-(LLFSELog+MLFSELog+OffFSELog)))\n                BIT_flushBits(&blockStream);                                /* (7)*/\n            BIT_addBits(&blockStream, sequences[n].litLength, llBits);\n            if (MEM_32bits() && ((llBits+mlBits)>24)) BIT_flushBits(&blockStream);\n            BIT_addBits(&blockStream, sequences[n].mlBase, mlBits);\n            if (MEM_32bits() || (ofBits+mlBits+llBits > 56)) BIT_flushBits(&blockStream);\n            if (longOffsets) {\n                unsigned const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);\n                if (extraBits) {\n                    BIT_addBits(&blockStream, sequences[n].offBase, extraBits);\n                    BIT_flushBits(&blockStream);                            /* (7)*/\n                }\n                BIT_addBits(&blockStream, sequences[n].offBase >> extraBits,\n                            ofBits - extraBits);                            /* 31 */\n            } else {\n                BIT_addBits(&blockStream, sequences[n].offBase, ofBits);     /* 31 */\n            }\n            BIT_flushBits(&blockStream);                                    /* (7)*/\n            DEBUGLOG(7, \"remaining space : %i\", (int)(blockStream.endPtr - blockStream.ptr));\n    }   }\n\n    DEBUGLOG(6, \"ZSTD_encodeSequences: flushing ML state with %u bits\", stateMatchLength.stateLog);\n    FSE_flushCState(&blockStream, &stateMatchLength);\n    DEBUGLOG(6, \"ZSTD_encodeSequences: flushing Off state with %u bits\", stateOffsetBits.stateLog);\n    FSE_flushCState(&blockStream, &stateOffsetBits);\n    DEBUGLOG(6, \"ZSTD_encodeSequences: flushing LL state with %u bits\", stateLitLength.stateLog);\n    FSE_flushCState(&blockStream, &stateLitLength);\n\n    {   size_t const streamSize = BIT_closeCStream(&blockStream);\n        RETURN_ERROR_IF(streamSize==0, dstSize_tooSmall, \"not enough space\");\n        return streamSize;\n    }\n}\n\nstatic size_t\nZSTD_encodeSequences_default(\n            void* dst, size_t dstCapacity,\n            FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,\n            FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,\n            FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,\n            SeqDef const* sequences, size_t nbSeq, int longOffsets)\n{\n    return ZSTD_encodeSequences_body(dst, dstCapacity,\n                                    CTable_MatchLength, mlCodeTable,\n                                    CTable_OffsetBits, ofCodeTable,\n                                    CTable_LitLength, llCodeTable,\n                                    sequences, nbSeq, longOffsets);\n}\n\n\n#if DYNAMIC_BMI2\n\nstatic BMI2_TARGET_ATTRIBUTE size_t\nZSTD_encodeSequences_bmi2(\n            void* dst, size_t dstCapacity,\n            FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,\n            FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,\n            FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,\n            SeqDef const* sequences, size_t nbSeq, int longOffsets)\n{\n    return ZSTD_encodeSequences_body(dst, dstCapacity,\n                                    CTable_MatchLength, mlCodeTable,\n                                    CTable_OffsetBits, ofCodeTable,\n                                    CTable_LitLength, llCodeTable,\n                                    sequences, nbSeq, longOffsets);\n}\n\n#endif\n\nsize_t ZSTD_encodeSequences(\n            void* dst, size_t dstCapacity,\n            FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,\n            FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,\n            FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,\n            SeqDef const* sequences, size_t nbSeq, int longOffsets, int bmi2)\n{\n    DEBUGLOG(5, \"ZSTD_encodeSequences: dstCapacity = %u\", (unsigned)dstCapacity);\n#if DYNAMIC_BMI2\n    if (bmi2) {\n        return ZSTD_encodeSequences_bmi2(dst, dstCapacity,\n                                         CTable_MatchLength, mlCodeTable,\n                                         CTable_OffsetBits, ofCodeTable,\n                                         CTable_LitLength, llCodeTable,\n                                         sequences, nbSeq, longOffsets);\n    }\n#endif\n    (void)bmi2;\n    return ZSTD_encodeSequences_default(dst, dstCapacity,\n                                        CTable_MatchLength, mlCodeTable,\n                                        CTable_OffsetBits, ofCodeTable,\n                                        CTable_LitLength, llCodeTable,\n                                        sequences, nbSeq, longOffsets);\n}\n"
  },
  {
    "path": "lib/compress/zstd_compress_sequences.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_COMPRESS_SEQUENCES_H\n#define ZSTD_COMPRESS_SEQUENCES_H\n\n#include \"zstd_compress_internal.h\" /* SeqDef */\n#include \"../common/fse.h\" /* FSE_repeat, FSE_CTable */\n#include \"../common/zstd_internal.h\" /* SymbolEncodingType_e, ZSTD_strategy */\n\ntypedef enum {\n    ZSTD_defaultDisallowed = 0,\n    ZSTD_defaultAllowed = 1\n} ZSTD_DefaultPolicy_e;\n\nSymbolEncodingType_e\nZSTD_selectEncodingType(\n        FSE_repeat* repeatMode, unsigned const* count, unsigned const max,\n        size_t const mostFrequent, size_t nbSeq, unsigned const FSELog,\n        FSE_CTable const* prevCTable,\n        short const* defaultNorm, U32 defaultNormLog,\n        ZSTD_DefaultPolicy_e const isDefaultAllowed,\n        ZSTD_strategy const strategy);\n\nsize_t\nZSTD_buildCTable(void* dst, size_t dstCapacity,\n                FSE_CTable* nextCTable, U32 FSELog, SymbolEncodingType_e type,\n                unsigned* count, U32 max,\n                const BYTE* codeTable, size_t nbSeq,\n                const S16* defaultNorm, U32 defaultNormLog, U32 defaultMax,\n                const FSE_CTable* prevCTable, size_t prevCTableSize,\n                void* entropyWorkspace, size_t entropyWorkspaceSize);\n\nsize_t ZSTD_encodeSequences(\n            void* dst, size_t dstCapacity,\n            FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,\n            FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,\n            FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,\n            SeqDef const* sequences, size_t nbSeq, int longOffsets, int bmi2);\n\nsize_t ZSTD_fseBitCost(\n    FSE_CTable const* ctable,\n    unsigned const* count,\n    unsigned const max);\n\nsize_t ZSTD_crossEntropyCost(short const* norm, unsigned accuracyLog,\n                             unsigned const* count, unsigned const max);\n#endif /* ZSTD_COMPRESS_SEQUENCES_H */\n"
  },
  {
    "path": "lib/compress/zstd_compress_superblock.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n /*-*************************************\n *  Dependencies\n ***************************************/\n#include \"zstd_compress_superblock.h\"\n\n#include \"../common/zstd_internal.h\"  /* ZSTD_getSequenceLength */\n#include \"hist.h\"                     /* HIST_countFast_wksp */\n#include \"zstd_compress_internal.h\"   /* ZSTD_[huf|fse|entropy]CTablesMetadata_t */\n#include \"zstd_compress_sequences.h\"\n#include \"zstd_compress_literals.h\"\n\n/** ZSTD_compressSubBlock_literal() :\n *  Compresses literals section for a sub-block.\n *  When we have to write the Huffman table we will sometimes choose a header\n *  size larger than necessary. This is because we have to pick the header size\n *  before we know the table size + compressed size, so we have a bound on the\n *  table size. If we guessed incorrectly, we fall back to uncompressed literals.\n *\n *  We write the header when writeEntropy=1 and set entropyWritten=1 when we succeeded\n *  in writing the header, otherwise it is set to 0.\n *\n *  hufMetadata->hType has literals block type info.\n *      If it is set_basic, all sub-blocks literals section will be Raw_Literals_Block.\n *      If it is set_rle, all sub-blocks literals section will be RLE_Literals_Block.\n *      If it is set_compressed, first sub-block's literals section will be Compressed_Literals_Block\n *      If it is set_compressed, first sub-block's literals section will be Treeless_Literals_Block\n *      and the following sub-blocks' literals sections will be Treeless_Literals_Block.\n *  @return : compressed size of literals section of a sub-block\n *            Or 0 if unable to compress.\n *            Or error code */\nstatic size_t\nZSTD_compressSubBlock_literal(const HUF_CElt* hufTable,\n                              const ZSTD_hufCTablesMetadata_t* hufMetadata,\n                              const BYTE* literals, size_t litSize,\n                              void* dst, size_t dstSize,\n                              const int bmi2, int writeEntropy, int* entropyWritten)\n{\n    size_t const header = writeEntropy ? 200 : 0;\n    size_t const lhSize = 3 + (litSize >= (1 KB - header)) + (litSize >= (16 KB - header));\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = ostart + dstSize;\n    BYTE* op = ostart + lhSize;\n    U32 const singleStream = lhSize == 3;\n    SymbolEncodingType_e hType = writeEntropy ? hufMetadata->hType : set_repeat;\n    size_t cLitSize = 0;\n\n    DEBUGLOG(5, \"ZSTD_compressSubBlock_literal (litSize=%zu, lhSize=%zu, writeEntropy=%d)\", litSize, lhSize, writeEntropy);\n\n    *entropyWritten = 0;\n    if (litSize == 0 || hufMetadata->hType == set_basic) {\n      DEBUGLOG(5, \"ZSTD_compressSubBlock_literal using raw literal\");\n      return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize);\n    } else if (hufMetadata->hType == set_rle) {\n      DEBUGLOG(5, \"ZSTD_compressSubBlock_literal using rle literal\");\n      return ZSTD_compressRleLiteralsBlock(dst, dstSize, literals, litSize);\n    }\n\n    assert(litSize > 0);\n    assert(hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat);\n\n    if (writeEntropy && hufMetadata->hType == set_compressed) {\n        ZSTD_memcpy(op, hufMetadata->hufDesBuffer, hufMetadata->hufDesSize);\n        op += hufMetadata->hufDesSize;\n        cLitSize += hufMetadata->hufDesSize;\n        DEBUGLOG(5, \"ZSTD_compressSubBlock_literal (hSize=%zu)\", hufMetadata->hufDesSize);\n    }\n\n    {   int const flags = bmi2 ? HUF_flags_bmi2 : 0;\n        const size_t cSize = singleStream ? HUF_compress1X_usingCTable(op, (size_t)(oend-op), literals, litSize, hufTable, flags)\n                                          : HUF_compress4X_usingCTable(op, (size_t)(oend-op), literals, litSize, hufTable, flags);\n        op += cSize;\n        cLitSize += cSize;\n        if (cSize == 0 || ERR_isError(cSize)) {\n            DEBUGLOG(5, \"Failed to write entropy tables %s\", ZSTD_getErrorName(cSize));\n            return 0;\n        }\n        /* If we expand and we aren't writing a header then emit uncompressed */\n        if (!writeEntropy && cLitSize >= litSize) {\n            DEBUGLOG(5, \"ZSTD_compressSubBlock_literal using raw literal because uncompressible\");\n            return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize);\n        }\n        /* If we are writing headers then allow expansion that doesn't change our header size. */\n        if (lhSize < (size_t)(3 + (cLitSize >= 1 KB) + (cLitSize >= 16 KB))) {\n            assert(cLitSize > litSize);\n            DEBUGLOG(5, \"Literals expanded beyond allowed header size\");\n            return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize);\n        }\n        DEBUGLOG(5, \"ZSTD_compressSubBlock_literal (cSize=%zu)\", cSize);\n    }\n\n    /* Build header */\n    switch(lhSize)\n    {\n    case 3: /* 2 - 2 - 10 - 10 */\n        {   U32 const lhc = hType + ((U32)(!singleStream) << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<14);\n            MEM_writeLE24(ostart, lhc);\n            break;\n        }\n    case 4: /* 2 - 2 - 14 - 14 */\n        {   U32 const lhc = hType + (2 << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<18);\n            MEM_writeLE32(ostart, lhc);\n            break;\n        }\n    case 5: /* 2 - 2 - 18 - 18 */\n        {   U32 const lhc = hType + (3 << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<22);\n            MEM_writeLE32(ostart, lhc);\n            ostart[4] = (BYTE)(cLitSize >> 10);\n            break;\n        }\n    default:  /* not possible : lhSize is {3,4,5} */\n        assert(0);\n    }\n    *entropyWritten = 1;\n    DEBUGLOG(5, \"Compressed literals: %u -> %u\", (U32)litSize, (U32)(op-ostart));\n    return (size_t)(op-ostart);\n}\n\nstatic size_t\nZSTD_seqDecompressedSize(SeqStore_t const* seqStore,\n                   const SeqDef* sequences, size_t nbSeqs,\n                         size_t litSize, int lastSubBlock)\n{\n    size_t matchLengthSum = 0;\n    size_t litLengthSum = 0;\n    size_t n;\n    for (n=0; n<nbSeqs; n++) {\n        const ZSTD_SequenceLength seqLen = ZSTD_getSequenceLength(seqStore, sequences+n);\n        litLengthSum += seqLen.litLength;\n        matchLengthSum += seqLen.matchLength;\n    }\n    DEBUGLOG(5, \"ZSTD_seqDecompressedSize: %u sequences from %p: %u literals + %u matchlength\",\n                (unsigned)nbSeqs, (const void*)sequences,\n                (unsigned)litLengthSum, (unsigned)matchLengthSum);\n    if (!lastSubBlock)\n        assert(litLengthSum == litSize);\n    else\n        assert(litLengthSum <= litSize);\n    (void)litLengthSum;\n    return matchLengthSum + litSize;\n}\n\n/** ZSTD_compressSubBlock_sequences() :\n *  Compresses sequences section for a sub-block.\n *  fseMetadata->llType, fseMetadata->ofType, and fseMetadata->mlType have\n *  symbol compression modes for the super-block.\n *  The first successfully compressed block will have these in its header.\n *  We set entropyWritten=1 when we succeed in compressing the sequences.\n *  The following sub-blocks will always have repeat mode.\n *  @return : compressed size of sequences section of a sub-block\n *            Or 0 if it is unable to compress\n *            Or error code. */\nstatic size_t\nZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables,\n                                const ZSTD_fseCTablesMetadata_t* fseMetadata,\n                                const SeqDef* sequences, size_t nbSeq,\n                                const BYTE* llCode, const BYTE* mlCode, const BYTE* ofCode,\n                                const ZSTD_CCtx_params* cctxParams,\n                                void* dst, size_t dstCapacity,\n                                const int bmi2, int writeEntropy, int* entropyWritten)\n{\n    const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = ostart + dstCapacity;\n    BYTE* op = ostart;\n    BYTE* seqHead;\n\n    DEBUGLOG(5, \"ZSTD_compressSubBlock_sequences (nbSeq=%zu, writeEntropy=%d, longOffsets=%d)\", nbSeq, writeEntropy, longOffsets);\n\n    *entropyWritten = 0;\n    /* Sequences Header */\n    RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/,\n                    dstSize_tooSmall, \"\");\n    if (nbSeq < 128)\n        *op++ = (BYTE)nbSeq;\n    else if (nbSeq < LONGNBSEQ)\n        op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;\n    else\n        op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;\n    if (nbSeq==0) {\n        return (size_t)(op - ostart);\n    }\n\n    /* seqHead : flags for FSE encoding type */\n    seqHead = op++;\n\n    DEBUGLOG(5, \"ZSTD_compressSubBlock_sequences (seqHeadSize=%u)\", (unsigned)(op-ostart));\n\n    if (writeEntropy) {\n        const U32 LLtype = fseMetadata->llType;\n        const U32 Offtype = fseMetadata->ofType;\n        const U32 MLtype = fseMetadata->mlType;\n        DEBUGLOG(5, \"ZSTD_compressSubBlock_sequences (fseTablesSize=%zu)\", fseMetadata->fseTablesSize);\n        *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));\n        ZSTD_memcpy(op, fseMetadata->fseTablesBuffer, fseMetadata->fseTablesSize);\n        op += fseMetadata->fseTablesSize;\n    } else {\n        const U32 repeat = set_repeat;\n        *seqHead = (BYTE)((repeat<<6) + (repeat<<4) + (repeat<<2));\n    }\n\n    {   size_t const bitstreamSize = ZSTD_encodeSequences(\n                                        op, (size_t)(oend - op),\n                                        fseTables->matchlengthCTable, mlCode,\n                                        fseTables->offcodeCTable, ofCode,\n                                        fseTables->litlengthCTable, llCode,\n                                        sequences, nbSeq,\n                                        longOffsets, bmi2);\n        FORWARD_IF_ERROR(bitstreamSize, \"ZSTD_encodeSequences failed\");\n        op += bitstreamSize;\n        /* zstd versions <= 1.3.4 mistakenly report corruption when\n         * FSE_readNCount() receives a buffer < 4 bytes.\n         * Fixed by https://github.com/facebook/zstd/pull/1146.\n         * This can happen when the last set_compressed table present is 2\n         * bytes and the bitstream is only one byte.\n         * In this exceedingly rare case, we will simply emit an uncompressed\n         * block, since it isn't worth optimizing.\n         */\n#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION\n        if (writeEntropy && fseMetadata->lastCountSize && fseMetadata->lastCountSize + bitstreamSize < 4) {\n            /* NCountSize >= 2 && bitstreamSize > 0 ==> lastCountSize == 3 */\n            assert(fseMetadata->lastCountSize + bitstreamSize == 3);\n            DEBUGLOG(5, \"Avoiding bug in zstd decoder in versions <= 1.3.4 by \"\n                        \"emitting an uncompressed block.\");\n            return 0;\n        }\n#endif\n        DEBUGLOG(5, \"ZSTD_compressSubBlock_sequences (bitstreamSize=%zu)\", bitstreamSize);\n    }\n\n    /* zstd versions <= 1.4.0 mistakenly report error when\n     * sequences section body size is less than 3 bytes.\n     * Fixed by https://github.com/facebook/zstd/pull/1664.\n     * This can happen when the previous sequences section block is compressed\n     * with rle mode and the current block's sequences section is compressed\n     * with repeat mode where sequences section body size can be 1 byte.\n     */\n#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION\n    if (op-seqHead < 4) {\n        DEBUGLOG(5, \"Avoiding bug in zstd decoder in versions <= 1.4.0 by emitting \"\n                    \"an uncompressed block when sequences are < 4 bytes\");\n        return 0;\n    }\n#endif\n\n    *entropyWritten = 1;\n    return (size_t)(op - ostart);\n}\n\n/** ZSTD_compressSubBlock() :\n *  Compresses a single sub-block.\n *  @return : compressed size of the sub-block\n *            Or 0 if it failed to compress. */\nstatic size_t ZSTD_compressSubBlock(const ZSTD_entropyCTables_t* entropy,\n                                    const ZSTD_entropyCTablesMetadata_t* entropyMetadata,\n                                    const SeqDef* sequences, size_t nbSeq,\n                                    const BYTE* literals, size_t litSize,\n                                    const BYTE* llCode, const BYTE* mlCode, const BYTE* ofCode,\n                                    const ZSTD_CCtx_params* cctxParams,\n                                    void* dst, size_t dstCapacity,\n                                    const int bmi2,\n                                    int writeLitEntropy, int writeSeqEntropy,\n                                    int* litEntropyWritten, int* seqEntropyWritten,\n                                    U32 lastBlock)\n{\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = ostart + dstCapacity;\n    BYTE* op = ostart + ZSTD_blockHeaderSize;\n    DEBUGLOG(5, \"ZSTD_compressSubBlock (litSize=%zu, nbSeq=%zu, writeLitEntropy=%d, writeSeqEntropy=%d, lastBlock=%d)\",\n                litSize, nbSeq, writeLitEntropy, writeSeqEntropy, lastBlock);\n    {   size_t cLitSize = ZSTD_compressSubBlock_literal((const HUF_CElt*)entropy->huf.CTable,\n                                                        &entropyMetadata->hufMetadata, literals, litSize,\n                                                        op, (size_t)(oend-op),\n                                                        bmi2, writeLitEntropy, litEntropyWritten);\n        FORWARD_IF_ERROR(cLitSize, \"ZSTD_compressSubBlock_literal failed\");\n        if (cLitSize == 0) return 0;\n        op += cLitSize;\n    }\n    {   size_t cSeqSize = ZSTD_compressSubBlock_sequences(&entropy->fse,\n                                                  &entropyMetadata->fseMetadata,\n                                                  sequences, nbSeq,\n                                                  llCode, mlCode, ofCode,\n                                                  cctxParams,\n                                                  op, (size_t)(oend-op),\n                                                  bmi2, writeSeqEntropy, seqEntropyWritten);\n        FORWARD_IF_ERROR(cSeqSize, \"ZSTD_compressSubBlock_sequences failed\");\n        if (cSeqSize == 0) return 0;\n        op += cSeqSize;\n    }\n    /* Write block header */\n    {   size_t cSize = (size_t)(op-ostart) - ZSTD_blockHeaderSize;\n        U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);\n        MEM_writeLE24(ostart, cBlockHeader24);\n    }\n    return (size_t)(op-ostart);\n}\n\nstatic size_t ZSTD_estimateSubBlockSize_literal(const BYTE* literals, size_t litSize,\n                                                const ZSTD_hufCTables_t* huf,\n                                                const ZSTD_hufCTablesMetadata_t* hufMetadata,\n                                                void* workspace, size_t wkspSize,\n                                                int writeEntropy)\n{\n    unsigned* const countWksp = (unsigned*)workspace;\n    unsigned maxSymbolValue = 255;\n    size_t literalSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */\n\n    if (hufMetadata->hType == set_basic) return litSize;\n    else if (hufMetadata->hType == set_rle) return 1;\n    else if (hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat) {\n        size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)literals, litSize, workspace, wkspSize);\n        if (ZSTD_isError(largest)) return litSize;\n        {   size_t cLitSizeEstimate = HUF_estimateCompressedSize((const HUF_CElt*)huf->CTable, countWksp, maxSymbolValue);\n            if (writeEntropy) cLitSizeEstimate += hufMetadata->hufDesSize;\n            return cLitSizeEstimate + literalSectionHeaderSize;\n    }   }\n    assert(0); /* impossible */\n    return 0;\n}\n\nstatic size_t ZSTD_estimateSubBlockSize_symbolType(SymbolEncodingType_e type,\n                        const BYTE* codeTable, unsigned maxCode,\n                        size_t nbSeq, const FSE_CTable* fseCTable,\n                        const U8* additionalBits,\n                        short const* defaultNorm, U32 defaultNormLog, U32 defaultMax,\n                        void* workspace, size_t wkspSize)\n{\n    unsigned* const countWksp = (unsigned*)workspace;\n    const BYTE* ctp = codeTable;\n    const BYTE* const ctStart = ctp;\n    const BYTE* const ctEnd = ctStart + nbSeq;\n    size_t cSymbolTypeSizeEstimateInBits = 0;\n    unsigned max = maxCode;\n\n    HIST_countFast_wksp(countWksp, &max, codeTable, nbSeq, workspace, wkspSize);  /* can't fail */\n    if (type == set_basic) {\n        /* We selected this encoding type, so it must be valid. */\n        assert(max <= defaultMax);\n        cSymbolTypeSizeEstimateInBits = max <= defaultMax\n                ? ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, countWksp, max)\n                : ERROR(GENERIC);\n    } else if (type == set_rle) {\n        cSymbolTypeSizeEstimateInBits = 0;\n    } else if (type == set_compressed || type == set_repeat) {\n        cSymbolTypeSizeEstimateInBits = ZSTD_fseBitCost(fseCTable, countWksp, max);\n    }\n    if (ZSTD_isError(cSymbolTypeSizeEstimateInBits)) return nbSeq * 10;\n    while (ctp < ctEnd) {\n        if (additionalBits) cSymbolTypeSizeEstimateInBits += additionalBits[*ctp];\n        else cSymbolTypeSizeEstimateInBits += *ctp; /* for offset, offset code is also the number of additional bits */\n        ctp++;\n    }\n    return cSymbolTypeSizeEstimateInBits / 8;\n}\n\nstatic size_t ZSTD_estimateSubBlockSize_sequences(const BYTE* ofCodeTable,\n                                                  const BYTE* llCodeTable,\n                                                  const BYTE* mlCodeTable,\n                                                  size_t nbSeq,\n                                                  const ZSTD_fseCTables_t* fseTables,\n                                                  const ZSTD_fseCTablesMetadata_t* fseMetadata,\n                                                  void* workspace, size_t wkspSize,\n                                                  int writeEntropy)\n{\n    size_t const sequencesSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */\n    size_t cSeqSizeEstimate = 0;\n    if (nbSeq == 0) return sequencesSectionHeaderSize;\n    cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->ofType, ofCodeTable, MaxOff,\n                                         nbSeq, fseTables->offcodeCTable, NULL,\n                                         OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,\n                                         workspace, wkspSize);\n    cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->llType, llCodeTable, MaxLL,\n                                         nbSeq, fseTables->litlengthCTable, LL_bits,\n                                         LL_defaultNorm, LL_defaultNormLog, MaxLL,\n                                         workspace, wkspSize);\n    cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->mlType, mlCodeTable, MaxML,\n                                         nbSeq, fseTables->matchlengthCTable, ML_bits,\n                                         ML_defaultNorm, ML_defaultNormLog, MaxML,\n                                         workspace, wkspSize);\n    if (writeEntropy) cSeqSizeEstimate += fseMetadata->fseTablesSize;\n    return cSeqSizeEstimate + sequencesSectionHeaderSize;\n}\n\ntypedef struct {\n    size_t estLitSize;\n    size_t estBlockSize;\n} EstimatedBlockSize;\nstatic EstimatedBlockSize ZSTD_estimateSubBlockSize(const BYTE* literals, size_t litSize,\n                                        const BYTE* ofCodeTable,\n                                        const BYTE* llCodeTable,\n                                        const BYTE* mlCodeTable,\n                                        size_t nbSeq,\n                                        const ZSTD_entropyCTables_t* entropy,\n                                        const ZSTD_entropyCTablesMetadata_t* entropyMetadata,\n                                        void* workspace, size_t wkspSize,\n                                        int writeLitEntropy, int writeSeqEntropy)\n{\n    EstimatedBlockSize ebs;\n    ebs.estLitSize = ZSTD_estimateSubBlockSize_literal(literals, litSize,\n                                                        &entropy->huf, &entropyMetadata->hufMetadata,\n                                                        workspace, wkspSize, writeLitEntropy);\n    ebs.estBlockSize = ZSTD_estimateSubBlockSize_sequences(ofCodeTable, llCodeTable, mlCodeTable,\n                                                         nbSeq, &entropy->fse, &entropyMetadata->fseMetadata,\n                                                         workspace, wkspSize, writeSeqEntropy);\n    ebs.estBlockSize += ebs.estLitSize + ZSTD_blockHeaderSize;\n    return ebs;\n}\n\nstatic int ZSTD_needSequenceEntropyTables(ZSTD_fseCTablesMetadata_t const* fseMetadata)\n{\n    if (fseMetadata->llType == set_compressed || fseMetadata->llType == set_rle)\n        return 1;\n    if (fseMetadata->mlType == set_compressed || fseMetadata->mlType == set_rle)\n        return 1;\n    if (fseMetadata->ofType == set_compressed || fseMetadata->ofType == set_rle)\n        return 1;\n    return 0;\n}\n\nstatic size_t countLiterals(SeqStore_t const* seqStore, const SeqDef* sp, size_t seqCount)\n{\n    size_t n, total = 0;\n    assert(sp != NULL);\n    for (n=0; n<seqCount; n++) {\n        total += ZSTD_getSequenceLength(seqStore, sp+n).litLength;\n    }\n    DEBUGLOG(6, \"countLiterals for %zu sequences from %p => %zu bytes\", seqCount, (const void*)sp, total);\n    return total;\n}\n\n#define BYTESCALE 256\n\nstatic size_t sizeBlockSequences(const SeqDef* sp, size_t nbSeqs,\n                size_t targetBudget, size_t avgLitCost, size_t avgSeqCost,\n                int firstSubBlock)\n{\n    size_t n, budget = 0, inSize=0;\n    /* entropy headers */\n    size_t const headerSize = (size_t)firstSubBlock * 120 * BYTESCALE; /* generous estimate */\n    assert(firstSubBlock==0 || firstSubBlock==1);\n    budget += headerSize;\n\n    /* first sequence => at least one sequence*/\n    budget += sp[0].litLength * avgLitCost + avgSeqCost;\n    if (budget > targetBudget) return 1;\n    inSize = sp[0].litLength + (sp[0].mlBase+MINMATCH);\n\n    /* loop over sequences */\n    for (n=1; n<nbSeqs; n++) {\n        size_t currentCost = sp[n].litLength * avgLitCost + avgSeqCost;\n        budget += currentCost;\n        inSize += sp[n].litLength + (sp[n].mlBase+MINMATCH);\n        /* stop when sub-block budget is reached */\n        if ( (budget > targetBudget)\n            /* though continue to expand until the sub-block is deemed compressible */\n          && (budget < inSize * BYTESCALE) )\n            break;\n    }\n\n    return n;\n}\n\n/** ZSTD_compressSubBlock_multi() :\n *  Breaks super-block into multiple sub-blocks and compresses them.\n *  Entropy will be written into the first block.\n *  The following blocks use repeat_mode to compress.\n *  Sub-blocks are all compressed, except the last one when beneficial.\n *  @return : compressed size of the super block (which features multiple ZSTD blocks)\n *            or 0 if it failed to compress. */\nstatic size_t ZSTD_compressSubBlock_multi(const SeqStore_t* seqStorePtr,\n                            const ZSTD_compressedBlockState_t* prevCBlock,\n                            ZSTD_compressedBlockState_t* nextCBlock,\n                            const ZSTD_entropyCTablesMetadata_t* entropyMetadata,\n                            const ZSTD_CCtx_params* cctxParams,\n                                  void* dst, size_t dstCapacity,\n                            const void* src, size_t srcSize,\n                            const int bmi2, U32 lastBlock,\n                            void* workspace, size_t wkspSize)\n{\n    const SeqDef* const sstart = seqStorePtr->sequencesStart;\n    const SeqDef* const send = seqStorePtr->sequences;\n    const SeqDef* sp = sstart; /* tracks progresses within seqStorePtr->sequences */\n    size_t const nbSeqs = (size_t)(send - sstart);\n    const BYTE* const lstart = seqStorePtr->litStart;\n    const BYTE* const lend = seqStorePtr->lit;\n    const BYTE* lp = lstart;\n    size_t const nbLiterals = (size_t)(lend - lstart);\n    BYTE const* ip = (BYTE const*)src;\n    BYTE const* const iend = ip + srcSize;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = ostart + dstCapacity;\n    BYTE* op = ostart;\n    const BYTE* llCodePtr = seqStorePtr->llCode;\n    const BYTE* mlCodePtr = seqStorePtr->mlCode;\n    const BYTE* ofCodePtr = seqStorePtr->ofCode;\n    size_t const minTarget = ZSTD_TARGETCBLOCKSIZE_MIN; /* enforce minimum size, to reduce undesirable side effects */\n    size_t const targetCBlockSize = MAX(minTarget, cctxParams->targetCBlockSize);\n    int writeLitEntropy = (entropyMetadata->hufMetadata.hType == set_compressed);\n    int writeSeqEntropy = 1;\n\n    DEBUGLOG(5, \"ZSTD_compressSubBlock_multi (srcSize=%u, litSize=%u, nbSeq=%u)\",\n               (unsigned)srcSize, (unsigned)(lend-lstart), (unsigned)(send-sstart));\n\n        /* let's start by a general estimation for the full block */\n    if (nbSeqs > 0) {\n        EstimatedBlockSize const ebs =\n                ZSTD_estimateSubBlockSize(lp, nbLiterals,\n                                        ofCodePtr, llCodePtr, mlCodePtr, nbSeqs,\n                                        &nextCBlock->entropy, entropyMetadata,\n                                        workspace, wkspSize,\n                                        writeLitEntropy, writeSeqEntropy);\n        /* quick estimation */\n        size_t const avgLitCost = nbLiterals ? (ebs.estLitSize * BYTESCALE) / nbLiterals : BYTESCALE;\n        size_t const avgSeqCost = ((ebs.estBlockSize - ebs.estLitSize) * BYTESCALE) / nbSeqs;\n        const size_t nbSubBlocks = MAX((ebs.estBlockSize + (targetCBlockSize/2)) / targetCBlockSize, 1);\n        size_t n, avgBlockBudget, blockBudgetSupp=0;\n        avgBlockBudget = (ebs.estBlockSize * BYTESCALE) / nbSubBlocks;\n        DEBUGLOG(5, \"estimated fullblock size=%u bytes ; avgLitCost=%.2f ; avgSeqCost=%.2f ; targetCBlockSize=%u, nbSubBlocks=%u ; avgBlockBudget=%.0f bytes\",\n                    (unsigned)ebs.estBlockSize, (double)avgLitCost/BYTESCALE, (double)avgSeqCost/BYTESCALE,\n                    (unsigned)targetCBlockSize, (unsigned)nbSubBlocks, (double)avgBlockBudget/BYTESCALE);\n        /* simplification: if estimates states that the full superblock doesn't compress, just bail out immediately\n         * this will result in the production of a single uncompressed block covering @srcSize.*/\n        if (ebs.estBlockSize > srcSize) return 0;\n\n        /* compress and write sub-blocks */\n        assert(nbSubBlocks>0);\n        for (n=0; n < nbSubBlocks-1; n++) {\n            /* determine nb of sequences for current sub-block + nbLiterals from next sequence */\n            size_t const seqCount = sizeBlockSequences(sp, (size_t)(send-sp),\n                                        avgBlockBudget + blockBudgetSupp, avgLitCost, avgSeqCost, n==0);\n            /* if reached last sequence : break to last sub-block (simplification) */\n            assert(seqCount <= (size_t)(send-sp));\n            if (sp + seqCount == send) break;\n            assert(seqCount > 0);\n            /* compress sub-block */\n            {   int litEntropyWritten = 0;\n                int seqEntropyWritten = 0;\n                size_t litSize = countLiterals(seqStorePtr, sp, seqCount);\n                const size_t decompressedSize =\n                        ZSTD_seqDecompressedSize(seqStorePtr, sp, seqCount, litSize, 0);\n                size_t const cSize = ZSTD_compressSubBlock(&nextCBlock->entropy, entropyMetadata,\n                                                sp, seqCount,\n                                                lp, litSize,\n                                                llCodePtr, mlCodePtr, ofCodePtr,\n                                                cctxParams,\n                                                op, (size_t)(oend-op),\n                                                bmi2, writeLitEntropy, writeSeqEntropy,\n                                                &litEntropyWritten, &seqEntropyWritten,\n                                                0);\n                FORWARD_IF_ERROR(cSize, \"ZSTD_compressSubBlock failed\");\n\n                /* check compressibility, update state components */\n                if (cSize > 0 && cSize < decompressedSize) {\n                    DEBUGLOG(5, \"Committed sub-block compressing %u bytes => %u bytes\",\n                                (unsigned)decompressedSize, (unsigned)cSize);\n                    assert(ip + decompressedSize <= iend);\n                    ip += decompressedSize;\n                    lp += litSize;\n                    op += cSize;\n                    llCodePtr += seqCount;\n                    mlCodePtr += seqCount;\n                    ofCodePtr += seqCount;\n                    /* Entropy only needs to be written once */\n                    if (litEntropyWritten) {\n                        writeLitEntropy = 0;\n                    }\n                    if (seqEntropyWritten) {\n                        writeSeqEntropy = 0;\n                    }\n                    sp += seqCount;\n                    blockBudgetSupp = 0;\n            }   }\n            /* otherwise : do not compress yet, coalesce current sub-block with following one */\n        }\n    } /* if (nbSeqs > 0) */\n\n    /* write last block */\n    DEBUGLOG(5, \"Generate last sub-block: %u sequences remaining\", (unsigned)(send - sp));\n    {   int litEntropyWritten = 0;\n        int seqEntropyWritten = 0;\n        size_t litSize = (size_t)(lend - lp);\n        size_t seqCount = (size_t)(send - sp);\n        const size_t decompressedSize =\n                ZSTD_seqDecompressedSize(seqStorePtr, sp, seqCount, litSize, 1);\n        size_t const cSize = ZSTD_compressSubBlock(&nextCBlock->entropy, entropyMetadata,\n                                            sp, seqCount,\n                                            lp, litSize,\n                                            llCodePtr, mlCodePtr, ofCodePtr,\n                                            cctxParams,\n                                            op, (size_t)(oend-op),\n                                            bmi2, writeLitEntropy, writeSeqEntropy,\n                                            &litEntropyWritten, &seqEntropyWritten,\n                                            lastBlock);\n        FORWARD_IF_ERROR(cSize, \"ZSTD_compressSubBlock failed\");\n\n        /* update pointers, the nb of literals borrowed from next sequence must be preserved */\n        if (cSize > 0 && cSize < decompressedSize) {\n            DEBUGLOG(5, \"Last sub-block compressed %u bytes => %u bytes\",\n                        (unsigned)decompressedSize, (unsigned)cSize);\n            assert(ip + decompressedSize <= iend);\n            ip += decompressedSize;\n            lp += litSize;\n            op += cSize;\n            llCodePtr += seqCount;\n            mlCodePtr += seqCount;\n            ofCodePtr += seqCount;\n            /* Entropy only needs to be written once */\n            if (litEntropyWritten) {\n                writeLitEntropy = 0;\n            }\n            if (seqEntropyWritten) {\n                writeSeqEntropy = 0;\n            }\n            sp += seqCount;\n        }\n    }\n\n\n    if (writeLitEntropy) {\n        DEBUGLOG(5, \"Literal entropy tables were never written\");\n        ZSTD_memcpy(&nextCBlock->entropy.huf, &prevCBlock->entropy.huf, sizeof(prevCBlock->entropy.huf));\n    }\n    if (writeSeqEntropy && ZSTD_needSequenceEntropyTables(&entropyMetadata->fseMetadata)) {\n        /* If we haven't written our entropy tables, then we've violated our contract and\n         * must emit an uncompressed block.\n         */\n        DEBUGLOG(5, \"Sequence entropy tables were never written => cancel, emit an uncompressed block\");\n        return 0;\n    }\n\n    if (ip < iend) {\n        /* some data left : last part of the block sent uncompressed */\n        size_t const rSize = (size_t)((iend - ip));\n        size_t const cSize = ZSTD_noCompressBlock(op, (size_t)(oend - op), ip, rSize, lastBlock);\n        DEBUGLOG(5, \"Generate last uncompressed sub-block of %u bytes\", (unsigned)(rSize));\n        FORWARD_IF_ERROR(cSize, \"ZSTD_noCompressBlock failed\");\n        assert(cSize != 0);\n        op += cSize;\n        /* We have to regenerate the repcodes because we've skipped some sequences */\n        if (sp < send) {\n            const SeqDef* seq;\n            Repcodes_t rep;\n            ZSTD_memcpy(&rep, prevCBlock->rep, sizeof(rep));\n            for (seq = sstart; seq < sp; ++seq) {\n                ZSTD_updateRep(rep.rep, seq->offBase, ZSTD_getSequenceLength(seqStorePtr, seq).litLength == 0);\n            }\n            ZSTD_memcpy(nextCBlock->rep, &rep, sizeof(rep));\n        }\n    }\n\n    DEBUGLOG(5, \"ZSTD_compressSubBlock_multi compressed all subBlocks: total compressed size = %u\",\n                (unsigned)(op-ostart));\n    return (size_t)(op-ostart);\n}\n\nsize_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc,\n                               void* dst, size_t dstCapacity,\n                               const void* src, size_t srcSize,\n                               unsigned lastBlock)\n{\n    ZSTD_entropyCTablesMetadata_t entropyMetadata;\n\n    FORWARD_IF_ERROR(ZSTD_buildBlockEntropyStats(&zc->seqStore,\n          &zc->blockState.prevCBlock->entropy,\n          &zc->blockState.nextCBlock->entropy,\n          &zc->appliedParams,\n          &entropyMetadata,\n          zc->tmpWorkspace, zc->tmpWkspSize /* statically allocated in resetCCtx */), \"\");\n\n    return ZSTD_compressSubBlock_multi(&zc->seqStore,\n            zc->blockState.prevCBlock,\n            zc->blockState.nextCBlock,\n            &entropyMetadata,\n            &zc->appliedParams,\n            dst, dstCapacity,\n            src, srcSize,\n            zc->bmi2, lastBlock,\n            zc->tmpWorkspace, zc->tmpWkspSize /* statically allocated in resetCCtx */);\n}\n"
  },
  {
    "path": "lib/compress/zstd_compress_superblock.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_COMPRESS_ADVANCED_H\n#define ZSTD_COMPRESS_ADVANCED_H\n\n/*-*************************************\n*  Dependencies\n***************************************/\n\n#include \"../zstd.h\" /* ZSTD_CCtx */\n\n/*-*************************************\n*  Target Compressed Block Size\n***************************************/\n\n/* ZSTD_compressSuperBlock() :\n * Used to compress a super block when targetCBlockSize is being used.\n * The given block will be compressed into multiple sub blocks that are around targetCBlockSize. */\nsize_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc,\n                               void* dst, size_t dstCapacity,\n                               void const* src, size_t srcSize,\n                               unsigned lastBlock);\n\n#endif /* ZSTD_COMPRESS_ADVANCED_H */\n"
  },
  {
    "path": "lib/compress/zstd_cwksp.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_CWKSP_H\n#define ZSTD_CWKSP_H\n\n/*-*************************************\n*  Dependencies\n***************************************/\n#include \"../common/allocations.h\"  /* ZSTD_customMalloc, ZSTD_customFree */\n#include \"../common/zstd_internal.h\"\n#include \"../common/portability_macros.h\"\n#include \"../common/compiler.h\" /* ZS2_isPower2 */\n\n/*-*************************************\n*  Constants\n***************************************/\n\n/* Since the workspace is effectively its own little malloc implementation /\n * arena, when we run under ASAN, we should similarly insert redzones between\n * each internal element of the workspace, so ASAN will catch overruns that\n * reach outside an object but that stay inside the workspace.\n *\n * This defines the size of that redzone.\n */\n#ifndef ZSTD_CWKSP_ASAN_REDZONE_SIZE\n#define ZSTD_CWKSP_ASAN_REDZONE_SIZE 128\n#endif\n\n\n/* Set our tables and aligneds to align by 64 bytes */\n#define ZSTD_CWKSP_ALIGNMENT_BYTES 64\n\n/*-*************************************\n*  Structures\n***************************************/\ntypedef enum {\n    ZSTD_cwksp_alloc_objects,\n    ZSTD_cwksp_alloc_aligned_init_once,\n    ZSTD_cwksp_alloc_aligned,\n    ZSTD_cwksp_alloc_buffers\n} ZSTD_cwksp_alloc_phase_e;\n\n/**\n * Used to describe whether the workspace is statically allocated (and will not\n * necessarily ever be freed), or if it's dynamically allocated and we can\n * expect a well-formed caller to free this.\n */\ntypedef enum {\n    ZSTD_cwksp_dynamic_alloc,\n    ZSTD_cwksp_static_alloc\n} ZSTD_cwksp_static_alloc_e;\n\n/**\n * Zstd fits all its internal datastructures into a single continuous buffer,\n * so that it only needs to perform a single OS allocation (or so that a buffer\n * can be provided to it and it can perform no allocations at all). This buffer\n * is called the workspace.\n *\n * Several optimizations complicate that process of allocating memory ranges\n * from this workspace for each internal datastructure:\n *\n * - These different internal datastructures have different setup requirements:\n *\n *   - The static objects need to be cleared once and can then be trivially\n *     reused for each compression.\n *\n *   - Various buffers don't need to be initialized at all--they are always\n *     written into before they're read.\n *\n *   - The matchstate tables have a unique requirement that they don't need\n *     their memory to be totally cleared, but they do need the memory to have\n *     some bound, i.e., a guarantee that all values in the memory they've been\n *     allocated is less than some maximum value (which is the starting value\n *     for the indices that they will then use for compression). When this\n *     guarantee is provided to them, they can use the memory without any setup\n *     work. When it can't, they have to clear the area.\n *\n * - These buffers also have different alignment requirements.\n *\n * - We would like to reuse the objects in the workspace for multiple\n *   compressions without having to perform any expensive reallocation or\n *   reinitialization work.\n *\n * - We would like to be able to efficiently reuse the workspace across\n *   multiple compressions **even when the compression parameters change** and\n *   we need to resize some of the objects (where possible).\n *\n * To attempt to manage this buffer, given these constraints, the ZSTD_cwksp\n * abstraction was created. It works as follows:\n *\n * Workspace Layout:\n *\n * [                        ... workspace ...                           ]\n * [objects][tables ->] free space [<- buffers][<- aligned][<- init once]\n *\n * The various objects that live in the workspace are divided into the\n * following categories, and are allocated separately:\n *\n * - Static objects: this is optionally the enclosing ZSTD_CCtx or ZSTD_CDict,\n *   so that literally everything fits in a single buffer. Note: if present,\n *   this must be the first object in the workspace, since ZSTD_customFree{CCtx,\n *   CDict}() rely on a pointer comparison to see whether one or two frees are\n *   required.\n *\n * - Fixed size objects: these are fixed-size, fixed-count objects that are\n *   nonetheless \"dynamically\" allocated in the workspace so that we can\n *   control how they're initialized separately from the broader ZSTD_CCtx.\n *   Examples:\n *   - Entropy Workspace\n *   - 2 x ZSTD_compressedBlockState_t\n *   - CDict dictionary contents\n *\n * - Tables: these are any of several different datastructures (hash tables,\n *   chain tables, binary trees) that all respect a common format: they are\n *   uint32_t arrays, all of whose values are between 0 and (nextSrc - base).\n *   Their sizes depend on the cparams. These tables are 64-byte aligned.\n *\n * - Init once: these buffers require to be initialized at least once before\n *   use. They should be used when we want to skip memory initialization\n *   while not triggering memory checkers (like Valgrind) when reading from\n *   from this memory without writing to it first.\n *   These buffers should be used carefully as they might contain data\n *   from previous compressions.\n *   Buffers are aligned to 64 bytes.\n *\n * - Aligned: these buffers don't require any initialization before they're\n *   used. The user of the buffer should make sure they write into a buffer\n *   location before reading from it.\n *   Buffers are aligned to 64 bytes.\n *\n * - Buffers: these buffers are used for various purposes that don't require\n *   any alignment or initialization before they're used. This means they can\n *   be moved around at no cost for a new compression.\n *\n * Allocating Memory:\n *\n * The various types of objects must be allocated in order, so they can be\n * correctly packed into the workspace buffer. That order is:\n *\n * 1. Objects\n * 2. Init once / Tables\n * 3. Aligned / Tables\n * 4. Buffers / Tables\n *\n * Attempts to reserve objects of different types out of order will fail.\n */\ntypedef struct {\n    void* workspace;\n    void* workspaceEnd;\n\n    void* objectEnd;\n    void* tableEnd;\n    void* tableValidEnd;\n    void* allocStart;\n    void* initOnceStart;\n\n    BYTE allocFailed;\n    int workspaceOversizedDuration;\n    ZSTD_cwksp_alloc_phase_e phase;\n    ZSTD_cwksp_static_alloc_e isStatic;\n} ZSTD_cwksp;\n\n/*-*************************************\n*  Functions\n***************************************/\n\nMEM_STATIC size_t ZSTD_cwksp_available_space(ZSTD_cwksp* ws);\nMEM_STATIC void*  ZSTD_cwksp_initialAllocStart(ZSTD_cwksp* ws);\n\nMEM_STATIC void ZSTD_cwksp_assert_internal_consistency(ZSTD_cwksp* ws) {\n    (void)ws;\n    assert(ws->workspace <= ws->objectEnd);\n    assert(ws->objectEnd <= ws->tableEnd);\n    assert(ws->objectEnd <= ws->tableValidEnd);\n    assert(ws->tableEnd <= ws->allocStart);\n    assert(ws->tableValidEnd <= ws->allocStart);\n    assert(ws->allocStart <= ws->workspaceEnd);\n    assert(ws->initOnceStart <= ZSTD_cwksp_initialAllocStart(ws));\n    assert(ws->workspace <= ws->initOnceStart);\n#if ZSTD_MEMORY_SANITIZER\n    {\n        intptr_t const offset = __msan_test_shadow(ws->initOnceStart,\n            (U8*)ZSTD_cwksp_initialAllocStart(ws) - (U8*)ws->initOnceStart);\n        (void)offset;\n#if defined(ZSTD_MSAN_PRINT)\n        if(offset!=-1) {\n            __msan_print_shadow((U8*)ws->initOnceStart + offset - 8, 32);\n        }\n#endif\n        assert(offset==-1);\n    };\n#endif\n}\n\n/**\n * Align must be a power of 2.\n */\nMEM_STATIC size_t ZSTD_cwksp_align(size_t size, size_t align) {\n    size_t const mask = align - 1;\n    assert(ZSTD_isPower2(align));\n    return (size + mask) & ~mask;\n}\n\n/**\n * Use this to determine how much space in the workspace we will consume to\n * allocate this object. (Normally it should be exactly the size of the object,\n * but under special conditions, like ASAN, where we pad each object, it might\n * be larger.)\n *\n * Since tables aren't currently redzoned, you don't need to call through this\n * to figure out how much space you need for the matchState tables. Everything\n * else is though.\n *\n * Do not use for sizing aligned buffers. Instead, use ZSTD_cwksp_aligned64_alloc_size().\n */\nMEM_STATIC size_t ZSTD_cwksp_alloc_size(size_t size) {\n    if (size == 0)\n        return 0;\n#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)\n    return size + 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE;\n#else\n    return size;\n#endif\n}\n\nMEM_STATIC size_t ZSTD_cwksp_aligned_alloc_size(size_t size, size_t alignment) {\n    return ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(size, alignment));\n}\n\n/**\n * Returns an adjusted alloc size that is the nearest larger multiple of 64 bytes.\n * Used to determine the number of bytes required for a given \"aligned\".\n */\nMEM_STATIC size_t ZSTD_cwksp_aligned64_alloc_size(size_t size) {\n    return ZSTD_cwksp_aligned_alloc_size(size, ZSTD_CWKSP_ALIGNMENT_BYTES);\n}\n\n/**\n * Returns the amount of additional space the cwksp must allocate\n * for internal purposes (currently only alignment).\n */\nMEM_STATIC size_t ZSTD_cwksp_slack_space_required(void) {\n    /* For alignment, the wksp will always allocate an additional 2*ZSTD_CWKSP_ALIGNMENT_BYTES\n     * bytes to align the beginning of tables section and end of buffers;\n     */\n    size_t const slackSpace = ZSTD_CWKSP_ALIGNMENT_BYTES * 2;\n    return slackSpace;\n}\n\n\n/**\n * Return the number of additional bytes required to align a pointer to the given number of bytes.\n * alignBytes must be a power of two.\n */\nMEM_STATIC size_t ZSTD_cwksp_bytes_to_align_ptr(void* ptr, const size_t alignBytes) {\n    size_t const alignBytesMask = alignBytes - 1;\n    size_t const bytes = (alignBytes - ((size_t)ptr & (alignBytesMask))) & alignBytesMask;\n    assert(ZSTD_isPower2(alignBytes));\n    assert(bytes < alignBytes);\n    return bytes;\n}\n\n/**\n * Returns the initial value for allocStart which is used to determine the position from\n * which we can allocate from the end of the workspace.\n */\nMEM_STATIC void*  ZSTD_cwksp_initialAllocStart(ZSTD_cwksp* ws)\n{\n    char* endPtr = (char*)ws->workspaceEnd;\n    assert(ZSTD_isPower2(ZSTD_CWKSP_ALIGNMENT_BYTES));\n    endPtr = endPtr - ((size_t)endPtr % ZSTD_CWKSP_ALIGNMENT_BYTES);\n    return (void*)endPtr;\n}\n\n/**\n * Internal function. Do not use directly.\n * Reserves the given number of bytes within the aligned/buffer segment of the wksp,\n * which counts from the end of the wksp (as opposed to the object/table segment).\n *\n * Returns a pointer to the beginning of that space.\n */\nMEM_STATIC void*\nZSTD_cwksp_reserve_internal_buffer_space(ZSTD_cwksp* ws, size_t const bytes)\n{\n    void* const alloc = (BYTE*)ws->allocStart - bytes;\n    void* const bottom = ws->tableEnd;\n    DEBUGLOG(5, \"cwksp: reserving [0x%p]:%zd bytes; %zd bytes remaining\",\n        alloc, bytes, ZSTD_cwksp_available_space(ws) - bytes);\n    ZSTD_cwksp_assert_internal_consistency(ws);\n    assert(alloc >= bottom);\n    if (alloc < bottom) {\n        DEBUGLOG(4, \"cwksp: alloc failed!\");\n        ws->allocFailed = 1;\n        return NULL;\n    }\n    /* the area is reserved from the end of wksp.\n     * If it overlaps with tableValidEnd, it voids guarantees on values' range */\n    if (alloc < ws->tableValidEnd) {\n        ws->tableValidEnd = alloc;\n    }\n    ws->allocStart = alloc;\n    return alloc;\n}\n\n/**\n * Moves the cwksp to the next phase, and does any necessary allocations.\n * cwksp initialization must necessarily go through each phase in order.\n * Returns a 0 on success, or zstd error\n */\nMEM_STATIC size_t\nZSTD_cwksp_internal_advance_phase(ZSTD_cwksp* ws, ZSTD_cwksp_alloc_phase_e phase)\n{\n    assert(phase >= ws->phase);\n    if (phase > ws->phase) {\n        /* Going from allocating objects to allocating initOnce / tables */\n        if (ws->phase < ZSTD_cwksp_alloc_aligned_init_once &&\n            phase >= ZSTD_cwksp_alloc_aligned_init_once) {\n            ws->tableValidEnd = ws->objectEnd;\n            ws->initOnceStart = ZSTD_cwksp_initialAllocStart(ws);\n\n            {   /* Align the start of the tables to 64 bytes. Use [0, 63] bytes */\n                void *const alloc = ws->objectEnd;\n                size_t const bytesToAlign = ZSTD_cwksp_bytes_to_align_ptr(alloc, ZSTD_CWKSP_ALIGNMENT_BYTES);\n                void *const objectEnd = (BYTE *) alloc + bytesToAlign;\n                DEBUGLOG(5, \"reserving table alignment addtl space: %zu\", bytesToAlign);\n                RETURN_ERROR_IF(objectEnd > ws->workspaceEnd, memory_allocation,\n                                \"table phase - alignment initial allocation failed!\");\n                ws->objectEnd = objectEnd;\n                ws->tableEnd = objectEnd;  /* table area starts being empty */\n                if (ws->tableValidEnd < ws->tableEnd) {\n                    ws->tableValidEnd = ws->tableEnd;\n                }\n            }\n        }\n        ws->phase = phase;\n        ZSTD_cwksp_assert_internal_consistency(ws);\n    }\n    return 0;\n}\n\n/**\n * Returns whether this object/buffer/etc was allocated in this workspace.\n */\nMEM_STATIC int ZSTD_cwksp_owns_buffer(const ZSTD_cwksp* ws, const void* ptr)\n{\n    return (ptr != NULL) && (ws->workspace <= ptr) && (ptr < ws->workspaceEnd);\n}\n\n/**\n * Internal function. Do not use directly.\n */\nMEM_STATIC void*\nZSTD_cwksp_reserve_internal(ZSTD_cwksp* ws, size_t bytes, ZSTD_cwksp_alloc_phase_e phase)\n{\n    void* alloc;\n    if (ZSTD_isError(ZSTD_cwksp_internal_advance_phase(ws, phase)) || bytes == 0) {\n        return NULL;\n    }\n\n#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)\n    /* over-reserve space */\n    bytes += 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE;\n#endif\n\n    alloc = ZSTD_cwksp_reserve_internal_buffer_space(ws, bytes);\n\n#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)\n    /* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on\n     * either size. */\n    if (alloc) {\n        alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE;\n        if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {\n            /* We need to keep the redzone poisoned while unpoisoning the bytes that\n             * are actually allocated. */\n            __asan_unpoison_memory_region(alloc, bytes - 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE);\n        }\n    }\n#endif\n\n    return alloc;\n}\n\n/**\n * Reserves and returns unaligned memory.\n */\nMEM_STATIC BYTE* ZSTD_cwksp_reserve_buffer(ZSTD_cwksp* ws, size_t bytes)\n{\n    return (BYTE*)ZSTD_cwksp_reserve_internal(ws, bytes, ZSTD_cwksp_alloc_buffers);\n}\n\n/**\n * Reserves and returns memory sized on and aligned on ZSTD_CWKSP_ALIGNMENT_BYTES (64 bytes).\n * This memory has been initialized at least once in the past.\n * This doesn't mean it has been initialized this time, and it might contain data from previous\n * operations.\n * The main usage is for algorithms that might need read access into uninitialized memory.\n * The algorithm must maintain safety under these conditions and must make sure it doesn't\n * leak any of the past data (directly or in side channels).\n */\nMEM_STATIC void* ZSTD_cwksp_reserve_aligned_init_once(ZSTD_cwksp* ws, size_t bytes)\n{\n    size_t const alignedBytes = ZSTD_cwksp_align(bytes, ZSTD_CWKSP_ALIGNMENT_BYTES);\n    void* ptr = ZSTD_cwksp_reserve_internal(ws, alignedBytes, ZSTD_cwksp_alloc_aligned_init_once);\n    assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0);\n    if(ptr && ptr < ws->initOnceStart) {\n        /* We assume the memory following the current allocation is either:\n         * 1. Not usable as initOnce memory (end of workspace)\n         * 2. Another initOnce buffer that has been allocated before (and so was previously memset)\n         * 3. An ASAN redzone, in which case we don't want to write on it\n         * For these reasons it should be fine to not explicitly zero every byte up to ws->initOnceStart.\n         * Note that we assume here that MSAN and ASAN cannot run in the same time. */\n        ZSTD_memset(ptr, 0, MIN((size_t)((U8*)ws->initOnceStart - (U8*)ptr), alignedBytes));\n        ws->initOnceStart = ptr;\n    }\n#if ZSTD_MEMORY_SANITIZER\n    assert(__msan_test_shadow(ptr, bytes) == -1);\n#endif\n    return ptr;\n}\n\n/**\n * Reserves and returns memory sized on and aligned on ZSTD_CWKSP_ALIGNMENT_BYTES (64 bytes).\n */\nMEM_STATIC void* ZSTD_cwksp_reserve_aligned64(ZSTD_cwksp* ws, size_t bytes)\n{\n    void* const ptr = ZSTD_cwksp_reserve_internal(ws,\n                        ZSTD_cwksp_align(bytes, ZSTD_CWKSP_ALIGNMENT_BYTES),\n                        ZSTD_cwksp_alloc_aligned);\n    assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0);\n    return ptr;\n}\n\n/**\n * Aligned on 64 bytes. These buffers have the special property that\n * their values remain constrained, allowing us to reuse them without\n * memset()-ing them.\n */\nMEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes)\n{\n    const ZSTD_cwksp_alloc_phase_e phase = ZSTD_cwksp_alloc_aligned_init_once;\n    void* alloc;\n    void* end;\n    void* top;\n\n    /* We can only start allocating tables after we are done reserving space for objects at the\n     * start of the workspace */\n    if(ws->phase < phase) {\n        if (ZSTD_isError(ZSTD_cwksp_internal_advance_phase(ws, phase))) {\n            return NULL;\n        }\n    }\n    alloc = ws->tableEnd;\n    end = (BYTE *)alloc + bytes;\n    top = ws->allocStart;\n\n    DEBUGLOG(5, \"cwksp: reserving %p table %zd bytes, %zd bytes remaining\",\n        alloc, bytes, ZSTD_cwksp_available_space(ws) - bytes);\n    assert((bytes & (sizeof(U32)-1)) == 0);\n    ZSTD_cwksp_assert_internal_consistency(ws);\n    assert(end <= top);\n    if (end > top) {\n        DEBUGLOG(4, \"cwksp: table alloc failed!\");\n        ws->allocFailed = 1;\n        return NULL;\n    }\n    ws->tableEnd = end;\n\n#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)\n    if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {\n        __asan_unpoison_memory_region(alloc, bytes);\n    }\n#endif\n\n    assert((bytes & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0);\n    assert(((size_t)alloc & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0);\n    return alloc;\n}\n\n/**\n * Aligned on sizeof(void*).\n * Note : should happen only once, at workspace first initialization\n */\nMEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes)\n{\n    size_t const roundedBytes = ZSTD_cwksp_align(bytes, sizeof(void*));\n    void* alloc = ws->objectEnd;\n    void* end = (BYTE*)alloc + roundedBytes;\n\n#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)\n    /* over-reserve space */\n    end = (BYTE *)end + 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE;\n#endif\n\n    DEBUGLOG(4,\n        \"cwksp: reserving %p object %zd bytes (rounded to %zd), %zd bytes remaining\",\n        alloc, bytes, roundedBytes, ZSTD_cwksp_available_space(ws) - roundedBytes);\n    assert((size_t)alloc % ZSTD_ALIGNOF(void*) == 0);\n    assert(bytes % ZSTD_ALIGNOF(void*) == 0);\n    ZSTD_cwksp_assert_internal_consistency(ws);\n    /* we must be in the first phase, no advance is possible */\n    if (ws->phase != ZSTD_cwksp_alloc_objects || end > ws->workspaceEnd) {\n        DEBUGLOG(3, \"cwksp: object alloc failed!\");\n        ws->allocFailed = 1;\n        return NULL;\n    }\n    ws->objectEnd = end;\n    ws->tableEnd = end;\n    ws->tableValidEnd = end;\n\n#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)\n    /* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on\n     * either size. */\n    alloc = (BYTE*)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE;\n    if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {\n        __asan_unpoison_memory_region(alloc, bytes);\n    }\n#endif\n\n    return alloc;\n}\n/**\n * with alignment control\n * Note : should happen only once, at workspace first initialization\n */\nMEM_STATIC void* ZSTD_cwksp_reserve_object_aligned(ZSTD_cwksp* ws, size_t byteSize, size_t alignment)\n{\n    size_t const mask = alignment - 1;\n    size_t const surplus = (alignment > sizeof(void*)) ? alignment - sizeof(void*) : 0;\n    void* const start = ZSTD_cwksp_reserve_object(ws, byteSize + surplus);\n    if (start == NULL) return NULL;\n    if (surplus == 0) return start;\n    assert(ZSTD_isPower2(alignment));\n    return (void*)(((size_t)start + surplus) & ~mask);\n}\n\nMEM_STATIC void ZSTD_cwksp_mark_tables_dirty(ZSTD_cwksp* ws)\n{\n    DEBUGLOG(4, \"cwksp: ZSTD_cwksp_mark_tables_dirty\");\n\n#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)\n    /* To validate that the table reuse logic is sound, and that we don't\n     * access table space that we haven't cleaned, we re-\"poison\" the table\n     * space every time we mark it dirty.\n     * Since tableValidEnd space and initOnce space may overlap we don't poison\n     * the initOnce portion as it break its promise. This means that this poisoning\n     * check isn't always applied fully. */\n    {\n        size_t size = (BYTE*)ws->tableValidEnd - (BYTE*)ws->objectEnd;\n        assert(__msan_test_shadow(ws->objectEnd, size) == -1);\n        if((BYTE*)ws->tableValidEnd < (BYTE*)ws->initOnceStart) {\n            __msan_poison(ws->objectEnd, size);\n        } else {\n            assert(ws->initOnceStart >= ws->objectEnd);\n            __msan_poison(ws->objectEnd, (BYTE*)ws->initOnceStart - (BYTE*)ws->objectEnd);\n        }\n    }\n#endif\n\n    assert(ws->tableValidEnd >= ws->objectEnd);\n    assert(ws->tableValidEnd <= ws->allocStart);\n    ws->tableValidEnd = ws->objectEnd;\n    ZSTD_cwksp_assert_internal_consistency(ws);\n}\n\nMEM_STATIC void ZSTD_cwksp_mark_tables_clean(ZSTD_cwksp* ws) {\n    DEBUGLOG(4, \"cwksp: ZSTD_cwksp_mark_tables_clean\");\n    assert(ws->tableValidEnd >= ws->objectEnd);\n    assert(ws->tableValidEnd <= ws->allocStart);\n    if (ws->tableValidEnd < ws->tableEnd) {\n        ws->tableValidEnd = ws->tableEnd;\n    }\n    ZSTD_cwksp_assert_internal_consistency(ws);\n}\n\n/**\n * Zero the part of the allocated tables not already marked clean.\n */\nMEM_STATIC void ZSTD_cwksp_clean_tables(ZSTD_cwksp* ws) {\n    DEBUGLOG(4, \"cwksp: ZSTD_cwksp_clean_tables\");\n    assert(ws->tableValidEnd >= ws->objectEnd);\n    assert(ws->tableValidEnd <= ws->allocStart);\n    if (ws->tableValidEnd < ws->tableEnd) {\n        ZSTD_memset(ws->tableValidEnd, 0, (size_t)((BYTE*)ws->tableEnd - (BYTE*)ws->tableValidEnd));\n    }\n    ZSTD_cwksp_mark_tables_clean(ws);\n}\n\n/**\n * Invalidates table allocations.\n * All other allocations remain valid.\n */\nMEM_STATIC void ZSTD_cwksp_clear_tables(ZSTD_cwksp* ws)\n{\n    DEBUGLOG(4, \"cwksp: clearing tables!\");\n\n#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)\n    /* We don't do this when the workspace is statically allocated, because\n     * when that is the case, we have no capability to hook into the end of the\n     * workspace's lifecycle to unpoison the memory.\n     */\n    if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {\n        size_t size = (BYTE*)ws->tableValidEnd - (BYTE*)ws->objectEnd;\n        __asan_poison_memory_region(ws->objectEnd, size);\n    }\n#endif\n\n    ws->tableEnd = ws->objectEnd;\n    ZSTD_cwksp_assert_internal_consistency(ws);\n}\n\n/**\n * Invalidates all buffer, aligned, and table allocations.\n * Object allocations remain valid.\n */\nMEM_STATIC void ZSTD_cwksp_clear(ZSTD_cwksp* ws) {\n    DEBUGLOG(4, \"cwksp: clearing!\");\n\n#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)\n    /* To validate that the context reuse logic is sound, and that we don't\n     * access stuff that this compression hasn't initialized, we re-\"poison\"\n     * the workspace except for the areas in which we expect memory reuse\n     * without initialization (objects, valid tables area and init once\n     * memory). */\n    {\n        if((BYTE*)ws->tableValidEnd < (BYTE*)ws->initOnceStart) {\n            size_t size = (BYTE*)ws->initOnceStart - (BYTE*)ws->tableValidEnd;\n            __msan_poison(ws->tableValidEnd, size);\n        }\n    }\n#endif\n\n#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)\n    /* We don't do this when the workspace is statically allocated, because\n     * when that is the case, we have no capability to hook into the end of the\n     * workspace's lifecycle to unpoison the memory.\n     */\n    if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {\n        size_t size = (BYTE*)ws->workspaceEnd - (BYTE*)ws->objectEnd;\n        __asan_poison_memory_region(ws->objectEnd, size);\n    }\n#endif\n\n    ws->tableEnd = ws->objectEnd;\n    ws->allocStart = ZSTD_cwksp_initialAllocStart(ws);\n    ws->allocFailed = 0;\n    if (ws->phase > ZSTD_cwksp_alloc_aligned_init_once) {\n        ws->phase = ZSTD_cwksp_alloc_aligned_init_once;\n    }\n    ZSTD_cwksp_assert_internal_consistency(ws);\n}\n\nMEM_STATIC size_t ZSTD_cwksp_sizeof(const ZSTD_cwksp* ws) {\n    return (size_t)((BYTE*)ws->workspaceEnd - (BYTE*)ws->workspace);\n}\n\nMEM_STATIC size_t ZSTD_cwksp_used(const ZSTD_cwksp* ws) {\n    return (size_t)((BYTE*)ws->tableEnd - (BYTE*)ws->workspace)\n         + (size_t)((BYTE*)ws->workspaceEnd - (BYTE*)ws->allocStart);\n}\n\n/**\n * The provided workspace takes ownership of the buffer [start, start+size).\n * Any existing values in the workspace are ignored (the previously managed\n * buffer, if present, must be separately freed).\n */\nMEM_STATIC void ZSTD_cwksp_init(ZSTD_cwksp* ws, void* start, size_t size, ZSTD_cwksp_static_alloc_e isStatic) {\n    DEBUGLOG(4, \"cwksp: init'ing workspace with %zd bytes\", size);\n    assert(((size_t)start & (sizeof(void*)-1)) == 0); /* ensure correct alignment */\n    ws->workspace = start;\n    ws->workspaceEnd = (BYTE*)start + size;\n    ws->objectEnd = ws->workspace;\n    ws->tableValidEnd = ws->objectEnd;\n    ws->initOnceStart = ZSTD_cwksp_initialAllocStart(ws);\n    ws->phase = ZSTD_cwksp_alloc_objects;\n    ws->isStatic = isStatic;\n    ZSTD_cwksp_clear(ws);\n    ws->workspaceOversizedDuration = 0;\n    ZSTD_cwksp_assert_internal_consistency(ws);\n}\n\nMEM_STATIC size_t ZSTD_cwksp_create(ZSTD_cwksp* ws, size_t size, ZSTD_customMem customMem) {\n    void* workspace = ZSTD_customMalloc(size, customMem);\n    DEBUGLOG(4, \"cwksp: creating new workspace with %zd bytes\", size);\n    RETURN_ERROR_IF(workspace == NULL, memory_allocation, \"NULL pointer!\");\n    ZSTD_cwksp_init(ws, workspace, size, ZSTD_cwksp_dynamic_alloc);\n    return 0;\n}\n\nMEM_STATIC void ZSTD_cwksp_free(ZSTD_cwksp* ws, ZSTD_customMem customMem) {\n    void *ptr = ws->workspace;\n    DEBUGLOG(4, \"cwksp: freeing workspace\");\n#if ZSTD_MEMORY_SANITIZER && !defined(ZSTD_MSAN_DONT_POISON_WORKSPACE)\n    if (ptr != NULL && customMem.customFree != NULL) {\n        __msan_unpoison(ptr, ZSTD_cwksp_sizeof(ws));\n    }\n#endif\n    ZSTD_memset(ws, 0, sizeof(ZSTD_cwksp));\n    ZSTD_customFree(ptr, customMem);\n}\n\n/**\n * Moves the management of a workspace from one cwksp to another. The src cwksp\n * is left in an invalid state (src must be re-init()'ed before it's used again).\n */\nMEM_STATIC void ZSTD_cwksp_move(ZSTD_cwksp* dst, ZSTD_cwksp* src) {\n    *dst = *src;\n    ZSTD_memset(src, 0, sizeof(ZSTD_cwksp));\n}\n\nMEM_STATIC int ZSTD_cwksp_reserve_failed(const ZSTD_cwksp* ws) {\n    return ws->allocFailed;\n}\n\n/*-*************************************\n*  Functions Checking Free Space\n***************************************/\n\n/* ZSTD_alignmentSpaceWithinBounds() :\n * Returns if the estimated space needed for a wksp is within an acceptable limit of the\n * actual amount of space used.\n */\nMEM_STATIC int ZSTD_cwksp_estimated_space_within_bounds(const ZSTD_cwksp *const ws, size_t const estimatedSpace) {\n    /* We have an alignment space between objects and tables between tables and buffers, so we can have up to twice\n     * the alignment bytes difference between estimation and actual usage */\n    return (estimatedSpace - ZSTD_cwksp_slack_space_required()) <= ZSTD_cwksp_used(ws) &&\n           ZSTD_cwksp_used(ws) <= estimatedSpace;\n}\n\n\nMEM_STATIC size_t ZSTD_cwksp_available_space(ZSTD_cwksp* ws) {\n    return (size_t)((BYTE*)ws->allocStart - (BYTE*)ws->tableEnd);\n}\n\nMEM_STATIC int ZSTD_cwksp_check_available(ZSTD_cwksp* ws, size_t additionalNeededSpace) {\n    return ZSTD_cwksp_available_space(ws) >= additionalNeededSpace;\n}\n\nMEM_STATIC int ZSTD_cwksp_check_too_large(ZSTD_cwksp* ws, size_t additionalNeededSpace) {\n    return ZSTD_cwksp_check_available(\n        ws, additionalNeededSpace * ZSTD_WORKSPACETOOLARGE_FACTOR);\n}\n\nMEM_STATIC int ZSTD_cwksp_check_wasteful(ZSTD_cwksp* ws, size_t additionalNeededSpace) {\n    return ZSTD_cwksp_check_too_large(ws, additionalNeededSpace)\n        && ws->workspaceOversizedDuration > ZSTD_WORKSPACETOOLARGE_MAXDURATION;\n}\n\nMEM_STATIC void ZSTD_cwksp_bump_oversized_duration(\n        ZSTD_cwksp* ws, size_t additionalNeededSpace) {\n    if (ZSTD_cwksp_check_too_large(ws, additionalNeededSpace)) {\n        ws->workspaceOversizedDuration++;\n    } else {\n        ws->workspaceOversizedDuration = 0;\n    }\n}\n\n#endif /* ZSTD_CWKSP_H */\n"
  },
  {
    "path": "lib/compress/zstd_double_fast.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"zstd_compress_internal.h\"\n#include \"zstd_double_fast.h\"\n\n#ifndef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR\n\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_fillDoubleHashTableForCDict(ZSTD_MatchState_t* ms,\n                              void const* end, ZSTD_dictTableLoadMethod_e dtlm)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32* const hashLarge = ms->hashTable;\n    U32  const hBitsL = cParams->hashLog + ZSTD_SHORT_CACHE_TAG_BITS;\n    U32  const mls = cParams->minMatch;\n    U32* const hashSmall = ms->chainTable;\n    U32  const hBitsS = cParams->chainLog + ZSTD_SHORT_CACHE_TAG_BITS;\n    const BYTE* const base = ms->window.base;\n    const BYTE* ip = base + ms->nextToUpdate;\n    const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;\n    const U32 fastHashFillStep = 3;\n\n    /* Always insert every fastHashFillStep position into the hash tables.\n     * Insert the other positions into the large hash table if their entry\n     * is empty.\n     */\n    for (; ip + fastHashFillStep - 1 <= iend; ip += fastHashFillStep) {\n        U32 const curr = (U32)(ip - base);\n        U32 i;\n        for (i = 0; i < fastHashFillStep; ++i) {\n            size_t const smHashAndTag = ZSTD_hashPtr(ip + i, hBitsS, mls);\n            size_t const lgHashAndTag = ZSTD_hashPtr(ip + i, hBitsL, 8);\n            if (i == 0) {\n                ZSTD_writeTaggedIndex(hashSmall, smHashAndTag, curr + i);\n            }\n            if (i == 0 || hashLarge[lgHashAndTag >> ZSTD_SHORT_CACHE_TAG_BITS] == 0) {\n                ZSTD_writeTaggedIndex(hashLarge, lgHashAndTag, curr + i);\n            }\n            /* Only load extra positions for ZSTD_dtlm_full */\n            if (dtlm == ZSTD_dtlm_fast)\n                break;\n    }   }\n}\n\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_fillDoubleHashTableForCCtx(ZSTD_MatchState_t* ms,\n                              void const* end, ZSTD_dictTableLoadMethod_e dtlm)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32* const hashLarge = ms->hashTable;\n    U32  const hBitsL = cParams->hashLog;\n    U32  const mls = cParams->minMatch;\n    U32* const hashSmall = ms->chainTable;\n    U32  const hBitsS = cParams->chainLog;\n    const BYTE* const base = ms->window.base;\n    const BYTE* ip = base + ms->nextToUpdate;\n    const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;\n    const U32 fastHashFillStep = 3;\n\n    /* Always insert every fastHashFillStep position into the hash tables.\n     * Insert the other positions into the large hash table if their entry\n     * is empty.\n     */\n    for (; ip + fastHashFillStep - 1 <= iend; ip += fastHashFillStep) {\n        U32 const curr = (U32)(ip - base);\n        U32 i;\n        for (i = 0; i < fastHashFillStep; ++i) {\n            size_t const smHash = ZSTD_hashPtr(ip + i, hBitsS, mls);\n            size_t const lgHash = ZSTD_hashPtr(ip + i, hBitsL, 8);\n            if (i == 0)\n                hashSmall[smHash] = curr + i;\n            if (i == 0 || hashLarge[lgHash] == 0)\n                hashLarge[lgHash] = curr + i;\n            /* Only load extra positions for ZSTD_dtlm_full */\n            if (dtlm == ZSTD_dtlm_fast)\n                break;\n        }   }\n}\n\nvoid ZSTD_fillDoubleHashTable(ZSTD_MatchState_t* ms,\n                        const void* const end,\n                        ZSTD_dictTableLoadMethod_e dtlm,\n                        ZSTD_tableFillPurpose_e tfp)\n{\n    if (tfp == ZSTD_tfp_forCDict) {\n        ZSTD_fillDoubleHashTableForCDict(ms, end, dtlm);\n    } else {\n        ZSTD_fillDoubleHashTableForCCtx(ms, end, dtlm);\n    }\n}\n\n\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_compressBlock_doubleFast_noDict_generic(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize, U32 const mls /* template */)\n{\n    ZSTD_compressionParameters const* cParams = &ms->cParams;\n    U32* const hashLong = ms->hashTable;\n    const U32 hBitsL = cParams->hashLog;\n    U32* const hashSmall = ms->chainTable;\n    const U32 hBitsS = cParams->chainLog;\n    const BYTE* const base = ms->window.base;\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* anchor = istart;\n    const U32 endIndex = (U32)((size_t)(istart - base) + srcSize);\n    /* presumes that, if there is a dictionary, it must be using Attach mode */\n    const U32 prefixLowestIndex = ZSTD_getLowestPrefixIndex(ms, endIndex, cParams->windowLog);\n    const BYTE* const prefixLowest = base + prefixLowestIndex;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* const ilimit = iend - HASH_READ_SIZE;\n    U32 offset_1=rep[0], offset_2=rep[1];\n    U32 offsetSaved1 = 0, offsetSaved2 = 0;\n\n    size_t mLength;\n    U32 offset;\n    U32 curr;\n\n    /* how many positions to search before increasing step size */\n    const size_t kStepIncr = 1 << kSearchStrength;\n    /* the position at which to increment the step size if no match is found */\n    const BYTE* nextStep;\n    size_t step; /* the current step size */\n\n    size_t hl0; /* the long hash at ip */\n    size_t hl1; /* the long hash at ip1 */\n\n    U32 idxl0; /* the long match index for ip */\n    U32 idxl1; /* the long match index for ip1 */\n\n    const BYTE* matchl0; /* the long match for ip */\n    const BYTE* matchs0; /* the short match for ip */\n    const BYTE* matchl1; /* the long match for ip1 */\n    const BYTE* matchs0_safe; /* matchs0 or safe address */\n\n    const BYTE* ip = istart; /* the current position */\n    const BYTE* ip1; /* the next position */\n    /* Array of ~random data, should have low probability of matching data\n     * we load from here instead of from tables, if matchl0/matchl1 are\n     * invalid indices. Used to avoid unpredictable branches. */\n    const BYTE dummy[] = {0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0xe2,0xb4};\n\n    DEBUGLOG(5, \"ZSTD_compressBlock_doubleFast_noDict_generic\");\n\n    /* init */\n    ip += ((ip - prefixLowest) == 0);\n    {\n        U32 const current = (U32)(ip - base);\n        U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, current, cParams->windowLog);\n        U32 const maxRep = current - windowLow;\n        if (offset_2 > maxRep) offsetSaved2 = offset_2, offset_2 = 0;\n        if (offset_1 > maxRep) offsetSaved1 = offset_1, offset_1 = 0;\n    }\n\n    /* Outer Loop: one iteration per match found and stored */\n    while (1) {\n        step = 1;\n        nextStep = ip + kStepIncr;\n        ip1 = ip + step;\n\n        if (ip1 > ilimit) {\n            goto _cleanup;\n        }\n\n        hl0 = ZSTD_hashPtr(ip, hBitsL, 8);\n        idxl0 = hashLong[hl0];\n        matchl0 = base + idxl0;\n\n        /* Inner Loop: one iteration per search / position */\n        do {\n            const size_t hs0 = ZSTD_hashPtr(ip, hBitsS, mls);\n            const U32 idxs0 = hashSmall[hs0];\n            curr = (U32)(ip-base);\n            matchs0 = base + idxs0;\n\n            hashLong[hl0] = hashSmall[hs0] = curr;   /* update hash tables */\n\n            /* check noDict repcode */\n            if ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))) {\n                mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;\n                ip++;\n                ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, REPCODE1_TO_OFFBASE, mLength);\n                goto _match_stored;\n            }\n\n            hl1 = ZSTD_hashPtr(ip1, hBitsL, 8);\n\n            /* idxl0 > prefixLowestIndex is a (somewhat) unpredictable branch.\n             * However expression below complies into conditional move. Since\n             * match is unlikely and we only *branch* on idxl0 > prefixLowestIndex\n             * if there is a match, all branches become predictable. */\n            {   const BYTE*  const matchl0_safe = ZSTD_selectAddr(idxl0, prefixLowestIndex, matchl0, &dummy[0]);\n\n                /* check prefix long match */\n                if (MEM_read64(matchl0_safe) == MEM_read64(ip) && matchl0_safe == matchl0) {\n                    mLength = ZSTD_count(ip+8, matchl0+8, iend) + 8;\n                    offset = (U32)(ip-matchl0);\n                    while (((ip>anchor) & (matchl0>prefixLowest)) && (ip[-1] == matchl0[-1])) { ip--; matchl0--; mLength++; } /* catch up */\n                    goto _match_found;\n            }   }\n\n            idxl1 = hashLong[hl1];\n            matchl1 = base + idxl1;\n\n            /* Same optimization as matchl0 above */\n            matchs0_safe = ZSTD_selectAddr(idxs0, prefixLowestIndex, matchs0, &dummy[0]);\n\n            /* check prefix short match */\n            if(MEM_read32(matchs0_safe) == MEM_read32(ip) && matchs0_safe == matchs0) {\n                  goto _search_next_long;\n            }\n\n            if (ip1 >= nextStep) {\n                PREFETCH_L1(ip1 + 64);\n                PREFETCH_L1(ip1 + 128);\n                step++;\n                nextStep += kStepIncr;\n            }\n            ip = ip1;\n            ip1 += step;\n\n            hl0 = hl1;\n            idxl0 = idxl1;\n            matchl0 = matchl1;\n    #if defined(__aarch64__)\n            PREFETCH_L1(ip+256);\n    #endif\n        } while (ip1 <= ilimit);\n\n_cleanup:\n        /* If offset_1 started invalid (offsetSaved1 != 0) and became valid (offset_1 != 0),\n         * rotate saved offsets. See comment in ZSTD_compressBlock_fast_noDict for more context. */\n        offsetSaved2 = ((offsetSaved1 != 0) && (offset_1 != 0)) ? offsetSaved1 : offsetSaved2;\n\n        /* save reps for next block */\n        rep[0] = offset_1 ? offset_1 : offsetSaved1;\n        rep[1] = offset_2 ? offset_2 : offsetSaved2;\n\n        /* Return the last literals size */\n        return (size_t)(iend - anchor);\n\n_search_next_long:\n\n        /* short match found: let's check for a longer one */\n        mLength = ZSTD_count(ip+4, matchs0+4, iend) + 4;\n        offset = (U32)(ip - matchs0);\n\n        /* check long match at +1 position */\n        if ((idxl1 > prefixLowestIndex) && (MEM_read64(matchl1) == MEM_read64(ip1))) {\n            size_t const l1len = ZSTD_count(ip1+8, matchl1+8, iend) + 8;\n            if (l1len > mLength) {\n                /* use the long match instead */\n                ip = ip1;\n                mLength = l1len;\n                offset = (U32)(ip-matchl1);\n                matchs0 = matchl1;\n            }\n        }\n\n        while (((ip>anchor) & (matchs0>prefixLowest)) && (ip[-1] == matchs0[-1])) { ip--; matchs0--; mLength++; } /* complete backward */\n\n        /* fall-through */\n\n_match_found: /* requires ip, offset, mLength */\n        offset_2 = offset_1;\n        offset_1 = offset;\n\n        if (step < 4) {\n            /* It is unsafe to write this value back to the hashtable when ip1 is\n             * greater than or equal to the new ip we will have after we're done\n             * processing this match. Rather than perform that test directly\n             * (ip1 >= ip + mLength), which costs speed in practice, we do a simpler\n             * more predictable test. The minmatch even if we take a short match is\n             * 4 bytes, so as long as step, the distance between ip and ip1\n             * (initially) is less than 4, we know ip1 < new ip. */\n            hashLong[hl1] = (U32)(ip1 - base);\n        }\n\n        ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, OFFSET_TO_OFFBASE(offset), mLength);\n\n_match_stored:\n        /* match found */\n        ip += mLength;\n        anchor = ip;\n\n        if (ip <= ilimit) {\n            /* Complementary insertion */\n            /* done after iLimit test, as candidates could be > iend-8 */\n            {   U32 const indexToInsert = curr+2;\n                hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert;\n                hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base);\n                hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert;\n                hashSmall[ZSTD_hashPtr(ip-1, hBitsS, mls)] = (U32)(ip-1-base);\n            }\n\n            /* check immediate repcode */\n            while ( (ip <= ilimit)\n                 && ( (offset_2>0)\n                    & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {\n                /* store sequence */\n                size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;\n                U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff;  /* swap offset_2 <=> offset_1 */\n                hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip-base);\n                hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip-base);\n                ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, rLength);\n                ip += rLength;\n                anchor = ip;\n                continue;   /* faster when present ... (?) */\n            }\n        }\n    }\n}\n\n\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_compressBlock_doubleFast_dictMatchState_generic(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize,\n        U32 const mls /* template */)\n{\n    ZSTD_compressionParameters const* cParams = &ms->cParams;\n    U32* const hashLong = ms->hashTable;\n    const U32 hBitsL = cParams->hashLog;\n    U32* const hashSmall = ms->chainTable;\n    const U32 hBitsS = cParams->chainLog;\n    const BYTE* const base = ms->window.base;\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* ip = istart;\n    const BYTE* anchor = istart;\n    const U32 endIndex = (U32)((size_t)(istart - base) + srcSize);\n    /* presumes that, if there is a dictionary, it must be using Attach mode */\n    const U32 prefixLowestIndex = ZSTD_getLowestPrefixIndex(ms, endIndex, cParams->windowLog);\n    const BYTE* const prefixLowest = base + prefixLowestIndex;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* const ilimit = iend - HASH_READ_SIZE;\n    U32 offset_1=rep[0], offset_2=rep[1];\n\n    const ZSTD_MatchState_t* const dms = ms->dictMatchState;\n    const ZSTD_compressionParameters* const dictCParams = &dms->cParams;\n    const U32* const dictHashLong  = dms->hashTable;\n    const U32* const dictHashSmall = dms->chainTable;\n    const U32 dictStartIndex       = dms->window.dictLimit;\n    const BYTE* const dictBase     = dms->window.base;\n    const BYTE* const dictStart    = dictBase + dictStartIndex;\n    const BYTE* const dictEnd      = dms->window.nextSrc;\n    const U32 dictIndexDelta       = prefixLowestIndex - (U32)(dictEnd - dictBase);\n    const U32 dictHBitsL           = dictCParams->hashLog + ZSTD_SHORT_CACHE_TAG_BITS;\n    const U32 dictHBitsS           = dictCParams->chainLog + ZSTD_SHORT_CACHE_TAG_BITS;\n    const U32 dictAndPrefixLength  = (U32)((ip - prefixLowest) + (dictEnd - dictStart));\n\n    DEBUGLOG(5, \"ZSTD_compressBlock_doubleFast_dictMatchState_generic\");\n\n    /* if a dictionary is attached, it must be within window range */\n    assert(ms->window.dictLimit + (1U << cParams->windowLog) >= endIndex);\n\n    if (ms->prefetchCDictTables) {\n        size_t const hashTableBytes = (((size_t)1) << dictCParams->hashLog) * sizeof(U32);\n        size_t const chainTableBytes = (((size_t)1) << dictCParams->chainLog) * sizeof(U32);\n        PREFETCH_AREA(dictHashLong, hashTableBytes);\n        PREFETCH_AREA(dictHashSmall, chainTableBytes);\n    }\n\n    /* init */\n    ip += (dictAndPrefixLength == 0);\n\n    /* dictMatchState repCode checks don't currently handle repCode == 0\n     * disabling. */\n    assert(offset_1 <= dictAndPrefixLength);\n    assert(offset_2 <= dictAndPrefixLength);\n\n    /* Main Search Loop */\n    while (ip < ilimit) {   /* < instead of <=, because repcode check at (ip+1) */\n        size_t mLength;\n        U32 offset;\n        size_t const h2 = ZSTD_hashPtr(ip, hBitsL, 8);\n        size_t const h = ZSTD_hashPtr(ip, hBitsS, mls);\n        size_t const dictHashAndTagL = ZSTD_hashPtr(ip, dictHBitsL, 8);\n        size_t const dictHashAndTagS = ZSTD_hashPtr(ip, dictHBitsS, mls);\n        U32 const dictMatchIndexAndTagL = dictHashLong[dictHashAndTagL >> ZSTD_SHORT_CACHE_TAG_BITS];\n        U32 const dictMatchIndexAndTagS = dictHashSmall[dictHashAndTagS >> ZSTD_SHORT_CACHE_TAG_BITS];\n        int const dictTagsMatchL = ZSTD_comparePackedTags(dictMatchIndexAndTagL, dictHashAndTagL);\n        int const dictTagsMatchS = ZSTD_comparePackedTags(dictMatchIndexAndTagS, dictHashAndTagS);\n        U32 const curr = (U32)(ip-base);\n        U32 const matchIndexL = hashLong[h2];\n        U32 matchIndexS = hashSmall[h];\n        const BYTE* matchLong = base + matchIndexL;\n        const BYTE* match = base + matchIndexS;\n        const U32 repIndex = curr + 1 - offset_1;\n        const BYTE* repMatch = (repIndex < prefixLowestIndex) ?\n                               dictBase + (repIndex - dictIndexDelta) :\n                               base + repIndex;\n        hashLong[h2] = hashSmall[h] = curr;   /* update hash tables */\n\n        /* check repcode */\n        if ((ZSTD_index_overlap_check(prefixLowestIndex, repIndex))\n            && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {\n            const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;\n            mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;\n            ip++;\n            ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, REPCODE1_TO_OFFBASE, mLength);\n            goto _match_stored;\n        }\n\n        if ((matchIndexL >= prefixLowestIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) {\n            /* check prefix long match */\n            mLength = ZSTD_count(ip+8, matchLong+8, iend) + 8;\n            offset = (U32)(ip-matchLong);\n            while (((ip>anchor) & (matchLong>prefixLowest)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */\n            goto _match_found;\n        } else if (dictTagsMatchL) {\n            /* check dictMatchState long match */\n            U32 const dictMatchIndexL = dictMatchIndexAndTagL >> ZSTD_SHORT_CACHE_TAG_BITS;\n            const BYTE* dictMatchL = dictBase + dictMatchIndexL;\n            assert(dictMatchL < dictEnd);\n\n            if (dictMatchL > dictStart && MEM_read64(dictMatchL) == MEM_read64(ip)) {\n                mLength = ZSTD_count_2segments(ip+8, dictMatchL+8, iend, dictEnd, prefixLowest) + 8;\n                offset = (U32)(curr - dictMatchIndexL - dictIndexDelta);\n                while (((ip>anchor) & (dictMatchL>dictStart)) && (ip[-1] == dictMatchL[-1])) { ip--; dictMatchL--; mLength++; } /* catch up */\n                goto _match_found;\n        }   }\n\n        if (matchIndexS > prefixLowestIndex) {\n            /* short match  candidate */\n            if (MEM_read32(match) == MEM_read32(ip)) {\n                goto _search_next_long;\n            }\n        } else if (dictTagsMatchS) {\n            /* check dictMatchState short match */\n            U32 const dictMatchIndexS = dictMatchIndexAndTagS >> ZSTD_SHORT_CACHE_TAG_BITS;\n            match = dictBase + dictMatchIndexS;\n            matchIndexS = dictMatchIndexS + dictIndexDelta;\n\n            if (match > dictStart && MEM_read32(match) == MEM_read32(ip)) {\n                goto _search_next_long;\n        }   }\n\n        ip += ((ip-anchor) >> kSearchStrength) + 1;\n#if defined(__aarch64__)\n        PREFETCH_L1(ip+256);\n#endif\n        continue;\n\n_search_next_long:\n        {   size_t const hl3 = ZSTD_hashPtr(ip+1, hBitsL, 8);\n            size_t const dictHashAndTagL3 = ZSTD_hashPtr(ip+1, dictHBitsL, 8);\n            U32 const matchIndexL3 = hashLong[hl3];\n            U32 const dictMatchIndexAndTagL3 = dictHashLong[dictHashAndTagL3 >> ZSTD_SHORT_CACHE_TAG_BITS];\n            int const dictTagsMatchL3 = ZSTD_comparePackedTags(dictMatchIndexAndTagL3, dictHashAndTagL3);\n            const BYTE* matchL3 = base + matchIndexL3;\n            hashLong[hl3] = curr + 1;\n\n            /* check prefix long +1 match */\n            if ((matchIndexL3 >= prefixLowestIndex) && (MEM_read64(matchL3) == MEM_read64(ip+1))) {\n                mLength = ZSTD_count(ip+9, matchL3+8, iend) + 8;\n                ip++;\n                offset = (U32)(ip-matchL3);\n                while (((ip>anchor) & (matchL3>prefixLowest)) && (ip[-1] == matchL3[-1])) { ip--; matchL3--; mLength++; } /* catch up */\n                goto _match_found;\n            } else if (dictTagsMatchL3) {\n                /* check dict long +1 match */\n                U32 const dictMatchIndexL3 = dictMatchIndexAndTagL3 >> ZSTD_SHORT_CACHE_TAG_BITS;\n                const BYTE* dictMatchL3 = dictBase + dictMatchIndexL3;\n                assert(dictMatchL3 < dictEnd);\n                if (dictMatchL3 > dictStart && MEM_read64(dictMatchL3) == MEM_read64(ip+1)) {\n                    mLength = ZSTD_count_2segments(ip+1+8, dictMatchL3+8, iend, dictEnd, prefixLowest) + 8;\n                    ip++;\n                    offset = (U32)(curr + 1 - dictMatchIndexL3 - dictIndexDelta);\n                    while (((ip>anchor) & (dictMatchL3>dictStart)) && (ip[-1] == dictMatchL3[-1])) { ip--; dictMatchL3--; mLength++; } /* catch up */\n                    goto _match_found;\n        }   }   }\n\n        /* if no long +1 match, explore the short match we found */\n        if (matchIndexS < prefixLowestIndex) {\n            mLength = ZSTD_count_2segments(ip+4, match+4, iend, dictEnd, prefixLowest) + 4;\n            offset = (U32)(curr - matchIndexS);\n            while (((ip>anchor) & (match>dictStart)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */\n        } else {\n            mLength = ZSTD_count(ip+4, match+4, iend) + 4;\n            offset = (U32)(ip - match);\n            while (((ip>anchor) & (match>prefixLowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */\n        }\n\n_match_found:\n        offset_2 = offset_1;\n        offset_1 = offset;\n\n        ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, OFFSET_TO_OFFBASE(offset), mLength);\n\n_match_stored:\n        /* match found */\n        ip += mLength;\n        anchor = ip;\n\n        if (ip <= ilimit) {\n            /* Complementary insertion */\n            /* done after iLimit test, as candidates could be > iend-8 */\n            {   U32 const indexToInsert = curr+2;\n                hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert;\n                hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base);\n                hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert;\n                hashSmall[ZSTD_hashPtr(ip-1, hBitsS, mls)] = (U32)(ip-1-base);\n            }\n\n            /* check immediate repcode */\n            while (ip <= ilimit) {\n                U32 const current2 = (U32)(ip-base);\n                U32 const repIndex2 = current2 - offset_2;\n                const BYTE* repMatch2 = repIndex2 < prefixLowestIndex ?\n                        dictBase + repIndex2 - dictIndexDelta :\n                        base + repIndex2;\n                if ( (ZSTD_index_overlap_check(prefixLowestIndex, repIndex2))\n                   && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {\n                    const BYTE* const repEnd2 = repIndex2 < prefixLowestIndex ? dictEnd : iend;\n                    size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixLowest) + 4;\n                    U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset;   /* swap offset_2 <=> offset_1 */\n                    ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, repLength2);\n                    hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;\n                    hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;\n                    ip += repLength2;\n                    anchor = ip;\n                    continue;\n                }\n                break;\n            }\n        }\n    }   /* while (ip < ilimit) */\n\n    /* save reps for next block */\n    rep[0] = offset_1;\n    rep[1] = offset_2;\n\n    /* Return the last literals size */\n    return (size_t)(iend - anchor);\n}\n\n#define ZSTD_GEN_DFAST_FN(dictMode, mls)                                                                 \\\n    static size_t ZSTD_compressBlock_doubleFast_##dictMode##_##mls(                                      \\\n            ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],                          \\\n            void const* src, size_t srcSize)                                                             \\\n    {                                                                                                    \\\n        return ZSTD_compressBlock_doubleFast_##dictMode##_generic(ms, seqStore, rep, src, srcSize, mls); \\\n    }\n\nZSTD_GEN_DFAST_FN(noDict, 4)\nZSTD_GEN_DFAST_FN(noDict, 5)\nZSTD_GEN_DFAST_FN(noDict, 6)\nZSTD_GEN_DFAST_FN(noDict, 7)\n\nZSTD_GEN_DFAST_FN(dictMatchState, 4)\nZSTD_GEN_DFAST_FN(dictMatchState, 5)\nZSTD_GEN_DFAST_FN(dictMatchState, 6)\nZSTD_GEN_DFAST_FN(dictMatchState, 7)\n\n\nsize_t ZSTD_compressBlock_doubleFast(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    const U32 mls = ms->cParams.minMatch;\n    switch(mls)\n    {\n    default: /* includes case 3 */\n    case 4 :\n        return ZSTD_compressBlock_doubleFast_noDict_4(ms, seqStore, rep, src, srcSize);\n    case 5 :\n        return ZSTD_compressBlock_doubleFast_noDict_5(ms, seqStore, rep, src, srcSize);\n    case 6 :\n        return ZSTD_compressBlock_doubleFast_noDict_6(ms, seqStore, rep, src, srcSize);\n    case 7 :\n        return ZSTD_compressBlock_doubleFast_noDict_7(ms, seqStore, rep, src, srcSize);\n    }\n}\n\n\nsize_t ZSTD_compressBlock_doubleFast_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    const U32 mls = ms->cParams.minMatch;\n    switch(mls)\n    {\n    default: /* includes case 3 */\n    case 4 :\n        return ZSTD_compressBlock_doubleFast_dictMatchState_4(ms, seqStore, rep, src, srcSize);\n    case 5 :\n        return ZSTD_compressBlock_doubleFast_dictMatchState_5(ms, seqStore, rep, src, srcSize);\n    case 6 :\n        return ZSTD_compressBlock_doubleFast_dictMatchState_6(ms, seqStore, rep, src, srcSize);\n    case 7 :\n        return ZSTD_compressBlock_doubleFast_dictMatchState_7(ms, seqStore, rep, src, srcSize);\n    }\n}\n\n\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_compressBlock_doubleFast_extDict_generic(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize,\n        U32 const mls /* template */)\n{\n    ZSTD_compressionParameters const* cParams = &ms->cParams;\n    U32* const hashLong = ms->hashTable;\n    U32  const hBitsL = cParams->hashLog;\n    U32* const hashSmall = ms->chainTable;\n    U32  const hBitsS = cParams->chainLog;\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* ip = istart;\n    const BYTE* anchor = istart;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* const ilimit = iend - 8;\n    const BYTE* const base = ms->window.base;\n    const U32   endIndex = (U32)((size_t)(istart - base) + srcSize);\n    const U32   lowLimit = ZSTD_getLowestMatchIndex(ms, endIndex, cParams->windowLog);\n    const U32   dictStartIndex = lowLimit;\n    const U32   dictLimit = ms->window.dictLimit;\n    const U32   prefixStartIndex = (dictLimit > lowLimit) ? dictLimit : lowLimit;\n    const BYTE* const prefixStart = base + prefixStartIndex;\n    const BYTE* const dictBase = ms->window.dictBase;\n    const BYTE* const dictStart = dictBase + dictStartIndex;\n    const BYTE* const dictEnd = dictBase + prefixStartIndex;\n    U32 offset_1=rep[0], offset_2=rep[1];\n\n    DEBUGLOG(5, \"ZSTD_compressBlock_doubleFast_extDict_generic (srcSize=%zu)\", srcSize);\n\n    /* if extDict is invalidated due to maxDistance, switch to \"regular\" variant */\n    if (prefixStartIndex == dictStartIndex)\n        return ZSTD_compressBlock_doubleFast(ms, seqStore, rep, src, srcSize);\n\n    /* Search Loop */\n    while (ip < ilimit) {  /* < instead of <=, because (ip+1) */\n        const size_t hSmall = ZSTD_hashPtr(ip, hBitsS, mls);\n        const U32 matchIndex = hashSmall[hSmall];\n        const BYTE* const matchBase = matchIndex < prefixStartIndex ? dictBase : base;\n        const BYTE* match = matchBase + matchIndex;\n\n        const size_t hLong = ZSTD_hashPtr(ip, hBitsL, 8);\n        const U32 matchLongIndex = hashLong[hLong];\n        const BYTE* const matchLongBase = matchLongIndex < prefixStartIndex ? dictBase : base;\n        const BYTE* matchLong = matchLongBase + matchLongIndex;\n\n        const U32 curr = (U32)(ip-base);\n        const U32 repIndex = curr + 1 - offset_1;   /* offset_1 expected <= curr +1 */\n        const BYTE* const repBase = repIndex < prefixStartIndex ? dictBase : base;\n        const BYTE* const repMatch = repBase + repIndex;\n        size_t mLength;\n        hashSmall[hSmall] = hashLong[hLong] = curr;   /* update hash table */\n\n        if (((ZSTD_index_overlap_check(prefixStartIndex, repIndex))\n            & (offset_1 <= curr+1 - dictStartIndex)) /* note: we are searching at curr+1 */\n          && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {\n            const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;\n            mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;\n            ip++;\n            ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, REPCODE1_TO_OFFBASE, mLength);\n        } else {\n            if ((matchLongIndex > dictStartIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) {\n                const BYTE* const matchEnd = matchLongIndex < prefixStartIndex ? dictEnd : iend;\n                const BYTE* const lowMatchPtr = matchLongIndex < prefixStartIndex ? dictStart : prefixStart;\n                U32 offset;\n                mLength = ZSTD_count_2segments(ip+8, matchLong+8, iend, matchEnd, prefixStart) + 8;\n                offset = curr - matchLongIndex;\n                while (((ip>anchor) & (matchLong>lowMatchPtr)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; }   /* catch up */\n                offset_2 = offset_1;\n                offset_1 = offset;\n                ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, OFFSET_TO_OFFBASE(offset), mLength);\n\n            } else if ((matchIndex > dictStartIndex) && (MEM_read32(match) == MEM_read32(ip))) {\n                size_t const h3 = ZSTD_hashPtr(ip+1, hBitsL, 8);\n                U32 const matchIndex3 = hashLong[h3];\n                const BYTE* const match3Base = matchIndex3 < prefixStartIndex ? dictBase : base;\n                const BYTE* match3 = match3Base + matchIndex3;\n                U32 offset;\n                hashLong[h3] = curr + 1;\n                if ( (matchIndex3 > dictStartIndex) && (MEM_read64(match3) == MEM_read64(ip+1)) ) {\n                    const BYTE* const matchEnd = matchIndex3 < prefixStartIndex ? dictEnd : iend;\n                    const BYTE* const lowMatchPtr = matchIndex3 < prefixStartIndex ? dictStart : prefixStart;\n                    mLength = ZSTD_count_2segments(ip+9, match3+8, iend, matchEnd, prefixStart) + 8;\n                    ip++;\n                    offset = curr+1 - matchIndex3;\n                    while (((ip>anchor) & (match3>lowMatchPtr)) && (ip[-1] == match3[-1])) { ip--; match3--; mLength++; } /* catch up */\n                } else {\n                    const BYTE* const matchEnd = matchIndex < prefixStartIndex ? dictEnd : iend;\n                    const BYTE* const lowMatchPtr = matchIndex < prefixStartIndex ? dictStart : prefixStart;\n                    mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, prefixStart) + 4;\n                    offset = curr - matchIndex;\n                    while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; }   /* catch up */\n                }\n                offset_2 = offset_1;\n                offset_1 = offset;\n                ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, OFFSET_TO_OFFBASE(offset), mLength);\n\n            } else {\n                ip += ((ip-anchor) >> kSearchStrength) + 1;\n                continue;\n        }   }\n\n        /* move to next sequence start */\n        ip += mLength;\n        anchor = ip;\n\n        if (ip <= ilimit) {\n            /* Complementary insertion */\n            /* done after iLimit test, as candidates could be > iend-8 */\n            {   U32 const indexToInsert = curr+2;\n                hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert;\n                hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base);\n                hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert;\n                hashSmall[ZSTD_hashPtr(ip-1, hBitsS, mls)] = (U32)(ip-1-base);\n            }\n\n            /* check immediate repcode */\n            while (ip <= ilimit) {\n                U32 const current2 = (U32)(ip-base);\n                U32 const repIndex2 = current2 - offset_2;\n                const BYTE* repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2;\n                if ( ((ZSTD_index_overlap_check(prefixStartIndex, repIndex2))\n                    & (offset_2 <= current2 - dictStartIndex))\n                  && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {\n                    const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;\n                    size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;\n                    U32 const tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset;   /* swap offset_2 <=> offset_1 */\n                    ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, repLength2);\n                    hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;\n                    hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;\n                    ip += repLength2;\n                    anchor = ip;\n                    continue;\n                }\n                break;\n    }   }   }\n\n    /* save reps for next block */\n    rep[0] = offset_1;\n    rep[1] = offset_2;\n\n    /* Return the last literals size */\n    return (size_t)(iend - anchor);\n}\n\nZSTD_GEN_DFAST_FN(extDict, 4)\nZSTD_GEN_DFAST_FN(extDict, 5)\nZSTD_GEN_DFAST_FN(extDict, 6)\nZSTD_GEN_DFAST_FN(extDict, 7)\n\nsize_t ZSTD_compressBlock_doubleFast_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    U32 const mls = ms->cParams.minMatch;\n    switch(mls)\n    {\n    default: /* includes case 3 */\n    case 4 :\n        return ZSTD_compressBlock_doubleFast_extDict_4(ms, seqStore, rep, src, srcSize);\n    case 5 :\n        return ZSTD_compressBlock_doubleFast_extDict_5(ms, seqStore, rep, src, srcSize);\n    case 6 :\n        return ZSTD_compressBlock_doubleFast_extDict_6(ms, seqStore, rep, src, srcSize);\n    case 7 :\n        return ZSTD_compressBlock_doubleFast_extDict_7(ms, seqStore, rep, src, srcSize);\n    }\n}\n\n#endif /* ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR */\n"
  },
  {
    "path": "lib/compress/zstd_double_fast.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_DOUBLE_FAST_H\n#define ZSTD_DOUBLE_FAST_H\n\n#include \"../common/mem.h\"      /* U32 */\n#include \"zstd_compress_internal.h\"     /* ZSTD_CCtx, size_t */\n\n#ifndef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR\n\nvoid ZSTD_fillDoubleHashTable(ZSTD_MatchState_t* ms,\n                              void const* end, ZSTD_dictTableLoadMethod_e dtlm,\n                              ZSTD_tableFillPurpose_e tfp);\n\nsize_t ZSTD_compressBlock_doubleFast(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_doubleFast_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_doubleFast_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\n\n#define ZSTD_COMPRESSBLOCK_DOUBLEFAST ZSTD_compressBlock_doubleFast\n#define ZSTD_COMPRESSBLOCK_DOUBLEFAST_DICTMATCHSTATE ZSTD_compressBlock_doubleFast_dictMatchState\n#define ZSTD_COMPRESSBLOCK_DOUBLEFAST_EXTDICT ZSTD_compressBlock_doubleFast_extDict\n#else\n#define ZSTD_COMPRESSBLOCK_DOUBLEFAST NULL\n#define ZSTD_COMPRESSBLOCK_DOUBLEFAST_DICTMATCHSTATE NULL\n#define ZSTD_COMPRESSBLOCK_DOUBLEFAST_EXTDICT NULL\n#endif /* ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR */\n\n#endif /* ZSTD_DOUBLE_FAST_H */\n"
  },
  {
    "path": "lib/compress/zstd_fast.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"zstd_compress_internal.h\"  /* ZSTD_hashPtr, ZSTD_count, ZSTD_storeSeq */\n#include \"zstd_fast.h\"\n\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_fillHashTableForCDict(ZSTD_MatchState_t* ms,\n                        const void* const end,\n                        ZSTD_dictTableLoadMethod_e dtlm)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32* const hashTable = ms->hashTable;\n    U32  const hBits = cParams->hashLog + ZSTD_SHORT_CACHE_TAG_BITS;\n    U32  const mls = cParams->minMatch;\n    const BYTE* const base = ms->window.base;\n    const BYTE* ip = base + ms->nextToUpdate;\n    const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;\n    const U32 fastHashFillStep = 3;\n\n    /* Currently, we always use ZSTD_dtlm_full for filling CDict tables.\n     * Feel free to remove this assert if there's a good reason! */\n    assert(dtlm == ZSTD_dtlm_full);\n\n    /* Always insert every fastHashFillStep position into the hash table.\n     * Insert the other positions if their hash entry is empty.\n     */\n    for ( ; ip + fastHashFillStep < iend + 2; ip += fastHashFillStep) {\n        U32 const curr = (U32)(ip - base);\n        {   size_t const hashAndTag = ZSTD_hashPtr(ip, hBits, mls);\n            ZSTD_writeTaggedIndex(hashTable, hashAndTag, curr);   }\n\n        if (dtlm == ZSTD_dtlm_fast) continue;\n        /* Only load extra positions for ZSTD_dtlm_full */\n        {   U32 p;\n            for (p = 1; p < fastHashFillStep; ++p) {\n                size_t const hashAndTag = ZSTD_hashPtr(ip + p, hBits, mls);\n                if (hashTable[hashAndTag >> ZSTD_SHORT_CACHE_TAG_BITS] == 0) {  /* not yet filled */\n                    ZSTD_writeTaggedIndex(hashTable, hashAndTag, curr + p);\n    }   }   }   }\n}\n\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_fillHashTableForCCtx(ZSTD_MatchState_t* ms,\n                        const void* const end,\n                        ZSTD_dictTableLoadMethod_e dtlm)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32* const hashTable = ms->hashTable;\n    U32  const hBits = cParams->hashLog;\n    U32  const mls = cParams->minMatch;\n    const BYTE* const base = ms->window.base;\n    const BYTE* ip = base + ms->nextToUpdate;\n    const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;\n    const U32 fastHashFillStep = 3;\n\n    /* Currently, we always use ZSTD_dtlm_fast for filling CCtx tables.\n     * Feel free to remove this assert if there's a good reason! */\n    assert(dtlm == ZSTD_dtlm_fast);\n\n    /* Always insert every fastHashFillStep position into the hash table.\n     * Insert the other positions if their hash entry is empty.\n     */\n    for ( ; ip + fastHashFillStep < iend + 2; ip += fastHashFillStep) {\n        U32 const curr = (U32)(ip - base);\n        size_t const hash0 = ZSTD_hashPtr(ip, hBits, mls);\n        hashTable[hash0] = curr;\n        if (dtlm == ZSTD_dtlm_fast) continue;\n        /* Only load extra positions for ZSTD_dtlm_full */\n        {   U32 p;\n            for (p = 1; p < fastHashFillStep; ++p) {\n                size_t const hash = ZSTD_hashPtr(ip + p, hBits, mls);\n                if (hashTable[hash] == 0) {  /* not yet filled */\n                    hashTable[hash] = curr + p;\n    }   }   }   }\n}\n\nvoid ZSTD_fillHashTable(ZSTD_MatchState_t* ms,\n                        const void* const end,\n                        ZSTD_dictTableLoadMethod_e dtlm,\n                        ZSTD_tableFillPurpose_e tfp)\n{\n    if (tfp == ZSTD_tfp_forCDict) {\n        ZSTD_fillHashTableForCDict(ms, end, dtlm);\n    } else {\n        ZSTD_fillHashTableForCCtx(ms, end, dtlm);\n    }\n}\n\n\ntypedef int (*ZSTD_match4Found) (const BYTE* currentPtr, const BYTE* matchAddress, U32 matchIdx, U32 idxLowLimit);\n\nstatic int\nZSTD_match4Found_cmov(const BYTE* currentPtr, const BYTE* matchAddress, U32 matchIdx, U32 idxLowLimit)\n{\n    /* Array of ~random data, should have low probability of matching data.\n     * Load from here if the index is invalid.\n     * Used to avoid unpredictable branches. */\n    static const BYTE dummy[] = {0x12,0x34,0x56,0x78};\n\n    /* currentIdx >= lowLimit is a (somewhat) unpredictable branch.\n     * However expression below compiles into conditional move.\n     */\n    const BYTE* mvalAddr = ZSTD_selectAddr(matchIdx, idxLowLimit, matchAddress, dummy);\n    /* Note: this used to be written as : return test1 && test2;\n     * Unfortunately, once inlined, these tests become branches,\n     * in which case it becomes critical that they are executed in the right order (test1 then test2).\n     * So we have to write these tests in a specific manner to ensure their ordering.\n     */\n    if (MEM_read32(currentPtr) != MEM_read32(mvalAddr)) return 0;\n    /* force ordering of these tests, which matters once the function is inlined, as they become branches */\n#if defined(__GNUC__)\n    __asm__(\"\");\n#endif\n    return matchIdx >= idxLowLimit;\n}\n\nstatic int\nZSTD_match4Found_branch(const BYTE* currentPtr, const BYTE* matchAddress, U32 matchIdx, U32 idxLowLimit)\n{\n    /* using a branch instead of a cmov,\n     * because it's faster in scenarios where matchIdx >= idxLowLimit is generally true,\n     * aka almost all candidates are within range */\n    U32 mval;\n    if (matchIdx >= idxLowLimit) {\n        mval = MEM_read32(matchAddress);\n    } else {\n        mval = MEM_read32(currentPtr) ^ 1; /* guaranteed to not match. */\n    }\n\n    return (MEM_read32(currentPtr) == mval);\n}\n\n\n/**\n * If you squint hard enough (and ignore repcodes), the search operation at any\n * given position is broken into 4 stages:\n *\n * 1. Hash   (map position to hash value via input read)\n * 2. Lookup (map hash val to index via hashtable read)\n * 3. Load   (map index to value at that position via input read)\n * 4. Compare\n *\n * Each of these steps involves a memory read at an address which is computed\n * from the previous step. This means these steps must be sequenced and their\n * latencies are cumulative.\n *\n * Rather than do 1->2->3->4 sequentially for a single position before moving\n * onto the next, this implementation interleaves these operations across the\n * next few positions:\n *\n * R = Repcode Read & Compare\n * H = Hash\n * T = Table Lookup\n * M = Match Read & Compare\n *\n * Pos | Time -->\n * ----+-------------------\n * N   | ... M\n * N+1 | ...   TM\n * N+2 |    R H   T M\n * N+3 |         H    TM\n * N+4 |           R H   T M\n * N+5 |                H   ...\n * N+6 |                  R ...\n *\n * This is very much analogous to the pipelining of execution in a CPU. And just\n * like a CPU, we have to dump the pipeline when we find a match (i.e., take a\n * branch).\n *\n * When this happens, we throw away our current state, and do the following prep\n * to re-enter the loop:\n *\n * Pos | Time -->\n * ----+-------------------\n * N   | H T\n * N+1 |  H\n *\n * This is also the work we do at the beginning to enter the loop initially.\n */\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_compressBlock_fast_noDict_generic(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize,\n        U32 const mls, int useCmov)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32* const hashTable = ms->hashTable;\n    U32 const hlog = cParams->hashLog;\n    size_t const stepSize = cParams->targetLength + !(cParams->targetLength) + 1; /* min 2 */\n    const BYTE* const base = ms->window.base;\n    const BYTE* const istart = (const BYTE*)src;\n    const U32   endIndex = (U32)((size_t)(istart - base) + srcSize);\n    const U32   prefixStartIndex = ZSTD_getLowestPrefixIndex(ms, endIndex, cParams->windowLog);\n    const BYTE* const prefixStart = base + prefixStartIndex;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* const ilimit = iend - HASH_READ_SIZE;\n\n    const BYTE* anchor = istart;\n    const BYTE* ip0 = istart;\n    const BYTE* ip1;\n    const BYTE* ip2;\n    const BYTE* ip3;\n    U32 current0;\n\n    U32 rep_offset1 = rep[0];\n    U32 rep_offset2 = rep[1];\n    U32 offsetSaved1 = 0, offsetSaved2 = 0;\n\n    size_t hash0; /* hash for ip0 */\n    size_t hash1; /* hash for ip1 */\n    U32 matchIdx; /* match idx for ip0 */\n\n    U32 offcode;\n    const BYTE* match0;\n    size_t mLength;\n\n    /* ip0 and ip1 are always adjacent. The targetLength skipping and\n     * uncompressibility acceleration is applied to every other position,\n     * matching the behavior of #1562. step therefore represents the gap\n     * between pairs of positions, from ip0 to ip2 or ip1 to ip3. */\n    size_t step;\n    const BYTE* nextStep;\n    const size_t kStepIncr = (1 << (kSearchStrength - 1));\n    const ZSTD_match4Found matchFound = useCmov ? ZSTD_match4Found_cmov : ZSTD_match4Found_branch;\n\n    DEBUGLOG(5, \"ZSTD_compressBlock_fast_generic\");\n    ip0 += (ip0 == prefixStart);\n    {   U32 const curr = (U32)(ip0 - base);\n        U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, curr, cParams->windowLog);\n        U32 const maxRep = curr - windowLow;\n        if (rep_offset2 > maxRep) offsetSaved2 = rep_offset2, rep_offset2 = 0;\n        if (rep_offset1 > maxRep) offsetSaved1 = rep_offset1, rep_offset1 = 0;\n    }\n\n    /* start each op */\n_start: /* Requires: ip0 */\n\n    step = stepSize;\n    nextStep = ip0 + kStepIncr;\n\n    /* calculate positions, ip0 - anchor == 0, so we skip step calc */\n    ip1 = ip0 + 1;\n    ip2 = ip0 + step;\n    ip3 = ip2 + 1;\n\n    if (ip3 >= ilimit) {\n        goto _cleanup;\n    }\n\n    hash0 = ZSTD_hashPtr(ip0, hlog, mls);\n    hash1 = ZSTD_hashPtr(ip1, hlog, mls);\n\n    matchIdx = hashTable[hash0];\n\n    do {\n        /* load repcode match for ip[2]*/\n        const U32 rval = MEM_read32(ip2 - rep_offset1);\n\n        /* write back hash table entry */\n        current0 = (U32)(ip0 - base);\n        hashTable[hash0] = current0;\n\n        /* check repcode at ip[2] */\n        if ((MEM_read32(ip2) == rval) & (rep_offset1 > 0)) {\n            ip0 = ip2;\n            match0 = ip0 - rep_offset1;\n            mLength = ip0[-1] == match0[-1];\n            ip0 -= mLength;\n            match0 -= mLength;\n            offcode = REPCODE1_TO_OFFBASE;\n            mLength += 4;\n\n            /* Write next hash table entry: it's already calculated.\n             * This write is known to be safe because ip1 is before the\n             * repcode (ip2). */\n            hashTable[hash1] = (U32)(ip1 - base);\n\n            goto _match;\n        }\n\n         if (matchFound(ip0, base + matchIdx, matchIdx, prefixStartIndex)) {\n            /* Write next hash table entry (it's already calculated).\n            * This write is known to be safe because the ip1 == ip0 + 1,\n            * so searching will resume after ip1 */\n            hashTable[hash1] = (U32)(ip1 - base);\n\n            goto _offset;\n        }\n\n        /* lookup ip[1] */\n        matchIdx = hashTable[hash1];\n\n        /* hash ip[2] */\n        hash0 = hash1;\n        hash1 = ZSTD_hashPtr(ip2, hlog, mls);\n\n        /* advance to next positions */\n        ip0 = ip1;\n        ip1 = ip2;\n        ip2 = ip3;\n\n        /* write back hash table entry */\n        current0 = (U32)(ip0 - base);\n        hashTable[hash0] = current0;\n\n         if (matchFound(ip0, base + matchIdx, matchIdx, prefixStartIndex)) {\n            /* Write next hash table entry, since it's already calculated */\n            if (step <= 4) {\n                /* Avoid writing an index if it's >= position where search will resume.\n                * The minimum possible match has length 4, so search can resume at ip0 + 4.\n                */\n                hashTable[hash1] = (U32)(ip1 - base);\n            }\n            goto _offset;\n        }\n\n        /* lookup ip[1] */\n        matchIdx = hashTable[hash1];\n\n        /* hash ip[2] */\n        hash0 = hash1;\n        hash1 = ZSTD_hashPtr(ip2, hlog, mls);\n\n        /* advance to next positions */\n        ip0 = ip1;\n        ip1 = ip2;\n        ip2 = ip0 + step;\n        ip3 = ip1 + step;\n\n        /* calculate step */\n        if (ip2 >= nextStep) {\n            step++;\n            PREFETCH_L1(ip1 + 64);\n            PREFETCH_L1(ip1 + 128);\n            nextStep += kStepIncr;\n        }\n    } while (ip3 < ilimit);\n\n_cleanup:\n    /* Note that there are probably still a couple positions one could search.\n     * However, it seems to be a meaningful performance hit to try to search\n     * them. So let's not. */\n\n    /* When the repcodes are outside of the prefix, we set them to zero before the loop.\n     * When the offsets are still zero, we need to restore them after the block to have a correct\n     * repcode history. If only one offset was invalid, it is easy. The tricky case is when both\n     * offsets were invalid. We need to figure out which offset to refill with.\n     *     - If both offsets are zero they are in the same order.\n     *     - If both offsets are non-zero, we won't restore the offsets from `offsetSaved[12]`.\n     *     - If only one is zero, we need to decide which offset to restore.\n     *         - If rep_offset1 is non-zero, then rep_offset2 must be offsetSaved1.\n     *         - It is impossible for rep_offset2 to be non-zero.\n     *\n     * So if rep_offset1 started invalid (offsetSaved1 != 0) and became valid (rep_offset1 != 0), then\n     * set rep[0] = rep_offset1 and rep[1] = offsetSaved1.\n     */\n    offsetSaved2 = ((offsetSaved1 != 0) && (rep_offset1 != 0)) ? offsetSaved1 : offsetSaved2;\n\n    /* save reps for next block */\n    rep[0] = rep_offset1 ? rep_offset1 : offsetSaved1;\n    rep[1] = rep_offset2 ? rep_offset2 : offsetSaved2;\n\n    /* Return the last literals size */\n    return (size_t)(iend - anchor);\n\n_offset: /* Requires: ip0, idx */\n\n    /* Compute the offset code. */\n    match0 = base + matchIdx;\n    rep_offset2 = rep_offset1;\n    rep_offset1 = (U32)(ip0-match0);\n    offcode = OFFSET_TO_OFFBASE(rep_offset1);\n    mLength = 4;\n\n    /* Count the backwards match length. */\n    while (((ip0>anchor) & (match0>prefixStart)) && (ip0[-1] == match0[-1])) {\n        ip0--;\n        match0--;\n        mLength++;\n    }\n\n_match: /* Requires: ip0, match0, offcode */\n\n    /* Count the forward length. */\n    mLength += ZSTD_count(ip0 + mLength, match0 + mLength, iend);\n\n    ZSTD_storeSeq(seqStore, (size_t)(ip0 - anchor), anchor, iend, offcode, mLength);\n\n    ip0 += mLength;\n    anchor = ip0;\n\n    /* Fill table and check for immediate repcode. */\n    if (ip0 <= ilimit) {\n        /* Fill Table */\n        assert(base+current0+2 > istart);  /* check base overflow */\n        hashTable[ZSTD_hashPtr(base+current0+2, hlog, mls)] = current0+2;  /* here because current+2 could be > iend-8 */\n        hashTable[ZSTD_hashPtr(ip0-2, hlog, mls)] = (U32)(ip0-2-base);\n\n        if (rep_offset2 > 0) { /* rep_offset2==0 means rep_offset2 is invalidated */\n            while ( (ip0 <= ilimit) && (MEM_read32(ip0) == MEM_read32(ip0 - rep_offset2)) ) {\n                /* store sequence */\n                size_t const rLength = ZSTD_count(ip0+4, ip0+4-rep_offset2, iend) + 4;\n                { U32 const tmpOff = rep_offset2; rep_offset2 = rep_offset1; rep_offset1 = tmpOff; } /* swap rep_offset2 <=> rep_offset1 */\n                hashTable[ZSTD_hashPtr(ip0, hlog, mls)] = (U32)(ip0-base);\n                ip0 += rLength;\n                ZSTD_storeSeq(seqStore, 0 /*litLen*/, anchor, iend, REPCODE1_TO_OFFBASE, rLength);\n                anchor = ip0;\n                continue;   /* faster when present (confirmed on gcc-8) ... (?) */\n    }   }   }\n\n    goto _start;\n}\n\n#define ZSTD_GEN_FAST_FN(dictMode, mml, cmov)                                                       \\\n    static size_t ZSTD_compressBlock_fast_##dictMode##_##mml##_##cmov(                              \\\n            ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],                    \\\n            void const* src, size_t srcSize)                                                       \\\n    {                                                                                              \\\n        return ZSTD_compressBlock_fast_##dictMode##_generic(ms, seqStore, rep, src, srcSize, mml, cmov); \\\n    }\n\nZSTD_GEN_FAST_FN(noDict, 4, 1)\nZSTD_GEN_FAST_FN(noDict, 5, 1)\nZSTD_GEN_FAST_FN(noDict, 6, 1)\nZSTD_GEN_FAST_FN(noDict, 7, 1)\n\nZSTD_GEN_FAST_FN(noDict, 4, 0)\nZSTD_GEN_FAST_FN(noDict, 5, 0)\nZSTD_GEN_FAST_FN(noDict, 6, 0)\nZSTD_GEN_FAST_FN(noDict, 7, 0)\n\nsize_t ZSTD_compressBlock_fast(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    U32 const mml = ms->cParams.minMatch;\n    /* use cmov when \"candidate in range\" branch is likely unpredictable */\n    int const useCmov = ms->cParams.windowLog < 19;\n    assert(ms->dictMatchState == NULL);\n    if (useCmov) {\n        switch(mml)\n        {\n        default: /* includes case 3 */\n        case 4 :\n            return ZSTD_compressBlock_fast_noDict_4_1(ms, seqStore, rep, src, srcSize);\n        case 5 :\n            return ZSTD_compressBlock_fast_noDict_5_1(ms, seqStore, rep, src, srcSize);\n        case 6 :\n            return ZSTD_compressBlock_fast_noDict_6_1(ms, seqStore, rep, src, srcSize);\n        case 7 :\n            return ZSTD_compressBlock_fast_noDict_7_1(ms, seqStore, rep, src, srcSize);\n        }\n    } else {\n        /* use a branch instead */\n        switch(mml)\n        {\n        default: /* includes case 3 */\n        case 4 :\n            return ZSTD_compressBlock_fast_noDict_4_0(ms, seqStore, rep, src, srcSize);\n        case 5 :\n            return ZSTD_compressBlock_fast_noDict_5_0(ms, seqStore, rep, src, srcSize);\n        case 6 :\n            return ZSTD_compressBlock_fast_noDict_6_0(ms, seqStore, rep, src, srcSize);\n        case 7 :\n            return ZSTD_compressBlock_fast_noDict_7_0(ms, seqStore, rep, src, srcSize);\n        }\n    }\n}\n\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_compressBlock_fast_dictMatchState_generic(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize, U32 const mls, U32 const hasStep)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32* const hashTable = ms->hashTable;\n    U32 const hlog = cParams->hashLog;\n    /* support stepSize of 0 */\n    U32 const stepSize = cParams->targetLength + !(cParams->targetLength);\n    const BYTE* const base = ms->window.base;\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* ip0 = istart;\n    const BYTE* ip1 = ip0 + stepSize; /* we assert below that stepSize >= 1 */\n    const BYTE* anchor = istart;\n    const U32   prefixStartIndex = ms->window.dictLimit;\n    const BYTE* const prefixStart = base + prefixStartIndex;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* const ilimit = iend - HASH_READ_SIZE;\n    U32 offset_1=rep[0], offset_2=rep[1];\n\n    const ZSTD_MatchState_t* const dms = ms->dictMatchState;\n    const ZSTD_compressionParameters* const dictCParams = &dms->cParams ;\n    const U32* const dictHashTable = dms->hashTable;\n    const U32 dictStartIndex       = dms->window.dictLimit;\n    const BYTE* const dictBase     = dms->window.base;\n    const BYTE* const dictStart    = dictBase + dictStartIndex;\n    const BYTE* const dictEnd      = dms->window.nextSrc;\n    const U32 dictIndexDelta       = prefixStartIndex - (U32)(dictEnd - dictBase);\n    const U32 dictAndPrefixLength  = (U32)(istart - prefixStart + dictEnd - dictStart);\n    const U32 dictHBits            = dictCParams->hashLog + ZSTD_SHORT_CACHE_TAG_BITS;\n\n    /* if a dictionary is still attached, it necessarily means that\n     * it is within window size. So we just check it. */\n    const U32 maxDistance = 1U << cParams->windowLog;\n    const U32 endIndex = (U32)((size_t)(istart - base) + srcSize);\n    assert(endIndex - prefixStartIndex <= maxDistance);\n    (void)maxDistance; (void)endIndex;   /* these variables are not used when assert() is disabled */\n\n    (void)hasStep; /* not currently specialized on whether it's accelerated */\n\n    /* ensure there will be no underflow\n     * when translating a dict index into a local index */\n    assert(prefixStartIndex >= (U32)(dictEnd - dictBase));\n\n    if (ms->prefetchCDictTables) {\n        size_t const hashTableBytes = (((size_t)1) << dictCParams->hashLog) * sizeof(U32);\n        PREFETCH_AREA(dictHashTable, hashTableBytes);\n    }\n\n    /* init */\n    DEBUGLOG(5, \"ZSTD_compressBlock_fast_dictMatchState_generic\");\n    ip0 += (dictAndPrefixLength == 0);\n    /* dictMatchState repCode checks don't currently handle repCode == 0\n     * disabling. */\n    assert(offset_1 <= dictAndPrefixLength);\n    assert(offset_2 <= dictAndPrefixLength);\n\n    /* Outer search loop */\n    assert(stepSize >= 1);\n    while (ip1 <= ilimit) {   /* repcode check at (ip0 + 1) is safe because ip0 < ip1 */\n        size_t mLength;\n        size_t hash0 = ZSTD_hashPtr(ip0, hlog, mls);\n\n        size_t const dictHashAndTag0 = ZSTD_hashPtr(ip0, dictHBits, mls);\n        U32 dictMatchIndexAndTag = dictHashTable[dictHashAndTag0 >> ZSTD_SHORT_CACHE_TAG_BITS];\n        int dictTagsMatch = ZSTD_comparePackedTags(dictMatchIndexAndTag, dictHashAndTag0);\n\n        U32 matchIndex = hashTable[hash0];\n        U32 curr = (U32)(ip0 - base);\n        size_t step = stepSize;\n        const size_t kStepIncr = 1 << kSearchStrength;\n        const BYTE* nextStep = ip0 + kStepIncr;\n\n        /* Inner search loop */\n        while (1) {\n            const BYTE* match = base + matchIndex;\n            const U32 repIndex = curr + 1 - offset_1;\n            const BYTE* repMatch = (repIndex < prefixStartIndex) ?\n                                   dictBase + (repIndex - dictIndexDelta) :\n                                   base + repIndex;\n            const size_t hash1 = ZSTD_hashPtr(ip1, hlog, mls);\n            size_t const dictHashAndTag1 = ZSTD_hashPtr(ip1, dictHBits, mls);\n            hashTable[hash0] = curr;   /* update hash table */\n\n            if ((ZSTD_index_overlap_check(prefixStartIndex, repIndex))\n                && (MEM_read32(repMatch) == MEM_read32(ip0 + 1))) {\n                const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;\n                mLength = ZSTD_count_2segments(ip0 + 1 + 4, repMatch + 4, iend, repMatchEnd, prefixStart) + 4;\n                ip0++;\n                ZSTD_storeSeq(seqStore, (size_t) (ip0 - anchor), anchor, iend, REPCODE1_TO_OFFBASE, mLength);\n                break;\n            }\n\n            if (dictTagsMatch) {\n                /* Found a possible dict match */\n                const U32 dictMatchIndex = dictMatchIndexAndTag >> ZSTD_SHORT_CACHE_TAG_BITS;\n                const BYTE* dictMatch = dictBase + dictMatchIndex;\n                if (dictMatchIndex > dictStartIndex &&\n                    MEM_read32(dictMatch) == MEM_read32(ip0)) {\n                    /* To replicate extDict parse behavior, we only use dict matches when the normal matchIndex is invalid */\n                    if (matchIndex <= prefixStartIndex) {\n                        U32 const offset = (U32) (curr - dictMatchIndex - dictIndexDelta);\n                        mLength = ZSTD_count_2segments(ip0 + 4, dictMatch + 4, iend, dictEnd, prefixStart) + 4;\n                        while (((ip0 > anchor) & (dictMatch > dictStart))\n                            && (ip0[-1] == dictMatch[-1])) {\n                            ip0--;\n                            dictMatch--;\n                            mLength++;\n                        } /* catch up */\n                        offset_2 = offset_1;\n                        offset_1 = offset;\n                        ZSTD_storeSeq(seqStore, (size_t) (ip0 - anchor), anchor, iend, OFFSET_TO_OFFBASE(offset), mLength);\n                        break;\n                    }\n                }\n            }\n\n            if (ZSTD_match4Found_cmov(ip0, match, matchIndex, prefixStartIndex)) {\n                /* found a regular match of size >= 4 */\n                U32 const offset = (U32) (ip0 - match);\n                mLength = ZSTD_count(ip0 + 4, match + 4, iend) + 4;\n                while (((ip0 > anchor) & (match > prefixStart))\n                       && (ip0[-1] == match[-1])) {\n                    ip0--;\n                    match--;\n                    mLength++;\n                } /* catch up */\n                offset_2 = offset_1;\n                offset_1 = offset;\n                ZSTD_storeSeq(seqStore, (size_t) (ip0 - anchor), anchor, iend, OFFSET_TO_OFFBASE(offset), mLength);\n                break;\n            }\n\n            /* Prepare for next iteration */\n            dictMatchIndexAndTag = dictHashTable[dictHashAndTag1 >> ZSTD_SHORT_CACHE_TAG_BITS];\n            dictTagsMatch = ZSTD_comparePackedTags(dictMatchIndexAndTag, dictHashAndTag1);\n            matchIndex = hashTable[hash1];\n\n            if (ip1 >= nextStep) {\n                step++;\n                nextStep += kStepIncr;\n            }\n            ip0 = ip1;\n            ip1 = ip1 + step;\n            if (ip1 > ilimit) goto _cleanup;\n\n            curr = (U32)(ip0 - base);\n            hash0 = hash1;\n        }   /* end inner search loop */\n\n        /* match found */\n        assert(mLength);\n        ip0 += mLength;\n        anchor = ip0;\n\n        if (ip0 <= ilimit) {\n            /* Fill Table */\n            assert(base+curr+2 > istart);  /* check base overflow */\n            hashTable[ZSTD_hashPtr(base+curr+2, hlog, mls)] = curr+2;  /* here because curr+2 could be > iend-8 */\n            hashTable[ZSTD_hashPtr(ip0-2, hlog, mls)] = (U32)(ip0-2-base);\n\n            /* check immediate repcode */\n            while (ip0 <= ilimit) {\n                U32 const current2 = (U32)(ip0-base);\n                U32 const repIndex2 = current2 - offset_2;\n                const BYTE* repMatch2 = repIndex2 < prefixStartIndex ?\n                        dictBase - dictIndexDelta + repIndex2 :\n                        base + repIndex2;\n                if ( (ZSTD_index_overlap_check(prefixStartIndex, repIndex2))\n                   && (MEM_read32(repMatch2) == MEM_read32(ip0))) {\n                    const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;\n                    size_t const repLength2 = ZSTD_count_2segments(ip0+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;\n                    U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset;   /* swap offset_2 <=> offset_1 */\n                    ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, repLength2);\n                    hashTable[ZSTD_hashPtr(ip0, hlog, mls)] = current2;\n                    ip0 += repLength2;\n                    anchor = ip0;\n                    continue;\n                }\n                break;\n            }\n        }\n\n        /* Prepare for next iteration */\n        assert(ip0 == anchor);\n        ip1 = ip0 + stepSize;\n    }\n\n_cleanup:\n    /* save reps for next block */\n    rep[0] = offset_1;\n    rep[1] = offset_2;\n\n    /* Return the last literals size */\n    return (size_t)(iend - anchor);\n}\n\n\nZSTD_GEN_FAST_FN(dictMatchState, 4, 0)\nZSTD_GEN_FAST_FN(dictMatchState, 5, 0)\nZSTD_GEN_FAST_FN(dictMatchState, 6, 0)\nZSTD_GEN_FAST_FN(dictMatchState, 7, 0)\n\nsize_t ZSTD_compressBlock_fast_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    U32 const mls = ms->cParams.minMatch;\n    assert(ms->dictMatchState != NULL);\n    switch(mls)\n    {\n    default: /* includes case 3 */\n    case 4 :\n        return ZSTD_compressBlock_fast_dictMatchState_4_0(ms, seqStore, rep, src, srcSize);\n    case 5 :\n        return ZSTD_compressBlock_fast_dictMatchState_5_0(ms, seqStore, rep, src, srcSize);\n    case 6 :\n        return ZSTD_compressBlock_fast_dictMatchState_6_0(ms, seqStore, rep, src, srcSize);\n    case 7 :\n        return ZSTD_compressBlock_fast_dictMatchState_7_0(ms, seqStore, rep, src, srcSize);\n    }\n}\n\n\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_compressBlock_fast_extDict_generic(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize, U32 const mls, U32 const hasStep)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32* const hashTable = ms->hashTable;\n    U32 const hlog = cParams->hashLog;\n    /* support stepSize of 0 */\n    size_t const stepSize = cParams->targetLength + !(cParams->targetLength) + 1;\n    const BYTE* const base = ms->window.base;\n    const BYTE* const dictBase = ms->window.dictBase;\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* anchor = istart;\n    const U32   endIndex = (U32)((size_t)(istart - base) + srcSize);\n    const U32   lowLimit = ZSTD_getLowestMatchIndex(ms, endIndex, cParams->windowLog);\n    const U32   dictStartIndex = lowLimit;\n    const BYTE* const dictStart = dictBase + dictStartIndex;\n    const U32   dictLimit = ms->window.dictLimit;\n    const U32   prefixStartIndex = dictLimit < lowLimit ? lowLimit : dictLimit;\n    const BYTE* const prefixStart = base + prefixStartIndex;\n    const BYTE* const dictEnd = dictBase + prefixStartIndex;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* const ilimit = iend - 8;\n    U32 offset_1=rep[0], offset_2=rep[1];\n    U32 offsetSaved1 = 0, offsetSaved2 = 0;\n\n    const BYTE* ip0 = istart;\n    const BYTE* ip1;\n    const BYTE* ip2;\n    const BYTE* ip3;\n    U32 current0;\n\n\n    size_t hash0; /* hash for ip0 */\n    size_t hash1; /* hash for ip1 */\n    U32 idx; /* match idx for ip0 */\n    const BYTE* idxBase; /* base pointer for idx */\n\n    U32 offcode;\n    const BYTE* match0;\n    size_t mLength;\n    const BYTE* matchEnd = 0; /* initialize to avoid warning, assert != 0 later */\n\n    size_t step;\n    const BYTE* nextStep;\n    const size_t kStepIncr = (1 << (kSearchStrength - 1));\n\n    (void)hasStep; /* not currently specialized on whether it's accelerated */\n\n    DEBUGLOG(5, \"ZSTD_compressBlock_fast_extDict_generic (offset_1=%u)\", offset_1);\n\n    /* switch to \"regular\" variant if extDict is invalidated due to maxDistance */\n    if (prefixStartIndex == dictStartIndex)\n        return ZSTD_compressBlock_fast(ms, seqStore, rep, src, srcSize);\n\n    {   U32 const curr = (U32)(ip0 - base);\n        U32 const maxRep = curr - dictStartIndex;\n        if (offset_2 >= maxRep) offsetSaved2 = offset_2, offset_2 = 0;\n        if (offset_1 >= maxRep) offsetSaved1 = offset_1, offset_1 = 0;\n    }\n\n    /* start each op */\n_start: /* Requires: ip0 */\n\n    step = stepSize;\n    nextStep = ip0 + kStepIncr;\n\n    /* calculate positions, ip0 - anchor == 0, so we skip step calc */\n    ip1 = ip0 + 1;\n    ip2 = ip0 + step;\n    ip3 = ip2 + 1;\n\n    if (ip3 >= ilimit) {\n        goto _cleanup;\n    }\n\n    hash0 = ZSTD_hashPtr(ip0, hlog, mls);\n    hash1 = ZSTD_hashPtr(ip1, hlog, mls);\n\n    idx = hashTable[hash0];\n    idxBase = idx < prefixStartIndex ? dictBase : base;\n\n    do {\n        {   /* load repcode match for ip[2] */\n            U32 const current2 = (U32)(ip2 - base);\n            U32 const repIndex = current2 - offset_1;\n            const BYTE* const repBase = repIndex < prefixStartIndex ? dictBase : base;\n            U32 rval;\n            if ( ((U32)(prefixStartIndex - repIndex) >= 4) /* intentional underflow */\n                 & (offset_1 > 0) ) {\n                rval = MEM_read32(repBase + repIndex);\n            } else {\n                rval = MEM_read32(ip2) ^ 1; /* guaranteed to not match. */\n            }\n\n            /* write back hash table entry */\n            current0 = (U32)(ip0 - base);\n            hashTable[hash0] = current0;\n\n            /* check repcode at ip[2] */\n            if (MEM_read32(ip2) == rval) {\n                ip0 = ip2;\n                match0 = repBase + repIndex;\n                matchEnd = repIndex < prefixStartIndex ? dictEnd : iend;\n                assert((match0 != prefixStart) & (match0 != dictStart));\n                mLength = ip0[-1] == match0[-1];\n                ip0 -= mLength;\n                match0 -= mLength;\n                offcode = REPCODE1_TO_OFFBASE;\n                mLength += 4;\n                goto _match;\n        }   }\n\n        {   /* load match for ip[0] */\n            U32 const mval = idx >= dictStartIndex ?\n                    MEM_read32(idxBase + idx) :\n                    MEM_read32(ip0) ^ 1; /* guaranteed not to match */\n\n            /* check match at ip[0] */\n            if (MEM_read32(ip0) == mval) {\n                /* found a match! */\n                goto _offset;\n        }   }\n\n        /* lookup ip[1] */\n        idx = hashTable[hash1];\n        idxBase = idx < prefixStartIndex ? dictBase : base;\n\n        /* hash ip[2] */\n        hash0 = hash1;\n        hash1 = ZSTD_hashPtr(ip2, hlog, mls);\n\n        /* advance to next positions */\n        ip0 = ip1;\n        ip1 = ip2;\n        ip2 = ip3;\n\n        /* write back hash table entry */\n        current0 = (U32)(ip0 - base);\n        hashTable[hash0] = current0;\n\n        {   /* load match for ip[0] */\n            U32 const mval = idx >= dictStartIndex ?\n                    MEM_read32(idxBase + idx) :\n                    MEM_read32(ip0) ^ 1; /* guaranteed not to match */\n\n            /* check match at ip[0] */\n            if (MEM_read32(ip0) == mval) {\n                /* found a match! */\n                goto _offset;\n        }   }\n\n        /* lookup ip[1] */\n        idx = hashTable[hash1];\n        idxBase = idx < prefixStartIndex ? dictBase : base;\n\n        /* hash ip[2] */\n        hash0 = hash1;\n        hash1 = ZSTD_hashPtr(ip2, hlog, mls);\n\n        /* advance to next positions */\n        ip0 = ip1;\n        ip1 = ip2;\n        ip2 = ip0 + step;\n        ip3 = ip1 + step;\n\n        /* calculate step */\n        if (ip2 >= nextStep) {\n            step++;\n            PREFETCH_L1(ip1 + 64);\n            PREFETCH_L1(ip1 + 128);\n            nextStep += kStepIncr;\n        }\n    } while (ip3 < ilimit);\n\n_cleanup:\n    /* Note that there are probably still a couple positions we could search.\n     * However, it seems to be a meaningful performance hit to try to search\n     * them. So let's not. */\n\n    /* If offset_1 started invalid (offsetSaved1 != 0) and became valid (offset_1 != 0),\n     * rotate saved offsets. See comment in ZSTD_compressBlock_fast_noDict for more context. */\n    offsetSaved2 = ((offsetSaved1 != 0) && (offset_1 != 0)) ? offsetSaved1 : offsetSaved2;\n\n    /* save reps for next block */\n    rep[0] = offset_1 ? offset_1 : offsetSaved1;\n    rep[1] = offset_2 ? offset_2 : offsetSaved2;\n\n    /* Return the last literals size */\n    return (size_t)(iend - anchor);\n\n_offset: /* Requires: ip0, idx, idxBase */\n\n    /* Compute the offset code. */\n    {   U32 const offset = current0 - idx;\n        const BYTE* const lowMatchPtr = idx < prefixStartIndex ? dictStart : prefixStart;\n        matchEnd = idx < prefixStartIndex ? dictEnd : iend;\n        match0 = idxBase + idx;\n        offset_2 = offset_1;\n        offset_1 = offset;\n        offcode = OFFSET_TO_OFFBASE(offset);\n        mLength = 4;\n\n        /* Count the backwards match length. */\n        while (((ip0>anchor) & (match0>lowMatchPtr)) && (ip0[-1] == match0[-1])) {\n            ip0--;\n            match0--;\n            mLength++;\n    }   }\n\n_match: /* Requires: ip0, match0, offcode, matchEnd */\n\n    /* Count the forward length. */\n    assert(matchEnd != 0);\n    mLength += ZSTD_count_2segments(ip0 + mLength, match0 + mLength, iend, matchEnd, prefixStart);\n\n    ZSTD_storeSeq(seqStore, (size_t)(ip0 - anchor), anchor, iend, offcode, mLength);\n\n    ip0 += mLength;\n    anchor = ip0;\n\n    /* write next hash table entry */\n    if (ip1 < ip0) {\n        hashTable[hash1] = (U32)(ip1 - base);\n    }\n\n    /* Fill table and check for immediate repcode. */\n    if (ip0 <= ilimit) {\n        /* Fill Table */\n        assert(base+current0+2 > istart);  /* check base overflow */\n        hashTable[ZSTD_hashPtr(base+current0+2, hlog, mls)] = current0+2;  /* here because current+2 could be > iend-8 */\n        hashTable[ZSTD_hashPtr(ip0-2, hlog, mls)] = (U32)(ip0-2-base);\n\n        while (ip0 <= ilimit) {\n            U32 const repIndex2 = (U32)(ip0-base) - offset_2;\n            const BYTE* const repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2;\n            if ( ((ZSTD_index_overlap_check(prefixStartIndex, repIndex2)) & (offset_2 > 0))\n                 && (MEM_read32(repMatch2) == MEM_read32(ip0)) ) {\n                const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;\n                size_t const repLength2 = ZSTD_count_2segments(ip0+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;\n                { U32 const tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; }  /* swap offset_2 <=> offset_1 */\n                ZSTD_storeSeq(seqStore, 0 /*litlen*/, anchor, iend, REPCODE1_TO_OFFBASE, repLength2);\n                hashTable[ZSTD_hashPtr(ip0, hlog, mls)] = (U32)(ip0-base);\n                ip0 += repLength2;\n                anchor = ip0;\n                continue;\n            }\n            break;\n    }   }\n\n    goto _start;\n}\n\nZSTD_GEN_FAST_FN(extDict, 4, 0)\nZSTD_GEN_FAST_FN(extDict, 5, 0)\nZSTD_GEN_FAST_FN(extDict, 6, 0)\nZSTD_GEN_FAST_FN(extDict, 7, 0)\n\nsize_t ZSTD_compressBlock_fast_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    U32 const mls = ms->cParams.minMatch;\n    assert(ms->dictMatchState == NULL);\n    switch(mls)\n    {\n    default: /* includes case 3 */\n    case 4 :\n        return ZSTD_compressBlock_fast_extDict_4_0(ms, seqStore, rep, src, srcSize);\n    case 5 :\n        return ZSTD_compressBlock_fast_extDict_5_0(ms, seqStore, rep, src, srcSize);\n    case 6 :\n        return ZSTD_compressBlock_fast_extDict_6_0(ms, seqStore, rep, src, srcSize);\n    case 7 :\n        return ZSTD_compressBlock_fast_extDict_7_0(ms, seqStore, rep, src, srcSize);\n    }\n}\n"
  },
  {
    "path": "lib/compress/zstd_fast.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_FAST_H\n#define ZSTD_FAST_H\n\n#include \"../common/mem.h\"      /* U32 */\n#include \"zstd_compress_internal.h\"\n\nvoid ZSTD_fillHashTable(ZSTD_MatchState_t* ms,\n                        void const* end, ZSTD_dictTableLoadMethod_e dtlm,\n                        ZSTD_tableFillPurpose_e tfp);\nsize_t ZSTD_compressBlock_fast(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_fast_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_fast_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\n\n#endif /* ZSTD_FAST_H */\n"
  },
  {
    "path": "lib/compress/zstd_lazy.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"zstd_compress_internal.h\"\n#include \"zstd_lazy.h\"\n#include \"../common/bits.h\" /* ZSTD_countTrailingZeros64 */\n\n#if !defined(ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR)\n\n#define kLazySkippingStep 8\n\n\n/*-*************************************\n*  Binary Tree search\n***************************************/\n\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_updateDUBT(ZSTD_MatchState_t* ms,\n                const BYTE* ip, const BYTE* iend,\n                U32 mls)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32* const hashTable = ms->hashTable;\n    U32  const hashLog = cParams->hashLog;\n\n    U32* const bt = ms->chainTable;\n    U32  const btLog  = cParams->chainLog - 1;\n    U32  const btMask = (1 << btLog) - 1;\n\n    const BYTE* const base = ms->window.base;\n    U32 const target = (U32)(ip - base);\n    U32 idx = ms->nextToUpdate;\n\n    if (idx != target)\n        DEBUGLOG(7, \"ZSTD_updateDUBT, from %u to %u (dictLimit:%u)\",\n                    idx, target, ms->window.dictLimit);\n    assert(ip + 8 <= iend);   /* condition for ZSTD_hashPtr */\n    (void)iend;\n\n    assert(idx >= ms->window.dictLimit);   /* condition for valid base+idx */\n    for ( ; idx < target ; idx++) {\n        size_t const h  = ZSTD_hashPtr(base + idx, hashLog, mls);   /* assumption : ip + 8 <= iend */\n        U32    const matchIndex = hashTable[h];\n\n        U32*   const nextCandidatePtr = bt + 2*(idx&btMask);\n        U32*   const sortMarkPtr  = nextCandidatePtr + 1;\n\n        DEBUGLOG(8, \"ZSTD_updateDUBT: insert %u\", idx);\n        hashTable[h] = idx;   /* Update Hash Table */\n        *nextCandidatePtr = matchIndex;   /* update BT like a chain */\n        *sortMarkPtr = ZSTD_DUBT_UNSORTED_MARK;\n    }\n    ms->nextToUpdate = target;\n}\n\n\n/** ZSTD_insertDUBT1() :\n *  sort one already inserted but unsorted position\n *  assumption : curr >= btlow == (curr - btmask)\n *  doesn't fail */\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_insertDUBT1(const ZSTD_MatchState_t* ms,\n                 U32 curr, const BYTE* inputEnd,\n                 U32 nbCompares, U32 btLow,\n                 const ZSTD_dictMode_e dictMode)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32* const bt = ms->chainTable;\n    U32  const btLog  = cParams->chainLog - 1;\n    U32  const btMask = (1 << btLog) - 1;\n    size_t commonLengthSmaller=0, commonLengthLarger=0;\n    const BYTE* const base = ms->window.base;\n    const BYTE* const dictBase = ms->window.dictBase;\n    const U32 dictLimit = ms->window.dictLimit;\n    const BYTE* const ip = (curr>=dictLimit) ? base + curr : dictBase + curr;\n    const BYTE* const iend = (curr>=dictLimit) ? inputEnd : dictBase + dictLimit;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    const BYTE* const prefixStart = base + dictLimit;\n    const BYTE* match;\n    U32* smallerPtr = bt + 2*(curr&btMask);\n    U32* largerPtr  = smallerPtr + 1;\n    U32 matchIndex = *smallerPtr;   /* this candidate is unsorted : next sorted candidate is reached through *smallerPtr, while *largerPtr contains previous unsorted candidate (which is already saved and can be overwritten) */\n    U32 dummy32;   /* to be nullified at the end */\n    U32 const windowValid = ms->window.lowLimit;\n    U32 const maxDistance = 1U << cParams->windowLog;\n    U32 const windowLow = (curr - windowValid > maxDistance) ? curr - maxDistance : windowValid;\n\n\n    DEBUGLOG(8, \"ZSTD_insertDUBT1(%u) (dictLimit=%u, lowLimit=%u)\",\n                curr, dictLimit, windowLow);\n    assert(curr >= btLow);\n    assert(ip < iend);   /* condition for ZSTD_count */\n\n    for (; nbCompares && (matchIndex > windowLow); --nbCompares) {\n        U32* const nextPtr = bt + 2*(matchIndex & btMask);\n        size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger);   /* guaranteed minimum nb of common bytes */\n        assert(matchIndex < curr);\n        /* note : all candidates are now supposed sorted,\n         * but it's still possible to have nextPtr[1] == ZSTD_DUBT_UNSORTED_MARK\n         * when a real index has the same value as ZSTD_DUBT_UNSORTED_MARK */\n\n        if ( (dictMode != ZSTD_extDict)\n          || (matchIndex+matchLength >= dictLimit)  /* both in current segment*/\n          || (curr < dictLimit) /* both in extDict */) {\n            const BYTE* const mBase = ( (dictMode != ZSTD_extDict)\n                                     || (matchIndex+matchLength >= dictLimit)) ?\n                                        base : dictBase;\n            assert( (matchIndex+matchLength >= dictLimit)   /* might be wrong if extDict is incorrectly set to 0 */\n                 || (curr < dictLimit) );\n            match = mBase + matchIndex;\n            matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend);\n        } else {\n            match = dictBase + matchIndex;\n            matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);\n            if (matchIndex+matchLength >= dictLimit)\n                match = base + matchIndex;   /* preparation for next read of match[matchLength] */\n        }\n\n        DEBUGLOG(8, \"ZSTD_insertDUBT1: comparing %u with %u : found %u common bytes \",\n                    curr, matchIndex, (U32)matchLength);\n\n        if (ip+matchLength == iend) {   /* equal : no way to know if inf or sup */\n            break;   /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt tree */\n        }\n\n        if (match[matchLength] < ip[matchLength]) {  /* necessarily within buffer */\n            /* match is smaller than current */\n            *smallerPtr = matchIndex;             /* update smaller idx */\n            commonLengthSmaller = matchLength;    /* all smaller will now have at least this guaranteed common length */\n            if (matchIndex <= btLow) { smallerPtr=&dummy32; break; }   /* beyond tree size, stop searching */\n            DEBUGLOG(8, \"ZSTD_insertDUBT1: %u (>btLow=%u) is smaller : next => %u\",\n                        matchIndex, btLow, nextPtr[1]);\n            smallerPtr = nextPtr+1;               /* new \"candidate\" => larger than match, which was smaller than target */\n            matchIndex = nextPtr[1];              /* new matchIndex, larger than previous and closer to current */\n        } else {\n            /* match is larger than current */\n            *largerPtr = matchIndex;\n            commonLengthLarger = matchLength;\n            if (matchIndex <= btLow) { largerPtr=&dummy32; break; }   /* beyond tree size, stop searching */\n            DEBUGLOG(8, \"ZSTD_insertDUBT1: %u (>btLow=%u) is larger => %u\",\n                        matchIndex, btLow, nextPtr[0]);\n            largerPtr = nextPtr;\n            matchIndex = nextPtr[0];\n    }   }\n\n    *smallerPtr = *largerPtr = 0;\n}\n\n\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_DUBT_findBetterDictMatch (\n        const ZSTD_MatchState_t* ms,\n        const BYTE* const ip, const BYTE* const iend,\n        size_t* offsetPtr,\n        size_t bestLength,\n        U32 nbCompares,\n        U32 const mls,\n        const ZSTD_dictMode_e dictMode)\n{\n    const ZSTD_MatchState_t * const dms = ms->dictMatchState;\n    const ZSTD_compressionParameters* const dmsCParams = &dms->cParams;\n    const U32 * const dictHashTable = dms->hashTable;\n    U32         const hashLog = dmsCParams->hashLog;\n    size_t      const h  = ZSTD_hashPtr(ip, hashLog, mls);\n    U32               dictMatchIndex = dictHashTable[h];\n\n    const BYTE* const base = ms->window.base;\n    const BYTE* const prefixStart = base + ms->window.dictLimit;\n    U32         const curr = (U32)(ip-base);\n    const BYTE* const dictBase = dms->window.base;\n    const BYTE* const dictEnd = dms->window.nextSrc;\n    U32         const dictHighLimit = (U32)(dms->window.nextSrc - dms->window.base);\n    U32         const dictLowLimit = dms->window.lowLimit;\n    U32         const dictIndexDelta = ms->window.lowLimit - dictHighLimit;\n\n    U32*        const dictBt = dms->chainTable;\n    U32         const btLog  = dmsCParams->chainLog - 1;\n    U32         const btMask = (1 << btLog) - 1;\n    U32         const btLow = (btMask >= dictHighLimit - dictLowLimit) ? dictLowLimit : dictHighLimit - btMask;\n\n    size_t commonLengthSmaller=0, commonLengthLarger=0;\n\n    (void)dictMode;\n    assert(dictMode == ZSTD_dictMatchState);\n\n    for (; nbCompares && (dictMatchIndex > dictLowLimit); --nbCompares) {\n        U32* const nextPtr = dictBt + 2*(dictMatchIndex & btMask);\n        size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger);   /* guaranteed minimum nb of common bytes */\n        const BYTE* match = dictBase + dictMatchIndex;\n        matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);\n        if (dictMatchIndex+matchLength >= dictHighLimit)\n            match = base + dictMatchIndex + dictIndexDelta;   /* to prepare for next usage of match[matchLength] */\n\n        if (matchLength > bestLength) {\n            U32 matchIndex = dictMatchIndex + dictIndexDelta;\n            if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(curr-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) ) {\n                DEBUGLOG(9, \"ZSTD_DUBT_findBetterDictMatch(%u) : found better match length %u -> %u and offsetCode %u -> %u (dictMatchIndex %u, matchIndex %u)\",\n                    curr, (U32)bestLength, (U32)matchLength, (U32)*offsetPtr, OFFSET_TO_OFFBASE(curr - matchIndex), dictMatchIndex, matchIndex);\n                bestLength = matchLength, *offsetPtr = OFFSET_TO_OFFBASE(curr - matchIndex);\n            }\n            if (ip+matchLength == iend) {   /* reached end of input : ip[matchLength] is not valid, no way to know if it's larger or smaller than match */\n                break;   /* drop, to guarantee consistency (miss a little bit of compression) */\n            }\n        }\n\n        if (match[matchLength] < ip[matchLength]) {\n            if (dictMatchIndex <= btLow) { break; }   /* beyond tree size, stop the search */\n            commonLengthSmaller = matchLength;    /* all smaller will now have at least this guaranteed common length */\n            dictMatchIndex = nextPtr[1];              /* new matchIndex larger than previous (closer to current) */\n        } else {\n            /* match is larger than current */\n            if (dictMatchIndex <= btLow) { break; }   /* beyond tree size, stop the search */\n            commonLengthLarger = matchLength;\n            dictMatchIndex = nextPtr[0];\n        }\n    }\n\n    if (bestLength >= MINMATCH) {\n        U32 const mIndex = curr - (U32)OFFBASE_TO_OFFSET(*offsetPtr); (void)mIndex;\n        DEBUGLOG(8, \"ZSTD_DUBT_findBetterDictMatch(%u) : found match of length %u and offsetCode %u (pos %u)\",\n                    curr, (U32)bestLength, (U32)*offsetPtr, mIndex);\n    }\n    return bestLength;\n\n}\n\n\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_DUBT_findBestMatch(ZSTD_MatchState_t* ms,\n                        const BYTE* const ip, const BYTE* const iend,\n                        size_t* offBasePtr,\n                        U32 const mls,\n                        const ZSTD_dictMode_e dictMode)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32*   const hashTable = ms->hashTable;\n    U32    const hashLog = cParams->hashLog;\n    size_t const h  = ZSTD_hashPtr(ip, hashLog, mls);\n    U32          matchIndex  = hashTable[h];\n\n    const BYTE* const base = ms->window.base;\n    U32    const curr = (U32)(ip-base);\n    U32    const windowLow = ZSTD_getLowestMatchIndex(ms, curr, cParams->windowLog);\n\n    U32*   const bt = ms->chainTable;\n    U32    const btLog  = cParams->chainLog - 1;\n    U32    const btMask = (1 << btLog) - 1;\n    U32    const btLow = (btMask >= curr) ? 0 : curr - btMask;\n    U32    const unsortLimit = MAX(btLow, windowLow);\n\n    U32*         nextCandidate = bt + 2*(matchIndex&btMask);\n    U32*         unsortedMark = bt + 2*(matchIndex&btMask) + 1;\n    U32          nbCompares = 1U << cParams->searchLog;\n    U32          nbCandidates = nbCompares;\n    U32          previousCandidate = 0;\n\n    DEBUGLOG(7, \"ZSTD_DUBT_findBestMatch (%u) \", curr);\n    assert(ip <= iend-8);   /* required for h calculation */\n    assert(dictMode != ZSTD_dedicatedDictSearch);\n\n    /* reach end of unsorted candidates list */\n    while ( (matchIndex > unsortLimit)\n         && (*unsortedMark == ZSTD_DUBT_UNSORTED_MARK)\n         && (nbCandidates > 1) ) {\n        DEBUGLOG(8, \"ZSTD_DUBT_findBestMatch: candidate %u is unsorted\",\n                    matchIndex);\n        *unsortedMark = previousCandidate;  /* the unsortedMark becomes a reversed chain, to move up back to original position */\n        previousCandidate = matchIndex;\n        matchIndex = *nextCandidate;\n        nextCandidate = bt + 2*(matchIndex&btMask);\n        unsortedMark = bt + 2*(matchIndex&btMask) + 1;\n        nbCandidates --;\n    }\n\n    /* nullify last candidate if it's still unsorted\n     * simplification, detrimental to compression ratio, beneficial for speed */\n    if ( (matchIndex > unsortLimit)\n      && (*unsortedMark==ZSTD_DUBT_UNSORTED_MARK) ) {\n        DEBUGLOG(7, \"ZSTD_DUBT_findBestMatch: nullify last unsorted candidate %u\",\n                    matchIndex);\n        *nextCandidate = *unsortedMark = 0;\n    }\n\n    /* batch sort stacked candidates */\n    matchIndex = previousCandidate;\n    while (matchIndex) {  /* will end on matchIndex == 0 */\n        U32* const nextCandidateIdxPtr = bt + 2*(matchIndex&btMask) + 1;\n        U32 const nextCandidateIdx = *nextCandidateIdxPtr;\n        ZSTD_insertDUBT1(ms, matchIndex, iend,\n                         nbCandidates, unsortLimit, dictMode);\n        matchIndex = nextCandidateIdx;\n        nbCandidates++;\n    }\n\n    /* find longest match */\n    {   size_t commonLengthSmaller = 0, commonLengthLarger = 0;\n        const BYTE* const dictBase = ms->window.dictBase;\n        const U32 dictLimit = ms->window.dictLimit;\n        const BYTE* const dictEnd = dictBase + dictLimit;\n        const BYTE* const prefixStart = base + dictLimit;\n        U32* smallerPtr = bt + 2*(curr&btMask);\n        U32* largerPtr  = bt + 2*(curr&btMask) + 1;\n        U32 matchEndIdx = curr + 8 + 1;\n        U32 dummy32;   /* to be nullified at the end */\n        size_t bestLength = 0;\n\n        matchIndex  = hashTable[h];\n        hashTable[h] = curr;   /* Update Hash Table */\n\n        for (; nbCompares && (matchIndex > windowLow); --nbCompares) {\n            U32* const nextPtr = bt + 2*(matchIndex & btMask);\n            size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger);   /* guaranteed minimum nb of common bytes */\n            const BYTE* match;\n\n            if ((dictMode != ZSTD_extDict) || (matchIndex+matchLength >= dictLimit)) {\n                match = base + matchIndex;\n                matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend);\n            } else {\n                match = dictBase + matchIndex;\n                matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);\n                if (matchIndex+matchLength >= dictLimit)\n                    match = base + matchIndex;   /* to prepare for next usage of match[matchLength] */\n            }\n\n            if (matchLength > bestLength) {\n                if (matchLength > matchEndIdx - matchIndex)\n                    matchEndIdx = matchIndex + (U32)matchLength;\n                if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(curr - matchIndex + 1) - ZSTD_highbit32((U32)*offBasePtr)) )\n                    bestLength = matchLength, *offBasePtr = OFFSET_TO_OFFBASE(curr - matchIndex);\n                if (ip+matchLength == iend) {   /* equal : no way to know if inf or sup */\n                    if (dictMode == ZSTD_dictMatchState) {\n                        nbCompares = 0; /* in addition to avoiding checking any\n                                         * further in this loop, make sure we\n                                         * skip checking in the dictionary. */\n                    }\n                    break;   /* drop, to guarantee consistency (miss a little bit of compression) */\n                }\n            }\n\n            if (match[matchLength] < ip[matchLength]) {\n                /* match is smaller than current */\n                *smallerPtr = matchIndex;             /* update smaller idx */\n                commonLengthSmaller = matchLength;    /* all smaller will now have at least this guaranteed common length */\n                if (matchIndex <= btLow) { smallerPtr=&dummy32; break; }   /* beyond tree size, stop the search */\n                smallerPtr = nextPtr+1;               /* new \"smaller\" => larger of match */\n                matchIndex = nextPtr[1];              /* new matchIndex larger than previous (closer to current) */\n            } else {\n                /* match is larger than current */\n                *largerPtr = matchIndex;\n                commonLengthLarger = matchLength;\n                if (matchIndex <= btLow) { largerPtr=&dummy32; break; }   /* beyond tree size, stop the search */\n                largerPtr = nextPtr;\n                matchIndex = nextPtr[0];\n        }   }\n\n        *smallerPtr = *largerPtr = 0;\n\n        assert(nbCompares <= (1U << ZSTD_SEARCHLOG_MAX)); /* Check we haven't underflowed. */\n        if (dictMode == ZSTD_dictMatchState && nbCompares) {\n            bestLength = ZSTD_DUBT_findBetterDictMatch(\n                    ms, ip, iend,\n                    offBasePtr, bestLength, nbCompares,\n                    mls, dictMode);\n        }\n\n        assert(matchEndIdx > curr+8); /* ensure nextToUpdate is increased */\n        ms->nextToUpdate = matchEndIdx - 8;   /* skip repetitive patterns */\n        if (bestLength >= MINMATCH) {\n            U32 const mIndex = curr - (U32)OFFBASE_TO_OFFSET(*offBasePtr); (void)mIndex;\n            DEBUGLOG(8, \"ZSTD_DUBT_findBestMatch(%u) : found match of length %u and offsetCode %u (pos %u)\",\n                        curr, (U32)bestLength, (U32)*offBasePtr, mIndex);\n        }\n        return bestLength;\n    }\n}\n\n\n/** ZSTD_BtFindBestMatch() : Tree updater, providing best match */\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_BtFindBestMatch( ZSTD_MatchState_t* ms,\n                const BYTE* const ip, const BYTE* const iLimit,\n                      size_t* offBasePtr,\n                const U32 mls /* template */,\n                const ZSTD_dictMode_e dictMode)\n{\n    DEBUGLOG(7, \"ZSTD_BtFindBestMatch\");\n    if (ip < ms->window.base + ms->nextToUpdate) return 0;   /* skipped area */\n    ZSTD_updateDUBT(ms, ip, iLimit, mls);\n    return ZSTD_DUBT_findBestMatch(ms, ip, iLimit, offBasePtr, mls, dictMode);\n}\n\n/***********************************\n* Dedicated dict search\n***********************************/\n\nvoid ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_MatchState_t* ms, const BYTE* const ip)\n{\n    const BYTE* const base = ms->window.base;\n    U32 const target = (U32)(ip - base);\n    U32* const hashTable = ms->hashTable;\n    U32* const chainTable = ms->chainTable;\n    U32 const chainSize = 1 << ms->cParams.chainLog;\n    U32 idx = ms->nextToUpdate;\n    U32 const minChain = chainSize < target - idx ? target - chainSize : idx;\n    U32 const bucketSize = 1 << ZSTD_LAZY_DDSS_BUCKET_LOG;\n    U32 const cacheSize = bucketSize - 1;\n    U32 const chainAttempts = (1 << ms->cParams.searchLog) - cacheSize;\n    U32 const chainLimit = chainAttempts > 255 ? 255 : chainAttempts;\n\n    /* We know the hashtable is oversized by a factor of `bucketSize`.\n     * We are going to temporarily pretend `bucketSize == 1`, keeping only a\n     * single entry. We will use the rest of the space to construct a temporary\n     * chaintable.\n     */\n    U32 const hashLog = ms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG;\n    U32* const tmpHashTable = hashTable;\n    U32* const tmpChainTable = hashTable + ((size_t)1 << hashLog);\n    U32 const tmpChainSize = (U32)((1 << ZSTD_LAZY_DDSS_BUCKET_LOG) - 1) << hashLog;\n    U32 const tmpMinChain = tmpChainSize < target ? target - tmpChainSize : idx;\n    U32 hashIdx;\n\n    assert(ms->cParams.chainLog <= 24);\n    assert(ms->cParams.hashLog > ms->cParams.chainLog);\n    assert(idx != 0);\n    assert(tmpMinChain <= minChain);\n\n    /* fill conventional hash table and conventional chain table */\n    for ( ; idx < target; idx++) {\n        U32 const h = (U32)ZSTD_hashPtr(base + idx, hashLog, ms->cParams.minMatch);\n        if (idx >= tmpMinChain) {\n            tmpChainTable[idx - tmpMinChain] = hashTable[h];\n        }\n        tmpHashTable[h] = idx;\n    }\n\n    /* sort chains into ddss chain table */\n    {\n        U32 chainPos = 0;\n        for (hashIdx = 0; hashIdx < (1U << hashLog); hashIdx++) {\n            U32 count;\n            U32 countBeyondMinChain = 0;\n            U32 i = tmpHashTable[hashIdx];\n            for (count = 0; i >= tmpMinChain && count < cacheSize; count++) {\n                /* skip through the chain to the first position that won't be\n                 * in the hash cache bucket */\n                if (i < minChain) {\n                    countBeyondMinChain++;\n                }\n                i = tmpChainTable[i - tmpMinChain];\n            }\n            if (count == cacheSize) {\n                for (count = 0; count < chainLimit;) {\n                    if (i < minChain) {\n                        if (!i || ++countBeyondMinChain > cacheSize) {\n                            /* only allow pulling `cacheSize` number of entries\n                             * into the cache or chainTable beyond `minChain`,\n                             * to replace the entries pulled out of the\n                             * chainTable into the cache. This lets us reach\n                             * back further without increasing the total number\n                             * of entries in the chainTable, guaranteeing the\n                             * DDSS chain table will fit into the space\n                             * allocated for the regular one. */\n                            break;\n                        }\n                    }\n                    chainTable[chainPos++] = i;\n                    count++;\n                    if (i < tmpMinChain) {\n                        break;\n                    }\n                    i = tmpChainTable[i - tmpMinChain];\n                }\n            } else {\n                count = 0;\n            }\n            if (count) {\n                tmpHashTable[hashIdx] = ((chainPos - count) << 8) + count;\n            } else {\n                tmpHashTable[hashIdx] = 0;\n            }\n        }\n        assert(chainPos <= chainSize); /* I believe this is guaranteed... */\n    }\n\n    /* move chain pointers into the last entry of each hash bucket */\n    for (hashIdx = (1 << hashLog); hashIdx; ) {\n        U32 const bucketIdx = --hashIdx << ZSTD_LAZY_DDSS_BUCKET_LOG;\n        U32 const chainPackedPointer = tmpHashTable[hashIdx];\n        U32 i;\n        for (i = 0; i < cacheSize; i++) {\n            hashTable[bucketIdx + i] = 0;\n        }\n        hashTable[bucketIdx + bucketSize - 1] = chainPackedPointer;\n    }\n\n    /* fill the buckets of the hash table */\n    for (idx = ms->nextToUpdate; idx < target; idx++) {\n        U32 const h = (U32)ZSTD_hashPtr(base + idx, hashLog, ms->cParams.minMatch)\n                   << ZSTD_LAZY_DDSS_BUCKET_LOG;\n        U32 i;\n        /* Shift hash cache down 1. */\n        for (i = cacheSize - 1; i; i--)\n            hashTable[h + i] = hashTable[h + i - 1];\n        hashTable[h] = idx;\n    }\n\n    ms->nextToUpdate = target;\n}\n\n/* Returns the longest match length found in the dedicated dict search structure.\n * If none are longer than the argument ml, then ml will be returned.\n */\nFORCE_INLINE_TEMPLATE\nsize_t ZSTD_dedicatedDictSearch_lazy_search(size_t* offsetPtr, size_t ml, U32 nbAttempts,\n                                            const ZSTD_MatchState_t* const dms,\n                                            const BYTE* const ip, const BYTE* const iLimit,\n                                            const BYTE* const prefixStart, const U32 curr,\n                                            const U32 dictLimit, const size_t ddsIdx) {\n    const U32 ddsLowestIndex  = dms->window.dictLimit;\n    const BYTE* const ddsBase = dms->window.base;\n    const BYTE* const ddsEnd  = dms->window.nextSrc;\n    const U32 ddsSize         = (U32)(ddsEnd - ddsBase);\n    const U32 ddsIndexDelta   = dictLimit - ddsSize;\n    const U32 bucketSize      = (1 << ZSTD_LAZY_DDSS_BUCKET_LOG);\n    const U32 bucketLimit     = nbAttempts < bucketSize - 1 ? nbAttempts : bucketSize - 1;\n    U32 ddsAttempt;\n    U32 matchIndex;\n\n    for (ddsAttempt = 0; ddsAttempt < bucketSize - 1; ddsAttempt++) {\n        PREFETCH_L1(ddsBase + dms->hashTable[ddsIdx + ddsAttempt]);\n    }\n\n    {\n        U32 const chainPackedPointer = dms->hashTable[ddsIdx + bucketSize - 1];\n        U32 const chainIndex = chainPackedPointer >> 8;\n\n        PREFETCH_L1(&dms->chainTable[chainIndex]);\n    }\n\n    for (ddsAttempt = 0; ddsAttempt < bucketLimit; ddsAttempt++) {\n        size_t currentMl=0;\n        const BYTE* match;\n        matchIndex = dms->hashTable[ddsIdx + ddsAttempt];\n        match = ddsBase + matchIndex;\n\n        if (!matchIndex) {\n            return ml;\n        }\n\n        /* guaranteed by table construction */\n        (void)ddsLowestIndex;\n        assert(matchIndex >= ddsLowestIndex);\n        assert(match+4 <= ddsEnd);\n        if (MEM_read32(match) == MEM_read32(ip)) {\n            /* assumption : matchIndex <= dictLimit-4 (by table construction) */\n            currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, ddsEnd, prefixStart) + 4;\n        }\n\n        /* save best solution */\n        if (currentMl > ml) {\n            ml = currentMl;\n            *offsetPtr = OFFSET_TO_OFFBASE(curr - (matchIndex + ddsIndexDelta));\n            if (ip+currentMl == iLimit) {\n                /* best possible, avoids read overflow on next attempt */\n                return ml;\n            }\n        }\n    }\n\n    {\n        U32 const chainPackedPointer = dms->hashTable[ddsIdx + bucketSize - 1];\n        U32 chainIndex = chainPackedPointer >> 8;\n        U32 const chainLength = chainPackedPointer & 0xFF;\n        U32 const chainAttempts = nbAttempts - ddsAttempt;\n        U32 const chainLimit = chainAttempts > chainLength ? chainLength : chainAttempts;\n        U32 chainAttempt;\n\n        for (chainAttempt = 0 ; chainAttempt < chainLimit; chainAttempt++) {\n            PREFETCH_L1(ddsBase + dms->chainTable[chainIndex + chainAttempt]);\n        }\n\n        for (chainAttempt = 0 ; chainAttempt < chainLimit; chainAttempt++, chainIndex++) {\n            size_t currentMl=0;\n            const BYTE* match;\n            matchIndex = dms->chainTable[chainIndex];\n            match = ddsBase + matchIndex;\n\n            /* guaranteed by table construction */\n            assert(matchIndex >= ddsLowestIndex);\n            assert(match+4 <= ddsEnd);\n            if (MEM_read32(match) == MEM_read32(ip)) {\n                /* assumption : matchIndex <= dictLimit-4 (by table construction) */\n                currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, ddsEnd, prefixStart) + 4;\n            }\n\n            /* save best solution */\n            if (currentMl > ml) {\n                ml = currentMl;\n                *offsetPtr = OFFSET_TO_OFFBASE(curr - (matchIndex + ddsIndexDelta));\n                if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */\n            }\n        }\n    }\n    return ml;\n}\n\n\n/* *********************************\n*  Hash Chain\n***********************************/\n#define NEXT_IN_CHAIN(d, mask)   chainTable[(d) & (mask)]\n\n/* Update chains up to ip (excluded)\n   Assumption : always within prefix (i.e. not within extDict) */\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nU32 ZSTD_insertAndFindFirstIndex_internal(\n                        ZSTD_MatchState_t* ms,\n                        const ZSTD_compressionParameters* const cParams,\n                        const BYTE* ip, U32 const mls, U32 const lazySkipping)\n{\n    U32* const hashTable  = ms->hashTable;\n    const U32 hashLog = cParams->hashLog;\n    U32* const chainTable = ms->chainTable;\n    const U32 chainMask = (1 << cParams->chainLog) - 1;\n    const BYTE* const base = ms->window.base;\n    const U32 target = (U32)(ip - base);\n    U32 idx = ms->nextToUpdate;\n\n    while(idx < target) { /* catch up */\n        size_t const h = ZSTD_hashPtr(base+idx, hashLog, mls);\n        NEXT_IN_CHAIN(idx, chainMask) = hashTable[h];\n        hashTable[h] = idx;\n        idx++;\n        /* Stop inserting every position when in the lazy skipping mode. */\n        if (lazySkipping)\n            break;\n    }\n\n    ms->nextToUpdate = target;\n    return hashTable[ZSTD_hashPtr(ip, hashLog, mls)];\n}\n\nU32 ZSTD_insertAndFindFirstIndex(ZSTD_MatchState_t* ms, const BYTE* ip) {\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    return ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, ms->cParams.minMatch, /* lazySkipping*/ 0);\n}\n\n/* inlining is important to hardwire a hot branch (template emulation) */\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_HcFindBestMatch(\n                        ZSTD_MatchState_t* ms,\n                        const BYTE* const ip, const BYTE* const iLimit,\n                        size_t* offsetPtr,\n                        const U32 mls, const ZSTD_dictMode_e dictMode)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32* const chainTable = ms->chainTable;\n    const U32 chainSize = (1 << cParams->chainLog);\n    const U32 chainMask = chainSize-1;\n    const BYTE* const base = ms->window.base;\n    const BYTE* const dictBase = ms->window.dictBase;\n    const U32 dictLimit = ms->window.dictLimit;\n    const BYTE* const prefixStart = base + dictLimit;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    const U32 curr = (U32)(ip-base);\n    const U32 maxDistance = 1U << cParams->windowLog;\n    const U32 lowestValid = ms->window.lowLimit;\n    const U32 withinMaxDistance = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid;\n    const U32 isDictionary = (ms->loadedDictEnd != 0);\n    const U32 lowLimit = isDictionary ? lowestValid : withinMaxDistance;\n    const U32 minChain = curr > chainSize ? curr - chainSize : 0;\n    U32 nbAttempts = 1U << cParams->searchLog;\n    size_t ml=4-1;\n\n    const ZSTD_MatchState_t* const dms = ms->dictMatchState;\n    const U32 ddsHashLog = dictMode == ZSTD_dedicatedDictSearch\n                         ? dms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG : 0;\n    const size_t ddsIdx = dictMode == ZSTD_dedicatedDictSearch\n                        ? ZSTD_hashPtr(ip, ddsHashLog, mls) << ZSTD_LAZY_DDSS_BUCKET_LOG : 0;\n\n    U32 matchIndex;\n\n    if (dictMode == ZSTD_dedicatedDictSearch) {\n        const U32* entry = &dms->hashTable[ddsIdx];\n        PREFETCH_L1(entry);\n    }\n\n    /* HC4 match finder */\n    matchIndex = ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, mls, ms->lazySkipping);\n\n    for ( ; (matchIndex>=lowLimit) & (nbAttempts>0) ; nbAttempts--) {\n        size_t currentMl=0;\n        if ((dictMode != ZSTD_extDict) || matchIndex >= dictLimit) {\n            const BYTE* const match = base + matchIndex;\n            assert(matchIndex >= dictLimit);   /* ensures this is true if dictMode != ZSTD_extDict */\n            /* read 4B starting from (match + ml + 1 - sizeof(U32)) */\n            if (MEM_read32(match + ml - 3) == MEM_read32(ip + ml - 3))   /* potentially better */\n                currentMl = ZSTD_count(ip, match, iLimit);\n        } else {\n            const BYTE* const match = dictBase + matchIndex;\n            assert(match+4 <= dictEnd);\n            if (MEM_read32(match) == MEM_read32(ip))   /* assumption : matchIndex <= dictLimit-4 (by table construction) */\n                currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dictEnd, prefixStart) + 4;\n        }\n\n        /* save best solution */\n        if (currentMl > ml) {\n            ml = currentMl;\n            *offsetPtr = OFFSET_TO_OFFBASE(curr - matchIndex);\n            if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */\n        }\n\n        if (matchIndex <= minChain) break;\n        matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask);\n    }\n\n    assert(nbAttempts <= (1U << ZSTD_SEARCHLOG_MAX)); /* Check we haven't underflowed. */\n    if (dictMode == ZSTD_dedicatedDictSearch) {\n        ml = ZSTD_dedicatedDictSearch_lazy_search(offsetPtr, ml, nbAttempts, dms,\n                                                  ip, iLimit, prefixStart, curr, dictLimit, ddsIdx);\n    } else if (dictMode == ZSTD_dictMatchState) {\n        const U32* const dmsChainTable = dms->chainTable;\n        const U32 dmsChainSize         = (1 << dms->cParams.chainLog);\n        const U32 dmsChainMask         = dmsChainSize - 1;\n        const U32 dmsLowestIndex       = dms->window.dictLimit;\n        const BYTE* const dmsBase      = dms->window.base;\n        const BYTE* const dmsEnd       = dms->window.nextSrc;\n        const U32 dmsSize              = (U32)(dmsEnd - dmsBase);\n        const U32 dmsIndexDelta        = dictLimit - dmsSize;\n        const U32 dmsMinChain = dmsSize > dmsChainSize ? dmsSize - dmsChainSize : 0;\n\n        matchIndex = dms->hashTable[ZSTD_hashPtr(ip, dms->cParams.hashLog, mls)];\n\n        for ( ; (matchIndex>=dmsLowestIndex) & (nbAttempts>0) ; nbAttempts--) {\n            size_t currentMl=0;\n            const BYTE* const match = dmsBase + matchIndex;\n            assert(match+4 <= dmsEnd);\n            if (MEM_read32(match) == MEM_read32(ip))   /* assumption : matchIndex <= dictLimit-4 (by table construction) */\n                currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dmsEnd, prefixStart) + 4;\n\n            /* save best solution */\n            if (currentMl > ml) {\n                ml = currentMl;\n                assert(curr > matchIndex + dmsIndexDelta);\n                *offsetPtr = OFFSET_TO_OFFBASE(curr - (matchIndex + dmsIndexDelta));\n                if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */\n            }\n\n            if (matchIndex <= dmsMinChain) break;\n\n            matchIndex = dmsChainTable[matchIndex & dmsChainMask];\n        }\n    }\n\n    return ml;\n}\n\n/* *********************************\n* (SIMD) Row-based matchfinder\n***********************************/\n/* Constants for row-based hash */\n#define ZSTD_ROW_HASH_TAG_MASK ((1u << ZSTD_ROW_HASH_TAG_BITS) - 1)\n#define ZSTD_ROW_HASH_MAX_ENTRIES 64    /* absolute maximum number of entries per row, for all configurations */\n\n#define ZSTD_ROW_HASH_CACHE_MASK (ZSTD_ROW_HASH_CACHE_SIZE - 1)\n\ntypedef U64 ZSTD_VecMask;   /* Clarifies when we are interacting with a U64 representing a mask of matches */\n\n/* ZSTD_VecMask_next():\n * Starting from the LSB, returns the idx of the next non-zero bit.\n * Basically counting the nb of trailing zeroes.\n */\nMEM_STATIC U32 ZSTD_VecMask_next(ZSTD_VecMask val) {\n    return ZSTD_countTrailingZeros64(val);\n}\n\n/* ZSTD_row_nextIndex():\n * Returns the next index to insert at within a tagTable row, and updates the \"head\"\n * value to reflect the update. Essentially cycles backwards from [1, {entries per row})\n */\nFORCE_INLINE_TEMPLATE U32 ZSTD_row_nextIndex(BYTE* const tagRow, U32 const rowMask) {\n    U32 next = (*tagRow-1) & rowMask;\n    next += (next == 0) ? rowMask : 0; /* skip first position */\n    *tagRow = (BYTE)next;\n    return next;\n}\n\n/* ZSTD_isAligned():\n * Checks that a pointer is aligned to \"align\" bytes which must be a power of 2.\n */\nMEM_STATIC int ZSTD_isAligned(void const* ptr, size_t align) {\n    assert((align & (align - 1)) == 0);\n    return (((size_t)ptr) & (align - 1)) == 0;\n}\n\n/* ZSTD_row_prefetch():\n * Performs prefetching for the hashTable and tagTable at a given row.\n */\nFORCE_INLINE_TEMPLATE void ZSTD_row_prefetch(U32 const* hashTable, BYTE const* tagTable, U32 const relRow, U32 const rowLog) {\n    PREFETCH_L1(hashTable + relRow);\n    if (rowLog >= 5) {\n        PREFETCH_L1(hashTable + relRow + 16);\n        /* Note: prefetching more of the hash table does not appear to be beneficial for 128-entry rows */\n    }\n    PREFETCH_L1(tagTable + relRow);\n    if (rowLog == 6) {\n        PREFETCH_L1(tagTable + relRow + 32);\n    }\n    assert(rowLog == 4 || rowLog == 5 || rowLog == 6);\n    assert(ZSTD_isAligned(hashTable + relRow, 64));                 /* prefetched hash row always 64-byte aligned */\n    assert(ZSTD_isAligned(tagTable + relRow, (size_t)1 << rowLog)); /* prefetched tagRow sits on correct multiple of bytes (32,64,128) */\n}\n\n/* ZSTD_row_fillHashCache():\n * Fill up the hash cache starting at idx, prefetching up to ZSTD_ROW_HASH_CACHE_SIZE entries,\n * but not beyond iLimit.\n */\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_row_fillHashCache(ZSTD_MatchState_t* ms, const BYTE* base,\n                                   U32 const rowLog, U32 const mls,\n                                   U32 idx, const BYTE* const iLimit)\n{\n    U32 const* const hashTable = ms->hashTable;\n    BYTE const* const tagTable = ms->tagTable;\n    U32 const hashLog = ms->rowHashLog;\n    U32 const maxElemsToPrefetch = (base + idx) > iLimit ? 0 : (U32)(iLimit - (base + idx) + 1);\n    U32 const lim = idx + MIN(ZSTD_ROW_HASH_CACHE_SIZE, maxElemsToPrefetch);\n\n    for (; idx < lim; ++idx) {\n        U32 const hash = (U32)ZSTD_hashPtrSalted(base + idx, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls, ms->hashSalt);\n        U32 const row = (hash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog;\n        ZSTD_row_prefetch(hashTable, tagTable, row, rowLog);\n        ms->hashCache[idx & ZSTD_ROW_HASH_CACHE_MASK] = hash;\n    }\n\n    DEBUGLOG(6, \"ZSTD_row_fillHashCache(): [%u %u %u %u %u %u %u %u]\", ms->hashCache[0], ms->hashCache[1],\n                                                     ms->hashCache[2], ms->hashCache[3], ms->hashCache[4],\n                                                     ms->hashCache[5], ms->hashCache[6], ms->hashCache[7]);\n}\n\n/* ZSTD_row_nextCachedHash():\n * Returns the hash of base + idx, and replaces the hash in the hash cache with the byte at\n * base + idx + ZSTD_ROW_HASH_CACHE_SIZE. Also prefetches the appropriate rows from hashTable and tagTable.\n */\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nU32 ZSTD_row_nextCachedHash(U32* cache, U32 const* hashTable,\n                                                  BYTE const* tagTable, BYTE const* base,\n                                                  U32 idx, U32 const hashLog,\n                                                  U32 const rowLog, U32 const mls,\n                                                  U64 const hashSalt)\n{\n    U32 const newHash = (U32)ZSTD_hashPtrSalted(base+idx+ZSTD_ROW_HASH_CACHE_SIZE, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls, hashSalt);\n    U32 const row = (newHash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog;\n    ZSTD_row_prefetch(hashTable, tagTable, row, rowLog);\n    {   U32 const hash = cache[idx & ZSTD_ROW_HASH_CACHE_MASK];\n        cache[idx & ZSTD_ROW_HASH_CACHE_MASK] = newHash;\n        return hash;\n    }\n}\n\n/* ZSTD_row_update_internalImpl():\n * Updates the hash table with positions starting from updateStartIdx until updateEndIdx.\n */\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_row_update_internalImpl(ZSTD_MatchState_t* ms,\n                                  U32 updateStartIdx, U32 const updateEndIdx,\n                                  U32 const mls, U32 const rowLog,\n                                  U32 const rowMask, U32 const useCache)\n{\n    U32* const hashTable = ms->hashTable;\n    BYTE* const tagTable = ms->tagTable;\n    U32 const hashLog = ms->rowHashLog;\n    const BYTE* const base = ms->window.base;\n\n    DEBUGLOG(6, \"ZSTD_row_update_internalImpl(): updateStartIdx=%u, updateEndIdx=%u\", updateStartIdx, updateEndIdx);\n    for (; updateStartIdx < updateEndIdx; ++updateStartIdx) {\n        U32 const hash = useCache ? ZSTD_row_nextCachedHash(ms->hashCache, hashTable, tagTable, base, updateStartIdx, hashLog, rowLog, mls, ms->hashSalt)\n                                  : (U32)ZSTD_hashPtrSalted(base + updateStartIdx, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls, ms->hashSalt);\n        U32 const relRow = (hash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog;\n        U32* const row = hashTable + relRow;\n        BYTE* tagRow = tagTable + relRow;\n        U32 const pos = ZSTD_row_nextIndex(tagRow, rowMask);\n\n        assert(hash == ZSTD_hashPtrSalted(base + updateStartIdx, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls, ms->hashSalt));\n        tagRow[pos] = hash & ZSTD_ROW_HASH_TAG_MASK;\n        row[pos] = updateStartIdx;\n    }\n}\n\n/* ZSTD_row_update_internal():\n * Inserts the byte at ip into the appropriate position in the hash table, and updates ms->nextToUpdate.\n * Skips sections of long matches as is necessary.\n */\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_row_update_internal(ZSTD_MatchState_t* ms, const BYTE* ip,\n                              U32 const mls, U32 const rowLog,\n                              U32 const rowMask, U32 const useCache)\n{\n    U32 idx = ms->nextToUpdate;\n    const BYTE* const base = ms->window.base;\n    const U32 target = (U32)(ip - base);\n    const U32 kSkipThreshold = 384;\n    const U32 kMaxMatchStartPositionsToUpdate = 96;\n    const U32 kMaxMatchEndPositionsToUpdate = 32;\n\n    if (useCache) {\n        /* Only skip positions when using hash cache, i.e.\n         * if we are loading a dict, don't skip anything.\n         * If we decide to skip, then we only update a set number\n         * of positions at the beginning and end of the match.\n         */\n        if (UNLIKELY(target - idx > kSkipThreshold)) {\n            U32 const bound = idx + kMaxMatchStartPositionsToUpdate;\n            ZSTD_row_update_internalImpl(ms, idx, bound, mls, rowLog, rowMask, useCache);\n            idx = target - kMaxMatchEndPositionsToUpdate;\n            ZSTD_row_fillHashCache(ms, base, rowLog, mls, idx, ip+1);\n        }\n    }\n    assert(target >= idx);\n    ZSTD_row_update_internalImpl(ms, idx, target, mls, rowLog, rowMask, useCache);\n    ms->nextToUpdate = target;\n}\n\n/* ZSTD_row_update():\n * External wrapper for ZSTD_row_update_internal(). Used for filling the hashtable during dictionary\n * processing.\n */\nvoid ZSTD_row_update(ZSTD_MatchState_t* const ms, const BYTE* ip) {\n    const U32 rowLog = BOUNDED(4, ms->cParams.searchLog, 6);\n    const U32 rowMask = (1u << rowLog) - 1;\n    const U32 mls = MIN(ms->cParams.minMatch, 6 /* mls caps out at 6 */);\n\n    DEBUGLOG(5, \"ZSTD_row_update(), rowLog=%u\", rowLog);\n    ZSTD_row_update_internal(ms, ip, mls, rowLog, rowMask, 0 /* don't use cache */);\n}\n\n/* Returns the mask width of bits group of which will be set to 1. Given not all\n * architectures have easy movemask instruction, this helps to iterate over\n * groups of bits easier and faster.\n */\nFORCE_INLINE_TEMPLATE U32\nZSTD_row_matchMaskGroupWidth(const U32 rowEntries)\n{\n    assert((rowEntries == 16) || (rowEntries == 32) || rowEntries == 64);\n    assert(rowEntries <= ZSTD_ROW_HASH_MAX_ENTRIES);\n    (void)rowEntries;\n#if defined(ZSTD_ARCH_ARM_NEON)\n    /* NEON path only works for little endian */\n    if (!MEM_isLittleEndian()) {\n        return 1;\n    }\n    if (rowEntries == 16) {\n        return 4;\n    }\n    if (rowEntries == 32) {\n        return 2;\n    }\n    if (rowEntries == 64) {\n        return 1;\n    }\n#endif\n    return 1;\n}\n\n#if defined(ZSTD_ARCH_X86_SSE2)\nFORCE_INLINE_TEMPLATE ZSTD_VecMask\nZSTD_row_getSSEMask(int nbChunks, const BYTE* const src, const BYTE tag, const U32 head)\n{\n    const __m128i comparisonMask = _mm_set1_epi8((char)tag);\n    int matches[4] = {0};\n    int i;\n    assert(nbChunks == 1 || nbChunks == 2 || nbChunks == 4);\n    for (i=0; i<nbChunks; i++) {\n        const __m128i chunk = _mm_loadu_si128((const __m128i*)(const void*)(src + 16*i));\n        const __m128i equalMask = _mm_cmpeq_epi8(chunk, comparisonMask);\n        matches[i] = _mm_movemask_epi8(equalMask);\n    }\n    if (nbChunks == 1) return ZSTD_rotateRight_U16((U16)matches[0], head);\n    if (nbChunks == 2) return ZSTD_rotateRight_U32((U32)matches[1] << 16 | (U32)matches[0], head);\n    assert(nbChunks == 4);\n    return ZSTD_rotateRight_U64((U64)matches[3] << 48 | (U64)matches[2] << 32 | (U64)matches[1] << 16 | (U64)matches[0], head);\n}\n#endif\n\n#if defined(ZSTD_ARCH_ARM_NEON)\nFORCE_INLINE_TEMPLATE ZSTD_VecMask\nZSTD_row_getNEONMask(const U32 rowEntries, const BYTE* const src, const BYTE tag, const U32 headGrouped)\n{\n    assert((rowEntries == 16) || (rowEntries == 32) || rowEntries == 64);\n    if (rowEntries == 16) {\n        /* vshrn_n_u16 shifts by 4 every u16 and narrows to 8 lower bits.\n         * After that groups of 4 bits represent the equalMask. We lower\n         * all bits except the highest in these groups by doing AND with\n         * 0x88 = 0b10001000.\n         */\n        const uint8x16_t chunk = vld1q_u8(src);\n        const uint16x8_t equalMask = vreinterpretq_u16_u8(vceqq_u8(chunk, vdupq_n_u8(tag)));\n        const uint8x8_t res = vshrn_n_u16(equalMask, 4);\n        const U64 matches = vget_lane_u64(vreinterpret_u64_u8(res), 0);\n        return ZSTD_rotateRight_U64(matches, headGrouped) & 0x8888888888888888ull;\n    } else if (rowEntries == 32) {\n        /* Same idea as with rowEntries == 16 but doing AND with\n         * 0x55 = 0b01010101.\n         */\n        const uint16x8x2_t chunk = vld2q_u16((const uint16_t*)(const void*)src);\n        const uint8x16_t chunk0 = vreinterpretq_u8_u16(chunk.val[0]);\n        const uint8x16_t chunk1 = vreinterpretq_u8_u16(chunk.val[1]);\n        const uint8x16_t dup = vdupq_n_u8(tag);\n        const uint8x8_t t0 = vshrn_n_u16(vreinterpretq_u16_u8(vceqq_u8(chunk0, dup)), 6);\n        const uint8x8_t t1 = vshrn_n_u16(vreinterpretq_u16_u8(vceqq_u8(chunk1, dup)), 6);\n        const uint8x8_t res = vsli_n_u8(t0, t1, 4);\n        const U64 matches = vget_lane_u64(vreinterpret_u64_u8(res), 0) ;\n        return ZSTD_rotateRight_U64(matches, headGrouped) & 0x5555555555555555ull;\n    } else { /* rowEntries == 64 */\n        const uint8x16x4_t chunk = vld4q_u8(src);\n        const uint8x16_t dup = vdupq_n_u8(tag);\n        const uint8x16_t cmp0 = vceqq_u8(chunk.val[0], dup);\n        const uint8x16_t cmp1 = vceqq_u8(chunk.val[1], dup);\n        const uint8x16_t cmp2 = vceqq_u8(chunk.val[2], dup);\n        const uint8x16_t cmp3 = vceqq_u8(chunk.val[3], dup);\n\n        const uint8x16_t t0 = vsriq_n_u8(cmp1, cmp0, 1);\n        const uint8x16_t t1 = vsriq_n_u8(cmp3, cmp2, 1);\n        const uint8x16_t t2 = vsriq_n_u8(t1, t0, 2);\n        const uint8x16_t t3 = vsriq_n_u8(t2, t2, 4);\n        const uint8x8_t t4 = vshrn_n_u16(vreinterpretq_u16_u8(t3), 4);\n        const U64 matches = vget_lane_u64(vreinterpret_u64_u8(t4), 0);\n        return ZSTD_rotateRight_U64(matches, headGrouped);\n    }\n}\n#endif\n#if defined(ZSTD_ARCH_RISCV_RVV) && (__riscv_xlen == 64)\nFORCE_INLINE_TEMPLATE ZSTD_VecMask\nZSTD_row_getRVVMask(int rowEntries, const BYTE* const src, const BYTE tag, const U32 head)\n{\n    ZSTD_VecMask matches;\n    size_t vl;\n\n    if (rowEntries == 16) {\n        vl = __riscv_vsetvl_e8m1(16);\n        {\n            vuint8m1_t chunk = __riscv_vle8_v_u8m1(src, vl);\n            vbool8_t mask = __riscv_vmseq_vx_u8m1_b8(chunk, tag, vl);\n            vuint16m1_t mask_u16 = __riscv_vreinterpret_v_b8_u16m1(mask);\n            matches = __riscv_vmv_x_s_u16m1_u16(mask_u16);\n            return ZSTD_rotateRight_U16((U16)matches, head);\n        }\n\n    } else if (rowEntries == 32) {\n        vl = __riscv_vsetvl_e8m2(32);\n        {\n            vuint8m2_t chunk = __riscv_vle8_v_u8m2(src, vl);\n            vbool4_t mask = __riscv_vmseq_vx_u8m2_b4(chunk, tag, vl);\n            vuint32m1_t mask_u32 = __riscv_vreinterpret_v_b4_u32m1(mask);\n            matches = __riscv_vmv_x_s_u32m1_u32(mask_u32);\n            return ZSTD_rotateRight_U32((U32)matches, head);\n        }\n    } else { // rowEntries = 64\n        vl = __riscv_vsetvl_e8m4(64);\n        {\n            vuint8m4_t chunk = __riscv_vle8_v_u8m4(src, vl);\n            vbool2_t mask = __riscv_vmseq_vx_u8m4_b2(chunk, tag, vl);\n            vuint64m1_t mask_u64 = __riscv_vreinterpret_v_b2_u64m1(mask);\n            matches = __riscv_vmv_x_s_u64m1_u64(mask_u64);\n            return ZSTD_rotateRight_U64(matches, head);\n        }\n    }\n}\n#endif\n\n/* Returns a ZSTD_VecMask (U64) that has the nth group (determined by\n * ZSTD_row_matchMaskGroupWidth) of bits set to 1 if the newly-computed \"tag\"\n * matches the hash at the nth position in a row of the tagTable.\n * Each row is a circular buffer beginning at the value of \"headGrouped\". So we\n * must rotate the \"matches\" bitfield to match up with the actual layout of the\n * entries within the hashTable */\nFORCE_INLINE_TEMPLATE ZSTD_VecMask\nZSTD_row_getMatchMask(const BYTE* const tagRow, const BYTE tag, const U32 headGrouped, const U32 rowEntries)\n{\n    const BYTE* const src = tagRow;\n    assert((rowEntries == 16) || (rowEntries == 32) || rowEntries == 64);\n    assert(rowEntries <= ZSTD_ROW_HASH_MAX_ENTRIES);\n    assert(ZSTD_row_matchMaskGroupWidth(rowEntries) * rowEntries <= sizeof(ZSTD_VecMask) * 8);\n\n#if defined(ZSTD_ARCH_X86_SSE2)\n\n    return ZSTD_row_getSSEMask(rowEntries / 16, src, tag, headGrouped);\n\n#elif defined(ZSTD_ARCH_RISCV_RVV) && (__riscv_xlen == 64)\n\n    return ZSTD_row_getRVVMask(rowEntries, src, tag, headGrouped);\n\n#else\n\n#if defined(ZSTD_ARCH_ARM_NEON)\n  /* This NEON path only works for little endian - otherwise use SWAR below */\n    if (MEM_isLittleEndian()) {\n        return ZSTD_row_getNEONMask(rowEntries, src, tag, headGrouped);\n    }\n\n\n#endif\n    /* SWAR */\n    {   const int chunkSize = sizeof(size_t);\n        const size_t shiftAmount = ((chunkSize * 8) - chunkSize);\n        const size_t xFF = ~((size_t)0);\n        const size_t x01 = xFF / 0xFF;\n        const size_t x80 = x01 << 7;\n        const size_t splatChar = tag * x01;\n        ZSTD_VecMask matches = 0;\n        int i = rowEntries - chunkSize;\n        assert((sizeof(size_t) == 4) || (sizeof(size_t) == 8));\n        if (MEM_isLittleEndian()) { /* runtime check so have two loops */\n            const size_t extractMagic = (xFF / 0x7F) >> chunkSize;\n            do {\n                size_t chunk = MEM_readST(&src[i]);\n                chunk ^= splatChar;\n                chunk = (((chunk | x80) - x01) | chunk) & x80;\n                matches <<= chunkSize;\n                matches |= (chunk * extractMagic) >> shiftAmount;\n                i -= chunkSize;\n            } while (i >= 0);\n        } else { /* big endian: reverse bits during extraction */\n            const size_t msb = xFF ^ (xFF >> 1);\n            const size_t extractMagic = (msb / 0x1FF) | msb;\n            do {\n                size_t chunk = MEM_readST(&src[i]);\n                chunk ^= splatChar;\n                chunk = (((chunk | x80) - x01) | chunk) & x80;\n                matches <<= chunkSize;\n                matches |= ((chunk >> 7) * extractMagic) >> shiftAmount;\n                i -= chunkSize;\n            } while (i >= 0);\n        }\n        matches = ~matches;\n        if (rowEntries == 16) {\n            return ZSTD_rotateRight_U16((U16)matches, headGrouped);\n        } else if (rowEntries == 32) {\n            return ZSTD_rotateRight_U32((U32)matches, headGrouped);\n        } else {\n            return ZSTD_rotateRight_U64((U64)matches, headGrouped);\n        }\n    }\n#endif\n}\n\n/* The high-level approach of the SIMD row based match finder is as follows:\n * - Figure out where to insert the new entry:\n *      - Generate a hash for current input position and split it into a one byte of tag and `rowHashLog` bits of index.\n *           - The hash is salted by a value that changes on every context reset, so when the same table is used\n *             we will avoid collisions that would otherwise slow us down by introducing phantom matches.\n *      - The hashTable is effectively split into groups or \"rows\" of 15 or 31 entries of U32, and the index determines\n *        which row to insert into.\n *      - Determine the correct position within the row to insert the entry into. Each row of 15 or 31 can\n *        be considered as a circular buffer with a \"head\" index that resides in the tagTable (overall 16 or 32 bytes\n *        per row).\n * - Use SIMD to efficiently compare the tags in the tagTable to the 1-byte tag calculated for the position and\n *   generate a bitfield that we can cycle through to check the collisions in the hash table.\n * - Pick the longest match.\n * - Insert the tag into the equivalent row and position in the tagTable.\n */\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_RowFindBestMatch(\n                        ZSTD_MatchState_t* ms,\n                        const BYTE* const ip, const BYTE* const iLimit,\n                        size_t* offsetPtr,\n                        const U32 mls, const ZSTD_dictMode_e dictMode,\n                        const U32 rowLog)\n{\n    U32* const hashTable = ms->hashTable;\n    BYTE* const tagTable = ms->tagTable;\n    U32* const hashCache = ms->hashCache;\n    const U32 hashLog = ms->rowHashLog;\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    const BYTE* const base = ms->window.base;\n    const BYTE* const dictBase = ms->window.dictBase;\n    const U32 dictLimit = ms->window.dictLimit;\n    const BYTE* const prefixStart = base + dictLimit;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    const U32 curr = (U32)(ip-base);\n    const U32 maxDistance = 1U << cParams->windowLog;\n    const U32 lowestValid = ms->window.lowLimit;\n    const U32 withinMaxDistance = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid;\n    const U32 isDictionary = (ms->loadedDictEnd != 0);\n    const U32 lowLimit = isDictionary ? lowestValid : withinMaxDistance;\n    const U32 rowEntries = (1U << rowLog);\n    const U32 rowMask = rowEntries - 1;\n    const U32 cappedSearchLog = MIN(cParams->searchLog, rowLog); /* nb of searches is capped at nb entries per row */\n    const U32 groupWidth = ZSTD_row_matchMaskGroupWidth(rowEntries);\n    const U64 hashSalt = ms->hashSalt;\n    U32 nbAttempts = 1U << cappedSearchLog;\n    size_t ml=4-1;\n    U32 hash;\n\n    /* DMS/DDS variables that may be referenced laster */\n    const ZSTD_MatchState_t* const dms = ms->dictMatchState;\n\n    /* Initialize the following variables to satisfy static analyzer */\n    size_t ddsIdx = 0;\n    U32 ddsExtraAttempts = 0; /* cctx hash tables are limited in searches, but allow extra searches into DDS */\n    U32 dmsTag = 0;\n    U32* dmsRow = NULL;\n    BYTE* dmsTagRow = NULL;\n\n    if (dictMode == ZSTD_dedicatedDictSearch) {\n        const U32 ddsHashLog = dms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG;\n        {   /* Prefetch DDS hashtable entry */\n            ddsIdx = ZSTD_hashPtr(ip, ddsHashLog, mls) << ZSTD_LAZY_DDSS_BUCKET_LOG;\n            PREFETCH_L1(&dms->hashTable[ddsIdx]);\n        }\n        ddsExtraAttempts = cParams->searchLog > rowLog ? 1U << (cParams->searchLog - rowLog) : 0;\n    }\n\n    if (dictMode == ZSTD_dictMatchState) {\n        /* Prefetch DMS rows */\n        U32* const dmsHashTable = dms->hashTable;\n        BYTE* const dmsTagTable = dms->tagTable;\n        U32 const dmsHash = (U32)ZSTD_hashPtr(ip, dms->rowHashLog + ZSTD_ROW_HASH_TAG_BITS, mls);\n        U32 const dmsRelRow = (dmsHash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog;\n        dmsTag = dmsHash & ZSTD_ROW_HASH_TAG_MASK;\n        dmsTagRow = (BYTE*)(dmsTagTable + dmsRelRow);\n        dmsRow = dmsHashTable + dmsRelRow;\n        ZSTD_row_prefetch(dmsHashTable, dmsTagTable, dmsRelRow, rowLog);\n    }\n\n    /* Update the hashTable and tagTable up to (but not including) ip */\n    if (!ms->lazySkipping) {\n        ZSTD_row_update_internal(ms, ip, mls, rowLog, rowMask, 1 /* useCache */);\n        hash = ZSTD_row_nextCachedHash(hashCache, hashTable, tagTable, base, curr, hashLog, rowLog, mls, hashSalt);\n    } else {\n        /* Stop inserting every position when in the lazy skipping mode.\n         * The hash cache is also not kept up to date in this mode.\n         */\n        hash = (U32)ZSTD_hashPtrSalted(ip, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls, hashSalt);\n        ms->nextToUpdate = curr;\n    }\n    ms->hashSaltEntropy += hash; /* collect salt entropy */\n\n    {   /* Get the hash for ip, compute the appropriate row */\n        U32 const relRow = (hash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog;\n        U32 const tag = hash & ZSTD_ROW_HASH_TAG_MASK;\n        U32* const row = hashTable + relRow;\n        BYTE* tagRow = (BYTE*)(tagTable + relRow);\n        U32 const headGrouped = (*tagRow & rowMask) * groupWidth;\n        U32 matchBuffer[ZSTD_ROW_HASH_MAX_ENTRIES];\n        size_t numMatches = 0;\n        size_t currMatch = 0;\n        ZSTD_VecMask matches = ZSTD_row_getMatchMask(tagRow, (BYTE)tag, headGrouped, rowEntries);\n\n        /* Cycle through the matches and prefetch */\n        for (; (matches > 0) && (nbAttempts > 0); matches &= (matches - 1)) {\n            U32 const matchPos = ((headGrouped + ZSTD_VecMask_next(matches)) / groupWidth) & rowMask;\n            U32 const matchIndex = row[matchPos];\n            if(matchPos == 0) continue;\n            assert(numMatches < rowEntries);\n            if (matchIndex < lowLimit)\n                break;\n            if ((dictMode != ZSTD_extDict) || matchIndex >= dictLimit) {\n                PREFETCH_L1(base + matchIndex);\n            } else {\n                PREFETCH_L1(dictBase + matchIndex);\n            }\n            matchBuffer[numMatches++] = matchIndex;\n            --nbAttempts;\n        }\n\n        /* Speed opt: insert current byte into hashtable too. This allows us to avoid one iteration of the loop\n           in ZSTD_row_update_internal() at the next search. */\n        {\n            U32 const pos = ZSTD_row_nextIndex(tagRow, rowMask);\n            tagRow[pos] = (BYTE)tag;\n            row[pos] = ms->nextToUpdate++;\n        }\n\n        /* Return the longest match */\n        for (; currMatch < numMatches; ++currMatch) {\n            U32 const matchIndex = matchBuffer[currMatch];\n            size_t currentMl=0;\n            assert(matchIndex < curr);\n            assert(matchIndex >= lowLimit);\n\n            if ((dictMode != ZSTD_extDict) || matchIndex >= dictLimit) {\n                const BYTE* const match = base + matchIndex;\n                assert(matchIndex >= dictLimit);   /* ensures this is true if dictMode != ZSTD_extDict */\n                /* read 4B starting from (match + ml + 1 - sizeof(U32)) */\n                if (MEM_read32(match + ml - 3) == MEM_read32(ip + ml - 3))   /* potentially better */\n                    currentMl = ZSTD_count(ip, match, iLimit);\n            } else {\n                const BYTE* const match = dictBase + matchIndex;\n                assert(match+4 <= dictEnd);\n                if (MEM_read32(match) == MEM_read32(ip))   /* assumption : matchIndex <= dictLimit-4 (by table construction) */\n                    currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dictEnd, prefixStart) + 4;\n            }\n\n            /* Save best solution */\n            if (currentMl > ml) {\n                ml = currentMl;\n                *offsetPtr = OFFSET_TO_OFFBASE(curr - matchIndex);\n                if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */\n            }\n        }\n    }\n\n    assert(nbAttempts <= (1U << ZSTD_SEARCHLOG_MAX)); /* Check we haven't underflowed. */\n    if (dictMode == ZSTD_dedicatedDictSearch) {\n        ml = ZSTD_dedicatedDictSearch_lazy_search(offsetPtr, ml, nbAttempts + ddsExtraAttempts, dms,\n                                                  ip, iLimit, prefixStart, curr, dictLimit, ddsIdx);\n    } else if (dictMode == ZSTD_dictMatchState) {\n        /* TODO: Measure and potentially add prefetching to DMS */\n        const U32 dmsLowestIndex       = dms->window.dictLimit;\n        const BYTE* const dmsBase      = dms->window.base;\n        const BYTE* const dmsEnd       = dms->window.nextSrc;\n        const U32 dmsSize              = (U32)(dmsEnd - dmsBase);\n        const U32 dmsIndexDelta        = dictLimit - dmsSize;\n\n        {   U32 const headGrouped = (*dmsTagRow & rowMask) * groupWidth;\n            U32 matchBuffer[ZSTD_ROW_HASH_MAX_ENTRIES];\n            size_t numMatches = 0;\n            size_t currMatch = 0;\n            ZSTD_VecMask matches = ZSTD_row_getMatchMask(dmsTagRow, (BYTE)dmsTag, headGrouped, rowEntries);\n\n            for (; (matches > 0) && (nbAttempts > 0); matches &= (matches - 1)) {\n                U32 const matchPos = ((headGrouped + ZSTD_VecMask_next(matches)) / groupWidth) & rowMask;\n                U32 const matchIndex = dmsRow[matchPos];\n                if(matchPos == 0) continue;\n                if (matchIndex < dmsLowestIndex)\n                    break;\n                PREFETCH_L1(dmsBase + matchIndex);\n                matchBuffer[numMatches++] = matchIndex;\n                --nbAttempts;\n            }\n\n            /* Return the longest match */\n            for (; currMatch < numMatches; ++currMatch) {\n                U32 const matchIndex = matchBuffer[currMatch];\n                size_t currentMl=0;\n                assert(matchIndex >= dmsLowestIndex);\n                assert(matchIndex < curr);\n\n                {   const BYTE* const match = dmsBase + matchIndex;\n                    assert(match+4 <= dmsEnd);\n                    if (MEM_read32(match) == MEM_read32(ip))\n                        currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dmsEnd, prefixStart) + 4;\n                }\n\n                if (currentMl > ml) {\n                    ml = currentMl;\n                    assert(curr > matchIndex + dmsIndexDelta);\n                    *offsetPtr = OFFSET_TO_OFFBASE(curr - (matchIndex + dmsIndexDelta));\n                    if (ip+currentMl == iLimit) break;\n                }\n            }\n        }\n    }\n    return ml;\n}\n\n\n/**\n * Generate search functions templated on (dictMode, mls, rowLog).\n * These functions are outlined for code size & compilation time.\n * ZSTD_searchMax() dispatches to the correct implementation function.\n *\n * TODO: The start of the search function involves loading and calculating a\n * bunch of constants from the ZSTD_MatchState_t. These computations could be\n * done in an initialization function, and saved somewhere in the match state.\n * Then we could pass a pointer to the saved state instead of the match state,\n * and avoid duplicate computations.\n *\n * TODO: Move the match re-winding into searchMax. This improves compression\n * ratio, and unlocks further simplifications with the next TODO.\n *\n * TODO: Try moving the repcode search into searchMax. After the re-winding\n * and repcode search are in searchMax, there is no more logic in the match\n * finder loop that requires knowledge about the dictMode. So we should be\n * able to avoid force inlining it, and we can join the extDict loop with\n * the single segment loop. It should go in searchMax instead of its own\n * function to avoid having multiple virtual function calls per search.\n */\n\n#define ZSTD_BT_SEARCH_FN(dictMode, mls) ZSTD_BtFindBestMatch_##dictMode##_##mls\n#define ZSTD_HC_SEARCH_FN(dictMode, mls) ZSTD_HcFindBestMatch_##dictMode##_##mls\n#define ZSTD_ROW_SEARCH_FN(dictMode, mls, rowLog) ZSTD_RowFindBestMatch_##dictMode##_##mls##_##rowLog\n\n#define ZSTD_SEARCH_FN_ATTRS FORCE_NOINLINE\n\n#define GEN_ZSTD_BT_SEARCH_FN(dictMode, mls)                                           \\\n    ZSTD_SEARCH_FN_ATTRS size_t ZSTD_BT_SEARCH_FN(dictMode, mls)(                      \\\n            ZSTD_MatchState_t* ms,                                                     \\\n            const BYTE* ip, const BYTE* const iLimit,                                  \\\n            size_t* offBasePtr)                                                        \\\n    {                                                                                  \\\n        assert(MAX(4, MIN(6, ms->cParams.minMatch)) == mls);                           \\\n        return ZSTD_BtFindBestMatch(ms, ip, iLimit, offBasePtr, mls, ZSTD_##dictMode); \\\n    }                                                                                  \\\n\n#define GEN_ZSTD_HC_SEARCH_FN(dictMode, mls)                                          \\\n    ZSTD_SEARCH_FN_ATTRS size_t ZSTD_HC_SEARCH_FN(dictMode, mls)(                     \\\n            ZSTD_MatchState_t* ms,                                                    \\\n            const BYTE* ip, const BYTE* const iLimit,                                 \\\n            size_t* offsetPtr)                                                        \\\n    {                                                                                 \\\n        assert(MAX(4, MIN(6, ms->cParams.minMatch)) == mls);                          \\\n        return ZSTD_HcFindBestMatch(ms, ip, iLimit, offsetPtr, mls, ZSTD_##dictMode); \\\n    }                                                                                 \\\n\n#define GEN_ZSTD_ROW_SEARCH_FN(dictMode, mls, rowLog)                                          \\\n    ZSTD_SEARCH_FN_ATTRS size_t ZSTD_ROW_SEARCH_FN(dictMode, mls, rowLog)(                     \\\n            ZSTD_MatchState_t* ms,                                                             \\\n            const BYTE* ip, const BYTE* const iLimit,                                          \\\n            size_t* offsetPtr)                                                                 \\\n    {                                                                                          \\\n        assert(MAX(4, MIN(6, ms->cParams.minMatch)) == mls);                                   \\\n        assert(MAX(4, MIN(6, ms->cParams.searchLog)) == rowLog);                               \\\n        return ZSTD_RowFindBestMatch(ms, ip, iLimit, offsetPtr, mls, ZSTD_##dictMode, rowLog); \\\n    }                                                                                          \\\n\n#define ZSTD_FOR_EACH_ROWLOG(X, dictMode, mls) \\\n    X(dictMode, mls, 4)                        \\\n    X(dictMode, mls, 5)                        \\\n    X(dictMode, mls, 6)\n\n#define ZSTD_FOR_EACH_MLS_ROWLOG(X, dictMode) \\\n    ZSTD_FOR_EACH_ROWLOG(X, dictMode, 4)      \\\n    ZSTD_FOR_EACH_ROWLOG(X, dictMode, 5)      \\\n    ZSTD_FOR_EACH_ROWLOG(X, dictMode, 6)\n\n#define ZSTD_FOR_EACH_MLS(X, dictMode) \\\n    X(dictMode, 4)                     \\\n    X(dictMode, 5)                     \\\n    X(dictMode, 6)\n\n#define ZSTD_FOR_EACH_DICT_MODE(X, ...) \\\n    X(__VA_ARGS__, noDict)              \\\n    X(__VA_ARGS__, extDict)             \\\n    X(__VA_ARGS__, dictMatchState)      \\\n    X(__VA_ARGS__, dedicatedDictSearch)\n\n/* Generate row search fns for each combination of (dictMode, mls, rowLog) */\nZSTD_FOR_EACH_DICT_MODE(ZSTD_FOR_EACH_MLS_ROWLOG, GEN_ZSTD_ROW_SEARCH_FN)\n/* Generate binary Tree search fns for each combination of (dictMode, mls) */\nZSTD_FOR_EACH_DICT_MODE(ZSTD_FOR_EACH_MLS, GEN_ZSTD_BT_SEARCH_FN)\n/* Generate hash chain search fns for each combination of (dictMode, mls) */\nZSTD_FOR_EACH_DICT_MODE(ZSTD_FOR_EACH_MLS, GEN_ZSTD_HC_SEARCH_FN)\n\ntypedef enum { search_hashChain=0, search_binaryTree=1, search_rowHash=2 } searchMethod_e;\n\n#define GEN_ZSTD_CALL_BT_SEARCH_FN(dictMode, mls)                         \\\n    case mls:                                                             \\\n        return ZSTD_BT_SEARCH_FN(dictMode, mls)(ms, ip, iend, offsetPtr);\n#define GEN_ZSTD_CALL_HC_SEARCH_FN(dictMode, mls)                         \\\n    case mls:                                                             \\\n        return ZSTD_HC_SEARCH_FN(dictMode, mls)(ms, ip, iend, offsetPtr);\n#define GEN_ZSTD_CALL_ROW_SEARCH_FN(dictMode, mls, rowLog)                         \\\n    case rowLog:                                                                   \\\n        return ZSTD_ROW_SEARCH_FN(dictMode, mls, rowLog)(ms, ip, iend, offsetPtr);\n\n#define ZSTD_SWITCH_MLS(X, dictMode)   \\\n    switch (mls) {                     \\\n        ZSTD_FOR_EACH_MLS(X, dictMode) \\\n    }\n\n#define ZSTD_SWITCH_ROWLOG(dictMode, mls)                                    \\\n    case mls:                                                                \\\n        switch (rowLog) {                                                    \\\n            ZSTD_FOR_EACH_ROWLOG(GEN_ZSTD_CALL_ROW_SEARCH_FN, dictMode, mls) \\\n        }                                                                    \\\n        ZSTD_UNREACHABLE;                                                    \\\n        break;\n\n#define ZSTD_SWITCH_SEARCH_METHOD(dictMode)                       \\\n    switch (searchMethod) {                                       \\\n        case search_hashChain:                                    \\\n            ZSTD_SWITCH_MLS(GEN_ZSTD_CALL_HC_SEARCH_FN, dictMode) \\\n            break;                                                \\\n        case search_binaryTree:                                   \\\n            ZSTD_SWITCH_MLS(GEN_ZSTD_CALL_BT_SEARCH_FN, dictMode) \\\n            break;                                                \\\n        case search_rowHash:                                      \\\n            ZSTD_SWITCH_MLS(ZSTD_SWITCH_ROWLOG, dictMode)         \\\n            break;                                                \\\n    }                                                             \\\n    ZSTD_UNREACHABLE;\n\n/**\n * Searches for the longest match at @p ip.\n * Dispatches to the correct implementation function based on the\n * (searchMethod, dictMode, mls, rowLog). We use switch statements\n * here instead of using an indirect function call through a function\n * pointer because after Spectre and Meltdown mitigations, indirect\n * function calls can be very costly, especially in the kernel.\n *\n * NOTE: dictMode and searchMethod should be templated, so those switch\n * statements should be optimized out. Only the mls & rowLog switches\n * should be left.\n *\n * @param ms The match state.\n * @param ip The position to search at.\n * @param iend The end of the input data.\n * @param[out] offsetPtr Stores the match offset into this pointer.\n * @param mls The minimum search length, in the range [4, 6].\n * @param rowLog The row log (if applicable), in the range [4, 6].\n * @param searchMethod The search method to use (templated).\n * @param dictMode The dictMode (templated).\n *\n * @returns The length of the longest match found, or < mls if no match is found.\n * If a match is found its offset is stored in @p offsetPtr.\n */\nFORCE_INLINE_TEMPLATE size_t ZSTD_searchMax(\n    ZSTD_MatchState_t* ms,\n    const BYTE* ip,\n    const BYTE* iend,\n    size_t* offsetPtr,\n    U32 const mls,\n    U32 const rowLog,\n    searchMethod_e const searchMethod,\n    ZSTD_dictMode_e const dictMode)\n{\n    if (dictMode == ZSTD_noDict) {\n        ZSTD_SWITCH_SEARCH_METHOD(noDict)\n    } else if (dictMode == ZSTD_extDict) {\n        ZSTD_SWITCH_SEARCH_METHOD(extDict)\n    } else if (dictMode == ZSTD_dictMatchState) {\n        ZSTD_SWITCH_SEARCH_METHOD(dictMatchState)\n    } else if (dictMode == ZSTD_dedicatedDictSearch) {\n        ZSTD_SWITCH_SEARCH_METHOD(dedicatedDictSearch)\n    }\n    ZSTD_UNREACHABLE;\n    return 0;\n}\n\n/* *******************************\n*  Common parser - lazy strategy\n*********************************/\n\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_compressBlock_lazy_generic(\n                        ZSTD_MatchState_t* ms, SeqStore_t* seqStore,\n                        U32 rep[ZSTD_REP_NUM],\n                        const void* src, size_t srcSize,\n                        const searchMethod_e searchMethod, const U32 depth,\n                        ZSTD_dictMode_e const dictMode)\n{\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* ip = istart;\n    const BYTE* anchor = istart;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* const ilimit = (searchMethod == search_rowHash) ? iend - 8 - ZSTD_ROW_HASH_CACHE_SIZE : iend - 8;\n    const BYTE* const base = ms->window.base;\n    const U32 prefixLowestIndex = ms->window.dictLimit;\n    const BYTE* const prefixLowest = base + prefixLowestIndex;\n    const U32 mls = BOUNDED(4, ms->cParams.minMatch, 6);\n    const U32 rowLog = BOUNDED(4, ms->cParams.searchLog, 6);\n\n    U32 offset_1 = rep[0], offset_2 = rep[1];\n    U32 offsetSaved1 = 0, offsetSaved2 = 0;\n\n    const int isDMS = dictMode == ZSTD_dictMatchState;\n    const int isDDS = dictMode == ZSTD_dedicatedDictSearch;\n    const int isDxS = isDMS || isDDS;\n    const ZSTD_MatchState_t* const dms = ms->dictMatchState;\n    const U32 dictLowestIndex      = isDxS ? dms->window.dictLimit : 0;\n    const BYTE* const dictBase     = isDxS ? dms->window.base : NULL;\n    const BYTE* const dictLowest   = isDxS ? dictBase + dictLowestIndex : NULL;\n    const BYTE* const dictEnd      = isDxS ? dms->window.nextSrc : NULL;\n    const U32 dictIndexDelta       = isDxS ?\n                                     prefixLowestIndex - (U32)(dictEnd - dictBase) :\n                                     0;\n    const U32 dictAndPrefixLength = (U32)((ip - prefixLowest) + (dictEnd - dictLowest));\n\n    DEBUGLOG(5, \"ZSTD_compressBlock_lazy_generic (dictMode=%u) (searchFunc=%u)\", (U32)dictMode, (U32)searchMethod);\n    ip += (dictAndPrefixLength == 0);\n    if (dictMode == ZSTD_noDict) {\n        U32 const curr = (U32)(ip - base);\n        U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, curr, ms->cParams.windowLog);\n        U32 const maxRep = curr - windowLow;\n        if (offset_2 > maxRep) offsetSaved2 = offset_2, offset_2 = 0;\n        if (offset_1 > maxRep) offsetSaved1 = offset_1, offset_1 = 0;\n    }\n    if (isDxS) {\n        /* dictMatchState repCode checks don't currently handle repCode == 0\n         * disabling. */\n        assert(offset_1 <= dictAndPrefixLength);\n        assert(offset_2 <= dictAndPrefixLength);\n    }\n\n    /* Reset the lazy skipping state */\n    ms->lazySkipping = 0;\n\n    if (searchMethod == search_rowHash) {\n        ZSTD_row_fillHashCache(ms, base, rowLog, mls, ms->nextToUpdate, ilimit);\n    }\n\n    /* Match Loop */\n#if defined(__GNUC__) && defined(__x86_64__)\n    /* I've measured random a 5% speed loss on levels 5 & 6 (greedy) when the\n     * code alignment is perturbed. To fix the instability align the loop on 32-bytes.\n     */\n    __asm__(\".p2align 5\");\n#endif\n    while (ip < ilimit) {\n        size_t matchLength=0;\n        size_t offBase = REPCODE1_TO_OFFBASE;\n        const BYTE* start=ip+1;\n        DEBUGLOG(7, \"search baseline (depth 0)\");\n\n        /* check repCode */\n        if (isDxS) {\n            const U32 repIndex = (U32)(ip - base) + 1 - offset_1;\n            const BYTE* repMatch = ((dictMode == ZSTD_dictMatchState || dictMode == ZSTD_dedicatedDictSearch)\n                                && repIndex < prefixLowestIndex) ?\n                                   dictBase + (repIndex - dictIndexDelta) :\n                                   base + repIndex;\n            if ((ZSTD_index_overlap_check(prefixLowestIndex, repIndex))\n                && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {\n                const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;\n                matchLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;\n                if (depth==0) goto _storeSequence;\n            }\n        }\n        if ( dictMode == ZSTD_noDict\n          && ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)))) {\n            matchLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;\n            if (depth==0) goto _storeSequence;\n        }\n\n        /* first search (depth 0) */\n        {   size_t offbaseFound = 999999999;\n            size_t const ml2 = ZSTD_searchMax(ms, ip, iend, &offbaseFound, mls, rowLog, searchMethod, dictMode);\n            if (ml2 > matchLength)\n                matchLength = ml2, start = ip, offBase = offbaseFound;\n        }\n\n        if (matchLength < 4) {\n            size_t const step = ((size_t)(ip-anchor) >> kSearchStrength) + 1;   /* jump faster over incompressible sections */;\n            ip += step;\n            /* Enter the lazy skipping mode once we are skipping more than 8 bytes at a time.\n             * In this mode we stop inserting every position into our tables, and only insert\n             * positions that we search, which is one in step positions.\n             * The exact cutoff is flexible, I've just chosen a number that is reasonably high,\n             * so we minimize the compression ratio loss in \"normal\" scenarios. This mode gets\n             * triggered once we've gone 2KB without finding any matches.\n             */\n            ms->lazySkipping = step > kLazySkippingStep;\n            continue;\n        }\n\n        /* let's try to find a better solution */\n        if (depth>=1)\n        while (ip<ilimit) {\n            DEBUGLOG(7, \"search depth 1\");\n            ip ++;\n            if ( (dictMode == ZSTD_noDict)\n              && (offBase) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {\n                size_t const mlRep = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;\n                int const gain2 = (int)(mlRep * 3);\n                int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offBase) + 1);\n                if ((mlRep >= 4) && (gain2 > gain1))\n                    matchLength = mlRep, offBase = REPCODE1_TO_OFFBASE, start = ip;\n            }\n            if (isDxS) {\n                const U32 repIndex = (U32)(ip - base) - offset_1;\n                const BYTE* repMatch = repIndex < prefixLowestIndex ?\n                               dictBase + (repIndex - dictIndexDelta) :\n                               base + repIndex;\n                if ((ZSTD_index_overlap_check(prefixLowestIndex, repIndex))\n                    && (MEM_read32(repMatch) == MEM_read32(ip)) ) {\n                    const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;\n                    size_t const mlRep = ZSTD_count_2segments(ip+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;\n                    int const gain2 = (int)(mlRep * 3);\n                    int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offBase) + 1);\n                    if ((mlRep >= 4) && (gain2 > gain1))\n                        matchLength = mlRep, offBase = REPCODE1_TO_OFFBASE, start = ip;\n                }\n            }\n            {   size_t ofbCandidate=999999999;\n                size_t const ml2 = ZSTD_searchMax(ms, ip, iend, &ofbCandidate, mls, rowLog, searchMethod, dictMode);\n                int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)ofbCandidate));   /* raw approx */\n                int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offBase) + 4);\n                if ((ml2 >= 4) && (gain2 > gain1)) {\n                    matchLength = ml2, offBase = ofbCandidate, start = ip;\n                    continue;   /* search a better one */\n            }   }\n\n            /* let's find an even better one */\n            if ((depth==2) && (ip<ilimit)) {\n                DEBUGLOG(7, \"search depth 2\");\n                ip ++;\n                if ( (dictMode == ZSTD_noDict)\n                  && (offBase) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {\n                    size_t const mlRep = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;\n                    int const gain2 = (int)(mlRep * 4);\n                    int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offBase) + 1);\n                    if ((mlRep >= 4) && (gain2 > gain1))\n                        matchLength = mlRep, offBase = REPCODE1_TO_OFFBASE, start = ip;\n                }\n                if (isDxS) {\n                    const U32 repIndex = (U32)(ip - base) - offset_1;\n                    const BYTE* repMatch = repIndex < prefixLowestIndex ?\n                                   dictBase + (repIndex - dictIndexDelta) :\n                                   base + repIndex;\n                    if ((ZSTD_index_overlap_check(prefixLowestIndex, repIndex))\n                        && (MEM_read32(repMatch) == MEM_read32(ip)) ) {\n                        const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;\n                        size_t const mlRep = ZSTD_count_2segments(ip+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;\n                        int const gain2 = (int)(mlRep * 4);\n                        int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offBase) + 1);\n                        if ((mlRep >= 4) && (gain2 > gain1))\n                            matchLength = mlRep, offBase = REPCODE1_TO_OFFBASE, start = ip;\n                    }\n                }\n                {   size_t ofbCandidate=999999999;\n                    size_t const ml2 = ZSTD_searchMax(ms, ip, iend, &ofbCandidate, mls, rowLog, searchMethod, dictMode);\n                    int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)ofbCandidate));   /* raw approx */\n                    int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offBase) + 7);\n                    if ((ml2 >= 4) && (gain2 > gain1)) {\n                        matchLength = ml2, offBase = ofbCandidate, start = ip;\n                        continue;\n            }   }   }\n            break;  /* nothing found : store previous solution */\n        }\n\n        /* NOTE:\n         * Pay attention that `start[-value]` can lead to strange undefined behavior\n         * notably if `value` is unsigned, resulting in a large positive `-value`.\n         */\n        /* catch up */\n        if (OFFBASE_IS_OFFSET(offBase)) {\n            if (dictMode == ZSTD_noDict) {\n                while ( ((start > anchor) & (start - OFFBASE_TO_OFFSET(offBase) > prefixLowest))\n                     && (start[-1] == (start-OFFBASE_TO_OFFSET(offBase))[-1]) )  /* only search for offset within prefix */\n                    { start--; matchLength++; }\n            }\n            if (isDxS) {\n                U32 const matchIndex = (U32)((size_t)(start-base) - OFFBASE_TO_OFFSET(offBase));\n                const BYTE* match = (matchIndex < prefixLowestIndex) ? dictBase + matchIndex - dictIndexDelta : base + matchIndex;\n                const BYTE* const mStart = (matchIndex < prefixLowestIndex) ? dictLowest : prefixLowest;\n                while ((start>anchor) && (match>mStart) && (start[-1] == match[-1])) { start--; match--; matchLength++; }  /* catch up */\n            }\n            offset_2 = offset_1; offset_1 = (U32)OFFBASE_TO_OFFSET(offBase);\n        }\n        /* store sequence */\n_storeSequence:\n        {   size_t const litLength = (size_t)(start - anchor);\n            ZSTD_storeSeq(seqStore, litLength, anchor, iend, (U32)offBase, matchLength);\n            anchor = ip = start + matchLength;\n        }\n        if (ms->lazySkipping) {\n            /* We've found a match, disable lazy skipping mode, and refill the hash cache. */\n            if (searchMethod == search_rowHash) {\n                ZSTD_row_fillHashCache(ms, base, rowLog, mls, ms->nextToUpdate, ilimit);\n            }\n            ms->lazySkipping = 0;\n        }\n\n        /* check immediate repcode */\n        if (isDxS) {\n            while (ip <= ilimit) {\n                U32 const current2 = (U32)(ip-base);\n                U32 const repIndex = current2 - offset_2;\n                const BYTE* repMatch = repIndex < prefixLowestIndex ?\n                        dictBase - dictIndexDelta + repIndex :\n                        base + repIndex;\n                if ( (ZSTD_index_overlap_check(prefixLowestIndex, repIndex))\n                   && (MEM_read32(repMatch) == MEM_read32(ip)) ) {\n                    const BYTE* const repEnd2 = repIndex < prefixLowestIndex ? dictEnd : iend;\n                    matchLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd2, prefixLowest) + 4;\n                    offBase = offset_2; offset_2 = offset_1; offset_1 = (U32)offBase;   /* swap offset_2 <=> offset_1 */\n                    ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, matchLength);\n                    ip += matchLength;\n                    anchor = ip;\n                    continue;\n                }\n                break;\n            }\n        }\n\n        if (dictMode == ZSTD_noDict) {\n            while ( ((ip <= ilimit) & (offset_2>0))\n                 && (MEM_read32(ip) == MEM_read32(ip - offset_2)) ) {\n                /* store sequence */\n                matchLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;\n                offBase = offset_2; offset_2 = offset_1; offset_1 = (U32)offBase; /* swap repcodes */\n                ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, matchLength);\n                ip += matchLength;\n                anchor = ip;\n                continue;   /* faster when present ... (?) */\n    }   }   }\n\n    /* If offset_1 started invalid (offsetSaved1 != 0) and became valid (offset_1 != 0),\n     * rotate saved offsets. See comment in ZSTD_compressBlock_fast_noDict for more context. */\n    offsetSaved2 = ((offsetSaved1 != 0) && (offset_1 != 0)) ? offsetSaved1 : offsetSaved2;\n\n    /* save reps for next block */\n    rep[0] = offset_1 ? offset_1 : offsetSaved1;\n    rep[1] = offset_2 ? offset_2 : offsetSaved2;\n\n    /* Return the last literals size */\n    return (size_t)(iend - anchor);\n}\n#endif /* build exclusions */\n\n\n#ifndef ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_greedy(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0, ZSTD_noDict);\n}\n\nsize_t ZSTD_compressBlock_greedy_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0, ZSTD_dictMatchState);\n}\n\nsize_t ZSTD_compressBlock_greedy_dedicatedDictSearch(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0, ZSTD_dedicatedDictSearch);\n}\n\nsize_t ZSTD_compressBlock_greedy_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0, ZSTD_noDict);\n}\n\nsize_t ZSTD_compressBlock_greedy_dictMatchState_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0, ZSTD_dictMatchState);\n}\n\nsize_t ZSTD_compressBlock_greedy_dedicatedDictSearch_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0, ZSTD_dedicatedDictSearch);\n}\n#endif\n\n#ifndef ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_lazy(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1, ZSTD_noDict);\n}\n\nsize_t ZSTD_compressBlock_lazy_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1, ZSTD_dictMatchState);\n}\n\nsize_t ZSTD_compressBlock_lazy_dedicatedDictSearch(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1, ZSTD_dedicatedDictSearch);\n}\n\nsize_t ZSTD_compressBlock_lazy_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1, ZSTD_noDict);\n}\n\nsize_t ZSTD_compressBlock_lazy_dictMatchState_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1, ZSTD_dictMatchState);\n}\n\nsize_t ZSTD_compressBlock_lazy_dedicatedDictSearch_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1, ZSTD_dedicatedDictSearch);\n}\n#endif\n\n#ifndef ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_lazy2(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2, ZSTD_noDict);\n}\n\nsize_t ZSTD_compressBlock_lazy2_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2, ZSTD_dictMatchState);\n}\n\nsize_t ZSTD_compressBlock_lazy2_dedicatedDictSearch(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2, ZSTD_dedicatedDictSearch);\n}\n\nsize_t ZSTD_compressBlock_lazy2_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2, ZSTD_noDict);\n}\n\nsize_t ZSTD_compressBlock_lazy2_dictMatchState_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2, ZSTD_dictMatchState);\n}\n\nsize_t ZSTD_compressBlock_lazy2_dedicatedDictSearch_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2, ZSTD_dedicatedDictSearch);\n}\n#endif\n\n#ifndef ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_btlazy2(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_binaryTree, 2, ZSTD_noDict);\n}\n\nsize_t ZSTD_compressBlock_btlazy2_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_binaryTree, 2, ZSTD_dictMatchState);\n}\n#endif\n\n#if !defined(ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR)\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_compressBlock_lazy_extDict_generic(\n                        ZSTD_MatchState_t* ms, SeqStore_t* seqStore,\n                        U32 rep[ZSTD_REP_NUM],\n                        const void* src, size_t srcSize,\n                        const searchMethod_e searchMethod, const U32 depth)\n{\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* ip = istart;\n    const BYTE* anchor = istart;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* const ilimit = searchMethod == search_rowHash ? iend - 8 - ZSTD_ROW_HASH_CACHE_SIZE : iend - 8;\n    const BYTE* const base = ms->window.base;\n    const U32 dictLimit = ms->window.dictLimit;\n    const BYTE* const prefixStart = base + dictLimit;\n    const BYTE* const dictBase = ms->window.dictBase;\n    const BYTE* const dictEnd  = dictBase + dictLimit;\n    const BYTE* const dictStart  = dictBase + ms->window.lowLimit;\n    const U32 windowLog = ms->cParams.windowLog;\n    const U32 mls = BOUNDED(4, ms->cParams.minMatch, 6);\n    const U32 rowLog = BOUNDED(4, ms->cParams.searchLog, 6);\n\n    U32 offset_1 = rep[0], offset_2 = rep[1];\n\n    DEBUGLOG(5, \"ZSTD_compressBlock_lazy_extDict_generic (searchFunc=%u)\", (U32)searchMethod);\n\n    /* Reset the lazy skipping state */\n    ms->lazySkipping = 0;\n\n    /* init */\n    ip += (ip == prefixStart);\n    if (searchMethod == search_rowHash) {\n        ZSTD_row_fillHashCache(ms, base, rowLog, mls, ms->nextToUpdate, ilimit);\n    }\n\n    /* Match Loop */\n#if defined(__GNUC__) && defined(__x86_64__)\n    /* I've measured random a 5% speed loss on levels 5 & 6 (greedy) when the\n     * code alignment is perturbed. To fix the instability align the loop on 32-bytes.\n     */\n    __asm__(\".p2align 5\");\n#endif\n    while (ip < ilimit) {\n        size_t matchLength=0;\n        size_t offBase = REPCODE1_TO_OFFBASE;\n        const BYTE* start=ip+1;\n        U32 curr = (U32)(ip-base);\n\n        /* check repCode */\n        {   const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr+1, windowLog);\n            const U32 repIndex = (U32)(curr+1 - offset_1);\n            const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;\n            const BYTE* const repMatch = repBase + repIndex;\n            if ( (ZSTD_index_overlap_check(dictLimit, repIndex))\n               & (offset_1 <= curr+1 - windowLow) ) /* note: we are searching at curr+1 */\n            if (MEM_read32(ip+1) == MEM_read32(repMatch)) {\n                /* repcode detected we should take it */\n                const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;\n                matchLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repEnd, prefixStart) + 4;\n                if (depth==0) goto _storeSequence;\n        }   }\n\n        /* first search (depth 0) */\n        {   size_t ofbCandidate = 999999999;\n            size_t const ml2 = ZSTD_searchMax(ms, ip, iend, &ofbCandidate, mls, rowLog, searchMethod, ZSTD_extDict);\n            if (ml2 > matchLength)\n                matchLength = ml2, start = ip, offBase = ofbCandidate;\n        }\n\n        if (matchLength < 4) {\n            size_t const step = ((size_t)(ip-anchor) >> kSearchStrength);\n            ip += step + 1;   /* jump faster over incompressible sections */\n            /* Enter the lazy skipping mode once we are skipping more than 8 bytes at a time.\n             * In this mode we stop inserting every position into our tables, and only insert\n             * positions that we search, which is one in step positions.\n             * The exact cutoff is flexible, I've just chosen a number that is reasonably high,\n             * so we minimize the compression ratio loss in \"normal\" scenarios. This mode gets\n             * triggered once we've gone 2KB without finding any matches.\n             */\n            ms->lazySkipping = step > kLazySkippingStep;\n            continue;\n        }\n\n        /* let's try to find a better solution */\n        if (depth>=1)\n        while (ip<ilimit) {\n            ip ++;\n            curr++;\n            /* check repCode */\n            if (offBase) {\n                const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr, windowLog);\n                const U32 repIndex = (U32)(curr - offset_1);\n                const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;\n                const BYTE* const repMatch = repBase + repIndex;\n                if ( (ZSTD_index_overlap_check(dictLimit, repIndex))\n                   & (offset_1 <= curr - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */\n                if (MEM_read32(ip) == MEM_read32(repMatch)) {\n                    /* repcode detected */\n                    const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;\n                    size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;\n                    int const gain2 = (int)(repLength * 3);\n                    int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offBase) + 1);\n                    if ((repLength >= 4) && (gain2 > gain1))\n                        matchLength = repLength, offBase = REPCODE1_TO_OFFBASE, start = ip;\n            }   }\n\n            /* search match, depth 1 */\n            {   size_t ofbCandidate = 999999999;\n                size_t const ml2 = ZSTD_searchMax(ms, ip, iend, &ofbCandidate, mls, rowLog, searchMethod, ZSTD_extDict);\n                int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)ofbCandidate));   /* raw approx */\n                int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offBase) + 4);\n                if ((ml2 >= 4) && (gain2 > gain1)) {\n                    matchLength = ml2, offBase = ofbCandidate, start = ip;\n                    continue;   /* search a better one */\n            }   }\n\n            /* let's find an even better one */\n            if ((depth==2) && (ip<ilimit)) {\n                ip ++;\n                curr++;\n                /* check repCode */\n                if (offBase) {\n                    const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr, windowLog);\n                    const U32 repIndex = (U32)(curr - offset_1);\n                    const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;\n                    const BYTE* const repMatch = repBase + repIndex;\n                    if ( (ZSTD_index_overlap_check(dictLimit, repIndex))\n                       & (offset_1 <= curr - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */\n                    if (MEM_read32(ip) == MEM_read32(repMatch)) {\n                        /* repcode detected */\n                        const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;\n                        size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;\n                        int const gain2 = (int)(repLength * 4);\n                        int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offBase) + 1);\n                        if ((repLength >= 4) && (gain2 > gain1))\n                            matchLength = repLength, offBase = REPCODE1_TO_OFFBASE, start = ip;\n                }   }\n\n                /* search match, depth 2 */\n                {   size_t ofbCandidate = 999999999;\n                    size_t const ml2 = ZSTD_searchMax(ms, ip, iend, &ofbCandidate, mls, rowLog, searchMethod, ZSTD_extDict);\n                    int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)ofbCandidate));   /* raw approx */\n                    int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offBase) + 7);\n                    if ((ml2 >= 4) && (gain2 > gain1)) {\n                        matchLength = ml2, offBase = ofbCandidate, start = ip;\n                        continue;\n            }   }   }\n            break;  /* nothing found : store previous solution */\n        }\n\n        /* catch up */\n        if (OFFBASE_IS_OFFSET(offBase)) {\n            U32 const matchIndex = (U32)((size_t)(start-base) - OFFBASE_TO_OFFSET(offBase));\n            const BYTE* match = (matchIndex < dictLimit) ? dictBase + matchIndex : base + matchIndex;\n            const BYTE* const mStart = (matchIndex < dictLimit) ? dictStart : prefixStart;\n            while ((start>anchor) && (match>mStart) && (start[-1] == match[-1])) { start--; match--; matchLength++; }  /* catch up */\n            offset_2 = offset_1; offset_1 = (U32)OFFBASE_TO_OFFSET(offBase);\n        }\n\n        /* store sequence */\n_storeSequence:\n        {   size_t const litLength = (size_t)(start - anchor);\n            ZSTD_storeSeq(seqStore, litLength, anchor, iend, (U32)offBase, matchLength);\n            anchor = ip = start + matchLength;\n        }\n        if (ms->lazySkipping) {\n            /* We've found a match, disable lazy skipping mode, and refill the hash cache. */\n            if (searchMethod == search_rowHash) {\n                ZSTD_row_fillHashCache(ms, base, rowLog, mls, ms->nextToUpdate, ilimit);\n            }\n            ms->lazySkipping = 0;\n        }\n\n        /* check immediate repcode */\n        while (ip <= ilimit) {\n            const U32 repCurrent = (U32)(ip-base);\n            const U32 windowLow = ZSTD_getLowestMatchIndex(ms, repCurrent, windowLog);\n            const U32 repIndex = repCurrent - offset_2;\n            const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;\n            const BYTE* const repMatch = repBase + repIndex;\n            if ( (ZSTD_index_overlap_check(dictLimit, repIndex))\n               & (offset_2 <= repCurrent - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */\n            if (MEM_read32(ip) == MEM_read32(repMatch)) {\n                /* repcode detected we should take it */\n                const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;\n                matchLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;\n                offBase = offset_2; offset_2 = offset_1; offset_1 = (U32)offBase;   /* swap offset history */\n                ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, matchLength);\n                ip += matchLength;\n                anchor = ip;\n                continue;   /* faster when present ... (?) */\n            }\n            break;\n    }   }\n\n    /* Save reps for next block */\n    rep[0] = offset_1;\n    rep[1] = offset_2;\n\n    /* Return the last literals size */\n    return (size_t)(iend - anchor);\n}\n#endif /* build exclusions */\n\n#ifndef ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_greedy_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0);\n}\n\nsize_t ZSTD_compressBlock_greedy_extDict_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0);\n}\n#endif\n\n#ifndef ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_lazy_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n\n{\n    return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1);\n}\n\nsize_t ZSTD_compressBlock_lazy_extDict_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n\n{\n    return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1);\n}\n#endif\n\n#ifndef ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_lazy2_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n\n{\n    return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2);\n}\n\nsize_t ZSTD_compressBlock_lazy2_extDict_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2);\n}\n#endif\n\n#ifndef ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_btlazy2_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n\n{\n    return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_binaryTree, 2);\n}\n#endif\n"
  },
  {
    "path": "lib/compress/zstd_lazy.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_LAZY_H\n#define ZSTD_LAZY_H\n\n#include \"zstd_compress_internal.h\"\n\n/**\n * Dedicated Dictionary Search Structure bucket log. In the\n * ZSTD_dedicatedDictSearch mode, the hashTable has\n * 2 ** ZSTD_LAZY_DDSS_BUCKET_LOG entries in each bucket, rather than just\n * one.\n */\n#define ZSTD_LAZY_DDSS_BUCKET_LOG 2\n\n#define ZSTD_ROW_HASH_TAG_BITS 8        /* nb bits to use for the tag */\n\n#if !defined(ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR)\nU32 ZSTD_insertAndFindFirstIndex(ZSTD_MatchState_t* ms, const BYTE* ip);\nvoid ZSTD_row_update(ZSTD_MatchState_t* const ms, const BYTE* ip);\n\nvoid ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_MatchState_t* ms, const BYTE* const ip);\n\nvoid ZSTD_preserveUnsortedMark (U32* const table, U32 const size, U32 const reducerValue);  /*! used in ZSTD_reduceIndex(). preemptively increase value of ZSTD_DUBT_UNSORTED_MARK */\n#endif\n\n#ifndef ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_greedy(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_greedy_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_greedy_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_greedy_dictMatchState_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_greedy_dedicatedDictSearch(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_greedy_dedicatedDictSearch_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_greedy_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_greedy_extDict_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\n\n#define ZSTD_COMPRESSBLOCK_GREEDY ZSTD_compressBlock_greedy\n#define ZSTD_COMPRESSBLOCK_GREEDY_ROW ZSTD_compressBlock_greedy_row\n#define ZSTD_COMPRESSBLOCK_GREEDY_DICTMATCHSTATE ZSTD_compressBlock_greedy_dictMatchState\n#define ZSTD_COMPRESSBLOCK_GREEDY_DICTMATCHSTATE_ROW ZSTD_compressBlock_greedy_dictMatchState_row\n#define ZSTD_COMPRESSBLOCK_GREEDY_DEDICATEDDICTSEARCH ZSTD_compressBlock_greedy_dedicatedDictSearch\n#define ZSTD_COMPRESSBLOCK_GREEDY_DEDICATEDDICTSEARCH_ROW ZSTD_compressBlock_greedy_dedicatedDictSearch_row\n#define ZSTD_COMPRESSBLOCK_GREEDY_EXTDICT ZSTD_compressBlock_greedy_extDict\n#define ZSTD_COMPRESSBLOCK_GREEDY_EXTDICT_ROW ZSTD_compressBlock_greedy_extDict_row\n#else\n#define ZSTD_COMPRESSBLOCK_GREEDY NULL\n#define ZSTD_COMPRESSBLOCK_GREEDY_ROW NULL\n#define ZSTD_COMPRESSBLOCK_GREEDY_DICTMATCHSTATE NULL\n#define ZSTD_COMPRESSBLOCK_GREEDY_DICTMATCHSTATE_ROW NULL\n#define ZSTD_COMPRESSBLOCK_GREEDY_DEDICATEDDICTSEARCH NULL\n#define ZSTD_COMPRESSBLOCK_GREEDY_DEDICATEDDICTSEARCH_ROW NULL\n#define ZSTD_COMPRESSBLOCK_GREEDY_EXTDICT NULL\n#define ZSTD_COMPRESSBLOCK_GREEDY_EXTDICT_ROW NULL\n#endif\n\n#ifndef ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_lazy(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy_dictMatchState_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy_dedicatedDictSearch(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy_dedicatedDictSearch_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy_extDict_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\n\n#define ZSTD_COMPRESSBLOCK_LAZY ZSTD_compressBlock_lazy\n#define ZSTD_COMPRESSBLOCK_LAZY_ROW ZSTD_compressBlock_lazy_row\n#define ZSTD_COMPRESSBLOCK_LAZY_DICTMATCHSTATE ZSTD_compressBlock_lazy_dictMatchState\n#define ZSTD_COMPRESSBLOCK_LAZY_DICTMATCHSTATE_ROW ZSTD_compressBlock_lazy_dictMatchState_row\n#define ZSTD_COMPRESSBLOCK_LAZY_DEDICATEDDICTSEARCH ZSTD_compressBlock_lazy_dedicatedDictSearch\n#define ZSTD_COMPRESSBLOCK_LAZY_DEDICATEDDICTSEARCH_ROW ZSTD_compressBlock_lazy_dedicatedDictSearch_row\n#define ZSTD_COMPRESSBLOCK_LAZY_EXTDICT ZSTD_compressBlock_lazy_extDict\n#define ZSTD_COMPRESSBLOCK_LAZY_EXTDICT_ROW ZSTD_compressBlock_lazy_extDict_row\n#else\n#define ZSTD_COMPRESSBLOCK_LAZY NULL\n#define ZSTD_COMPRESSBLOCK_LAZY_ROW NULL\n#define ZSTD_COMPRESSBLOCK_LAZY_DICTMATCHSTATE NULL\n#define ZSTD_COMPRESSBLOCK_LAZY_DICTMATCHSTATE_ROW NULL\n#define ZSTD_COMPRESSBLOCK_LAZY_DEDICATEDDICTSEARCH NULL\n#define ZSTD_COMPRESSBLOCK_LAZY_DEDICATEDDICTSEARCH_ROW NULL\n#define ZSTD_COMPRESSBLOCK_LAZY_EXTDICT NULL\n#define ZSTD_COMPRESSBLOCK_LAZY_EXTDICT_ROW NULL\n#endif\n\n#ifndef ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_lazy2(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy2_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy2_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy2_dictMatchState_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy2_dedicatedDictSearch(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy2_dedicatedDictSearch_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy2_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy2_extDict_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\n\n#define ZSTD_COMPRESSBLOCK_LAZY2 ZSTD_compressBlock_lazy2\n#define ZSTD_COMPRESSBLOCK_LAZY2_ROW ZSTD_compressBlock_lazy2_row\n#define ZSTD_COMPRESSBLOCK_LAZY2_DICTMATCHSTATE ZSTD_compressBlock_lazy2_dictMatchState\n#define ZSTD_COMPRESSBLOCK_LAZY2_DICTMATCHSTATE_ROW ZSTD_compressBlock_lazy2_dictMatchState_row\n#define ZSTD_COMPRESSBLOCK_LAZY2_DEDICATEDDICTSEARCH ZSTD_compressBlock_lazy2_dedicatedDictSearch\n#define ZSTD_COMPRESSBLOCK_LAZY2_DEDICATEDDICTSEARCH_ROW ZSTD_compressBlock_lazy2_dedicatedDictSearch_row\n#define ZSTD_COMPRESSBLOCK_LAZY2_EXTDICT ZSTD_compressBlock_lazy2_extDict\n#define ZSTD_COMPRESSBLOCK_LAZY2_EXTDICT_ROW ZSTD_compressBlock_lazy2_extDict_row\n#else\n#define ZSTD_COMPRESSBLOCK_LAZY2 NULL\n#define ZSTD_COMPRESSBLOCK_LAZY2_ROW NULL\n#define ZSTD_COMPRESSBLOCK_LAZY2_DICTMATCHSTATE NULL\n#define ZSTD_COMPRESSBLOCK_LAZY2_DICTMATCHSTATE_ROW NULL\n#define ZSTD_COMPRESSBLOCK_LAZY2_DEDICATEDDICTSEARCH NULL\n#define ZSTD_COMPRESSBLOCK_LAZY2_DEDICATEDDICTSEARCH_ROW NULL\n#define ZSTD_COMPRESSBLOCK_LAZY2_EXTDICT NULL\n#define ZSTD_COMPRESSBLOCK_LAZY2_EXTDICT_ROW NULL\n#endif\n\n#ifndef ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_btlazy2(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_btlazy2_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_btlazy2_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\n\n#define ZSTD_COMPRESSBLOCK_BTLAZY2 ZSTD_compressBlock_btlazy2\n#define ZSTD_COMPRESSBLOCK_BTLAZY2_DICTMATCHSTATE ZSTD_compressBlock_btlazy2_dictMatchState\n#define ZSTD_COMPRESSBLOCK_BTLAZY2_EXTDICT ZSTD_compressBlock_btlazy2_extDict\n#else\n#define ZSTD_COMPRESSBLOCK_BTLAZY2 NULL\n#define ZSTD_COMPRESSBLOCK_BTLAZY2_DICTMATCHSTATE NULL\n#define ZSTD_COMPRESSBLOCK_BTLAZY2_EXTDICT NULL\n#endif\n\n#endif /* ZSTD_LAZY_H */\n"
  },
  {
    "path": "lib/compress/zstd_ldm.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"zstd_ldm.h\"\n\n#include \"../common/debug.h\"\n#include \"../common/xxhash.h\"\n#include \"zstd_fast.h\"          /* ZSTD_fillHashTable() */\n#include \"zstd_double_fast.h\"   /* ZSTD_fillDoubleHashTable() */\n#include \"zstd_ldm_geartab.h\"\n\n#define LDM_BUCKET_SIZE_LOG 4\n#define LDM_MIN_MATCH_LENGTH 64\n#define LDM_HASH_RLOG 7\n\ntypedef struct {\n    U64 rolling;\n    U64 stopMask;\n} ldmRollingHashState_t;\n\n/** ZSTD_ldm_gear_init():\n *\n * Initializes the rolling hash state such that it will honor the\n * settings in params. */\nstatic void ZSTD_ldm_gear_init(ldmRollingHashState_t* state, ldmParams_t const* params)\n{\n    unsigned maxBitsInMask = MIN(params->minMatchLength, 64);\n    unsigned hashRateLog = params->hashRateLog;\n\n    state->rolling = ~(U32)0;\n\n    /* The choice of the splitting criterion is subject to two conditions:\n     *   1. it has to trigger on average every 2^(hashRateLog) bytes;\n     *   2. ideally, it has to depend on a window of minMatchLength bytes.\n     *\n     * In the gear hash algorithm, bit n depends on the last n bytes;\n     * so in order to obtain a good quality splitting criterion it is\n     * preferable to use bits with high weight.\n     *\n     * To match condition 1 we use a mask with hashRateLog bits set\n     * and, because of the previous remark, we make sure these bits\n     * have the highest possible weight while still respecting\n     * condition 2.\n     */\n    if (hashRateLog > 0 && hashRateLog <= maxBitsInMask) {\n        state->stopMask = (((U64)1 << hashRateLog) - 1) << (maxBitsInMask - hashRateLog);\n    } else {\n        /* In this degenerate case we simply honor the hash rate. */\n        state->stopMask = ((U64)1 << hashRateLog) - 1;\n    }\n}\n\n/** ZSTD_ldm_gear_reset()\n * Feeds [data, data + minMatchLength) into the hash without registering any\n * splits. This effectively resets the hash state. This is used when skipping\n * over data, either at the beginning of a block, or skipping sections.\n */\nstatic void ZSTD_ldm_gear_reset(ldmRollingHashState_t* state,\n                                BYTE const* data, size_t minMatchLength)\n{\n    U64 hash = state->rolling;\n    size_t n = 0;\n\n#define GEAR_ITER_ONCE() do {                                  \\\n        hash = (hash << 1) + ZSTD_ldm_gearTab[data[n] & 0xff]; \\\n        n += 1;                                                \\\n    } while (0)\n    while (n + 3 < minMatchLength) {\n        GEAR_ITER_ONCE();\n        GEAR_ITER_ONCE();\n        GEAR_ITER_ONCE();\n        GEAR_ITER_ONCE();\n    }\n    while (n < minMatchLength) {\n        GEAR_ITER_ONCE();\n    }\n#undef GEAR_ITER_ONCE\n}\n\n/** ZSTD_ldm_gear_feed():\n *\n * Registers in the splits array all the split points found in the first\n * size bytes following the data pointer. This function terminates when\n * either all the data has been processed or LDM_BATCH_SIZE splits are\n * present in the splits array.\n *\n * Precondition: The splits array must not be full.\n * Returns: The number of bytes processed. */\nstatic size_t ZSTD_ldm_gear_feed(ldmRollingHashState_t* state,\n                                 BYTE const* data, size_t size,\n                                 size_t* splits, unsigned* numSplits)\n{\n    size_t n;\n    U64 hash, mask;\n\n    hash = state->rolling;\n    mask = state->stopMask;\n    n = 0;\n\n#define GEAR_ITER_ONCE() do { \\\n        hash = (hash << 1) + ZSTD_ldm_gearTab[data[n] & 0xff]; \\\n        n += 1; \\\n        if (UNLIKELY((hash & mask) == 0)) { \\\n            splits[*numSplits] = n; \\\n            *numSplits += 1; \\\n            if (*numSplits == LDM_BATCH_SIZE) \\\n                goto done; \\\n        } \\\n    } while (0)\n\n    while (n + 3 < size) {\n        GEAR_ITER_ONCE();\n        GEAR_ITER_ONCE();\n        GEAR_ITER_ONCE();\n        GEAR_ITER_ONCE();\n    }\n    while (n < size) {\n        GEAR_ITER_ONCE();\n    }\n\n#undef GEAR_ITER_ONCE\n\ndone:\n    state->rolling = hash;\n    return n;\n}\n\nvoid ZSTD_ldm_adjustParameters(ldmParams_t* params,\n                        const ZSTD_compressionParameters* cParams)\n{\n    params->windowLog = cParams->windowLog;\n    ZSTD_STATIC_ASSERT(LDM_BUCKET_SIZE_LOG <= ZSTD_LDM_BUCKETSIZELOG_MAX);\n    DEBUGLOG(4, \"ZSTD_ldm_adjustParameters\");\n    if (params->hashRateLog == 0) {\n        if (params->hashLog > 0) {\n            /* if params->hashLog is set, derive hashRateLog from it */\n            assert(params->hashLog <= ZSTD_HASHLOG_MAX);\n            if (params->windowLog > params->hashLog) {\n                params->hashRateLog = params->windowLog - params->hashLog;\n            }\n        } else {\n            assert(1 <= (int)cParams->strategy && (int)cParams->strategy <= 9);\n            /* mapping from [fast, rate7] to [btultra2, rate4] */\n            params->hashRateLog = 7 - (cParams->strategy/3);\n        }\n    }\n    if (params->hashLog == 0) {\n        if (params->windowLog <= params->hashRateLog) {\n            params->hashLog = ZSTD_HASHLOG_MIN;\n        } else {\n            params->hashLog = BOUNDED(ZSTD_HASHLOG_MIN, params->windowLog - params->hashRateLog, ZSTD_HASHLOG_MAX);\n        }\n    }\n    if (params->minMatchLength == 0) {\n        params->minMatchLength = LDM_MIN_MATCH_LENGTH;\n        if (cParams->strategy >= ZSTD_btultra)\n            params->minMatchLength /= 2;\n    }\n    if (params->bucketSizeLog==0) {\n        assert(1 <= (int)cParams->strategy && (int)cParams->strategy <= 9);\n        params->bucketSizeLog = BOUNDED(LDM_BUCKET_SIZE_LOG, (U32)cParams->strategy, ZSTD_LDM_BUCKETSIZELOG_MAX);\n    }\n    params->bucketSizeLog = MIN(params->bucketSizeLog, params->hashLog);\n}\n\nsize_t ZSTD_ldm_getTableSize(ldmParams_t params)\n{\n    size_t const ldmHSize = ((size_t)1) << params.hashLog;\n    size_t const ldmBucketSizeLog = MIN(params.bucketSizeLog, params.hashLog);\n    size_t const ldmBucketSize = ((size_t)1) << (params.hashLog - ldmBucketSizeLog);\n    size_t const totalSize = ZSTD_cwksp_alloc_size(ldmBucketSize)\n                           + ZSTD_cwksp_alloc_size(ldmHSize * sizeof(ldmEntry_t));\n    return params.enableLdm == ZSTD_ps_enable ? totalSize : 0;\n}\n\nsize_t ZSTD_ldm_getMaxNbSeq(ldmParams_t params, size_t maxChunkSize)\n{\n    return params.enableLdm == ZSTD_ps_enable ? (maxChunkSize / params.minMatchLength) : 0;\n}\n\n/** ZSTD_ldm_getBucket() :\n *  Returns a pointer to the start of the bucket associated with hash. */\nstatic ldmEntry_t* ZSTD_ldm_getBucket(\n        const ldmState_t* ldmState, size_t hash, U32 const bucketSizeLog)\n{\n    return ldmState->hashTable + (hash << bucketSizeLog);\n}\n\n/** ZSTD_ldm_insertEntry() :\n *  Insert the entry with corresponding hash into the hash table */\nstatic void ZSTD_ldm_insertEntry(ldmState_t* ldmState,\n                                 size_t const hash, const ldmEntry_t entry,\n                                 U32 const bucketSizeLog)\n{\n    BYTE* const pOffset = ldmState->bucketOffsets + hash;\n    unsigned const offset = *pOffset;\n\n    *(ZSTD_ldm_getBucket(ldmState, hash, bucketSizeLog) + offset) = entry;\n    *pOffset = (BYTE)((offset + 1) & ((1u << bucketSizeLog) - 1));\n\n}\n\n/** ZSTD_ldm_countBackwardsMatch() :\n *  Returns the number of bytes that match backwards before pIn and pMatch.\n *\n *  We count only bytes where pMatch >= pBase and pIn >= pAnchor. */\nstatic size_t ZSTD_ldm_countBackwardsMatch(\n            const BYTE* pIn, const BYTE* pAnchor,\n            const BYTE* pMatch, const BYTE* pMatchBase)\n{\n    size_t matchLength = 0;\n    while (pIn > pAnchor && pMatch > pMatchBase && pIn[-1] == pMatch[-1]) {\n        pIn--;\n        pMatch--;\n        matchLength++;\n    }\n    return matchLength;\n}\n\n/** ZSTD_ldm_countBackwardsMatch_2segments() :\n *  Returns the number of bytes that match backwards from pMatch,\n *  even with the backwards match spanning 2 different segments.\n *\n *  On reaching `pMatchBase`, start counting from mEnd */\nstatic size_t ZSTD_ldm_countBackwardsMatch_2segments(\n                    const BYTE* pIn, const BYTE* pAnchor,\n                    const BYTE* pMatch, const BYTE* pMatchBase,\n                    const BYTE* pExtDictStart, const BYTE* pExtDictEnd)\n{\n    size_t matchLength = ZSTD_ldm_countBackwardsMatch(pIn, pAnchor, pMatch, pMatchBase);\n    if (pMatch - matchLength != pMatchBase || pMatchBase == pExtDictStart) {\n        /* If backwards match is entirely in the extDict or prefix, immediately return */\n        return matchLength;\n    }\n    DEBUGLOG(7, \"ZSTD_ldm_countBackwardsMatch_2segments: found 2-parts backwards match (length in prefix==%zu)\", matchLength);\n    matchLength += ZSTD_ldm_countBackwardsMatch(pIn - matchLength, pAnchor, pExtDictEnd, pExtDictStart);\n    DEBUGLOG(7, \"final backwards match length = %zu\", matchLength);\n    return matchLength;\n}\n\n/** ZSTD_ldm_fillFastTables() :\n *\n *  Fills the relevant tables for the ZSTD_fast and ZSTD_dfast strategies.\n *  This is similar to ZSTD_loadDictionaryContent.\n *\n *  The tables for the other strategies are filled within their\n *  block compressors. */\nstatic size_t ZSTD_ldm_fillFastTables(ZSTD_MatchState_t* ms,\n                                      void const* end)\n{\n    const BYTE* const iend = (const BYTE*)end;\n\n    switch(ms->cParams.strategy)\n    {\n    case ZSTD_fast:\n        ZSTD_fillHashTable(ms, iend, ZSTD_dtlm_fast, ZSTD_tfp_forCCtx);\n        break;\n\n    case ZSTD_dfast:\n#ifndef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR\n        ZSTD_fillDoubleHashTable(ms, iend, ZSTD_dtlm_fast, ZSTD_tfp_forCCtx);\n#else\n        assert(0); /* shouldn't be called: cparams should've been adjusted. */\n#endif\n        break;\n\n    case ZSTD_greedy:\n    case ZSTD_lazy:\n    case ZSTD_lazy2:\n    case ZSTD_btlazy2:\n    case ZSTD_btopt:\n    case ZSTD_btultra:\n    case ZSTD_btultra2:\n        break;\n    default:\n        assert(0);  /* not possible : not a valid strategy id */\n    }\n\n    return 0;\n}\n\nvoid ZSTD_ldm_fillHashTable(\n            ldmState_t* ldmState, const BYTE* ip,\n            const BYTE* iend, ldmParams_t const* params)\n{\n    U32 const minMatchLength = params->minMatchLength;\n    U32 const bucketSizeLog = params->bucketSizeLog;\n    U32 const hBits = params->hashLog - bucketSizeLog;\n    BYTE const* const base = ldmState->window.base;\n    BYTE const* const istart = ip;\n    ldmRollingHashState_t hashState;\n    size_t* const splits = ldmState->splitIndices;\n    unsigned numSplits;\n\n    DEBUGLOG(5, \"ZSTD_ldm_fillHashTable\");\n\n    ZSTD_ldm_gear_init(&hashState, params);\n    while (ip < iend) {\n        size_t hashed;\n        unsigned n;\n\n        numSplits = 0;\n        hashed = ZSTD_ldm_gear_feed(&hashState, ip, (size_t)(iend - ip), splits, &numSplits);\n\n        for (n = 0; n < numSplits; n++) {\n            if (ip + splits[n] >= istart + minMatchLength) {\n                BYTE const* const split = ip + splits[n] - minMatchLength;\n                U64 const xxhash = XXH64(split, minMatchLength, 0);\n                U32 const hash = (U32)(xxhash & (((U32)1 << hBits) - 1));\n                ldmEntry_t entry;\n\n                entry.offset = (U32)(split - base);\n                entry.checksum = (U32)(xxhash >> 32);\n                ZSTD_ldm_insertEntry(ldmState, hash, entry, params->bucketSizeLog);\n            }\n        }\n\n        ip += hashed;\n    }\n}\n\n\n/** ZSTD_ldm_limitTableUpdate() :\n *\n *  Sets cctx->nextToUpdate to a position corresponding closer to anchor\n *  if it is far way\n *  (after a long match, only update tables a limited amount). */\nstatic void ZSTD_ldm_limitTableUpdate(ZSTD_MatchState_t* ms, const BYTE* anchor)\n{\n    U32 const curr = (U32)(anchor - ms->window.base);\n    if (curr > ms->nextToUpdate + 1024) {\n        ms->nextToUpdate =\n            curr - MIN(512, curr - ms->nextToUpdate - 1024);\n    }\n}\n\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_ldm_generateSequences_internal(\n        ldmState_t* ldmState, RawSeqStore_t* rawSeqStore,\n        ldmParams_t const* params, void const* src, size_t srcSize)\n{\n    /* LDM parameters */\n    int const extDict = ZSTD_window_hasExtDict(ldmState->window);\n    U32 const minMatchLength = params->minMatchLength;\n    U32 const entsPerBucket = 1U << params->bucketSizeLog;\n    U32 const hBits = params->hashLog - params->bucketSizeLog;\n    /* Prefix and extDict parameters */\n    U32 const dictLimit = ldmState->window.dictLimit;\n    U32 const lowestIndex = extDict ? ldmState->window.lowLimit : dictLimit;\n    BYTE const* const base = ldmState->window.base;\n    BYTE const* const dictBase = extDict ? ldmState->window.dictBase : NULL;\n    BYTE const* const dictStart = extDict ? dictBase + lowestIndex : NULL;\n    BYTE const* const dictEnd = extDict ? dictBase + dictLimit : NULL;\n    BYTE const* const lowPrefixPtr = base + dictLimit;\n    /* Input bounds */\n    BYTE const* const istart = (BYTE const*)src;\n    BYTE const* const iend = istart + srcSize;\n    BYTE const* const ilimit = iend - HASH_READ_SIZE;\n    /* Input positions */\n    BYTE const* anchor = istart;\n    BYTE const* ip = istart;\n    /* Rolling hash state */\n    ldmRollingHashState_t hashState;\n    /* Arrays for staged-processing */\n    size_t* const splits = ldmState->splitIndices;\n    ldmMatchCandidate_t* const candidates = ldmState->matchCandidates;\n    unsigned numSplits;\n\n    if (srcSize < minMatchLength)\n        return iend - anchor;\n\n    /* Initialize the rolling hash state with the first minMatchLength bytes */\n    ZSTD_ldm_gear_init(&hashState, params);\n    ZSTD_ldm_gear_reset(&hashState, ip, minMatchLength);\n    ip += minMatchLength;\n\n    while (ip < ilimit) {\n        size_t hashed;\n        unsigned n;\n\n        numSplits = 0;\n        hashed = ZSTD_ldm_gear_feed(&hashState, ip, ilimit - ip,\n                                    splits, &numSplits);\n\n        for (n = 0; n < numSplits; n++) {\n            BYTE const* const split = ip + splits[n] - minMatchLength;\n            U64 const xxhash = XXH64(split, minMatchLength, 0);\n            U32 const hash = (U32)(xxhash & (((U32)1 << hBits) - 1));\n\n            candidates[n].split = split;\n            candidates[n].hash = hash;\n            candidates[n].checksum = (U32)(xxhash >> 32);\n            candidates[n].bucket = ZSTD_ldm_getBucket(ldmState, hash, params->bucketSizeLog);\n            PREFETCH_L1(candidates[n].bucket);\n        }\n\n        for (n = 0; n < numSplits; n++) {\n            size_t forwardMatchLength = 0, backwardMatchLength = 0,\n                   bestMatchLength = 0, mLength;\n            U32 offset;\n            BYTE const* const split = candidates[n].split;\n            U32 const checksum = candidates[n].checksum;\n            U32 const hash = candidates[n].hash;\n            ldmEntry_t* const bucket = candidates[n].bucket;\n            ldmEntry_t const* cur;\n            ldmEntry_t const* bestEntry = NULL;\n            ldmEntry_t newEntry;\n\n            newEntry.offset = (U32)(split - base);\n            newEntry.checksum = checksum;\n\n            /* If a split point would generate a sequence overlapping with\n             * the previous one, we merely register it in the hash table and\n             * move on */\n            if (split < anchor) {\n                ZSTD_ldm_insertEntry(ldmState, hash, newEntry, params->bucketSizeLog);\n                continue;\n            }\n\n            for (cur = bucket; cur < bucket + entsPerBucket; cur++) {\n                size_t curForwardMatchLength, curBackwardMatchLength,\n                       curTotalMatchLength;\n                if (cur->checksum != checksum || cur->offset <= lowestIndex) {\n                    continue;\n                }\n                if (extDict) {\n                    BYTE const* const curMatchBase =\n                        cur->offset < dictLimit ? dictBase : base;\n                    BYTE const* const pMatch = curMatchBase + cur->offset;\n                    BYTE const* const matchEnd =\n                        cur->offset < dictLimit ? dictEnd : iend;\n                    BYTE const* const lowMatchPtr =\n                        cur->offset < dictLimit ? dictStart : lowPrefixPtr;\n                    curForwardMatchLength =\n                        ZSTD_count_2segments(split, pMatch, iend, matchEnd, lowPrefixPtr);\n                    if (curForwardMatchLength < minMatchLength) {\n                        continue;\n                    }\n                    curBackwardMatchLength = ZSTD_ldm_countBackwardsMatch_2segments(\n                            split, anchor, pMatch, lowMatchPtr, dictStart, dictEnd);\n                } else { /* !extDict */\n                    BYTE const* const pMatch = base + cur->offset;\n                    curForwardMatchLength = ZSTD_count(split, pMatch, iend);\n                    if (curForwardMatchLength < minMatchLength) {\n                        continue;\n                    }\n                    curBackwardMatchLength =\n                        ZSTD_ldm_countBackwardsMatch(split, anchor, pMatch, lowPrefixPtr);\n                }\n                curTotalMatchLength = curForwardMatchLength + curBackwardMatchLength;\n\n                if (curTotalMatchLength > bestMatchLength) {\n                    bestMatchLength = curTotalMatchLength;\n                    forwardMatchLength = curForwardMatchLength;\n                    backwardMatchLength = curBackwardMatchLength;\n                    bestEntry = cur;\n                }\n            }\n\n            /* No match found -- insert an entry into the hash table\n             * and process the next candidate match */\n            if (bestEntry == NULL) {\n                ZSTD_ldm_insertEntry(ldmState, hash, newEntry, params->bucketSizeLog);\n                continue;\n            }\n\n            /* Match found */\n            offset = (U32)(split - base) - bestEntry->offset;\n            mLength = forwardMatchLength + backwardMatchLength;\n            {\n                rawSeq* const seq = rawSeqStore->seq + rawSeqStore->size;\n\n                /* Out of sequence storage */\n                if (rawSeqStore->size == rawSeqStore->capacity)\n                    return ERROR(dstSize_tooSmall);\n                seq->litLength = (U32)(split - backwardMatchLength - anchor);\n                seq->matchLength = (U32)mLength;\n                seq->offset = offset;\n                rawSeqStore->size++;\n            }\n\n            /* Insert the current entry into the hash table --- it must be\n             * done after the previous block to avoid clobbering bestEntry */\n            ZSTD_ldm_insertEntry(ldmState, hash, newEntry, params->bucketSizeLog);\n\n            anchor = split + forwardMatchLength;\n\n            /* If we find a match that ends after the data that we've hashed\n             * then we have a repeating, overlapping, pattern. E.g. all zeros.\n             * If one repetition of the pattern matches our `stopMask` then all\n             * repetitions will. We don't need to insert them all into out table,\n             * only the first one. So skip over overlapping matches.\n             * This is a major speed boost (20x) for compressing a single byte\n             * repeated, when that byte ends up in the table.\n             */\n            if (anchor > ip + hashed) {\n                ZSTD_ldm_gear_reset(&hashState, anchor - minMatchLength, minMatchLength);\n                /* Continue the outer loop at anchor (ip + hashed == anchor). */\n                ip = anchor - hashed;\n                break;\n            }\n        }\n\n        ip += hashed;\n    }\n\n    return iend - anchor;\n}\n\n/*! ZSTD_ldm_reduceTable() :\n *  reduce table indexes by `reducerValue` */\nstatic void ZSTD_ldm_reduceTable(ldmEntry_t* const table, U32 const size,\n                                 U32 const reducerValue)\n{\n    U32 u;\n    for (u = 0; u < size; u++) {\n        if (table[u].offset < reducerValue) table[u].offset = 0;\n        else table[u].offset -= reducerValue;\n    }\n}\n\nsize_t ZSTD_ldm_generateSequences(\n        ldmState_t* ldmState, RawSeqStore_t* sequences,\n        ldmParams_t const* params, void const* src, size_t srcSize)\n{\n    U32 const maxDist = 1U << params->windowLog;\n    BYTE const* const istart = (BYTE const*)src;\n    BYTE const* const iend = istart + srcSize;\n    size_t const kMaxChunkSize = 1 << 20;\n    size_t const nbChunks = (srcSize / kMaxChunkSize) + ((srcSize % kMaxChunkSize) != 0);\n    size_t chunk;\n    size_t leftoverSize = 0;\n\n    assert(ZSTD_CHUNKSIZE_MAX >= kMaxChunkSize);\n    /* Check that ZSTD_window_update() has been called for this chunk prior\n     * to passing it to this function.\n     */\n    assert(ldmState->window.nextSrc >= (BYTE const*)src + srcSize);\n    /* The input could be very large (in zstdmt), so it must be broken up into\n     * chunks to enforce the maximum distance and handle overflow correction.\n     */\n    assert(sequences->pos <= sequences->size);\n    assert(sequences->size <= sequences->capacity);\n    for (chunk = 0; chunk < nbChunks && sequences->size < sequences->capacity; ++chunk) {\n        BYTE const* const chunkStart = istart + chunk * kMaxChunkSize;\n        size_t const remaining = (size_t)(iend - chunkStart);\n        BYTE const *const chunkEnd =\n            (remaining < kMaxChunkSize) ? iend : chunkStart + kMaxChunkSize;\n        size_t const chunkSize = chunkEnd - chunkStart;\n        size_t newLeftoverSize;\n        size_t const prevSize = sequences->size;\n\n        assert(chunkStart < iend);\n        /* 1. Perform overflow correction if necessary. */\n        if (ZSTD_window_needOverflowCorrection(ldmState->window, 0, maxDist, ldmState->loadedDictEnd, chunkStart, chunkEnd)) {\n            U32 const ldmHSize = 1U << params->hashLog;\n            U32 const correction = ZSTD_window_correctOverflow(\n                &ldmState->window, /* cycleLog */ 0, maxDist, chunkStart);\n            ZSTD_ldm_reduceTable(ldmState->hashTable, ldmHSize, correction);\n            /* invalidate dictionaries on overflow correction */\n            ldmState->loadedDictEnd = 0;\n        }\n        /* 2. We enforce the maximum offset allowed.\n         *\n         * kMaxChunkSize should be small enough that we don't lose too much of\n         * the window through early invalidation.\n         * TODO: * Test the chunk size.\n         *       * Try invalidation after the sequence generation and test the\n         *         offset against maxDist directly.\n         *\n         * NOTE: Because of dictionaries + sequence splitting we MUST make sure\n         * that any offset used is valid at the END of the sequence, since it may\n         * be split into two sequences. This condition holds when using\n         * ZSTD_window_enforceMaxDist(), but if we move to checking offsets\n         * against maxDist directly, we'll have to carefully handle that case.\n         */\n        ZSTD_window_enforceMaxDist(&ldmState->window, chunkEnd, maxDist, &ldmState->loadedDictEnd, NULL);\n        /* 3. Generate the sequences for the chunk, and get newLeftoverSize. */\n        newLeftoverSize = ZSTD_ldm_generateSequences_internal(\n            ldmState, sequences, params, chunkStart, chunkSize);\n        if (ZSTD_isError(newLeftoverSize))\n            return newLeftoverSize;\n        /* 4. We add the leftover literals from previous iterations to the first\n         *    newly generated sequence, or add the `newLeftoverSize` if none are\n         *    generated.\n         */\n        /* Prepend the leftover literals from the last call */\n        if (prevSize < sequences->size) {\n            sequences->seq[prevSize].litLength += (U32)leftoverSize;\n            leftoverSize = newLeftoverSize;\n        } else {\n            assert(newLeftoverSize == chunkSize);\n            leftoverSize += chunkSize;\n        }\n    }\n    return 0;\n}\n\nvoid\nZSTD_ldm_skipSequences(RawSeqStore_t* rawSeqStore, size_t srcSize, U32 const minMatch)\n{\n    while (srcSize > 0 && rawSeqStore->pos < rawSeqStore->size) {\n        rawSeq* seq = rawSeqStore->seq + rawSeqStore->pos;\n        if (srcSize <= seq->litLength) {\n            /* Skip past srcSize literals */\n            seq->litLength -= (U32)srcSize;\n            return;\n        }\n        srcSize -= seq->litLength;\n        seq->litLength = 0;\n        if (srcSize < seq->matchLength) {\n            /* Skip past the first srcSize of the match */\n            seq->matchLength -= (U32)srcSize;\n            if (seq->matchLength < minMatch) {\n                /* The match is too short, omit it */\n                if (rawSeqStore->pos + 1 < rawSeqStore->size) {\n                    seq[1].litLength += seq[0].matchLength;\n                }\n                rawSeqStore->pos++;\n            }\n            return;\n        }\n        srcSize -= seq->matchLength;\n        seq->matchLength = 0;\n        rawSeqStore->pos++;\n    }\n}\n\n/**\n * If the sequence length is longer than remaining then the sequence is split\n * between this block and the next.\n *\n * Returns the current sequence to handle, or if the rest of the block should\n * be literals, it returns a sequence with offset == 0.\n */\nstatic rawSeq maybeSplitSequence(RawSeqStore_t* rawSeqStore,\n                                 U32 const remaining, U32 const minMatch)\n{\n    rawSeq sequence = rawSeqStore->seq[rawSeqStore->pos];\n    assert(sequence.offset > 0);\n    /* Likely: No partial sequence */\n    if (remaining >= sequence.litLength + sequence.matchLength) {\n        rawSeqStore->pos++;\n        return sequence;\n    }\n    /* Cut the sequence short (offset == 0 ==> rest is literals). */\n    if (remaining <= sequence.litLength) {\n        sequence.offset = 0;\n    } else if (remaining < sequence.litLength + sequence.matchLength) {\n        sequence.matchLength = remaining - sequence.litLength;\n        if (sequence.matchLength < minMatch) {\n            sequence.offset = 0;\n        }\n    }\n    /* Skip past `remaining` bytes for the future sequences. */\n    ZSTD_ldm_skipSequences(rawSeqStore, remaining, minMatch);\n    return sequence;\n}\n\nvoid ZSTD_ldm_skipRawSeqStoreBytes(RawSeqStore_t* rawSeqStore, size_t nbBytes) {\n    U32 currPos = (U32)(rawSeqStore->posInSequence + nbBytes);\n    while (currPos && rawSeqStore->pos < rawSeqStore->size) {\n        rawSeq currSeq = rawSeqStore->seq[rawSeqStore->pos];\n        if (currPos >= currSeq.litLength + currSeq.matchLength) {\n            currPos -= currSeq.litLength + currSeq.matchLength;\n            rawSeqStore->pos++;\n        } else {\n            rawSeqStore->posInSequence = currPos;\n            break;\n        }\n    }\n    if (currPos == 0 || rawSeqStore->pos == rawSeqStore->size) {\n        rawSeqStore->posInSequence = 0;\n    }\n}\n\nsize_t ZSTD_ldm_blockCompress(RawSeqStore_t* rawSeqStore,\n    ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n    ZSTD_ParamSwitch_e useRowMatchFinder,\n    void const* src, size_t srcSize)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    unsigned const minMatch = cParams->minMatch;\n    ZSTD_BlockCompressor_f const blockCompressor =\n        ZSTD_selectBlockCompressor(cParams->strategy, useRowMatchFinder, ZSTD_matchState_dictMode(ms));\n    /* Input bounds */\n    BYTE const* const istart = (BYTE const*)src;\n    BYTE const* const iend = istart + srcSize;\n    /* Input positions */\n    BYTE const* ip = istart;\n\n    DEBUGLOG(5, \"ZSTD_ldm_blockCompress: srcSize=%zu\", srcSize);\n    /* If using opt parser, use LDMs only as candidates rather than always accepting them */\n    if (cParams->strategy >= ZSTD_btopt) {\n        size_t lastLLSize;\n        ms->ldmSeqStore = rawSeqStore;\n        lastLLSize = blockCompressor(ms, seqStore, rep, src, srcSize);\n        ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore, srcSize);\n        return lastLLSize;\n    }\n\n    assert(rawSeqStore->pos <= rawSeqStore->size);\n    assert(rawSeqStore->size <= rawSeqStore->capacity);\n    /* Loop through each sequence and apply the block compressor to the literals */\n    while (rawSeqStore->pos < rawSeqStore->size && ip < iend) {\n        /* maybeSplitSequence updates rawSeqStore->pos */\n        rawSeq const sequence = maybeSplitSequence(rawSeqStore,\n                                                   (U32)(iend - ip), minMatch);\n        /* End signal */\n        if (sequence.offset == 0)\n            break;\n\n        assert(ip + sequence.litLength + sequence.matchLength <= iend);\n\n        /* Fill tables for block compressor */\n        ZSTD_ldm_limitTableUpdate(ms, ip);\n        ZSTD_ldm_fillFastTables(ms, ip);\n        /* Run the block compressor */\n        DEBUGLOG(5, \"pos %u : calling block compressor on segment of size %u\", (unsigned)(ip-istart), sequence.litLength);\n        {\n            int i;\n            size_t const newLitLength =\n                blockCompressor(ms, seqStore, rep, ip, sequence.litLength);\n            ip += sequence.litLength;\n            /* Update the repcodes */\n            for (i = ZSTD_REP_NUM - 1; i > 0; i--)\n                rep[i] = rep[i-1];\n            rep[0] = sequence.offset;\n            /* Store the sequence */\n            ZSTD_storeSeq(seqStore, newLitLength, ip - newLitLength, iend,\n                          OFFSET_TO_OFFBASE(sequence.offset),\n                          sequence.matchLength);\n            ip += sequence.matchLength;\n        }\n    }\n    /* Fill the tables for the block compressor */\n    ZSTD_ldm_limitTableUpdate(ms, ip);\n    ZSTD_ldm_fillFastTables(ms, ip);\n    /* Compress the last literals */\n    return blockCompressor(ms, seqStore, rep, ip, iend - ip);\n}\n"
  },
  {
    "path": "lib/compress/zstd_ldm.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_LDM_H\n#define ZSTD_LDM_H\n\n#include \"zstd_compress_internal.h\"   /* ldmParams_t, U32 */\n#include \"../zstd.h\"   /* ZSTD_CCtx, size_t */\n\n/*-*************************************\n*  Long distance matching\n***************************************/\n\n#define ZSTD_LDM_DEFAULT_WINDOW_LOG ZSTD_WINDOWLOG_LIMIT_DEFAULT\n\nvoid ZSTD_ldm_fillHashTable(\n            ldmState_t* state, const BYTE* ip,\n            const BYTE* iend, ldmParams_t const* params);\n\n/**\n * ZSTD_ldm_generateSequences():\n *\n * Generates the sequences using the long distance match finder.\n * Generates long range matching sequences in `sequences`, which parse a prefix\n * of the source. `sequences` must be large enough to store every sequence,\n * which can be checked with `ZSTD_ldm_getMaxNbSeq()`.\n * @returns 0 or an error code.\n *\n * NOTE: The user must have called ZSTD_window_update() for all of the input\n * they have, even if they pass it to ZSTD_ldm_generateSequences() in chunks.\n * NOTE: This function returns an error if it runs out of space to store\n *       sequences.\n */\nsize_t ZSTD_ldm_generateSequences(\n            ldmState_t* ldms, RawSeqStore_t* sequences,\n            ldmParams_t const* params, void const* src, size_t srcSize);\n\n/**\n * ZSTD_ldm_blockCompress():\n *\n * Compresses a block using the predefined sequences, along with a secondary\n * block compressor. The literals section of every sequence is passed to the\n * secondary block compressor, and those sequences are interspersed with the\n * predefined sequences. Returns the length of the last literals.\n * Updates `rawSeqStore.pos` to indicate how many sequences have been consumed.\n * `rawSeqStore.seq` may also be updated to split the last sequence between two\n * blocks.\n * @return The length of the last literals.\n *\n * NOTE: The source must be at most the maximum block size, but the predefined\n * sequences can be any size, and may be longer than the block. In the case that\n * they are longer than the block, the last sequences may need to be split into\n * two. We handle that case correctly, and update `rawSeqStore` appropriately.\n * NOTE: This function does not return any errors.\n */\nsize_t ZSTD_ldm_blockCompress(RawSeqStore_t* rawSeqStore,\n            ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n            ZSTD_ParamSwitch_e useRowMatchFinder,\n            void const* src, size_t srcSize);\n\n/**\n * ZSTD_ldm_skipSequences():\n *\n * Skip past `srcSize` bytes worth of sequences in `rawSeqStore`.\n * Avoids emitting matches less than `minMatch` bytes.\n * Must be called for data that is not passed to ZSTD_ldm_blockCompress().\n */\nvoid ZSTD_ldm_skipSequences(RawSeqStore_t* rawSeqStore, size_t srcSize,\n    U32 const minMatch);\n\n/* ZSTD_ldm_skipRawSeqStoreBytes():\n * Moves forward in rawSeqStore by nbBytes, updating fields 'pos' and 'posInSequence'.\n * Not to be used in conjunction with ZSTD_ldm_skipSequences().\n * Must be called for data with is not passed to ZSTD_ldm_blockCompress().\n */\nvoid ZSTD_ldm_skipRawSeqStoreBytes(RawSeqStore_t* rawSeqStore, size_t nbBytes);\n\n/** ZSTD_ldm_getTableSize() :\n *  Estimate the space needed for long distance matching tables or 0 if LDM is\n *  disabled.\n */\nsize_t ZSTD_ldm_getTableSize(ldmParams_t params);\n\n/** ZSTD_ldm_getSeqSpace() :\n *  Return an upper bound on the number of sequences that can be produced by\n *  the long distance matcher, or 0 if LDM is disabled.\n */\nsize_t ZSTD_ldm_getMaxNbSeq(ldmParams_t params, size_t maxChunkSize);\n\n/** ZSTD_ldm_adjustParameters() :\n *  If the params->hashRateLog is not set, set it to its default value based on\n *  windowLog and params->hashLog.\n *\n *  Ensures that params->bucketSizeLog is <= params->hashLog (setting it to\n *  params->hashLog if it is not).\n *\n *  Ensures that the minMatchLength >= targetLength during optimal parsing.\n */\nvoid ZSTD_ldm_adjustParameters(ldmParams_t* params,\n                               ZSTD_compressionParameters const* cParams);\n\n#endif /* ZSTD_FAST_H */\n"
  },
  {
    "path": "lib/compress/zstd_ldm_geartab.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_LDM_GEARTAB_H\n#define ZSTD_LDM_GEARTAB_H\n\n#include \"../common/compiler.h\" /* UNUSED_ATTR */\n#include \"../common/mem.h\"      /* U64 */\n\nstatic UNUSED_ATTR const U64 ZSTD_ldm_gearTab[256] = {\n    0xf5b8f72c5f77775c, 0x84935f266b7ac412, 0xb647ada9ca730ccc,\n    0xb065bb4b114fb1de, 0x34584e7e8c3a9fd0, 0x4e97e17c6ae26b05,\n    0x3a03d743bc99a604, 0xcecd042422c4044f, 0x76de76c58524259e,\n    0x9c8528f65badeaca, 0x86563706e2097529, 0x2902475fa375d889,\n    0xafb32a9739a5ebe6, 0xce2714da3883e639, 0x21eaf821722e69e,\n    0x37b628620b628,    0x49a8d455d88caf5,  0x8556d711e6958140,\n    0x4f7ae74fc605c1f,  0x829f0c3468bd3a20, 0x4ffdc885c625179e,\n    0x8473de048a3daf1b, 0x51008822b05646b2, 0x69d75d12b2d1cc5f,\n    0x8c9d4a19159154bc, 0xc3cc10f4abbd4003, 0xd06ddc1cecb97391,\n    0xbe48e6e7ed80302e, 0x3481db31cee03547, 0xacc3f67cdaa1d210,\n    0x65cb771d8c7f96cc, 0x8eb27177055723dd, 0xc789950d44cd94be,\n    0x934feadc3700b12b, 0x5e485f11edbdf182, 0x1e2e2a46fd64767a,\n    0x2969ca71d82efa7c, 0x9d46e9935ebbba2e, 0xe056b67e05e6822b,\n    0x94d73f55739d03a0, 0xcd7010bdb69b5a03, 0x455ef9fcd79b82f4,\n    0x869cb54a8749c161, 0x38d1a4fa6185d225, 0xb475166f94bbe9bb,\n    0xa4143548720959f1, 0x7aed4780ba6b26ba, 0xd0ce264439e02312,\n    0x84366d746078d508, 0xa8ce973c72ed17be, 0x21c323a29a430b01,\n    0x9962d617e3af80ee, 0xab0ce91d9c8cf75b, 0x530e8ee6d19a4dbc,\n    0x2ef68c0cf53f5d72, 0xc03a681640a85506, 0x496e4e9f9c310967,\n    0x78580472b59b14a0, 0x273824c23b388577, 0x66bf923ad45cb553,\n    0x47ae1a5a2492ba86, 0x35e304569e229659, 0x4765182a46870b6f,\n    0x6cbab625e9099412, 0xddac9a2e598522c1, 0x7172086e666624f2,\n    0xdf5003ca503b7837, 0x88c0c1db78563d09, 0x58d51865acfc289d,\n    0x177671aec65224f1, 0xfb79d8a241e967d7, 0x2be1e101cad9a49a,\n    0x6625682f6e29186b, 0x399553457ac06e50, 0x35dffb4c23abb74,\n    0x429db2591f54aade, 0xc52802a8037d1009, 0x6acb27381f0b25f3,\n    0xf45e2551ee4f823b, 0x8b0ea2d99580c2f7, 0x3bed519cbcb4e1e1,\n    0xff452823dbb010a,  0x9d42ed614f3dd267, 0x5b9313c06257c57b,\n    0xa114b8008b5e1442, 0xc1fe311c11c13d4b, 0x66e8763ea34c5568,\n    0x8b982af1c262f05d, 0xee8876faaa75fbb7, 0x8a62a4d0d172bb2a,\n    0xc13d94a3b7449a97, 0x6dbbba9dc15d037c, 0xc786101f1d92e0f1,\n    0xd78681a907a0b79b, 0xf61aaf2962c9abb9, 0x2cfd16fcd3cb7ad9,\n    0x868c5b6744624d21, 0x25e650899c74ddd7, 0xba042af4a7c37463,\n    0x4eb1a539465a3eca, 0xbe09dbf03b05d5ca, 0x774e5a362b5472ba,\n    0x47a1221229d183cd, 0x504b0ca18ef5a2df, 0xdffbdfbde2456eb9,\n    0x46cd2b2fbee34634, 0xf2aef8fe819d98c3, 0x357f5276d4599d61,\n    0x24a5483879c453e3, 0x88026889192b4b9,  0x28da96671782dbec,\n    0x4ef37c40588e9aaa, 0x8837b90651bc9fb3, 0xc164f741d3f0e5d6,\n    0xbc135a0a704b70ba, 0x69cd868f7622ada,  0xbc37ba89e0b9c0ab,\n    0x47c14a01323552f6, 0x4f00794bacee98bb, 0x7107de7d637a69d5,\n    0x88af793bb6f2255e, 0xf3c6466b8799b598, 0xc288c616aa7f3b59,\n    0x81ca63cf42fca3fd, 0x88d85ace36a2674b, 0xd056bd3792389e7,\n    0xe55c396c4e9dd32d, 0xbefb504571e6c0a6, 0x96ab32115e91e8cc,\n    0xbf8acb18de8f38d1, 0x66dae58801672606, 0x833b6017872317fb,\n    0xb87c16f2d1c92864, 0xdb766a74e58b669c, 0x89659f85c61417be,\n    0xc8daad856011ea0c, 0x76a4b565b6fe7eae, 0xa469d085f6237312,\n    0xaaf0365683a3e96c, 0x4dbb746f8424f7b8, 0x638755af4e4acc1,\n    0x3d7807f5bde64486, 0x17be6d8f5bbb7639, 0x903f0cd44dc35dc,\n    0x67b672eafdf1196c, 0xa676ff93ed4c82f1, 0x521d1004c5053d9d,\n    0x37ba9ad09ccc9202, 0x84e54d297aacfb51, 0xa0b4b776a143445,\n    0x820d471e20b348e,  0x1874383cb83d46dc, 0x97edeec7a1efe11c,\n    0xb330e50b1bdc42aa, 0x1dd91955ce70e032, 0xa514cdb88f2939d5,\n    0x2791233fd90db9d3, 0x7b670a4cc50f7a9b, 0x77c07d2a05c6dfa5,\n    0xe3778b6646d0a6fa, 0xb39c8eda47b56749, 0x933ed448addbef28,\n    0xaf846af6ab7d0bf4, 0xe5af208eb666e49,  0x5e6622f73534cd6a,\n    0x297daeca42ef5b6e, 0x862daef3d35539a6, 0xe68722498f8e1ea9,\n    0x981c53093dc0d572, 0xfa09b0bfbf86fbf5, 0x30b1e96166219f15,\n    0x70e7d466bdc4fb83, 0x5a66736e35f2a8e9, 0xcddb59d2b7c1baef,\n    0xd6c7d247d26d8996, 0xea4e39eac8de1ba3, 0x539c8bb19fa3aff2,\n    0x9f90e4c5fd508d8,  0xa34e5956fbaf3385, 0x2e2f8e151d3ef375,\n    0x173691e9b83faec1, 0xb85a8d56bf016379, 0x8382381267408ae3,\n    0xb90f901bbdc0096d, 0x7c6ad32933bcec65, 0x76bb5e2f2c8ad595,\n    0x390f851a6cf46d28, 0xc3e6064da1c2da72, 0xc52a0c101cfa5389,\n    0xd78eaf84a3fbc530, 0x3781b9e2288b997e, 0x73c2f6dea83d05c4,\n    0x4228e364c5b5ed7,  0x9d7a3edf0da43911, 0x8edcfeda24686756,\n    0x5e7667a7b7a9b3a1, 0x4c4f389fa143791d, 0xb08bc1023da7cddc,\n    0x7ab4be3ae529b1cc, 0x754e6132dbe74ff9, 0x71635442a839df45,\n    0x2f6fb1643fbe52de, 0x961e0a42cf7a8177, 0xf3b45d83d89ef2ea,\n    0xee3de4cf4a6e3e9b, 0xcd6848542c3295e7, 0xe4cee1664c78662f,\n    0x9947548b474c68c4, 0x25d73777a5ed8b0b, 0xc915b1d636b7fc,\n    0x21c2ba75d9b0d2da, 0x5f6b5dcf608a64a1, 0xdcf333255ff9570c,\n    0x633b922418ced4ee, 0xc136dde0b004b34a, 0x58cc83b05d4b2f5a,\n    0x5eb424dda28e42d2, 0x62df47369739cd98, 0xb4e0b42485e4ce17,\n    0x16e1f0c1f9a8d1e7, 0x8ec3916707560ebf, 0x62ba6e2df2cc9db3,\n    0xcbf9f4ff77d83a16, 0x78d9d7d07d2bbcc4, 0xef554ce1e02c41f4,\n    0x8d7581127eccf94d, 0xa9b53336cb3c8a05, 0x38c42c0bf45c4f91,\n    0x640893cdf4488863, 0x80ec34bc575ea568, 0x39f324f5b48eaa40,\n    0xe9d9ed1f8eff527f, 0x9224fc058cc5a214, 0xbaba00b04cfe7741,\n    0x309a9f120fcf52af, 0xa558f3ec65626212, 0x424bec8b7adabe2f,\n    0x41622513a6aea433, 0xb88da2d5324ca798, 0xd287733b245528a4,\n    0x9a44697e6d68aec3, 0x7b1093be2f49bb28, 0x50bbec632e3d8aad,\n    0x6cd90723e1ea8283, 0x897b9e7431b02bf3, 0x219efdcb338a7047,\n    0x3b0311f0a27c0656, 0xdb17bf91c0db96e7, 0x8cd4fd6b4e85a5b2,\n    0xfab071054ba6409d, 0x40d6fe831fa9dfd9, 0xaf358debad7d791e,\n    0xeb8d0e25a65e3e58, 0xbbcbd3df14e08580, 0xcf751f27ecdab2b,\n    0x2b4da14f2613d8f4\n};\n\n#endif /* ZSTD_LDM_GEARTAB_H */\n"
  },
  {
    "path": "lib/compress/zstd_opt.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"zstd_compress_internal.h\"\n#include \"hist.h\"\n#include \"zstd_opt.h\"\n\n#if !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR)\n\n#define ZSTD_LITFREQ_ADD    2   /* scaling factor for litFreq, so that frequencies adapt faster to new stats */\n#define ZSTD_MAX_PRICE     (1<<30)\n\n#define ZSTD_PREDEF_THRESHOLD 8   /* if srcSize < ZSTD_PREDEF_THRESHOLD, symbols' cost is assumed static, directly determined by pre-defined distributions */\n\n\n/*-*************************************\n*  Price functions for optimal parser\n***************************************/\n\n#if 0    /* approximation at bit level (for tests) */\n#  define BITCOST_ACCURACY 0\n#  define BITCOST_MULTIPLIER (1 << BITCOST_ACCURACY)\n#  define WEIGHT(stat, opt) ((void)(opt), ZSTD_bitWeight(stat))\n#elif 0  /* fractional bit accuracy (for tests) */\n#  define BITCOST_ACCURACY 8\n#  define BITCOST_MULTIPLIER (1 << BITCOST_ACCURACY)\n#  define WEIGHT(stat,opt) ((void)(opt), ZSTD_fracWeight(stat))\n#else    /* opt==approx, ultra==accurate */\n#  define BITCOST_ACCURACY 8\n#  define BITCOST_MULTIPLIER (1 << BITCOST_ACCURACY)\n#  define WEIGHT(stat,opt) ((opt) ? ZSTD_fracWeight(stat) : ZSTD_bitWeight(stat))\n#endif\n\n/* ZSTD_bitWeight() :\n * provide estimated \"cost\" of a stat in full bits only */\nMEM_STATIC U32 ZSTD_bitWeight(U32 stat)\n{\n    return (ZSTD_highbit32(stat+1) * BITCOST_MULTIPLIER);\n}\n\n/* ZSTD_fracWeight() :\n * provide fractional-bit \"cost\" of a stat,\n * using linear interpolation approximation */\nMEM_STATIC U32 ZSTD_fracWeight(U32 rawStat)\n{\n    U32 const stat = rawStat + 1;\n    U32 const hb = ZSTD_highbit32(stat);\n    U32 const BWeight = hb * BITCOST_MULTIPLIER;\n    /* Fweight was meant for \"Fractional weight\"\n     * but it's effectively a value between 1 and 2\n     * using fixed point arithmetic */\n    U32 const FWeight = (stat << BITCOST_ACCURACY) >> hb;\n    U32 const weight = BWeight + FWeight;\n    assert(hb + BITCOST_ACCURACY < 31);\n    return weight;\n}\n\n#if (DEBUGLEVEL>=2)\n/* debugging function,\n * @return price in bytes as fractional value\n * for debug messages only */\nMEM_STATIC double ZSTD_fCost(int price)\n{\n    return (double)price / (BITCOST_MULTIPLIER*8);\n}\n#endif\n\nstatic int ZSTD_compressedLiterals(optState_t const* const optPtr)\n{\n    return optPtr->literalCompressionMode != ZSTD_ps_disable;\n}\n\nstatic void ZSTD_setBasePrices(optState_t* optPtr, int optLevel)\n{\n    if (ZSTD_compressedLiterals(optPtr))\n        optPtr->litSumBasePrice = WEIGHT(optPtr->litSum, optLevel);\n    optPtr->litLengthSumBasePrice = WEIGHT(optPtr->litLengthSum, optLevel);\n    optPtr->matchLengthSumBasePrice = WEIGHT(optPtr->matchLengthSum, optLevel);\n    optPtr->offCodeSumBasePrice = WEIGHT(optPtr->offCodeSum, optLevel);\n}\n\n\nstatic U32 sum_u32(const unsigned table[], size_t nbElts)\n{\n    size_t n;\n    U32 total = 0;\n    for (n=0; n<nbElts; n++) {\n        total += table[n];\n    }\n    return total;\n}\n\ntypedef enum { base_0possible=0, base_1guaranteed=1 } base_directive_e;\n\nstatic U32\nZSTD_downscaleStats(unsigned* table, U32 lastEltIndex, U32 shift, base_directive_e base1)\n{\n    U32 s, sum=0;\n    DEBUGLOG(5, \"ZSTD_downscaleStats (nbElts=%u, shift=%u)\",\n            (unsigned)lastEltIndex+1, (unsigned)shift );\n    assert(shift < 30);\n    for (s=0; s<lastEltIndex+1; s++) {\n        unsigned const base = base1 ? 1 : (table[s]>0);\n        unsigned const newStat = base + (table[s] >> shift);\n        sum += newStat;\n        table[s] = newStat;\n    }\n    return sum;\n}\n\n/* ZSTD_scaleStats() :\n * reduce all elt frequencies in table if sum too large\n * return the resulting sum of elements */\nstatic U32 ZSTD_scaleStats(unsigned* table, U32 lastEltIndex, U32 logTarget)\n{\n    U32 const prevsum = sum_u32(table, lastEltIndex+1);\n    U32 const factor = prevsum >> logTarget;\n    DEBUGLOG(5, \"ZSTD_scaleStats (nbElts=%u, target=%u)\", (unsigned)lastEltIndex+1, (unsigned)logTarget);\n    assert(logTarget < 30);\n    if (factor <= 1) return prevsum;\n    return ZSTD_downscaleStats(table, lastEltIndex, ZSTD_highbit32(factor), base_1guaranteed);\n}\n\n/* ZSTD_rescaleFreqs() :\n * if first block (detected by optPtr->litLengthSum == 0) : init statistics\n *    take hints from dictionary if there is one\n *    and init from zero if there is none,\n *    using src for literals stats, and baseline stats for sequence symbols\n * otherwise downscale existing stats, to be used as seed for next block.\n */\nstatic void\nZSTD_rescaleFreqs(optState_t* const optPtr,\n            const BYTE* const src, size_t const srcSize,\n                  int const optLevel)\n{\n    int const compressedLiterals = ZSTD_compressedLiterals(optPtr);\n    DEBUGLOG(5, \"ZSTD_rescaleFreqs (srcSize=%u)\", (unsigned)srcSize);\n    optPtr->priceType = zop_dynamic;\n\n    if (optPtr->litLengthSum == 0) {  /* no literals stats collected -> first block assumed -> init */\n\n        /* heuristic: use pre-defined stats for too small inputs */\n        if (srcSize <= ZSTD_PREDEF_THRESHOLD) {\n            DEBUGLOG(5, \"srcSize <= %i : use predefined stats\", ZSTD_PREDEF_THRESHOLD);\n            optPtr->priceType = zop_predef;\n        }\n\n        assert(optPtr->symbolCosts != NULL);\n        if (optPtr->symbolCosts->huf.repeatMode == HUF_repeat_valid) {\n\n            /* huffman stats covering the full value set : table presumed generated by dictionary */\n            optPtr->priceType = zop_dynamic;\n\n            if (compressedLiterals) {\n                /* generate literals statistics from huffman table */\n                unsigned lit;\n                assert(optPtr->litFreq != NULL);\n                optPtr->litSum = 0;\n                for (lit=0; lit<=MaxLit; lit++) {\n                    U32 const scaleLog = 11;   /* scale to 2K */\n                    U32 const bitCost = HUF_getNbBitsFromCTable(optPtr->symbolCosts->huf.CTable, lit);\n                    assert(bitCost <= scaleLog);\n                    optPtr->litFreq[lit] = bitCost ? 1 << (scaleLog-bitCost) : 1 /*minimum to calculate cost*/;\n                    optPtr->litSum += optPtr->litFreq[lit];\n            }   }\n\n            {   unsigned ll;\n                FSE_CState_t llstate;\n                FSE_initCState(&llstate, optPtr->symbolCosts->fse.litlengthCTable);\n                optPtr->litLengthSum = 0;\n                for (ll=0; ll<=MaxLL; ll++) {\n                    U32 const scaleLog = 10;   /* scale to 1K */\n                    U32 const bitCost = FSE_getMaxNbBits(llstate.symbolTT, ll);\n                    assert(bitCost < scaleLog);\n                    optPtr->litLengthFreq[ll] = bitCost ? 1 << (scaleLog-bitCost) : 1 /*minimum to calculate cost*/;\n                    optPtr->litLengthSum += optPtr->litLengthFreq[ll];\n            }   }\n\n            {   unsigned ml;\n                FSE_CState_t mlstate;\n                FSE_initCState(&mlstate, optPtr->symbolCosts->fse.matchlengthCTable);\n                optPtr->matchLengthSum = 0;\n                for (ml=0; ml<=MaxML; ml++) {\n                    U32 const scaleLog = 10;\n                    U32 const bitCost = FSE_getMaxNbBits(mlstate.symbolTT, ml);\n                    assert(bitCost < scaleLog);\n                    optPtr->matchLengthFreq[ml] = bitCost ? 1 << (scaleLog-bitCost) : 1 /*minimum to calculate cost*/;\n                    optPtr->matchLengthSum += optPtr->matchLengthFreq[ml];\n            }   }\n\n            {   unsigned of;\n                FSE_CState_t ofstate;\n                FSE_initCState(&ofstate, optPtr->symbolCosts->fse.offcodeCTable);\n                optPtr->offCodeSum = 0;\n                for (of=0; of<=MaxOff; of++) {\n                    U32 const scaleLog = 10;\n                    U32 const bitCost = FSE_getMaxNbBits(ofstate.symbolTT, of);\n                    assert(bitCost < scaleLog);\n                    optPtr->offCodeFreq[of] = bitCost ? 1 << (scaleLog-bitCost) : 1 /*minimum to calculate cost*/;\n                    optPtr->offCodeSum += optPtr->offCodeFreq[of];\n            }   }\n\n        } else {  /* first block, no dictionary */\n\n            assert(optPtr->litFreq != NULL);\n            if (compressedLiterals) {\n                /* base initial cost of literals on direct frequency within src */\n                unsigned lit = MaxLit;\n                HIST_count_simple(optPtr->litFreq, &lit, src, srcSize);   /* use raw first block to init statistics */\n                optPtr->litSum = ZSTD_downscaleStats(optPtr->litFreq, MaxLit, 8, base_0possible);\n            }\n\n            {   unsigned const baseLLfreqs[MaxLL+1] = {\n                    4, 2, 1, 1, 1, 1, 1, 1,\n                    1, 1, 1, 1, 1, 1, 1, 1,\n                    1, 1, 1, 1, 1, 1, 1, 1,\n                    1, 1, 1, 1, 1, 1, 1, 1,\n                    1, 1, 1, 1\n                };\n                ZSTD_memcpy(optPtr->litLengthFreq, baseLLfreqs, sizeof(baseLLfreqs));\n                optPtr->litLengthSum = sum_u32(baseLLfreqs, MaxLL+1);\n            }\n\n            {   unsigned ml;\n                for (ml=0; ml<=MaxML; ml++)\n                    optPtr->matchLengthFreq[ml] = 1;\n            }\n            optPtr->matchLengthSum = MaxML+1;\n\n            {   unsigned const baseOFCfreqs[MaxOff+1] = {\n                    6, 2, 1, 1, 2, 3, 4, 4,\n                    4, 3, 2, 1, 1, 1, 1, 1,\n                    1, 1, 1, 1, 1, 1, 1, 1,\n                    1, 1, 1, 1, 1, 1, 1, 1\n                };\n                ZSTD_memcpy(optPtr->offCodeFreq, baseOFCfreqs, sizeof(baseOFCfreqs));\n                optPtr->offCodeSum = sum_u32(baseOFCfreqs, MaxOff+1);\n            }\n\n        }\n\n    } else {   /* new block : scale down accumulated statistics */\n\n        if (compressedLiterals)\n            optPtr->litSum = ZSTD_scaleStats(optPtr->litFreq, MaxLit, 12);\n        optPtr->litLengthSum = ZSTD_scaleStats(optPtr->litLengthFreq, MaxLL, 11);\n        optPtr->matchLengthSum = ZSTD_scaleStats(optPtr->matchLengthFreq, MaxML, 11);\n        optPtr->offCodeSum = ZSTD_scaleStats(optPtr->offCodeFreq, MaxOff, 11);\n    }\n\n    ZSTD_setBasePrices(optPtr, optLevel);\n}\n\n/* ZSTD_rawLiteralsCost() :\n * price of literals (only) in specified segment (which length can be 0).\n * does not include price of literalLength symbol */\nstatic U32 ZSTD_rawLiteralsCost(const BYTE* const literals, U32 const litLength,\n                                const optState_t* const optPtr,\n                                int optLevel)\n{\n    DEBUGLOG(8, \"ZSTD_rawLiteralsCost (%u literals)\", litLength);\n    if (litLength == 0) return 0;\n\n    if (!ZSTD_compressedLiterals(optPtr))\n        return (litLength << 3) * BITCOST_MULTIPLIER;  /* Uncompressed - 8 bytes per literal. */\n\n    if (optPtr->priceType == zop_predef)\n        return (litLength*6) * BITCOST_MULTIPLIER;  /* 6 bit per literal - no statistic used */\n\n    /* dynamic statistics */\n    {   U32 price = optPtr->litSumBasePrice * litLength;\n        U32 const litPriceMax = optPtr->litSumBasePrice - BITCOST_MULTIPLIER;\n        U32 u;\n        assert(optPtr->litSumBasePrice >= BITCOST_MULTIPLIER);\n        for (u=0; u < litLength; u++) {\n            U32 litPrice = WEIGHT(optPtr->litFreq[literals[u]], optLevel);\n            if (UNLIKELY(litPrice > litPriceMax)) litPrice = litPriceMax;\n            price -= litPrice;\n        }\n        return price;\n    }\n}\n\n/* ZSTD_litLengthPrice() :\n * cost of literalLength symbol */\nstatic U32 ZSTD_litLengthPrice(U32 const litLength, const optState_t* const optPtr, int optLevel)\n{\n    assert(litLength <= ZSTD_BLOCKSIZE_MAX);\n    if (optPtr->priceType == zop_predef)\n        return WEIGHT(litLength, optLevel);\n\n    /* ZSTD_LLcode() can't compute litLength price for sizes >= ZSTD_BLOCKSIZE_MAX\n     * because it isn't representable in the zstd format.\n     * So instead just pretend it would cost 1 bit more than ZSTD_BLOCKSIZE_MAX - 1.\n     * In such a case, the block would be all literals.\n     */\n    if (litLength == ZSTD_BLOCKSIZE_MAX)\n        return BITCOST_MULTIPLIER + ZSTD_litLengthPrice(ZSTD_BLOCKSIZE_MAX - 1, optPtr, optLevel);\n\n    /* dynamic statistics */\n    {   U32 const llCode = ZSTD_LLcode(litLength);\n        return (LL_bits[llCode] * BITCOST_MULTIPLIER)\n             + optPtr->litLengthSumBasePrice\n             - WEIGHT(optPtr->litLengthFreq[llCode], optLevel);\n    }\n}\n\n/* ZSTD_getMatchPrice() :\n * Provides the cost of the match part (offset + matchLength) of a sequence.\n * Must be combined with ZSTD_fullLiteralsCost() to get the full cost of a sequence.\n * @offBase : sumtype, representing an offset or a repcode, and using numeric representation of ZSTD_storeSeq()\n * @optLevel: when <2, favors small offset for decompression speed (improved cache efficiency)\n */\nFORCE_INLINE_TEMPLATE U32\nZSTD_getMatchPrice(U32 const offBase,\n                   U32 const matchLength,\n             const optState_t* const optPtr,\n                   int const optLevel)\n{\n    U32 price;\n    U32 const offCode = ZSTD_highbit32(offBase);\n    U32 const mlBase = matchLength - MINMATCH;\n    assert(matchLength >= MINMATCH);\n\n    if (optPtr->priceType == zop_predef)  /* fixed scheme, does not use statistics */\n        return WEIGHT(mlBase, optLevel)\n             + ((16 + offCode) * BITCOST_MULTIPLIER); /* emulated offset cost */\n\n    /* dynamic statistics */\n    price = (offCode * BITCOST_MULTIPLIER) + (optPtr->offCodeSumBasePrice - WEIGHT(optPtr->offCodeFreq[offCode], optLevel));\n    if ((optLevel<2) /*static*/ && offCode >= 20)\n        price += (offCode-19)*2 * BITCOST_MULTIPLIER; /* handicap for long distance offsets, favor decompression speed */\n\n    /* match Length */\n    {   U32 const mlCode = ZSTD_MLcode(mlBase);\n        price += (ML_bits[mlCode] * BITCOST_MULTIPLIER) + (optPtr->matchLengthSumBasePrice - WEIGHT(optPtr->matchLengthFreq[mlCode], optLevel));\n    }\n\n    price += BITCOST_MULTIPLIER / 5;   /* heuristic : make matches a bit more costly to favor less sequences -> faster decompression speed */\n\n    DEBUGLOG(8, \"ZSTD_getMatchPrice(ml:%u) = %u\", matchLength, price);\n    return price;\n}\n\n/* ZSTD_updateStats() :\n * assumption : literals + litLength <= iend */\nstatic void ZSTD_updateStats(optState_t* const optPtr,\n                             U32 litLength, const BYTE* literals,\n                             U32 offBase, U32 matchLength)\n{\n    /* literals */\n    if (ZSTD_compressedLiterals(optPtr)) {\n        U32 u;\n        for (u=0; u < litLength; u++)\n            optPtr->litFreq[literals[u]] += ZSTD_LITFREQ_ADD;\n        optPtr->litSum += litLength*ZSTD_LITFREQ_ADD;\n    }\n\n    /* literal Length */\n    {   U32 const llCode = ZSTD_LLcode(litLength);\n        optPtr->litLengthFreq[llCode]++;\n        optPtr->litLengthSum++;\n    }\n\n    /* offset code : follows storeSeq() numeric representation */\n    {   U32 const offCode = ZSTD_highbit32(offBase);\n        assert(offCode <= MaxOff);\n        optPtr->offCodeFreq[offCode]++;\n        optPtr->offCodeSum++;\n    }\n\n    /* match Length */\n    {   U32 const mlBase = matchLength - MINMATCH;\n        U32 const mlCode = ZSTD_MLcode(mlBase);\n        optPtr->matchLengthFreq[mlCode]++;\n        optPtr->matchLengthSum++;\n    }\n}\n\n\n/* ZSTD_readMINMATCH() :\n * function safe only for comparisons\n * assumption : memPtr must be at least 4 bytes before end of buffer */\nMEM_STATIC U32 ZSTD_readMINMATCH(const void* memPtr, U32 length)\n{\n    switch (length)\n    {\n    default :\n    case 4 : return MEM_read32(memPtr);\n    case 3 : if (MEM_isLittleEndian())\n                return MEM_read32(memPtr)<<8;\n             else\n                return MEM_read32(memPtr)>>8;\n    }\n}\n\n\n/* Update hashTable3 up to ip (excluded)\n   Assumption : always within prefix (i.e. not within extDict) */\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nU32 ZSTD_insertAndFindFirstIndexHash3 (const ZSTD_MatchState_t* ms,\n                                       U32* nextToUpdate3,\n                                       const BYTE* const ip)\n{\n    U32* const hashTable3 = ms->hashTable3;\n    U32 const hashLog3 = ms->hashLog3;\n    const BYTE* const base = ms->window.base;\n    U32 idx = *nextToUpdate3;\n    U32 const target = (U32)(ip - base);\n    size_t const hash3 = ZSTD_hash3Ptr(ip, hashLog3);\n    assert(hashLog3 > 0);\n\n    while(idx < target) {\n        hashTable3[ZSTD_hash3Ptr(base+idx, hashLog3)] = idx;\n        idx++;\n    }\n\n    *nextToUpdate3 = target;\n    return hashTable3[hash3];\n}\n\n\n/*-*************************************\n*  Binary Tree search\n***************************************/\n/** ZSTD_insertBt1() : add one or multiple positions to tree.\n * @param ip assumed <= iend-8 .\n * @param target The target of ZSTD_updateTree_internal() - we are filling to this position\n * @return : nb of positions added */\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nU32 ZSTD_insertBt1(\n                const ZSTD_MatchState_t* ms,\n                const BYTE* const ip, const BYTE* const iend,\n                U32 const target,\n                U32 const mls, const int extDict)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32*   const hashTable = ms->hashTable;\n    U32    const hashLog = cParams->hashLog;\n    size_t const h  = ZSTD_hashPtr(ip, hashLog, mls);\n    U32*   const bt = ms->chainTable;\n    U32    const btLog  = cParams->chainLog - 1;\n    U32    const btMask = (1 << btLog) - 1;\n    U32 matchIndex = hashTable[h];\n    size_t commonLengthSmaller=0, commonLengthLarger=0;\n    const BYTE* const base = ms->window.base;\n    const BYTE* const dictBase = ms->window.dictBase;\n    const U32 dictLimit = ms->window.dictLimit;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    const BYTE* const prefixStart = base + dictLimit;\n    const BYTE* match;\n    const U32 curr = (U32)(ip-base);\n    const U32 btLow = btMask >= curr ? 0 : curr - btMask;\n    U32* smallerPtr = bt + 2*(curr&btMask);\n    U32* largerPtr  = smallerPtr + 1;\n    U32 dummy32;   /* to be nullified at the end */\n    /* windowLow is based on target because\n     * we only need positions that will be in the window at the end of the tree update.\n     */\n    U32 const windowLow = ZSTD_getLowestMatchIndex(ms, target, cParams->windowLog);\n    U32 matchEndIdx = curr+8+1;\n    size_t bestLength = 8;\n    U32 nbCompares = 1U << cParams->searchLog;\n#ifdef ZSTD_C_PREDICT\n    U32 predictedSmall = *(bt + 2*((curr-1)&btMask) + 0);\n    U32 predictedLarge = *(bt + 2*((curr-1)&btMask) + 1);\n    predictedSmall += (predictedSmall>0);\n    predictedLarge += (predictedLarge>0);\n#endif /* ZSTD_C_PREDICT */\n\n    DEBUGLOG(8, \"ZSTD_insertBt1 (%u)\", curr);\n\n    assert(curr <= target);\n    assert(ip <= iend-8);   /* required for h calculation */\n    hashTable[h] = curr;   /* Update Hash Table */\n\n    assert(windowLow > 0);\n    for (; nbCompares && (matchIndex >= windowLow); --nbCompares) {\n        U32* const nextPtr = bt + 2*(matchIndex & btMask);\n        size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger);   /* guaranteed minimum nb of common bytes */\n        assert(matchIndex < curr);\n\n#ifdef ZSTD_C_PREDICT   /* note : can create issues when hlog small <= 11 */\n        const U32* predictPtr = bt + 2*((matchIndex-1) & btMask);   /* written this way, as bt is a roll buffer */\n        if (matchIndex == predictedSmall) {\n            /* no need to check length, result known */\n            *smallerPtr = matchIndex;\n            if (matchIndex <= btLow) { smallerPtr=&dummy32; break; }   /* beyond tree size, stop the search */\n            smallerPtr = nextPtr+1;               /* new \"smaller\" => larger of match */\n            matchIndex = nextPtr[1];              /* new matchIndex larger than previous (closer to current) */\n            predictedSmall = predictPtr[1] + (predictPtr[1]>0);\n            continue;\n        }\n        if (matchIndex == predictedLarge) {\n            *largerPtr = matchIndex;\n            if (matchIndex <= btLow) { largerPtr=&dummy32; break; }   /* beyond tree size, stop the search */\n            largerPtr = nextPtr;\n            matchIndex = nextPtr[0];\n            predictedLarge = predictPtr[0] + (predictPtr[0]>0);\n            continue;\n        }\n#endif\n\n        if (!extDict || (matchIndex+matchLength >= dictLimit)) {\n            assert(matchIndex+matchLength >= dictLimit);   /* might be wrong if actually extDict */\n            match = base + matchIndex;\n            matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend);\n        } else {\n            match = dictBase + matchIndex;\n            matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);\n            if (matchIndex+matchLength >= dictLimit)\n                match = base + matchIndex;   /* to prepare for next usage of match[matchLength] */\n        }\n\n        if (matchLength > bestLength) {\n            bestLength = matchLength;\n            if (matchLength > matchEndIdx - matchIndex)\n                matchEndIdx = matchIndex + (U32)matchLength;\n        }\n\n        if (ip+matchLength == iend) {   /* equal : no way to know if inf or sup */\n            break;   /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt tree */\n        }\n\n        if (match[matchLength] < ip[matchLength]) {  /* necessarily within buffer */\n            /* match is smaller than current */\n            *smallerPtr = matchIndex;             /* update smaller idx */\n            commonLengthSmaller = matchLength;    /* all smaller will now have at least this guaranteed common length */\n            if (matchIndex <= btLow) { smallerPtr=&dummy32; break; }   /* beyond tree size, stop searching */\n            smallerPtr = nextPtr+1;               /* new \"candidate\" => larger than match, which was smaller than target */\n            matchIndex = nextPtr[1];              /* new matchIndex, larger than previous and closer to current */\n        } else {\n            /* match is larger than current */\n            *largerPtr = matchIndex;\n            commonLengthLarger = matchLength;\n            if (matchIndex <= btLow) { largerPtr=&dummy32; break; }   /* beyond tree size, stop searching */\n            largerPtr = nextPtr;\n            matchIndex = nextPtr[0];\n    }   }\n\n    *smallerPtr = *largerPtr = 0;\n    {   U32 positions = 0;\n        if (bestLength > 384) positions = MIN(192, (U32)(bestLength - 384));   /* speed optimization */\n        assert(matchEndIdx > curr + 8);\n        return MAX(positions, matchEndIdx - (curr + 8));\n    }\n}\n\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_updateTree_internal(\n                ZSTD_MatchState_t* ms,\n                const BYTE* const ip, const BYTE* const iend,\n                const U32 mls, const ZSTD_dictMode_e dictMode)\n{\n    const BYTE* const base = ms->window.base;\n    U32 const target = (U32)(ip - base);\n    U32 idx = ms->nextToUpdate;\n    DEBUGLOG(7, \"ZSTD_updateTree_internal, from %u to %u  (dictMode:%u)\",\n                idx, target, dictMode);\n\n    while(idx < target) {\n        U32 const forward = ZSTD_insertBt1(ms, base+idx, iend, target, mls, dictMode == ZSTD_extDict);\n        assert(idx < (U32)(idx + forward));\n        idx += forward;\n    }\n    assert((size_t)(ip - base) <= (size_t)(U32)(-1));\n    assert((size_t)(iend - base) <= (size_t)(U32)(-1));\n    ms->nextToUpdate = target;\n}\n\nvoid ZSTD_updateTree(ZSTD_MatchState_t* ms, const BYTE* ip, const BYTE* iend) {\n    ZSTD_updateTree_internal(ms, ip, iend, ms->cParams.minMatch, ZSTD_noDict);\n}\n\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nU32\nZSTD_insertBtAndGetAllMatches (\n                ZSTD_match_t* matches,  /* store result (found matches) in this table (presumed large enough) */\n                ZSTD_MatchState_t* ms,\n                U32* nextToUpdate3,\n                const BYTE* const ip, const BYTE* const iLimit,\n                const ZSTD_dictMode_e dictMode,\n                const U32 rep[ZSTD_REP_NUM],\n                const U32 ll0,  /* tells if associated literal length is 0 or not. This value must be 0 or 1 */\n                const U32 lengthToBeat,\n                const U32 mls /* template */)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);\n    const BYTE* const base = ms->window.base;\n    U32 const curr = (U32)(ip-base);\n    U32 const hashLog = cParams->hashLog;\n    U32 const minMatch = (mls==3) ? 3 : 4;\n    U32* const hashTable = ms->hashTable;\n    size_t const h  = ZSTD_hashPtr(ip, hashLog, mls);\n    U32 matchIndex  = hashTable[h];\n    U32* const bt   = ms->chainTable;\n    U32 const btLog = cParams->chainLog - 1;\n    U32 const btMask= (1U << btLog) - 1;\n    size_t commonLengthSmaller=0, commonLengthLarger=0;\n    const BYTE* const dictBase = ms->window.dictBase;\n    U32 const dictLimit = ms->window.dictLimit;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    const BYTE* const prefixStart = base + dictLimit;\n    U32 const btLow = (btMask >= curr) ? 0 : curr - btMask;\n    U32 const windowLow = ZSTD_getLowestMatchIndex(ms, curr, cParams->windowLog);\n    U32 const matchLow = windowLow ? windowLow : 1;\n    U32* smallerPtr = bt + 2*(curr&btMask);\n    U32* largerPtr  = bt + 2*(curr&btMask) + 1;\n    U32 matchEndIdx = curr+8+1;   /* farthest referenced position of any match => detects repetitive patterns */\n    U32 dummy32;   /* to be nullified at the end */\n    U32 mnum = 0;\n    U32 nbCompares = 1U << cParams->searchLog;\n\n    const ZSTD_MatchState_t* dms    = dictMode == ZSTD_dictMatchState ? ms->dictMatchState : NULL;\n    const ZSTD_compressionParameters* const dmsCParams =\n                                      dictMode == ZSTD_dictMatchState ? &dms->cParams : NULL;\n    const BYTE* const dmsBase       = dictMode == ZSTD_dictMatchState ? dms->window.base : NULL;\n    const BYTE* const dmsEnd        = dictMode == ZSTD_dictMatchState ? dms->window.nextSrc : NULL;\n    U32         const dmsHighLimit  = dictMode == ZSTD_dictMatchState ? (U32)(dmsEnd - dmsBase) : 0;\n    U32         const dmsLowLimit   = dictMode == ZSTD_dictMatchState ? dms->window.lowLimit : 0;\n    U32         const dmsIndexDelta = dictMode == ZSTD_dictMatchState ? windowLow - dmsHighLimit : 0;\n    U32         const dmsHashLog    = dictMode == ZSTD_dictMatchState ? dmsCParams->hashLog : hashLog;\n    U32         const dmsBtLog      = dictMode == ZSTD_dictMatchState ? dmsCParams->chainLog - 1 : btLog;\n    U32         const dmsBtMask     = dictMode == ZSTD_dictMatchState ? (1U << dmsBtLog) - 1 : 0;\n    U32         const dmsBtLow      = dictMode == ZSTD_dictMatchState && dmsBtMask < dmsHighLimit - dmsLowLimit ? dmsHighLimit - dmsBtMask : dmsLowLimit;\n\n    size_t bestLength = lengthToBeat-1;\n    DEBUGLOG(8, \"ZSTD_insertBtAndGetAllMatches: current=%u\", curr);\n\n    /* check repCode */\n    assert(ll0 <= 1);   /* necessarily 1 or 0 */\n    {   U32 const lastR = ZSTD_REP_NUM + ll0;\n        U32 repCode;\n        for (repCode = ll0; repCode < lastR; repCode++) {\n            U32 const repOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];\n            U32 const repIndex = curr - repOffset;\n            U32 repLen = 0;\n            assert(curr >= dictLimit);\n            if (repOffset-1 /* intentional overflow, discards 0 and -1 */ < curr-dictLimit) {  /* equivalent to `curr > repIndex >= dictLimit` */\n                /* We must validate the repcode offset because when we're using a dictionary the\n                 * valid offset range shrinks when the dictionary goes out of bounds.\n                 */\n                if ((repIndex >= windowLow) & (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(ip - repOffset, minMatch))) {\n                    repLen = (U32)ZSTD_count(ip+minMatch, ip+minMatch-repOffset, iLimit) + minMatch;\n                }\n            } else {  /* repIndex < dictLimit || repIndex >= curr */\n                const BYTE* const repMatch = dictMode == ZSTD_dictMatchState ?\n                                             dmsBase + repIndex - dmsIndexDelta :\n                                             dictBase + repIndex;\n                assert(curr >= windowLow);\n                if ( dictMode == ZSTD_extDict\n                  && ( ((repOffset-1) /*intentional overflow*/ < curr - windowLow)  /* equivalent to `curr > repIndex >= windowLow` */\n                     & (ZSTD_index_overlap_check(dictLimit, repIndex)) )\n                  && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) {\n                    repLen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iLimit, dictEnd, prefixStart) + minMatch;\n                }\n                if (dictMode == ZSTD_dictMatchState\n                  && ( ((repOffset-1) /*intentional overflow*/ < curr - (dmsLowLimit + dmsIndexDelta))  /* equivalent to `curr > repIndex >= dmsLowLimit` */\n                     & (ZSTD_index_overlap_check(dictLimit, repIndex)) )\n                  && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) {\n                    repLen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iLimit, dmsEnd, prefixStart) + minMatch;\n            }   }\n            /* save longer solution */\n            if (repLen > bestLength) {\n                DEBUGLOG(8, \"found repCode %u (ll0:%u, offset:%u) of length %u\",\n                            repCode, ll0, repOffset, repLen);\n                bestLength = repLen;\n                matches[mnum].off = REPCODE_TO_OFFBASE(repCode - ll0 + 1);  /* expect value between 1 and 3 */\n                matches[mnum].len = (U32)repLen;\n                mnum++;\n                if ( (repLen > sufficient_len)\n                   | (ip+repLen == iLimit) ) {  /* best possible */\n                    return mnum;\n    }   }   }   }\n\n    /* HC3 match finder */\n    if ((mls == 3) /*static*/ && (bestLength < mls)) {\n        U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, nextToUpdate3, ip);\n        if ((matchIndex3 >= matchLow)\n          & (curr - matchIndex3 < (1<<18)) /*heuristic : longer distance likely too expensive*/ ) {\n            size_t mlen;\n            if ((dictMode == ZSTD_noDict) /*static*/ || (dictMode == ZSTD_dictMatchState) /*static*/ || (matchIndex3 >= dictLimit)) {\n                const BYTE* const match = base + matchIndex3;\n                mlen = ZSTD_count(ip, match, iLimit);\n            } else {\n                const BYTE* const match = dictBase + matchIndex3;\n                mlen = ZSTD_count_2segments(ip, match, iLimit, dictEnd, prefixStart);\n            }\n\n            /* save best solution */\n            if (mlen >= mls /* == 3 > bestLength */) {\n                DEBUGLOG(8, \"found small match with hlog3, of length %u\",\n                            (U32)mlen);\n                bestLength = mlen;\n                assert(curr > matchIndex3);\n                assert(mnum==0);  /* no prior solution */\n                matches[0].off = OFFSET_TO_OFFBASE(curr - matchIndex3);\n                matches[0].len = (U32)mlen;\n                mnum = 1;\n                if ( (mlen > sufficient_len) |\n                     (ip+mlen == iLimit) ) {  /* best possible length */\n                    ms->nextToUpdate = curr+1;  /* skip insertion */\n                    return 1;\n        }   }   }\n        /* no dictMatchState lookup: dicts don't have a populated HC3 table */\n    }  /* if (mls == 3) */\n\n    hashTable[h] = curr;   /* Update Hash Table */\n\n    for (; nbCompares && (matchIndex >= matchLow); --nbCompares) {\n        U32* const nextPtr = bt + 2*(matchIndex & btMask);\n        const BYTE* match;\n        size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger);   /* guaranteed minimum nb of common bytes */\n        assert(curr > matchIndex);\n\n        if ((dictMode == ZSTD_noDict) || (dictMode == ZSTD_dictMatchState) || (matchIndex+matchLength >= dictLimit)) {\n            assert(matchIndex+matchLength >= dictLimit);  /* ensure the condition is correct when !extDict */\n            match = base + matchIndex;\n            if (matchIndex >= dictLimit) assert(memcmp(match, ip, matchLength) == 0);  /* ensure early section of match is equal as expected */\n            matchLength += ZSTD_count(ip+matchLength, match+matchLength, iLimit);\n        } else {\n            match = dictBase + matchIndex;\n            assert(memcmp(match, ip, matchLength) == 0);  /* ensure early section of match is equal as expected */\n            matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iLimit, dictEnd, prefixStart);\n            if (matchIndex+matchLength >= dictLimit)\n                match = base + matchIndex;   /* prepare for match[matchLength] read */\n        }\n\n        if (matchLength > bestLength) {\n            DEBUGLOG(8, \"found match of length %u at distance %u (offBase=%u)\",\n                    (U32)matchLength, curr - matchIndex, OFFSET_TO_OFFBASE(curr - matchIndex));\n            assert(matchEndIdx > matchIndex);\n            if (matchLength > matchEndIdx - matchIndex)\n                matchEndIdx = matchIndex + (U32)matchLength;\n            bestLength = matchLength;\n            matches[mnum].off = OFFSET_TO_OFFBASE(curr - matchIndex);\n            matches[mnum].len = (U32)matchLength;\n            mnum++;\n            if ( (matchLength > ZSTD_OPT_NUM)\n               | (ip+matchLength == iLimit) /* equal : no way to know if inf or sup */) {\n                if (dictMode == ZSTD_dictMatchState) nbCompares = 0; /* break should also skip searching dms */\n                break; /* drop, to preserve bt consistency (miss a little bit of compression) */\n        }   }\n\n        if (match[matchLength] < ip[matchLength]) {\n            /* match smaller than current */\n            *smallerPtr = matchIndex;             /* update smaller idx */\n            commonLengthSmaller = matchLength;    /* all smaller will now have at least this guaranteed common length */\n            if (matchIndex <= btLow) { smallerPtr=&dummy32; break; }   /* beyond tree size, stop the search */\n            smallerPtr = nextPtr+1;               /* new candidate => larger than match, which was smaller than current */\n            matchIndex = nextPtr[1];              /* new matchIndex, larger than previous, closer to current */\n        } else {\n            *largerPtr = matchIndex;\n            commonLengthLarger = matchLength;\n            if (matchIndex <= btLow) { largerPtr=&dummy32; break; }   /* beyond tree size, stop the search */\n            largerPtr = nextPtr;\n            matchIndex = nextPtr[0];\n    }   }\n\n    *smallerPtr = *largerPtr = 0;\n\n    assert(nbCompares <= (1U << ZSTD_SEARCHLOG_MAX)); /* Check we haven't underflowed. */\n    if (dictMode == ZSTD_dictMatchState && nbCompares) {\n        size_t const dmsH = ZSTD_hashPtr(ip, dmsHashLog, mls);\n        U32 dictMatchIndex = dms->hashTable[dmsH];\n        const U32* const dmsBt = dms->chainTable;\n        commonLengthSmaller = commonLengthLarger = 0;\n        for (; nbCompares && (dictMatchIndex > dmsLowLimit); --nbCompares) {\n            const U32* const nextPtr = dmsBt + 2*(dictMatchIndex & dmsBtMask);\n            size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger);   /* guaranteed minimum nb of common bytes */\n            const BYTE* match = dmsBase + dictMatchIndex;\n            matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iLimit, dmsEnd, prefixStart);\n            if (dictMatchIndex+matchLength >= dmsHighLimit)\n                match = base + dictMatchIndex + dmsIndexDelta;   /* to prepare for next usage of match[matchLength] */\n\n            if (matchLength > bestLength) {\n                matchIndex = dictMatchIndex + dmsIndexDelta;\n                DEBUGLOG(8, \"found dms match of length %u at distance %u (offBase=%u)\",\n                        (U32)matchLength, curr - matchIndex, OFFSET_TO_OFFBASE(curr - matchIndex));\n                if (matchLength > matchEndIdx - matchIndex)\n                    matchEndIdx = matchIndex + (U32)matchLength;\n                bestLength = matchLength;\n                matches[mnum].off = OFFSET_TO_OFFBASE(curr - matchIndex);\n                matches[mnum].len = (U32)matchLength;\n                mnum++;\n                if ( (matchLength > ZSTD_OPT_NUM)\n                   | (ip+matchLength == iLimit) /* equal : no way to know if inf or sup */) {\n                    break;   /* drop, to guarantee consistency (miss a little bit of compression) */\n            }   }\n\n            if (dictMatchIndex <= dmsBtLow) { break; }   /* beyond tree size, stop the search */\n            if (match[matchLength] < ip[matchLength]) {\n                commonLengthSmaller = matchLength;    /* all smaller will now have at least this guaranteed common length */\n                dictMatchIndex = nextPtr[1];              /* new matchIndex larger than previous (closer to current) */\n            } else {\n                /* match is larger than current */\n                commonLengthLarger = matchLength;\n                dictMatchIndex = nextPtr[0];\n    }   }   }  /* if (dictMode == ZSTD_dictMatchState) */\n\n    assert(matchEndIdx > curr+8);\n    ms->nextToUpdate = matchEndIdx - 8;  /* skip repetitive patterns */\n    return mnum;\n}\n\ntypedef U32 (*ZSTD_getAllMatchesFn)(\n    ZSTD_match_t*,\n    ZSTD_MatchState_t*,\n    U32*,\n    const BYTE*,\n    const BYTE*,\n    const U32 rep[ZSTD_REP_NUM],\n    U32 const ll0,\n    U32 const lengthToBeat);\n\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nU32 ZSTD_btGetAllMatches_internal(\n        ZSTD_match_t* matches,\n        ZSTD_MatchState_t* ms,\n        U32* nextToUpdate3,\n        const BYTE* ip,\n        const BYTE* const iHighLimit,\n        const U32 rep[ZSTD_REP_NUM],\n        U32 const ll0,\n        U32 const lengthToBeat,\n        const ZSTD_dictMode_e dictMode,\n        const U32 mls)\n{\n    assert(BOUNDED(3, ms->cParams.minMatch, 6) == mls);\n    DEBUGLOG(8, \"ZSTD_BtGetAllMatches(dictMode=%d, mls=%u)\", (int)dictMode, mls);\n    if (ip < ms->window.base + ms->nextToUpdate)\n        return 0;   /* skipped area */\n    ZSTD_updateTree_internal(ms, ip, iHighLimit, mls, dictMode);\n    return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, mls);\n}\n\n#define ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, mls) ZSTD_btGetAllMatches_##dictMode##_##mls\n\n#define GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, mls)            \\\n    static U32 ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, mls)(      \\\n            ZSTD_match_t* matches,                             \\\n            ZSTD_MatchState_t* ms,                             \\\n            U32* nextToUpdate3,                                \\\n            const BYTE* ip,                                    \\\n            const BYTE* const iHighLimit,                      \\\n            const U32 rep[ZSTD_REP_NUM],                       \\\n            U32 const ll0,                                     \\\n            U32 const lengthToBeat)                            \\\n    {                                                          \\\n        return ZSTD_btGetAllMatches_internal(                  \\\n                matches, ms, nextToUpdate3, ip, iHighLimit,    \\\n                rep, ll0, lengthToBeat, ZSTD_##dictMode, mls); \\\n    }\n\n#define GEN_ZSTD_BT_GET_ALL_MATCHES(dictMode)  \\\n    GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, 3)  \\\n    GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, 4)  \\\n    GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, 5)  \\\n    GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, 6)\n\nGEN_ZSTD_BT_GET_ALL_MATCHES(noDict)\nGEN_ZSTD_BT_GET_ALL_MATCHES(extDict)\nGEN_ZSTD_BT_GET_ALL_MATCHES(dictMatchState)\n\n#define ZSTD_BT_GET_ALL_MATCHES_ARRAY(dictMode)  \\\n    {                                            \\\n        ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, 3), \\\n        ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, 4), \\\n        ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, 5), \\\n        ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, 6)  \\\n    }\n\nstatic ZSTD_getAllMatchesFn\nZSTD_selectBtGetAllMatches(ZSTD_MatchState_t const* ms, ZSTD_dictMode_e const dictMode)\n{\n    ZSTD_getAllMatchesFn const getAllMatchesFns[3][4] = {\n        ZSTD_BT_GET_ALL_MATCHES_ARRAY(noDict),\n        ZSTD_BT_GET_ALL_MATCHES_ARRAY(extDict),\n        ZSTD_BT_GET_ALL_MATCHES_ARRAY(dictMatchState)\n    };\n    U32 const mls = BOUNDED(3, ms->cParams.minMatch, 6);\n    assert((U32)dictMode < 3);\n    assert(mls - 3 < 4);\n    return getAllMatchesFns[(int)dictMode][mls - 3];\n}\n\n/*************************\n*  LDM helper functions  *\n*************************/\n\n/* Struct containing info needed to make decision about ldm inclusion */\ntypedef struct {\n    RawSeqStore_t seqStore;   /* External match candidates store for this block */\n    U32 startPosInBlock;      /* Start position of the current match candidate */\n    U32 endPosInBlock;        /* End position of the current match candidate */\n    U32 offset;               /* Offset of the match candidate */\n} ZSTD_optLdm_t;\n\n/* ZSTD_optLdm_skipRawSeqStoreBytes():\n * Moves forward in @rawSeqStore by @nbBytes,\n * which will update the fields 'pos' and 'posInSequence'.\n */\nstatic void ZSTD_optLdm_skipRawSeqStoreBytes(RawSeqStore_t* rawSeqStore, size_t nbBytes)\n{\n    U32 currPos = (U32)(rawSeqStore->posInSequence + nbBytes);\n    while (currPos && rawSeqStore->pos < rawSeqStore->size) {\n        rawSeq currSeq = rawSeqStore->seq[rawSeqStore->pos];\n        if (currPos >= currSeq.litLength + currSeq.matchLength) {\n            currPos -= currSeq.litLength + currSeq.matchLength;\n            rawSeqStore->pos++;\n        } else {\n            rawSeqStore->posInSequence = currPos;\n            break;\n        }\n    }\n    if (currPos == 0 || rawSeqStore->pos == rawSeqStore->size) {\n        rawSeqStore->posInSequence = 0;\n    }\n}\n\n/* ZSTD_opt_getNextMatchAndUpdateSeqStore():\n * Calculates the beginning and end of the next match in the current block.\n * Updates 'pos' and 'posInSequence' of the ldmSeqStore.\n */\nstatic void\nZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 currPosInBlock,\n                                       U32 blockBytesRemaining)\n{\n    rawSeq currSeq;\n    U32 currBlockEndPos;\n    U32 literalsBytesRemaining;\n    U32 matchBytesRemaining;\n\n    /* Setting match end position to MAX to ensure we never use an LDM during this block */\n    if (optLdm->seqStore.size == 0 || optLdm->seqStore.pos >= optLdm->seqStore.size) {\n        optLdm->startPosInBlock = UINT_MAX;\n        optLdm->endPosInBlock = UINT_MAX;\n        return;\n    }\n    /* Calculate appropriate bytes left in matchLength and litLength\n     * after adjusting based on ldmSeqStore->posInSequence */\n    currSeq = optLdm->seqStore.seq[optLdm->seqStore.pos];\n    assert(optLdm->seqStore.posInSequence <= currSeq.litLength + currSeq.matchLength);\n    currBlockEndPos = currPosInBlock + blockBytesRemaining;\n    literalsBytesRemaining = (optLdm->seqStore.posInSequence < currSeq.litLength) ?\n            currSeq.litLength - (U32)optLdm->seqStore.posInSequence :\n            0;\n    matchBytesRemaining = (literalsBytesRemaining == 0) ?\n            currSeq.matchLength - ((U32)optLdm->seqStore.posInSequence - currSeq.litLength) :\n            currSeq.matchLength;\n\n    /* If there are more literal bytes than bytes remaining in block, no ldm is possible */\n    if (literalsBytesRemaining >= blockBytesRemaining) {\n        optLdm->startPosInBlock = UINT_MAX;\n        optLdm->endPosInBlock = UINT_MAX;\n        ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, blockBytesRemaining);\n        return;\n    }\n\n    /* Matches may be < minMatch by this process. In that case, we will reject them\n       when we are deciding whether or not to add the ldm */\n    optLdm->startPosInBlock = currPosInBlock + literalsBytesRemaining;\n    optLdm->endPosInBlock = optLdm->startPosInBlock + matchBytesRemaining;\n    optLdm->offset = currSeq.offset;\n\n    if (optLdm->endPosInBlock > currBlockEndPos) {\n        /* Match ends after the block ends, we can't use the whole match */\n        optLdm->endPosInBlock = currBlockEndPos;\n        ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, currBlockEndPos - currPosInBlock);\n    } else {\n        /* Consume nb of bytes equal to size of sequence left */\n        ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, literalsBytesRemaining + matchBytesRemaining);\n    }\n}\n\n/* ZSTD_optLdm_maybeAddMatch():\n * Adds a match if it's long enough,\n * based on it's 'matchStartPosInBlock' and 'matchEndPosInBlock',\n * into 'matches'. Maintains the correct ordering of 'matches'.\n */\nstatic void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches,\n                                      const ZSTD_optLdm_t* optLdm, U32 currPosInBlock,\n                                      U32 minMatch)\n{\n    U32 const posDiff = currPosInBlock - optLdm->startPosInBlock;\n    /* Note: ZSTD_match_t actually contains offBase and matchLength (before subtracting MINMATCH) */\n    U32 const candidateMatchLength = optLdm->endPosInBlock - optLdm->startPosInBlock - posDiff;\n\n    /* Ensure that current block position is not outside of the match */\n    if (currPosInBlock < optLdm->startPosInBlock\n      || currPosInBlock >= optLdm->endPosInBlock\n      || candidateMatchLength < minMatch) {\n        return;\n    }\n\n    if (*nbMatches == 0 || ((candidateMatchLength > matches[*nbMatches-1].len) && *nbMatches < ZSTD_OPT_NUM)) {\n        U32 const candidateOffBase = OFFSET_TO_OFFBASE(optLdm->offset);\n        DEBUGLOG(6, \"ZSTD_optLdm_maybeAddMatch(): Adding ldm candidate match (offBase: %u matchLength %u) at block position=%u\",\n                 candidateOffBase, candidateMatchLength, currPosInBlock);\n        matches[*nbMatches].len = candidateMatchLength;\n        matches[*nbMatches].off = candidateOffBase;\n        (*nbMatches)++;\n    }\n}\n\n/* ZSTD_optLdm_processMatchCandidate():\n * Wrapper function to update ldm seq store and call ldm functions as necessary.\n */\nstatic void\nZSTD_optLdm_processMatchCandidate(ZSTD_optLdm_t* optLdm,\n                                  ZSTD_match_t* matches, U32* nbMatches,\n                                  U32 currPosInBlock, U32 remainingBytes,\n                                  U32 minMatch)\n{\n    if (optLdm->seqStore.size == 0 || optLdm->seqStore.pos >= optLdm->seqStore.size) {\n        return;\n    }\n\n    if (currPosInBlock >= optLdm->endPosInBlock) {\n        if (currPosInBlock > optLdm->endPosInBlock) {\n            /* The position at which ZSTD_optLdm_processMatchCandidate() is called is not necessarily\n             * at the end of a match from the ldm seq store, and will often be some bytes\n             * over beyond matchEndPosInBlock. As such, we need to correct for these \"overshoots\"\n             */\n            U32 const posOvershoot = currPosInBlock - optLdm->endPosInBlock;\n            ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, posOvershoot);\n        }\n        ZSTD_opt_getNextMatchAndUpdateSeqStore(optLdm, currPosInBlock, remainingBytes);\n    }\n    ZSTD_optLdm_maybeAddMatch(matches, nbMatches, optLdm, currPosInBlock, minMatch);\n}\n\n\n/*-*******************************\n*  Optimal parser\n*********************************/\n\n#if 0 /* debug */\n\nstatic void\nlistStats(const U32* table, int lastEltID)\n{\n    int const nbElts = lastEltID + 1;\n    int enb;\n    for (enb=0; enb < nbElts; enb++) {\n        (void)table;\n        /* RAWLOG(2, \"%3i:%3i,  \", enb, table[enb]); */\n        RAWLOG(2, \"%4i,\", table[enb]);\n    }\n    RAWLOG(2, \" \\n\");\n}\n\n#endif\n\n#define LIT_PRICE(_p) (int)ZSTD_rawLiteralsCost(_p, 1, optStatePtr, optLevel)\n#define LL_PRICE(_l) (int)ZSTD_litLengthPrice(_l, optStatePtr, optLevel)\n#define LL_INCPRICE(_l) (LL_PRICE(_l) - LL_PRICE(_l-1))\n\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t\nZSTD_compressBlock_opt_generic(ZSTD_MatchState_t* ms,\n                               SeqStore_t* seqStore,\n                               U32 rep[ZSTD_REP_NUM],\n                         const void* src, size_t srcSize,\n                         const int optLevel,\n                         const ZSTD_dictMode_e dictMode)\n{\n    optState_t* const optStatePtr = &ms->opt;\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* ip = istart;\n    const BYTE* anchor = istart;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* const ilimit = iend - 8;\n    const BYTE* const base = ms->window.base;\n    const BYTE* const prefixStart = base + ms->window.dictLimit;\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n\n    ZSTD_getAllMatchesFn getAllMatches = ZSTD_selectBtGetAllMatches(ms, dictMode);\n\n    U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);\n    U32 const minMatch = (cParams->minMatch == 3) ? 3 : 4;\n    U32 nextToUpdate3 = ms->nextToUpdate;\n\n    ZSTD_optimal_t* const opt = optStatePtr->priceTable;\n    ZSTD_match_t* const matches = optStatePtr->matchTable;\n    ZSTD_optimal_t lastStretch;\n    ZSTD_optLdm_t optLdm;\n\n    ZSTD_memset(&lastStretch, 0, sizeof(ZSTD_optimal_t));\n\n    optLdm.seqStore = ms->ldmSeqStore ? *ms->ldmSeqStore : kNullRawSeqStore;\n    optLdm.endPosInBlock = optLdm.startPosInBlock = optLdm.offset = 0;\n    ZSTD_opt_getNextMatchAndUpdateSeqStore(&optLdm, (U32)(ip-istart), (U32)(iend-ip));\n\n    /* init */\n    DEBUGLOG(5, \"ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u\",\n                (U32)(ip - base), ms->window.dictLimit, ms->nextToUpdate);\n    assert(optLevel <= 2);\n    ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize, optLevel);\n    ip += (ip==prefixStart);\n\n    /* Match Loop */\n    while (ip < ilimit) {\n        U32 cur, last_pos = 0;\n\n        /* find first match */\n        {   U32 const litlen = (U32)(ip - anchor);\n            U32 const ll0 = !litlen;\n            U32 nbMatches = getAllMatches(matches, ms, &nextToUpdate3, ip, iend, rep, ll0, minMatch);\n            ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches,\n                                              (U32)(ip-istart), (U32)(iend-ip),\n                                              minMatch);\n            if (!nbMatches) {\n                DEBUGLOG(8, \"no match found at cPos %u\", (unsigned)(ip-istart));\n                ip++;\n                continue;\n            }\n\n            /* Match found: let's store this solution, and eventually find more candidates.\n             * During this forward pass, @opt is used to store stretches,\n             * defined as \"a match followed by N literals\".\n             * Note how this is different from a Sequence, which is \"N literals followed by a match\".\n             * Storing stretches allows us to store different match predecessors\n             * for each literal position part of a literals run. */\n\n            /* initialize opt[0] */\n            opt[0].mlen = 0;  /* there are only literals so far */\n            opt[0].litlen = litlen;\n            /* No need to include the actual price of the literals before the first match\n             * because it is static for the duration of the forward pass, and is included\n             * in every subsequent price. But, we include the literal length because\n             * the cost variation of litlen depends on the value of litlen.\n             */\n            opt[0].price = LL_PRICE(litlen);\n            ZSTD_STATIC_ASSERT(sizeof(opt[0].rep[0]) == sizeof(rep[0]));\n            ZSTD_memcpy(&opt[0].rep, rep, sizeof(opt[0].rep));\n\n            /* large match -> immediate encoding */\n            {   U32 const maxML = matches[nbMatches-1].len;\n                U32 const maxOffBase = matches[nbMatches-1].off;\n                DEBUGLOG(6, \"found %u matches of maxLength=%u and maxOffBase=%u at cPos=%u => start new series\",\n                            nbMatches, maxML, maxOffBase, (U32)(ip-prefixStart));\n\n                if (maxML > sufficient_len) {\n                    lastStretch.litlen = 0;\n                    lastStretch.mlen = maxML;\n                    lastStretch.off = maxOffBase;\n                    DEBUGLOG(6, \"large match (%u>%u) => immediate encoding\",\n                                maxML, sufficient_len);\n                    cur = 0;\n                    last_pos = maxML;\n                    goto _shortestPath;\n            }   }\n\n            /* set prices for first matches starting position == 0 */\n            assert(opt[0].price >= 0);\n            {   U32 pos;\n                U32 matchNb;\n                for (pos = 1; pos < minMatch; pos++) {\n                    opt[pos].price = ZSTD_MAX_PRICE;\n                    opt[pos].mlen = 0;\n                    opt[pos].litlen = litlen + pos;\n                }\n                for (matchNb = 0; matchNb < nbMatches; matchNb++) {\n                    U32 const offBase = matches[matchNb].off;\n                    U32 const end = matches[matchNb].len;\n                    for ( ; pos <= end ; pos++ ) {\n                        int const matchPrice = (int)ZSTD_getMatchPrice(offBase, pos, optStatePtr, optLevel);\n                        int const sequencePrice = opt[0].price + matchPrice;\n                        DEBUGLOG(7, \"rPos:%u => set initial price : %.2f\",\n                                    pos, ZSTD_fCost(sequencePrice));\n                        opt[pos].mlen = pos;\n                        opt[pos].off = offBase;\n                        opt[pos].litlen = 0; /* end of match */\n                        opt[pos].price = sequencePrice + LL_PRICE(0);\n                    }\n                }\n                last_pos = pos-1;\n                opt[pos].price = ZSTD_MAX_PRICE;\n            }\n        }\n\n        /* check further positions */\n        for (cur = 1; cur <= last_pos; cur++) {\n            const BYTE* const inr = ip + cur;\n            assert(cur <= ZSTD_OPT_NUM);\n            DEBUGLOG(7, \"cPos:%i==rPos:%u\", (int)(inr-istart), cur);\n\n            /* Fix current position with one literal if cheaper */\n            {   U32 const litlen = opt[cur-1].litlen + 1;\n                int const price = opt[cur-1].price\n                                + LIT_PRICE(ip+cur-1)\n                                + LL_INCPRICE(litlen);\n                assert(price < 1000000000); /* overflow check */\n                if (price <= opt[cur].price) {\n                    ZSTD_optimal_t const prevMatch = opt[cur];\n                    DEBUGLOG(7, \"cPos:%i==rPos:%u : better price (%.2f<=%.2f) using literal (ll==%u) (hist:%u,%u,%u)\",\n                                (int)(inr-istart), cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price), litlen,\n                                opt[cur-1].rep[0], opt[cur-1].rep[1], opt[cur-1].rep[2]);\n                    opt[cur] = opt[cur-1];\n                    opt[cur].litlen = litlen;\n                    opt[cur].price = price;\n                    if ( (optLevel >= 1) /* additional check only for higher modes */\n                      && (prevMatch.litlen == 0) /* replace a match */\n                      && (LL_INCPRICE(1) < 0) /* ll1 is cheaper than ll0 */\n                      && LIKELY(ip + cur < iend)\n                    ) {\n                        /* check next position, in case it would be cheaper */\n                        int with1literal = prevMatch.price + LIT_PRICE(ip+cur) + LL_INCPRICE(1);\n                        int withMoreLiterals = price + LIT_PRICE(ip+cur) + LL_INCPRICE(litlen+1);\n                        DEBUGLOG(7, \"then at next rPos %u : match+1lit %.2f vs %ulits %.2f\",\n                                cur+1, ZSTD_fCost(with1literal), litlen+1, ZSTD_fCost(withMoreLiterals));\n                        if ( (with1literal < withMoreLiterals)\n                          && (with1literal < opt[cur+1].price) ) {\n                            /* update offset history - before it disappears */\n                            U32 const prev = cur - prevMatch.mlen;\n                            Repcodes_t const newReps = ZSTD_newRep(opt[prev].rep, prevMatch.off, opt[prev].litlen==0);\n                            assert(cur >= prevMatch.mlen);\n                            DEBUGLOG(7, \"==> match+1lit is cheaper (%.2f < %.2f) (hist:%u,%u,%u) !\",\n                                        ZSTD_fCost(with1literal), ZSTD_fCost(withMoreLiterals),\n                                        newReps.rep[0], newReps.rep[1], newReps.rep[2] );\n                            opt[cur+1] = prevMatch;  /* mlen & offbase */\n                            ZSTD_memcpy(opt[cur+1].rep, &newReps, sizeof(Repcodes_t));\n                            opt[cur+1].litlen = 1;\n                            opt[cur+1].price = with1literal;\n                            if (last_pos < cur+1) last_pos = cur+1;\n                        }\n                    }\n                } else {\n                    DEBUGLOG(7, \"cPos:%i==rPos:%u : literal would cost more (%.2f>%.2f)\",\n                                (int)(inr-istart), cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price));\n                }\n            }\n\n            /* Offset history is not updated during match comparison.\n             * Do it here, now that the match is selected and confirmed.\n             */\n            ZSTD_STATIC_ASSERT(sizeof(opt[cur].rep) == sizeof(Repcodes_t));\n            assert(cur >= opt[cur].mlen);\n            if (opt[cur].litlen == 0) {\n                /* just finished a match => alter offset history */\n                U32 const prev = cur - opt[cur].mlen;\n                Repcodes_t const newReps = ZSTD_newRep(opt[prev].rep, opt[cur].off, opt[prev].litlen==0);\n                ZSTD_memcpy(opt[cur].rep, &newReps, sizeof(Repcodes_t));\n            }\n\n            /* last match must start at a minimum distance of 8 from oend */\n            if (inr > ilimit) continue;\n\n            if (cur == last_pos) break;\n\n            if ( (optLevel==0) /*static_test*/\n              && (opt[cur+1].price <= opt[cur].price + (BITCOST_MULTIPLIER/2)) ) {\n                DEBUGLOG(7, \"skip current position : next rPos(%u) price is cheaper\", cur+1);\n                continue;  /* skip unpromising positions; about ~+6% speed, -0.01 ratio */\n            }\n\n            assert(opt[cur].price >= 0);\n            {   U32 const ll0 = (opt[cur].litlen == 0);\n                int const previousPrice = opt[cur].price;\n                int const basePrice = previousPrice + LL_PRICE(0);\n                U32 nbMatches = getAllMatches(matches, ms, &nextToUpdate3, inr, iend, opt[cur].rep, ll0, minMatch);\n                U32 matchNb;\n\n                ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches,\n                                                  (U32)(inr-istart), (U32)(iend-inr),\n                                                  minMatch);\n\n                if (!nbMatches) {\n                    DEBUGLOG(7, \"rPos:%u : no match found\", cur);\n                    continue;\n                }\n\n                {   U32 const longestML = matches[nbMatches-1].len;\n                    DEBUGLOG(7, \"cPos:%i==rPos:%u, found %u matches, of longest ML=%u\",\n                                (int)(inr-istart), cur, nbMatches, longestML);\n\n                    if ( (longestML > sufficient_len)\n                      || (cur + longestML >= ZSTD_OPT_NUM)\n                      || (ip + cur + longestML >= iend) ) {\n                        lastStretch.mlen = longestML;\n                        lastStretch.off = matches[nbMatches-1].off;\n                        lastStretch.litlen = 0;\n                        last_pos = cur + longestML;\n                        goto _shortestPath;\n                }   }\n\n                /* set prices using matches found at position == cur */\n                for (matchNb = 0; matchNb < nbMatches; matchNb++) {\n                    U32 const offset = matches[matchNb].off;\n                    U32 const lastML = matches[matchNb].len;\n                    U32 const startML = (matchNb>0) ? matches[matchNb-1].len+1 : minMatch;\n                    U32 mlen;\n\n                    DEBUGLOG(7, \"testing match %u => offBase=%4u, mlen=%2u, llen=%2u\",\n                                matchNb, matches[matchNb].off, lastML, opt[cur].litlen);\n\n                    for (mlen = lastML; mlen >= startML; mlen--) {  /* scan downward */\n                        U32 const pos = cur + mlen;\n                        int const price = basePrice + (int)ZSTD_getMatchPrice(offset, mlen, optStatePtr, optLevel);\n\n                        if ((pos > last_pos) || (price < opt[pos].price)) {\n                            DEBUGLOG(7, \"rPos:%u (ml=%2u) => new better price (%.2f<%.2f)\",\n                                        pos, mlen, ZSTD_fCost(price), ZSTD_fCost(opt[pos].price));\n                            while (last_pos < pos) {\n                                /* fill empty positions, for future comparisons */\n                                last_pos++;\n                                opt[last_pos].price = ZSTD_MAX_PRICE;\n                                opt[last_pos].litlen = !0;  /* just needs to be != 0, to mean \"not an end of match\" */\n                            }\n                            opt[pos].mlen = mlen;\n                            opt[pos].off = offset;\n                            opt[pos].litlen = 0;\n                            opt[pos].price = price;\n                        } else {\n                            DEBUGLOG(7, \"rPos:%u (ml=%2u) => new price is worse (%.2f>=%.2f)\",\n                                        pos, mlen, ZSTD_fCost(price), ZSTD_fCost(opt[pos].price));\n                            if (optLevel==0) break;  /* early update abort; gets ~+10% speed for about -0.01 ratio loss */\n                        }\n            }   }   }\n            opt[last_pos+1].price = ZSTD_MAX_PRICE;\n        }  /* for (cur = 1; cur <= last_pos; cur++) */\n\n        lastStretch = opt[last_pos];\n        assert(cur >= lastStretch.mlen);\n        cur = last_pos - lastStretch.mlen;\n\n_shortestPath:   /* cur, last_pos, best_mlen, best_off have to be set */\n        assert(opt[0].mlen == 0);\n        assert(last_pos >= lastStretch.mlen);\n        assert(cur == last_pos - lastStretch.mlen);\n\n        if (lastStretch.mlen==0) {\n            /* no solution : all matches have been converted into literals */\n            assert(lastStretch.litlen == (ip - anchor) + last_pos);\n            ip += last_pos;\n            continue;\n        }\n        assert(lastStretch.off > 0);\n\n        /* Update offset history */\n        if (lastStretch.litlen == 0) {\n            /* finishing on a match : update offset history */\n            Repcodes_t const reps = ZSTD_newRep(opt[cur].rep, lastStretch.off, opt[cur].litlen==0);\n            ZSTD_memcpy(rep, &reps, sizeof(Repcodes_t));\n        } else {\n            ZSTD_memcpy(rep, lastStretch.rep, sizeof(Repcodes_t));\n            assert(cur >= lastStretch.litlen);\n            cur -= lastStretch.litlen;\n        }\n\n        /* Let's write the shortest path solution.\n         * It is stored in @opt in reverse order,\n         * starting from @storeEnd (==cur+2),\n         * effectively partially @opt overwriting.\n         * Content is changed too:\n         * - So far, @opt stored stretches, aka a match followed by literals\n         * - Now, it will store sequences, aka literals followed by a match\n         */\n        {   U32 const storeEnd = cur + 2;\n            U32 storeStart = storeEnd;\n            U32 stretchPos = cur;\n\n            DEBUGLOG(6, \"start reverse traversal (last_pos:%u, cur:%u)\",\n                        last_pos, cur); (void)last_pos;\n            assert(storeEnd < ZSTD_OPT_SIZE);\n            DEBUGLOG(6, \"last stretch copied into pos=%u (llen=%u,mlen=%u,ofc=%u)\",\n                        storeEnd, lastStretch.litlen, lastStretch.mlen, lastStretch.off);\n            opt[storeEnd] = lastStretch;  /* note: litlen will be fixed */\n            storeStart = storeEnd;\n            while (1) {\n                ZSTD_optimal_t nextStretch = opt[stretchPos];\n                opt[storeStart].litlen = nextStretch.litlen;\n                DEBUGLOG(6, \"selected sequence (llen=%u,mlen=%u,ofc=%u)\",\n                            opt[storeStart].litlen, opt[storeStart].mlen, opt[storeStart].off);\n                if (nextStretch.mlen == 0) {\n                    /* reaching beginning of segment */\n                    break;\n                }\n                storeStart--;\n                opt[storeStart] = nextStretch; /* note: litlen will be fixed */\n                assert(nextStretch.litlen + nextStretch.mlen <= stretchPos);\n                stretchPos -= nextStretch.litlen + nextStretch.mlen;\n            }\n\n            /* save sequences */\n            DEBUGLOG(6, \"sending selected sequences into seqStore\");\n            {   U32 storePos;\n                for (storePos=storeStart; storePos <= storeEnd; storePos++) {\n                    U32 const llen = opt[storePos].litlen;\n                    U32 const mlen = opt[storePos].mlen;\n                    U32 const offBase = opt[storePos].off;\n                    U32 const advance = llen + mlen;\n                    DEBUGLOG(6, \"considering seq starting at %i, llen=%u, mlen=%u\",\n                                (int)(anchor - istart), (unsigned)llen, (unsigned)mlen);\n\n                    if (mlen==0) {  /* only literals => must be last \"sequence\", actually starting a new stream of sequences */\n                        assert(storePos == storeEnd);   /* must be last sequence */\n                        ip = anchor + llen;     /* last \"sequence\" is a bunch of literals => don't progress anchor */\n                        continue;   /* will finish */\n                    }\n\n                    assert(anchor + llen <= iend);\n                    ZSTD_updateStats(optStatePtr, llen, anchor, offBase, mlen);\n                    ZSTD_storeSeq(seqStore, llen, anchor, iend, offBase, mlen);\n                    anchor += advance;\n                    ip = anchor;\n            }   }\n            DEBUGLOG(7, \"new offset history : %u, %u, %u\", rep[0], rep[1], rep[2]);\n\n            /* update all costs */\n            ZSTD_setBasePrices(optStatePtr, optLevel);\n        }\n    }   /* while (ip < ilimit) */\n\n    /* Return the last literals size */\n    return (size_t)(iend - anchor);\n}\n#endif /* build exclusions */\n\n#ifndef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR\nstatic size_t ZSTD_compressBlock_opt0(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        const void* src, size_t srcSize, const ZSTD_dictMode_e dictMode)\n{\n    return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /* optLevel */, dictMode);\n}\n#endif\n\n#ifndef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR\nstatic size_t ZSTD_compressBlock_opt2(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        const void* src, size_t srcSize, const ZSTD_dictMode_e dictMode)\n{\n    return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /* optLevel */, dictMode);\n}\n#endif\n\n#ifndef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_btopt(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        const void* src, size_t srcSize)\n{\n    DEBUGLOG(5, \"ZSTD_compressBlock_btopt\");\n    return ZSTD_compressBlock_opt0(ms, seqStore, rep, src, srcSize, ZSTD_noDict);\n}\n#endif\n\n\n\n\n#ifndef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR\n/* ZSTD_initStats_ultra():\n * make a first compression pass, just to seed stats with more accurate starting values.\n * only works on first block, with no dictionary and no ldm.\n * this function cannot error out, its narrow contract must be respected.\n */\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_initStats_ultra(ZSTD_MatchState_t* ms,\n                          SeqStore_t* seqStore,\n                          U32 rep[ZSTD_REP_NUM],\n                    const void* src, size_t srcSize)\n{\n    U32 tmpRep[ZSTD_REP_NUM];  /* updated rep codes will sink here */\n    ZSTD_memcpy(tmpRep, rep, sizeof(tmpRep));\n\n    DEBUGLOG(4, \"ZSTD_initStats_ultra (srcSize=%zu)\", srcSize);\n    assert(ms->opt.litLengthSum == 0);    /* first block */\n    assert(seqStore->sequences == seqStore->sequencesStart);   /* no ldm */\n    assert(ms->window.dictLimit == ms->window.lowLimit);   /* no dictionary */\n    assert(ms->window.dictLimit - ms->nextToUpdate <= 1);  /* no prefix (note: intentional overflow, defined as 2-complement) */\n\n    ZSTD_compressBlock_opt2(ms, seqStore, tmpRep, src, srcSize, ZSTD_noDict);   /* generate stats into ms->opt*/\n\n    /* invalidate first scan from history, only keep entropy stats */\n    ZSTD_resetSeqStore(seqStore);\n    ms->window.base -= srcSize;\n    ms->window.dictLimit += (U32)srcSize;\n    ms->window.lowLimit = ms->window.dictLimit;\n    ms->nextToUpdate = ms->window.dictLimit;\n\n}\n\nsize_t ZSTD_compressBlock_btultra(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        const void* src, size_t srcSize)\n{\n    DEBUGLOG(5, \"ZSTD_compressBlock_btultra (srcSize=%zu)\", srcSize);\n    return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_noDict);\n}\n\nsize_t ZSTD_compressBlock_btultra2(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        const void* src, size_t srcSize)\n{\n    U32 const curr = (U32)((const BYTE*)src - ms->window.base);\n    DEBUGLOG(5, \"ZSTD_compressBlock_btultra2 (srcSize=%zu)\", srcSize);\n\n    /* 2-passes strategy:\n     * this strategy makes a first pass over first block to collect statistics\n     * in order to seed next round's statistics with it.\n     * After 1st pass, function forgets history, and starts a new block.\n     * Consequently, this can only work if no data has been previously loaded in tables,\n     * aka, no dictionary, no prefix, no ldm preprocessing.\n     * The compression ratio gain is generally small (~0.5% on first block),\n     * the cost is 2x cpu time on first block. */\n    assert(srcSize <= ZSTD_BLOCKSIZE_MAX);\n    if ( (ms->opt.litLengthSum==0)   /* first block */\n      && (seqStore->sequences == seqStore->sequencesStart)  /* no ldm */\n      && (ms->window.dictLimit == ms->window.lowLimit)   /* no dictionary */\n      && (curr == ms->window.dictLimit)    /* start of frame, nothing already loaded nor skipped */\n      && (srcSize > ZSTD_PREDEF_THRESHOLD) /* input large enough to not employ default stats */\n      ) {\n        ZSTD_initStats_ultra(ms, seqStore, rep, src, srcSize);\n    }\n\n    return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_noDict);\n}\n#endif\n\n#ifndef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_btopt_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        const void* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_opt0(ms, seqStore, rep, src, srcSize, ZSTD_dictMatchState);\n}\n\nsize_t ZSTD_compressBlock_btopt_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        const void* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_opt0(ms, seqStore, rep, src, srcSize, ZSTD_extDict);\n}\n#endif\n\n#ifndef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_btultra_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        const void* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_dictMatchState);\n}\n\nsize_t ZSTD_compressBlock_btultra_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        const void* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_extDict);\n}\n#endif\n\n/* note : no btultra2 variant for extDict nor dictMatchState,\n * because btultra2 is not meant to work with dictionaries\n * and is only specific for the first block (no prefix) */\n"
  },
  {
    "path": "lib/compress/zstd_opt.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_OPT_H\n#define ZSTD_OPT_H\n\n#include \"zstd_compress_internal.h\"\n\n#if !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR)\n/* used in ZSTD_loadDictionaryContent() */\nvoid ZSTD_updateTree(ZSTD_MatchState_t* ms, const BYTE* ip, const BYTE* iend);\n#endif\n\n#ifndef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_btopt(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_btopt_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_btopt_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\n\n#define ZSTD_COMPRESSBLOCK_BTOPT ZSTD_compressBlock_btopt\n#define ZSTD_COMPRESSBLOCK_BTOPT_DICTMATCHSTATE ZSTD_compressBlock_btopt_dictMatchState\n#define ZSTD_COMPRESSBLOCK_BTOPT_EXTDICT ZSTD_compressBlock_btopt_extDict\n#else\n#define ZSTD_COMPRESSBLOCK_BTOPT NULL\n#define ZSTD_COMPRESSBLOCK_BTOPT_DICTMATCHSTATE NULL\n#define ZSTD_COMPRESSBLOCK_BTOPT_EXTDICT NULL\n#endif\n\n#ifndef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_btultra(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_btultra_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_btultra_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\n\n        /* note : no btultra2 variant for extDict nor dictMatchState,\n         * because btultra2 is not meant to work with dictionaries\n         * and is only specific for the first block (no prefix) */\nsize_t ZSTD_compressBlock_btultra2(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\n\n#define ZSTD_COMPRESSBLOCK_BTULTRA ZSTD_compressBlock_btultra\n#define ZSTD_COMPRESSBLOCK_BTULTRA_DICTMATCHSTATE ZSTD_compressBlock_btultra_dictMatchState\n#define ZSTD_COMPRESSBLOCK_BTULTRA_EXTDICT ZSTD_compressBlock_btultra_extDict\n#define ZSTD_COMPRESSBLOCK_BTULTRA2 ZSTD_compressBlock_btultra2\n#else\n#define ZSTD_COMPRESSBLOCK_BTULTRA NULL\n#define ZSTD_COMPRESSBLOCK_BTULTRA_DICTMATCHSTATE NULL\n#define ZSTD_COMPRESSBLOCK_BTULTRA_EXTDICT NULL\n#define ZSTD_COMPRESSBLOCK_BTULTRA2 NULL\n#endif\n\n#endif /* ZSTD_OPT_H */\n"
  },
  {
    "path": "lib/compress/zstd_preSplit.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"../common/compiler.h\" /* ZSTD_ALIGNOF */\n#include \"../common/mem.h\" /* S64 */\n#include \"../common/zstd_deps.h\" /* ZSTD_memset */\n#include \"../common/zstd_internal.h\" /* ZSTD_STATIC_ASSERT */\n#include \"hist.h\" /* HIST_add */\n#include \"zstd_preSplit.h\"\n\n\n#define BLOCKSIZE_MIN 3500\n#define THRESHOLD_PENALTY_RATE 16\n#define THRESHOLD_BASE (THRESHOLD_PENALTY_RATE - 2)\n#define THRESHOLD_PENALTY 3\n\n#define HASHLENGTH 2\n#define HASHLOG_MAX 10\n#define HASHTABLESIZE (1 << HASHLOG_MAX)\n#define HASHMASK (HASHTABLESIZE - 1)\n#define KNUTH 0x9e3779b9\n\n/* for hashLog > 8, hash 2 bytes.\n * for hashLog == 8, just take the byte, no hashing.\n * The speed of this method relies on compile-time constant propagation */\nFORCE_INLINE_TEMPLATE unsigned hash2(const void *p, unsigned hashLog)\n{\n    assert(hashLog >= 8);\n    if (hashLog == 8) return (U32)((const BYTE*)p)[0];\n    assert(hashLog <= HASHLOG_MAX);\n    return (U32)(MEM_read16(p)) * KNUTH >> (32 - hashLog);\n}\n\n\ntypedef struct {\n  unsigned events[HASHTABLESIZE];\n  size_t nbEvents;\n} Fingerprint;\ntypedef struct {\n    Fingerprint pastEvents;\n    Fingerprint newEvents;\n} FPStats;\n\nstatic void initStats(FPStats* fpstats)\n{\n    ZSTD_memset(fpstats, 0, sizeof(FPStats));\n}\n\nFORCE_INLINE_TEMPLATE void\naddEvents_generic(Fingerprint* fp, const void* src, size_t srcSize, size_t samplingRate, unsigned hashLog)\n{\n    const char* p = (const char*)src;\n    size_t limit = srcSize - HASHLENGTH + 1;\n    size_t n;\n    assert(srcSize >= HASHLENGTH);\n    for (n = 0; n < limit; n+=samplingRate) {\n        fp->events[hash2(p+n, hashLog)]++;\n    }\n    fp->nbEvents += limit/samplingRate;\n}\n\nFORCE_INLINE_TEMPLATE void\nrecordFingerprint_generic(Fingerprint* fp, const void* src, size_t srcSize, size_t samplingRate, unsigned hashLog)\n{\n    ZSTD_memset(fp, 0, sizeof(unsigned) * ((size_t)1 << hashLog));\n    fp->nbEvents = 0;\n    addEvents_generic(fp, src, srcSize, samplingRate, hashLog);\n}\n\ntypedef void (*RecordEvents_f)(Fingerprint* fp, const void* src, size_t srcSize);\n\n#define FP_RECORD(_rate) ZSTD_recordFingerprint_##_rate\n\n#define ZSTD_GEN_RECORD_FINGERPRINT(_rate, _hSize)                                 \\\n    static void FP_RECORD(_rate)(Fingerprint* fp, const void* src, size_t srcSize) \\\n    {                                                                              \\\n        recordFingerprint_generic(fp, src, srcSize, _rate, _hSize);                \\\n    }\n\nZSTD_GEN_RECORD_FINGERPRINT(1, 10)\nZSTD_GEN_RECORD_FINGERPRINT(5, 10)\nZSTD_GEN_RECORD_FINGERPRINT(11, 9)\nZSTD_GEN_RECORD_FINGERPRINT(43, 8)\n\n\nstatic U64 abs64(S64 s64) { return (U64)((s64 < 0) ? -s64 : s64); }\n\nstatic U64 fpDistance(const Fingerprint* fp1, const Fingerprint* fp2, unsigned hashLog)\n{\n    U64 distance = 0;\n    size_t n;\n    assert(hashLog <= HASHLOG_MAX);\n    for (n = 0; n < ((size_t)1 << hashLog); n++) {\n        distance +=\n            abs64((S64)fp1->events[n] * (S64)fp2->nbEvents - (S64)fp2->events[n] * (S64)fp1->nbEvents);\n    }\n    return distance;\n}\n\n/* Compare newEvents with pastEvents\n * return 1 when considered \"too different\"\n */\nstatic int compareFingerprints(const Fingerprint* ref,\n                            const Fingerprint* newfp,\n                            int penalty,\n                            unsigned hashLog)\n{\n    assert(ref->nbEvents > 0);\n    assert(newfp->nbEvents > 0);\n    {   U64 p50 = (U64)ref->nbEvents * (U64)newfp->nbEvents;\n        U64 deviation = fpDistance(ref, newfp, hashLog);\n        U64 threshold = p50 * (U64)(THRESHOLD_BASE + penalty) / THRESHOLD_PENALTY_RATE;\n        return deviation >= threshold;\n    }\n}\n\nstatic void mergeEvents(Fingerprint* acc, const Fingerprint* newfp)\n{\n    size_t n;\n    for (n = 0; n < HASHTABLESIZE; n++) {\n        acc->events[n] += newfp->events[n];\n    }\n    acc->nbEvents += newfp->nbEvents;\n}\n\nstatic void flushEvents(FPStats* fpstats)\n{\n    size_t n;\n    for (n = 0; n < HASHTABLESIZE; n++) {\n        fpstats->pastEvents.events[n] = fpstats->newEvents.events[n];\n    }\n    fpstats->pastEvents.nbEvents = fpstats->newEvents.nbEvents;\n    ZSTD_memset(&fpstats->newEvents, 0, sizeof(fpstats->newEvents));\n}\n\nstatic void removeEvents(Fingerprint* acc, const Fingerprint* slice)\n{\n    size_t n;\n    for (n = 0; n < HASHTABLESIZE; n++) {\n        assert(acc->events[n] >= slice->events[n]);\n        acc->events[n] -= slice->events[n];\n    }\n    acc->nbEvents -= slice->nbEvents;\n}\n\n#define CHUNKSIZE (8 << 10)\nstatic size_t ZSTD_splitBlock_byChunks(const void* blockStart, size_t blockSize,\n                        int level,\n                        void* workspace, size_t wkspSize)\n{\n    static const RecordEvents_f records_fs[] = {\n        FP_RECORD(43), FP_RECORD(11), FP_RECORD(5), FP_RECORD(1)\n    };\n    static const unsigned hashParams[] = { 8, 9, 10, 10 };\n    const RecordEvents_f record_f = (assert(0<=level && level<=3), records_fs[level]);\n    FPStats* const fpstats = (FPStats*)workspace;\n    const char* p = (const char*)blockStart;\n    int penalty = THRESHOLD_PENALTY;\n    size_t pos = 0;\n    assert(blockSize == (128 << 10));\n    assert(workspace != NULL);\n    assert((size_t)workspace % ZSTD_ALIGNOF(FPStats) == 0);\n    ZSTD_STATIC_ASSERT(ZSTD_SLIPBLOCK_WORKSPACESIZE >= sizeof(FPStats));\n    assert(wkspSize >= sizeof(FPStats)); (void)wkspSize;\n\n    initStats(fpstats);\n    record_f(&fpstats->pastEvents, p, CHUNKSIZE);\n    for (pos = CHUNKSIZE; pos <= blockSize - CHUNKSIZE; pos += CHUNKSIZE) {\n        record_f(&fpstats->newEvents, p + pos, CHUNKSIZE);\n        if (compareFingerprints(&fpstats->pastEvents, &fpstats->newEvents, penalty, hashParams[level])) {\n            return pos;\n        } else {\n            mergeEvents(&fpstats->pastEvents, &fpstats->newEvents);\n            if (penalty > 0) penalty--;\n        }\n    }\n    assert(pos == blockSize);\n    return blockSize;\n    (void)flushEvents; (void)removeEvents;\n}\n\n/* ZSTD_splitBlock_fromBorders(): very fast strategy :\n * compare fingerprint from beginning and end of the block,\n * derive from their difference if it's preferable to split in the middle,\n * repeat the process a second time, for finer grained decision.\n * 3 times did not brought improvements, so I stopped at 2.\n * Benefits are good enough for a cheap heuristic.\n * More accurate splitting saves more, but speed impact is also more perceptible.\n * For better accuracy, use more elaborate variant *_byChunks.\n */\nstatic size_t ZSTD_splitBlock_fromBorders(const void* blockStart, size_t blockSize,\n                        void* workspace, size_t wkspSize)\n{\n#define SEGMENT_SIZE 512\n    FPStats* const fpstats = (FPStats*)workspace;\n    Fingerprint* middleEvents = (Fingerprint*)(void*)((char*)workspace + 512 * sizeof(unsigned));\n    assert(blockSize == (128 << 10));\n    assert(workspace != NULL);\n    assert((size_t)workspace % ZSTD_ALIGNOF(FPStats) == 0);\n    ZSTD_STATIC_ASSERT(ZSTD_SLIPBLOCK_WORKSPACESIZE >= sizeof(FPStats));\n    assert(wkspSize >= sizeof(FPStats)); (void)wkspSize;\n\n    initStats(fpstats);\n    HIST_add(fpstats->pastEvents.events, blockStart, SEGMENT_SIZE);\n    HIST_add(fpstats->newEvents.events, (const char*)blockStart + blockSize - SEGMENT_SIZE, SEGMENT_SIZE);\n    fpstats->pastEvents.nbEvents = fpstats->newEvents.nbEvents = SEGMENT_SIZE;\n    if (!compareFingerprints(&fpstats->pastEvents, &fpstats->newEvents, 0, 8))\n        return blockSize;\n\n    HIST_add(middleEvents->events, (const char*)blockStart + blockSize/2 - SEGMENT_SIZE/2, SEGMENT_SIZE);\n    middleEvents->nbEvents = SEGMENT_SIZE;\n    {   U64 const distFromBegin = fpDistance(&fpstats->pastEvents, middleEvents, 8);\n        U64 const distFromEnd = fpDistance(&fpstats->newEvents, middleEvents, 8);\n        U64 const minDistance = SEGMENT_SIZE * SEGMENT_SIZE / 3;\n        if (abs64((S64)distFromBegin - (S64)distFromEnd) < minDistance)\n            return 64 KB;\n        return (distFromBegin > distFromEnd) ? 32 KB : 96 KB;\n    }\n}\n\nsize_t ZSTD_splitBlock(const void* blockStart, size_t blockSize,\n                    int level,\n                    void* workspace, size_t wkspSize)\n{\n    DEBUGLOG(6, \"ZSTD_splitBlock (level=%i)\", level);\n    assert(0<=level && level<=4);\n    if (level == 0)\n        return ZSTD_splitBlock_fromBorders(blockStart, blockSize, workspace, wkspSize);\n    /* level >= 1*/\n    return ZSTD_splitBlock_byChunks(blockStart, blockSize, level-1, workspace, wkspSize);\n}\n"
  },
  {
    "path": "lib/compress/zstd_preSplit.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_PRESPLIT_H\n#define ZSTD_PRESPLIT_H\n\n#include <stddef.h>  /* size_t */\n\n#define ZSTD_SLIPBLOCK_WORKSPACESIZE 8208\n\n/* ZSTD_splitBlock():\n * @level must be a value between 0 and 4.\n *        higher levels spend more energy to detect block boundaries.\n * @workspace must be aligned for size_t.\n * @wkspSize must be at least >= ZSTD_SLIPBLOCK_WORKSPACESIZE\n * note:\n * For the time being, this function only accepts full 128 KB blocks.\n * Therefore, @blockSize must be == 128 KB.\n * While this could be extended to smaller sizes in the future,\n * it is not yet clear if this would be useful. TBD.\n */\nsize_t ZSTD_splitBlock(const void* blockStart, size_t blockSize,\n                    int level,\n                    void* workspace, size_t wkspSize);\n\n#endif /* ZSTD_PRESPLIT_H */\n"
  },
  {
    "path": "lib/compress/zstdmt_compress.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/* ======   Compiler specifics   ====== */\n#if defined(_MSC_VER)\n#  pragma warning(disable : 4204)   /* disable: C4204: non-constant aggregate initializer */\n#endif\n\n\n/* ======   Dependencies   ====== */\n#include \"../common/allocations.h\" /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */\n#include \"../common/zstd_deps.h\"   /* ZSTD_memcpy, ZSTD_memset, INT_MAX, UINT_MAX */\n#include \"../common/mem.h\"         /* MEM_STATIC */\n#include \"../common/pool.h\"        /* threadpool */\n#include \"../common/threading.h\"   /* mutex */\n#include \"zstd_compress_internal.h\" /* MIN, ERROR, ZSTD_*, ZSTD_highbit32 */\n#include \"zstd_ldm.h\"\n#include \"zstdmt_compress.h\"\n\n/* Guards code to support resizing the SeqPool.\n * We will want to resize the SeqPool to save memory in the future.\n * Until then, comment the code out since it is unused.\n */\n#define ZSTD_RESIZE_SEQPOOL 0\n\n/* ======   Debug   ====== */\n#if defined(DEBUGLEVEL) && (DEBUGLEVEL>=2) \\\n    && !defined(_MSC_VER) \\\n    && !defined(__MINGW32__)\n\n#  include <stdio.h>\n#  include <unistd.h>\n#  include <sys/times.h>\n\n#  define DEBUG_PRINTHEX(l,p,n)                                       \\\n    do {                                                              \\\n        unsigned debug_u;                                             \\\n        for (debug_u=0; debug_u<(n); debug_u++)                       \\\n            RAWLOG(l, \"%02X \", ((const unsigned char*)(p))[debug_u]); \\\n        RAWLOG(l, \" \\n\");                                             \\\n    } while (0)\n\nstatic unsigned long long GetCurrentClockTimeMicroseconds(void)\n{\n   static clock_t _ticksPerSecond = 0;\n   if (_ticksPerSecond <= 0) _ticksPerSecond = sysconf(_SC_CLK_TCK);\n\n   {   struct tms junk; clock_t newTicks = (clock_t) times(&junk);\n       return ((((unsigned long long)newTicks)*(1000000))/_ticksPerSecond);\n}  }\n\n#define MUTEX_WAIT_TIME_DLEVEL 6\n#define ZSTD_PTHREAD_MUTEX_LOCK(mutex)                                                  \\\n    do {                                                                                \\\n        if (DEBUGLEVEL >= MUTEX_WAIT_TIME_DLEVEL) {                                     \\\n            unsigned long long const beforeTime = GetCurrentClockTimeMicroseconds();    \\\n            ZSTD_pthread_mutex_lock(mutex);                                             \\\n            {   unsigned long long const afterTime = GetCurrentClockTimeMicroseconds(); \\\n                unsigned long long const elapsedTime = (afterTime-beforeTime);          \\\n                if (elapsedTime > 1000) {                                               \\\n                    /* or whatever threshold you like; I'm using 1 millisecond here */  \\\n                    DEBUGLOG(MUTEX_WAIT_TIME_DLEVEL,                                    \\\n                        \"Thread took %llu microseconds to acquire mutex %s \\n\",         \\\n                        elapsedTime, #mutex);                                           \\\n            }   }                                                                       \\\n        } else {                                                                        \\\n            ZSTD_pthread_mutex_lock(mutex);                                             \\\n        }                                                                               \\\n    } while (0)\n\n#else\n\n#  define ZSTD_PTHREAD_MUTEX_LOCK(m) ZSTD_pthread_mutex_lock(m)\n#  define DEBUG_PRINTHEX(l,p,n) do { } while (0)\n\n#endif\n\n\n/* =====   Buffer Pool   ===== */\n/* a single Buffer Pool can be invoked from multiple threads in parallel */\n\ntypedef struct buffer_s {\n    void* start;\n    size_t capacity;\n} Buffer;\n\nstatic const Buffer g_nullBuffer = { NULL, 0 };\n\ntypedef struct ZSTDMT_bufferPool_s {\n    ZSTD_pthread_mutex_t poolMutex;\n    size_t bufferSize;\n    unsigned totalBuffers;\n    unsigned nbBuffers;\n    ZSTD_customMem cMem;\n    Buffer* buffers;\n} ZSTDMT_bufferPool;\n\nstatic void ZSTDMT_freeBufferPool(ZSTDMT_bufferPool* bufPool)\n{\n    DEBUGLOG(3, \"ZSTDMT_freeBufferPool (address:%08X)\", (U32)(size_t)bufPool);\n    if (!bufPool) return;   /* compatibility with free on NULL */\n    if (bufPool->buffers) {\n        unsigned u;\n        for (u=0; u<bufPool->totalBuffers; u++) {\n            DEBUGLOG(4, \"free buffer %2u (address:%08X)\", u, (U32)(size_t)bufPool->buffers[u].start);\n            ZSTD_customFree(bufPool->buffers[u].start, bufPool->cMem);\n        }\n        ZSTD_customFree(bufPool->buffers, bufPool->cMem);\n    }\n    ZSTD_pthread_mutex_destroy(&bufPool->poolMutex);\n    ZSTD_customFree(bufPool, bufPool->cMem);\n}\n\nstatic ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned maxNbBuffers, ZSTD_customMem cMem)\n{\n    ZSTDMT_bufferPool* const bufPool =\n        (ZSTDMT_bufferPool*)ZSTD_customCalloc(sizeof(ZSTDMT_bufferPool), cMem);\n    if (bufPool==NULL) return NULL;\n    if (ZSTD_pthread_mutex_init(&bufPool->poolMutex, NULL)) {\n        ZSTD_customFree(bufPool, cMem);\n        return NULL;\n    }\n    bufPool->buffers = (Buffer*)ZSTD_customCalloc(maxNbBuffers * sizeof(Buffer), cMem);\n    if (bufPool->buffers==NULL) {\n        ZSTDMT_freeBufferPool(bufPool);\n        return NULL;\n    }\n    bufPool->bufferSize = 64 KB;\n    bufPool->totalBuffers = maxNbBuffers;\n    bufPool->nbBuffers = 0;\n    bufPool->cMem = cMem;\n    return bufPool;\n}\n\n/* only works at initialization, not during compression */\nstatic size_t ZSTDMT_sizeof_bufferPool(ZSTDMT_bufferPool* bufPool)\n{\n    size_t const poolSize = sizeof(*bufPool);\n    size_t const arraySize = bufPool->totalBuffers * sizeof(Buffer);\n    unsigned u;\n    size_t totalBufferSize = 0;\n    ZSTD_pthread_mutex_lock(&bufPool->poolMutex);\n    for (u=0; u<bufPool->totalBuffers; u++)\n        totalBufferSize += bufPool->buffers[u].capacity;\n    ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);\n\n    return poolSize + arraySize + totalBufferSize;\n}\n\n/* ZSTDMT_setBufferSize() :\n * all future buffers provided by this buffer pool will have _at least_ this size\n * note : it's better for all buffers to have same size,\n * as they become freely interchangeable, reducing malloc/free usages and memory fragmentation */\nstatic void ZSTDMT_setBufferSize(ZSTDMT_bufferPool* const bufPool, size_t const bSize)\n{\n    ZSTD_pthread_mutex_lock(&bufPool->poolMutex);\n    DEBUGLOG(4, \"ZSTDMT_setBufferSize: bSize = %u\", (U32)bSize);\n    bufPool->bufferSize = bSize;\n    ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);\n}\n\n\nstatic ZSTDMT_bufferPool* ZSTDMT_expandBufferPool(ZSTDMT_bufferPool* srcBufPool, unsigned maxNbBuffers)\n{\n    if (srcBufPool==NULL) return NULL;\n    if (srcBufPool->totalBuffers >= maxNbBuffers) /* good enough */\n        return srcBufPool;\n    /* need a larger buffer pool */\n    {   ZSTD_customMem const cMem = srcBufPool->cMem;\n        size_t const bSize = srcBufPool->bufferSize;   /* forward parameters */\n        ZSTDMT_bufferPool* newBufPool;\n        ZSTDMT_freeBufferPool(srcBufPool);\n        newBufPool = ZSTDMT_createBufferPool(maxNbBuffers, cMem);\n        if (newBufPool==NULL) return newBufPool;\n        ZSTDMT_setBufferSize(newBufPool, bSize);\n        return newBufPool;\n    }\n}\n\n/** ZSTDMT_getBuffer() :\n *  assumption : bufPool must be valid\n * @return : a buffer, with start pointer and size\n *  note: allocation may fail, in this case, start==NULL and size==0 */\nstatic Buffer ZSTDMT_getBuffer(ZSTDMT_bufferPool* bufPool)\n{\n    size_t const bSize = bufPool->bufferSize;\n    DEBUGLOG(5, \"ZSTDMT_getBuffer: bSize = %u\", (U32)bufPool->bufferSize);\n    ZSTD_pthread_mutex_lock(&bufPool->poolMutex);\n    if (bufPool->nbBuffers) {   /* try to use an existing buffer */\n        Buffer const buf = bufPool->buffers[--(bufPool->nbBuffers)];\n        size_t const availBufferSize = buf.capacity;\n        bufPool->buffers[bufPool->nbBuffers] = g_nullBuffer;\n        if ((availBufferSize >= bSize) & ((availBufferSize>>3) <= bSize)) {\n            /* large enough, but not too much */\n            DEBUGLOG(5, \"ZSTDMT_getBuffer: provide buffer %u of size %u\",\n                        bufPool->nbBuffers, (U32)buf.capacity);\n            ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);\n            return buf;\n        }\n        /* size conditions not respected : scratch this buffer, create new one */\n        DEBUGLOG(5, \"ZSTDMT_getBuffer: existing buffer does not meet size conditions => freeing\");\n        ZSTD_customFree(buf.start, bufPool->cMem);\n    }\n    ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);\n    /* create new buffer */\n    DEBUGLOG(5, \"ZSTDMT_getBuffer: create a new buffer\");\n    {   Buffer buffer;\n        void* const start = ZSTD_customMalloc(bSize, bufPool->cMem);\n        buffer.start = start;   /* note : start can be NULL if malloc fails ! */\n        buffer.capacity = (start==NULL) ? 0 : bSize;\n        if (start==NULL) {\n            DEBUGLOG(5, \"ZSTDMT_getBuffer: buffer allocation failure !!\");\n        } else {\n            DEBUGLOG(5, \"ZSTDMT_getBuffer: created buffer of size %u\", (U32)bSize);\n        }\n        return buffer;\n    }\n}\n\n#if ZSTD_RESIZE_SEQPOOL\n/** ZSTDMT_resizeBuffer() :\n * assumption : bufPool must be valid\n * @return : a buffer that is at least the buffer pool buffer size.\n *           If a reallocation happens, the data in the input buffer is copied.\n */\nstatic Buffer ZSTDMT_resizeBuffer(ZSTDMT_bufferPool* bufPool, Buffer buffer)\n{\n    size_t const bSize = bufPool->bufferSize;\n    if (buffer.capacity < bSize) {\n        void* const start = ZSTD_customMalloc(bSize, bufPool->cMem);\n        Buffer newBuffer;\n        newBuffer.start = start;\n        newBuffer.capacity = start == NULL ? 0 : bSize;\n        if (start != NULL) {\n            assert(newBuffer.capacity >= buffer.capacity);\n            ZSTD_memcpy(newBuffer.start, buffer.start, buffer.capacity);\n            DEBUGLOG(5, \"ZSTDMT_resizeBuffer: created buffer of size %u\", (U32)bSize);\n            return newBuffer;\n        }\n        DEBUGLOG(5, \"ZSTDMT_resizeBuffer: buffer allocation failure !!\");\n    }\n    return buffer;\n}\n#endif\n\n/* store buffer for later re-use, up to pool capacity */\nstatic void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, Buffer buf)\n{\n    DEBUGLOG(5, \"ZSTDMT_releaseBuffer\");\n    if (buf.start == NULL) return;   /* compatible with release on NULL */\n    ZSTD_pthread_mutex_lock(&bufPool->poolMutex);\n    if (bufPool->nbBuffers < bufPool->totalBuffers) {\n        bufPool->buffers[bufPool->nbBuffers++] = buf;  /* stored for later use */\n        DEBUGLOG(5, \"ZSTDMT_releaseBuffer: stored buffer of size %u in slot %u\",\n                    (U32)buf.capacity, (U32)(bufPool->nbBuffers-1));\n        ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);\n        return;\n    }\n    ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);\n    /* Reached bufferPool capacity (note: should not happen) */\n    DEBUGLOG(5, \"ZSTDMT_releaseBuffer: pool capacity reached => freeing \");\n    ZSTD_customFree(buf.start, bufPool->cMem);\n}\n\n/* We need 2 output buffers per worker since each dstBuff must be flushed after it is released.\n * The 3 additional buffers are as follows:\n *   1 buffer for input loading\n *   1 buffer for \"next input\" when submitting current one\n *   1 buffer stuck in queue */\n#define BUF_POOL_MAX_NB_BUFFERS(nbWorkers) (2*(nbWorkers) + 3)\n\n/* After a worker releases its rawSeqStore, it is immediately ready for reuse.\n * So we only need one seq buffer per worker. */\n#define SEQ_POOL_MAX_NB_BUFFERS(nbWorkers) (nbWorkers)\n\n/* =====   Seq Pool Wrapper   ====== */\n\ntypedef ZSTDMT_bufferPool ZSTDMT_seqPool;\n\nstatic size_t ZSTDMT_sizeof_seqPool(ZSTDMT_seqPool* seqPool)\n{\n    return ZSTDMT_sizeof_bufferPool(seqPool);\n}\n\nstatic RawSeqStore_t bufferToSeq(Buffer buffer)\n{\n    RawSeqStore_t seq = kNullRawSeqStore;\n    seq.seq = (rawSeq*)buffer.start;\n    seq.capacity = buffer.capacity / sizeof(rawSeq);\n    return seq;\n}\n\nstatic Buffer seqToBuffer(RawSeqStore_t seq)\n{\n    Buffer buffer;\n    buffer.start = seq.seq;\n    buffer.capacity = seq.capacity * sizeof(rawSeq);\n    return buffer;\n}\n\nstatic RawSeqStore_t ZSTDMT_getSeq(ZSTDMT_seqPool* seqPool)\n{\n    if (seqPool->bufferSize == 0) {\n        return kNullRawSeqStore;\n    }\n    return bufferToSeq(ZSTDMT_getBuffer(seqPool));\n}\n\n#if ZSTD_RESIZE_SEQPOOL\nstatic RawSeqStore_t ZSTDMT_resizeSeq(ZSTDMT_seqPool* seqPool, RawSeqStore_t seq)\n{\n  return bufferToSeq(ZSTDMT_resizeBuffer(seqPool, seqToBuffer(seq)));\n}\n#endif\n\nstatic void ZSTDMT_releaseSeq(ZSTDMT_seqPool* seqPool, RawSeqStore_t seq)\n{\n  ZSTDMT_releaseBuffer(seqPool, seqToBuffer(seq));\n}\n\nstatic void ZSTDMT_setNbSeq(ZSTDMT_seqPool* const seqPool, size_t const nbSeq)\n{\n  ZSTDMT_setBufferSize(seqPool, nbSeq * sizeof(rawSeq));\n}\n\nstatic ZSTDMT_seqPool* ZSTDMT_createSeqPool(unsigned nbWorkers, ZSTD_customMem cMem)\n{\n    ZSTDMT_seqPool* const seqPool = ZSTDMT_createBufferPool(SEQ_POOL_MAX_NB_BUFFERS(nbWorkers), cMem);\n    if (seqPool == NULL) return NULL;\n    ZSTDMT_setNbSeq(seqPool, 0);\n    return seqPool;\n}\n\nstatic void ZSTDMT_freeSeqPool(ZSTDMT_seqPool* seqPool)\n{\n    ZSTDMT_freeBufferPool(seqPool);\n}\n\nstatic ZSTDMT_seqPool* ZSTDMT_expandSeqPool(ZSTDMT_seqPool* pool, U32 nbWorkers)\n{\n    return ZSTDMT_expandBufferPool(pool, SEQ_POOL_MAX_NB_BUFFERS(nbWorkers));\n}\n\n\n/* =====   CCtx Pool   ===== */\n/* a single CCtx Pool can be invoked from multiple threads in parallel */\n\ntypedef struct {\n    ZSTD_pthread_mutex_t poolMutex;\n    int totalCCtx;\n    int availCCtx;\n    ZSTD_customMem cMem;\n    ZSTD_CCtx** cctxs;\n} ZSTDMT_CCtxPool;\n\n/* note : all CCtx borrowed from the pool must be reverted back to the pool _before_ freeing the pool */\nstatic void ZSTDMT_freeCCtxPool(ZSTDMT_CCtxPool* pool)\n{\n    if (!pool) return;\n    ZSTD_pthread_mutex_destroy(&pool->poolMutex);\n    if (pool->cctxs) {\n        int cid;\n        for (cid=0; cid<pool->totalCCtx; cid++)\n            ZSTD_freeCCtx(pool->cctxs[cid]);  /* free compatible with NULL */\n        ZSTD_customFree(pool->cctxs, pool->cMem);\n    }\n    ZSTD_customFree(pool, pool->cMem);\n}\n\n/* ZSTDMT_createCCtxPool() :\n * implies nbWorkers >= 1 , checked by caller ZSTDMT_createCCtx() */\nstatic ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(int nbWorkers,\n                                              ZSTD_customMem cMem)\n{\n    ZSTDMT_CCtxPool* const cctxPool =\n        (ZSTDMT_CCtxPool*) ZSTD_customCalloc(sizeof(ZSTDMT_CCtxPool), cMem);\n    assert(nbWorkers > 0);\n    if (!cctxPool) return NULL;\n    if (ZSTD_pthread_mutex_init(&cctxPool->poolMutex, NULL)) {\n        ZSTD_customFree(cctxPool, cMem);\n        return NULL;\n    }\n    cctxPool->totalCCtx = nbWorkers;\n    cctxPool->cctxs = (ZSTD_CCtx**)ZSTD_customCalloc(nbWorkers * sizeof(ZSTD_CCtx*), cMem);\n    if (!cctxPool->cctxs) {\n        ZSTDMT_freeCCtxPool(cctxPool);\n        return NULL;\n    }\n    cctxPool->cMem = cMem;\n    cctxPool->cctxs[0] = ZSTD_createCCtx_advanced(cMem);\n    if (!cctxPool->cctxs[0]) { ZSTDMT_freeCCtxPool(cctxPool); return NULL; }\n    cctxPool->availCCtx = 1;   /* at least one cctx for single-thread mode */\n    DEBUGLOG(3, \"cctxPool created, with %u workers\", nbWorkers);\n    return cctxPool;\n}\n\nstatic ZSTDMT_CCtxPool* ZSTDMT_expandCCtxPool(ZSTDMT_CCtxPool* srcPool,\n                                              int nbWorkers)\n{\n    if (srcPool==NULL) return NULL;\n    if (nbWorkers <= srcPool->totalCCtx) return srcPool;   /* good enough */\n    /* need a larger cctx pool */\n    {   ZSTD_customMem const cMem = srcPool->cMem;\n        ZSTDMT_freeCCtxPool(srcPool);\n        return ZSTDMT_createCCtxPool(nbWorkers, cMem);\n    }\n}\n\n/* only works during initialization phase, not during compression */\nstatic size_t ZSTDMT_sizeof_CCtxPool(ZSTDMT_CCtxPool* cctxPool)\n{\n    ZSTD_pthread_mutex_lock(&cctxPool->poolMutex);\n    {   unsigned const nbWorkers = cctxPool->totalCCtx;\n        size_t const poolSize = sizeof(*cctxPool);\n        size_t const arraySize = cctxPool->totalCCtx * sizeof(ZSTD_CCtx*);\n        size_t totalCCtxSize = 0;\n        unsigned u;\n        for (u=0; u<nbWorkers; u++) {\n            totalCCtxSize += ZSTD_sizeof_CCtx(cctxPool->cctxs[u]);\n        }\n        ZSTD_pthread_mutex_unlock(&cctxPool->poolMutex);\n        assert(nbWorkers > 0);\n        return poolSize + arraySize + totalCCtxSize;\n    }\n}\n\nstatic ZSTD_CCtx* ZSTDMT_getCCtx(ZSTDMT_CCtxPool* cctxPool)\n{\n    DEBUGLOG(5, \"ZSTDMT_getCCtx\");\n    ZSTD_pthread_mutex_lock(&cctxPool->poolMutex);\n    if (cctxPool->availCCtx) {\n        cctxPool->availCCtx--;\n        {   ZSTD_CCtx* const cctx = cctxPool->cctxs[cctxPool->availCCtx];\n            ZSTD_pthread_mutex_unlock(&cctxPool->poolMutex);\n            return cctx;\n    }   }\n    ZSTD_pthread_mutex_unlock(&cctxPool->poolMutex);\n    DEBUGLOG(5, \"create one more CCtx\");\n    return ZSTD_createCCtx_advanced(cctxPool->cMem);   /* note : can be NULL, when creation fails ! */\n}\n\nstatic void ZSTDMT_releaseCCtx(ZSTDMT_CCtxPool* pool, ZSTD_CCtx* cctx)\n{\n    if (cctx==NULL) return;   /* compatibility with release on NULL */\n    ZSTD_pthread_mutex_lock(&pool->poolMutex);\n    if (pool->availCCtx < pool->totalCCtx)\n        pool->cctxs[pool->availCCtx++] = cctx;\n    else {\n        /* pool overflow : should not happen, since totalCCtx==nbWorkers */\n        DEBUGLOG(4, \"CCtx pool overflow : free cctx\");\n        ZSTD_freeCCtx(cctx);\n    }\n    ZSTD_pthread_mutex_unlock(&pool->poolMutex);\n}\n\n/* ====   Serial State   ==== */\n\ntypedef struct {\n    void const* start;\n    size_t size;\n} Range;\n\ntypedef struct {\n    /* All variables in the struct are protected by mutex. */\n    ZSTD_pthread_mutex_t mutex;\n    ZSTD_pthread_cond_t cond;\n    ZSTD_CCtx_params params;\n    ldmState_t ldmState;\n    XXH64_state_t xxhState;\n    unsigned nextJobID;\n    /* Protects ldmWindow.\n     * Must be acquired after the main mutex when acquiring both.\n     */\n    ZSTD_pthread_mutex_t ldmWindowMutex;\n    ZSTD_pthread_cond_t ldmWindowCond;  /* Signaled when ldmWindow is updated */\n    ZSTD_window_t ldmWindow;  /* A thread-safe copy of ldmState.window */\n} SerialState;\n\nstatic int\nZSTDMT_serialState_reset(SerialState* serialState,\n                         ZSTDMT_seqPool* seqPool,\n                         ZSTD_CCtx_params params,\n                         size_t jobSize,\n                         const void* dict, size_t const dictSize,\n                         ZSTD_dictContentType_e dictContentType)\n{\n    /* Adjust parameters */\n    if (params.ldmParams.enableLdm == ZSTD_ps_enable) {\n        DEBUGLOG(4, \"LDM window size = %u KB\", (1U << params.cParams.windowLog) >> 10);\n        ZSTD_ldm_adjustParameters(&params.ldmParams, &params.cParams);\n        assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog);\n        assert(params.ldmParams.hashRateLog < 32);\n    } else {\n        ZSTD_memset(&params.ldmParams, 0, sizeof(params.ldmParams));\n    }\n    serialState->nextJobID = 0;\n    if (params.fParams.checksumFlag)\n        XXH64_reset(&serialState->xxhState, 0);\n    if (params.ldmParams.enableLdm == ZSTD_ps_enable) {\n        ZSTD_customMem cMem = params.customMem;\n        unsigned const hashLog = params.ldmParams.hashLog;\n        size_t const hashSize = ((size_t)1 << hashLog) * sizeof(ldmEntry_t);\n        unsigned const bucketLog =\n            params.ldmParams.hashLog - params.ldmParams.bucketSizeLog;\n        unsigned const prevBucketLog =\n            serialState->params.ldmParams.hashLog -\n            serialState->params.ldmParams.bucketSizeLog;\n        size_t const numBuckets = (size_t)1 << bucketLog;\n        /* Size the seq pool tables */\n        ZSTDMT_setNbSeq(seqPool, ZSTD_ldm_getMaxNbSeq(params.ldmParams, jobSize));\n        /* Reset the window */\n        ZSTD_window_init(&serialState->ldmState.window);\n        /* Resize tables and output space if necessary. */\n        if (serialState->ldmState.hashTable == NULL || serialState->params.ldmParams.hashLog < hashLog) {\n            ZSTD_customFree(serialState->ldmState.hashTable, cMem);\n            serialState->ldmState.hashTable = (ldmEntry_t*)ZSTD_customMalloc(hashSize, cMem);\n        }\n        if (serialState->ldmState.bucketOffsets == NULL || prevBucketLog < bucketLog) {\n            ZSTD_customFree(serialState->ldmState.bucketOffsets, cMem);\n            serialState->ldmState.bucketOffsets = (BYTE*)ZSTD_customMalloc(numBuckets, cMem);\n        }\n        if (!serialState->ldmState.hashTable || !serialState->ldmState.bucketOffsets)\n            return 1;\n        /* Zero the tables */\n        ZSTD_memset(serialState->ldmState.hashTable, 0, hashSize);\n        ZSTD_memset(serialState->ldmState.bucketOffsets, 0, numBuckets);\n\n        /* Update window state and fill hash table with dict */\n        serialState->ldmState.loadedDictEnd = 0;\n        if (dictSize > 0) {\n            if (dictContentType == ZSTD_dct_rawContent) {\n                BYTE const* const dictEnd = (const BYTE*)dict + dictSize;\n                ZSTD_window_update(&serialState->ldmState.window, dict, dictSize, /* forceNonContiguous */ 0);\n                ZSTD_ldm_fillHashTable(&serialState->ldmState, (const BYTE*)dict, dictEnd, &params.ldmParams);\n                serialState->ldmState.loadedDictEnd = params.forceWindow ? 0 : (U32)(dictEnd - serialState->ldmState.window.base);\n            } else {\n                /* don't even load anything */\n            }\n        }\n\n        /* Initialize serialState's copy of ldmWindow. */\n        serialState->ldmWindow = serialState->ldmState.window;\n    }\n\n    serialState->params = params;\n    serialState->params.jobSize = (U32)jobSize;\n    return 0;\n}\n\nstatic int ZSTDMT_serialState_init(SerialState* serialState)\n{\n    int initError = 0;\n    ZSTD_memset(serialState, 0, sizeof(*serialState));\n    initError |= ZSTD_pthread_mutex_init(&serialState->mutex, NULL);\n    initError |= ZSTD_pthread_cond_init(&serialState->cond, NULL);\n    initError |= ZSTD_pthread_mutex_init(&serialState->ldmWindowMutex, NULL);\n    initError |= ZSTD_pthread_cond_init(&serialState->ldmWindowCond, NULL);\n    return initError;\n}\n\nstatic void ZSTDMT_serialState_free(SerialState* serialState)\n{\n    ZSTD_customMem cMem = serialState->params.customMem;\n    ZSTD_pthread_mutex_destroy(&serialState->mutex);\n    ZSTD_pthread_cond_destroy(&serialState->cond);\n    ZSTD_pthread_mutex_destroy(&serialState->ldmWindowMutex);\n    ZSTD_pthread_cond_destroy(&serialState->ldmWindowCond);\n    ZSTD_customFree(serialState->ldmState.hashTable, cMem);\n    ZSTD_customFree(serialState->ldmState.bucketOffsets, cMem);\n}\n\nstatic void\nZSTDMT_serialState_genSequences(SerialState* serialState,\n                                RawSeqStore_t* seqStore,\n                                Range src, unsigned jobID)\n{\n    /* Wait for our turn */\n    ZSTD_PTHREAD_MUTEX_LOCK(&serialState->mutex);\n    while (serialState->nextJobID < jobID) {\n        DEBUGLOG(5, \"wait for serialState->cond\");\n        ZSTD_pthread_cond_wait(&serialState->cond, &serialState->mutex);\n    }\n    /* A future job may error and skip our job */\n    if (serialState->nextJobID == jobID) {\n        /* It is now our turn, do any processing necessary */\n        if (serialState->params.ldmParams.enableLdm == ZSTD_ps_enable) {\n            size_t error;\n            DEBUGLOG(6, \"ZSTDMT_serialState_genSequences: LDM update\");\n            assert(seqStore->seq != NULL && seqStore->pos == 0 &&\n                   seqStore->size == 0 && seqStore->capacity > 0);\n            assert(src.size <= serialState->params.jobSize);\n            ZSTD_window_update(&serialState->ldmState.window, src.start, src.size, /* forceNonContiguous */ 0);\n            error = ZSTD_ldm_generateSequences(\n                &serialState->ldmState, seqStore,\n                &serialState->params.ldmParams, src.start, src.size);\n            /* We provide a large enough buffer to never fail. */\n            assert(!ZSTD_isError(error)); (void)error;\n            /* Update ldmWindow to match the ldmState.window and signal the main\n             * thread if it is waiting for a buffer.\n             */\n            ZSTD_PTHREAD_MUTEX_LOCK(&serialState->ldmWindowMutex);\n            serialState->ldmWindow = serialState->ldmState.window;\n            ZSTD_pthread_cond_signal(&serialState->ldmWindowCond);\n            ZSTD_pthread_mutex_unlock(&serialState->ldmWindowMutex);\n        }\n        if (serialState->params.fParams.checksumFlag && src.size > 0)\n            XXH64_update(&serialState->xxhState, src.start, src.size);\n    }\n    /* Now it is the next jobs turn */\n    serialState->nextJobID++;\n    ZSTD_pthread_cond_broadcast(&serialState->cond);\n    ZSTD_pthread_mutex_unlock(&serialState->mutex);\n}\n\nstatic void\nZSTDMT_serialState_applySequences(const SerialState* serialState, /* just for an assert() check */\n                                  ZSTD_CCtx* jobCCtx,\n                                  const RawSeqStore_t* seqStore)\n{\n    if (seqStore->size > 0) {\n        DEBUGLOG(5, \"ZSTDMT_serialState_applySequences: uploading %u external sequences\", (unsigned)seqStore->size);\n        assert(serialState->params.ldmParams.enableLdm == ZSTD_ps_enable); (void)serialState;\n        assert(jobCCtx);\n        ZSTD_referenceExternalSequences(jobCCtx, seqStore->seq, seqStore->size);\n    }\n}\n\nstatic void ZSTDMT_serialState_ensureFinished(SerialState* serialState,\n                                              unsigned jobID, size_t cSize)\n{\n    ZSTD_PTHREAD_MUTEX_LOCK(&serialState->mutex);\n    if (serialState->nextJobID <= jobID) {\n        assert(ZSTD_isError(cSize)); (void)cSize;\n        DEBUGLOG(5, \"Skipping past job %u because of error\", jobID);\n        serialState->nextJobID = jobID + 1;\n        ZSTD_pthread_cond_broadcast(&serialState->cond);\n\n        ZSTD_PTHREAD_MUTEX_LOCK(&serialState->ldmWindowMutex);\n        ZSTD_window_clear(&serialState->ldmWindow);\n        ZSTD_pthread_cond_signal(&serialState->ldmWindowCond);\n        ZSTD_pthread_mutex_unlock(&serialState->ldmWindowMutex);\n    }\n    ZSTD_pthread_mutex_unlock(&serialState->mutex);\n\n}\n\n\n/* ------------------------------------------ */\n/* =====          Worker thread         ===== */\n/* ------------------------------------------ */\n\nstatic const Range kNullRange = { NULL, 0 };\n\ntypedef struct {\n    size_t   consumed;                 /* SHARED - set0 by mtctx, then modified by worker AND read by mtctx */\n    size_t   cSize;                    /* SHARED - set0 by mtctx, then modified by worker AND read by mtctx, then set0 by mtctx */\n    ZSTD_pthread_mutex_t job_mutex;    /* Thread-safe - used by mtctx and worker */\n    ZSTD_pthread_cond_t job_cond;      /* Thread-safe - used by mtctx and worker */\n    ZSTDMT_CCtxPool* cctxPool;         /* Thread-safe - used by mtctx and (all) workers */\n    ZSTDMT_bufferPool* bufPool;        /* Thread-safe - used by mtctx and (all) workers */\n    ZSTDMT_seqPool* seqPool;           /* Thread-safe - used by mtctx and (all) workers */\n    SerialState* serial;               /* Thread-safe - used by mtctx and (all) workers */\n    Buffer dstBuff;                    /* set by worker (or mtctx), then read by worker & mtctx, then modified by mtctx => no barrier */\n    Range prefix;                      /* set by mtctx, then read by worker & mtctx => no barrier */\n    Range src;                         /* set by mtctx, then read by worker & mtctx => no barrier */\n    unsigned jobID;                    /* set by mtctx, then read by worker => no barrier */\n    unsigned firstJob;                 /* set by mtctx, then read by worker => no barrier */\n    unsigned lastJob;                  /* set by mtctx, then read by worker => no barrier */\n    ZSTD_CCtx_params params;           /* set by mtctx, then read by worker => no barrier */\n    const ZSTD_CDict* cdict;           /* set by mtctx, then read by worker => no barrier */\n    unsigned long long fullFrameSize;  /* set by mtctx, then read by worker => no barrier */\n    size_t   dstFlushed;               /* used only by mtctx */\n    unsigned frameChecksumNeeded;      /* used only by mtctx */\n} ZSTDMT_jobDescription;\n\n#define JOB_ERROR(e)                                \\\n    do {                                            \\\n        ZSTD_PTHREAD_MUTEX_LOCK(&job->job_mutex);   \\\n        job->cSize = e;                             \\\n        ZSTD_pthread_mutex_unlock(&job->job_mutex); \\\n        goto _endJob;                               \\\n    } while (0)\n\n/* ZSTDMT_compressionJob() is a POOL_function type */\nstatic void ZSTDMT_compressionJob(void* jobDescription)\n{\n    ZSTDMT_jobDescription* const job = (ZSTDMT_jobDescription*)jobDescription;\n    ZSTD_CCtx_params jobParams = job->params;   /* do not modify job->params ! copy it, modify the copy */\n    ZSTD_CCtx* const cctx = ZSTDMT_getCCtx(job->cctxPool);\n    RawSeqStore_t rawSeqStore = ZSTDMT_getSeq(job->seqPool);\n    Buffer dstBuff = job->dstBuff;\n    size_t lastCBlockSize = 0;\n\n    DEBUGLOG(5, \"ZSTDMT_compressionJob: job %u\", job->jobID);\n    /* resources */\n    if (cctx==NULL) JOB_ERROR(ERROR(memory_allocation));\n    if (dstBuff.start == NULL) {   /* streaming job : doesn't provide a dstBuffer */\n        dstBuff = ZSTDMT_getBuffer(job->bufPool);\n        if (dstBuff.start==NULL) JOB_ERROR(ERROR(memory_allocation));\n        job->dstBuff = dstBuff;   /* this value can be read in ZSTDMT_flush, when it copies the whole job */\n    }\n    if (jobParams.ldmParams.enableLdm == ZSTD_ps_enable && rawSeqStore.seq == NULL)\n        JOB_ERROR(ERROR(memory_allocation));\n\n    /* Don't compute the checksum for chunks, since we compute it externally,\n     * but write it in the header.\n     */\n    if (job->jobID != 0) jobParams.fParams.checksumFlag = 0;\n    /* Don't run LDM for the chunks, since we handle it externally */\n    jobParams.ldmParams.enableLdm = ZSTD_ps_disable;\n    /* Correct nbWorkers to 0. */\n    jobParams.nbWorkers = 0;\n\n\n    /* init */\n\n    /* Perform serial step as early as possible */\n    ZSTDMT_serialState_genSequences(job->serial, &rawSeqStore, job->src, job->jobID);\n\n    if (job->cdict) {\n        size_t const initError = ZSTD_compressBegin_advanced_internal(cctx, NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast, job->cdict, &jobParams, job->fullFrameSize);\n        assert(job->firstJob);  /* only allowed for first job */\n        if (ZSTD_isError(initError)) JOB_ERROR(initError);\n    } else {\n        U64 const pledgedSrcSize = job->firstJob ? job->fullFrameSize : job->src.size;\n        {   size_t const forceWindowError = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_forceMaxWindow, !job->firstJob);\n            if (ZSTD_isError(forceWindowError)) JOB_ERROR(forceWindowError);\n        }\n        if (!job->firstJob) {\n            size_t const err = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_deterministicRefPrefix, 0);\n            if (ZSTD_isError(err)) JOB_ERROR(err);\n        }\n        DEBUGLOG(6, \"ZSTDMT_compressionJob: job %u: loading prefix of size %zu\", job->jobID, job->prefix.size);\n        {   size_t const initError = ZSTD_compressBegin_advanced_internal(cctx,\n                                        job->prefix.start, job->prefix.size, ZSTD_dct_rawContent,\n                                        ZSTD_dtlm_fast,\n                                        NULL, /*cdict*/\n                                        &jobParams, pledgedSrcSize);\n            if (ZSTD_isError(initError)) JOB_ERROR(initError);\n    }   }\n\n    /* External Sequences can only be applied after CCtx initialization */\n    ZSTDMT_serialState_applySequences(job->serial, cctx, &rawSeqStore);\n\n    if (!job->firstJob) {  /* flush and overwrite frame header when it's not first job */\n        size_t const hSize = ZSTD_compressContinue_public(cctx, dstBuff.start, dstBuff.capacity, job->src.start, 0);\n        if (ZSTD_isError(hSize)) JOB_ERROR(hSize);\n        DEBUGLOG(5, \"ZSTDMT_compressionJob: flush and overwrite %u bytes of frame header (not first job)\", (U32)hSize);\n        ZSTD_invalidateRepCodes(cctx);\n    }\n\n    /* compress the entire job by smaller chunks, for better granularity */\n    {   size_t const chunkSize = 4*ZSTD_BLOCKSIZE_MAX;\n        int const nbChunks = (int)((job->src.size + (chunkSize-1)) / chunkSize);\n        const BYTE* ip = (const BYTE*) job->src.start;\n        BYTE* const ostart = (BYTE*)dstBuff.start;\n        BYTE* op = ostart;\n        BYTE* oend = op + dstBuff.capacity;\n        int chunkNb;\n        if (sizeof(size_t) > sizeof(int)) assert(job->src.size < ((size_t)INT_MAX) * chunkSize);   /* check overflow */\n        DEBUGLOG(5, \"ZSTDMT_compressionJob: compress %u bytes in %i blocks\", (U32)job->src.size, nbChunks);\n        assert(job->cSize == 0);\n        for (chunkNb = 1; chunkNb < nbChunks; chunkNb++) {\n            size_t const cSize = ZSTD_compressContinue_public(cctx, op, oend-op, ip, chunkSize);\n            if (ZSTD_isError(cSize)) JOB_ERROR(cSize);\n            ip += chunkSize;\n            op += cSize; assert(op < oend);\n            /* stats */\n            ZSTD_PTHREAD_MUTEX_LOCK(&job->job_mutex);\n            job->cSize += cSize;\n            job->consumed = chunkSize * chunkNb;\n            DEBUGLOG(5, \"ZSTDMT_compressionJob: compress new block : cSize==%u bytes (total: %u)\",\n                        (U32)cSize, (U32)job->cSize);\n            ZSTD_pthread_cond_signal(&job->job_cond);   /* warns some more data is ready to be flushed */\n            ZSTD_pthread_mutex_unlock(&job->job_mutex);\n        }\n        /* last block */\n        assert(chunkSize > 0);\n        assert((chunkSize & (chunkSize - 1)) == 0);  /* chunkSize must be power of 2 for mask==(chunkSize-1) to work */\n        if ((nbChunks > 0) | job->lastJob /*must output a \"last block\" flag*/ ) {\n            size_t const lastBlockSize1 = job->src.size & (chunkSize-1);\n            size_t const lastBlockSize = ((lastBlockSize1==0) & (job->src.size>=chunkSize)) ? chunkSize : lastBlockSize1;\n            size_t const cSize = (job->lastJob) ?\n                 ZSTD_compressEnd_public(cctx, op, oend-op, ip, lastBlockSize) :\n                 ZSTD_compressContinue_public(cctx, op, oend-op, ip, lastBlockSize);\n            if (ZSTD_isError(cSize)) JOB_ERROR(cSize);\n            lastCBlockSize = cSize;\n    }   }\n    if (!job->firstJob) {\n        /* Double check that we don't have an ext-dict, because then our\n         * repcode invalidation doesn't work.\n         */\n        assert(!ZSTD_window_hasExtDict(cctx->blockState.matchState.window));\n    }\n    ZSTD_CCtx_trace(cctx, 0);\n\n_endJob:\n    ZSTDMT_serialState_ensureFinished(job->serial, job->jobID, job->cSize);\n    if (job->prefix.size > 0)\n        DEBUGLOG(5, \"Finished with prefix: %zx\", (size_t)job->prefix.start);\n    DEBUGLOG(5, \"Finished with source: %zx\", (size_t)job->src.start);\n    /* release resources */\n    ZSTDMT_releaseSeq(job->seqPool, rawSeqStore);\n    ZSTDMT_releaseCCtx(job->cctxPool, cctx);\n    /* report */\n    ZSTD_PTHREAD_MUTEX_LOCK(&job->job_mutex);\n    if (ZSTD_isError(job->cSize)) assert(lastCBlockSize == 0);\n    job->cSize += lastCBlockSize;\n    job->consumed = job->src.size;  /* when job->consumed == job->src.size , compression job is presumed completed */\n    ZSTD_pthread_cond_signal(&job->job_cond);\n    ZSTD_pthread_mutex_unlock(&job->job_mutex);\n}\n\n\n/* ------------------------------------------ */\n/* =====   Multi-threaded compression   ===== */\n/* ------------------------------------------ */\n\ntypedef struct {\n    Range prefix;         /* read-only non-owned prefix buffer */\n    Buffer buffer;\n    size_t filled;\n} InBuff_t;\n\ntypedef struct {\n  BYTE* buffer;     /* The round input buffer. All jobs get references\n                     * to pieces of the buffer. ZSTDMT_tryGetInputRange()\n                     * handles handing out job input buffers, and makes\n                     * sure it doesn't overlap with any pieces still in use.\n                     */\n  size_t capacity;  /* The capacity of buffer. */\n  size_t pos;       /* The position of the current inBuff in the round\n                     * buffer. Updated past the end if the inBuff once\n                     * the inBuff is sent to the worker thread.\n                     * pos <= capacity.\n                     */\n} RoundBuff_t;\n\nstatic const RoundBuff_t kNullRoundBuff = {NULL, 0, 0};\n\n#define RSYNC_LENGTH 32\n/* Don't create chunks smaller than the zstd block size.\n * This stops us from regressing compression ratio too much,\n * and ensures our output fits in ZSTD_compressBound().\n *\n * If this is shrunk < ZSTD_BLOCKSIZELOG_MIN then\n * ZSTD_COMPRESSBOUND() will need to be updated.\n */\n#define RSYNC_MIN_BLOCK_LOG ZSTD_BLOCKSIZELOG_MAX\n#define RSYNC_MIN_BLOCK_SIZE (1<<RSYNC_MIN_BLOCK_LOG)\n\ntypedef struct {\n  U64 hash;\n  U64 hitMask;\n  U64 primePower;\n} RSyncState_t;\n\nstruct ZSTDMT_CCtx_s {\n    POOL_ctx* factory;\n    ZSTDMT_jobDescription* jobs;\n    ZSTDMT_bufferPool* bufPool;\n    ZSTDMT_CCtxPool* cctxPool;\n    ZSTDMT_seqPool* seqPool;\n    ZSTD_CCtx_params params;\n    size_t targetSectionSize;\n    size_t targetPrefixSize;\n    int jobReady;        /* 1 => one job is already prepared, but pool has shortage of workers. Don't create a new job. */\n    InBuff_t inBuff;\n    RoundBuff_t roundBuff;\n    SerialState serial;\n    RSyncState_t rsync;\n    unsigned jobIDMask;\n    unsigned doneJobID;\n    unsigned nextJobID;\n    unsigned frameEnded;\n    unsigned allJobsCompleted;\n    unsigned long long frameContentSize;\n    unsigned long long consumed;\n    unsigned long long produced;\n    ZSTD_customMem cMem;\n    ZSTD_CDict* cdictLocal;\n    const ZSTD_CDict* cdict;\n    unsigned providedFactory: 1;\n};\n\nstatic void ZSTDMT_freeJobsTable(ZSTDMT_jobDescription* jobTable, U32 nbJobs, ZSTD_customMem cMem)\n{\n    U32 jobNb;\n    if (jobTable == NULL) return;\n    for (jobNb=0; jobNb<nbJobs; jobNb++) {\n        ZSTD_pthread_mutex_destroy(&jobTable[jobNb].job_mutex);\n        ZSTD_pthread_cond_destroy(&jobTable[jobNb].job_cond);\n    }\n    ZSTD_customFree(jobTable, cMem);\n}\n\n/* ZSTDMT_allocJobsTable()\n * allocate and init a job table.\n * update *nbJobsPtr to next power of 2 value, as size of table */\nstatic ZSTDMT_jobDescription* ZSTDMT_createJobsTable(U32* nbJobsPtr, ZSTD_customMem cMem)\n{\n    U32 const nbJobsLog2 = ZSTD_highbit32(*nbJobsPtr) + 1;\n    U32 const nbJobs = 1 << nbJobsLog2;\n    U32 jobNb;\n    ZSTDMT_jobDescription* const jobTable = (ZSTDMT_jobDescription*)\n                ZSTD_customCalloc(nbJobs * sizeof(ZSTDMT_jobDescription), cMem);\n    int initError = 0;\n    if (jobTable==NULL) return NULL;\n    *nbJobsPtr = nbJobs;\n    for (jobNb=0; jobNb<nbJobs; jobNb++) {\n        initError |= ZSTD_pthread_mutex_init(&jobTable[jobNb].job_mutex, NULL);\n        initError |= ZSTD_pthread_cond_init(&jobTable[jobNb].job_cond, NULL);\n    }\n    if (initError != 0) {\n        ZSTDMT_freeJobsTable(jobTable, nbJobs, cMem);\n        return NULL;\n    }\n    return jobTable;\n}\n\nstatic size_t ZSTDMT_expandJobsTable (ZSTDMT_CCtx* mtctx, U32 nbWorkers) {\n    U32 nbJobs = nbWorkers + 2;\n    if (nbJobs > mtctx->jobIDMask+1) {  /* need more job capacity */\n        ZSTDMT_freeJobsTable(mtctx->jobs, mtctx->jobIDMask+1, mtctx->cMem);\n        mtctx->jobIDMask = 0;\n        mtctx->jobs = ZSTDMT_createJobsTable(&nbJobs, mtctx->cMem);\n        if (mtctx->jobs==NULL) return ERROR(memory_allocation);\n        assert((nbJobs != 0) && ((nbJobs & (nbJobs - 1)) == 0));  /* ensure nbJobs is a power of 2 */\n        mtctx->jobIDMask = nbJobs - 1;\n    }\n    return 0;\n}\n\n\n/* ZSTDMT_CCtxParam_setNbWorkers():\n * Internal use only */\nstatic size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers)\n{\n    return ZSTD_CCtxParams_setParameter(params, ZSTD_c_nbWorkers, (int)nbWorkers);\n}\n\nMEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers, ZSTD_customMem cMem, ZSTD_threadPool* pool)\n{\n    ZSTDMT_CCtx* mtctx;\n    U32 nbJobs = nbWorkers + 2;\n    int initError;\n    DEBUGLOG(3, \"ZSTDMT_createCCtx_advanced (nbWorkers = %u)\", nbWorkers);\n\n    if (nbWorkers < 1) return NULL;\n    nbWorkers = MIN(nbWorkers , ZSTDMT_NBWORKERS_MAX);\n    if ((cMem.customAlloc!=NULL) ^ (cMem.customFree!=NULL))\n        /* invalid custom allocator */\n        return NULL;\n\n    mtctx = (ZSTDMT_CCtx*) ZSTD_customCalloc(sizeof(ZSTDMT_CCtx), cMem);\n    if (!mtctx) return NULL;\n    ZSTDMT_CCtxParam_setNbWorkers(&mtctx->params, nbWorkers);\n    mtctx->cMem = cMem;\n    mtctx->allJobsCompleted = 1;\n    if (pool != NULL) {\n      mtctx->factory = pool;\n      mtctx->providedFactory = 1;\n    }\n    else {\n      mtctx->factory = POOL_create_advanced(nbWorkers, 0, cMem);\n      mtctx->providedFactory = 0;\n    }\n    mtctx->jobs = ZSTDMT_createJobsTable(&nbJobs, cMem);\n    assert(nbJobs > 0); assert((nbJobs & (nbJobs - 1)) == 0);  /* ensure nbJobs is a power of 2 */\n    mtctx->jobIDMask = nbJobs - 1;\n    mtctx->bufPool = ZSTDMT_createBufferPool(BUF_POOL_MAX_NB_BUFFERS(nbWorkers), cMem);\n    mtctx->cctxPool = ZSTDMT_createCCtxPool(nbWorkers, cMem);\n    mtctx->seqPool = ZSTDMT_createSeqPool(nbWorkers, cMem);\n    initError = ZSTDMT_serialState_init(&mtctx->serial);\n    mtctx->roundBuff = kNullRoundBuff;\n    if (!mtctx->factory | !mtctx->jobs | !mtctx->bufPool | !mtctx->cctxPool | !mtctx->seqPool | initError) {\n        ZSTDMT_freeCCtx(mtctx);\n        return NULL;\n    }\n    DEBUGLOG(3, \"mt_cctx created, for %u threads\", nbWorkers);\n    return mtctx;\n}\n\nZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem, ZSTD_threadPool* pool)\n{\n#ifdef ZSTD_MULTITHREAD\n    return ZSTDMT_createCCtx_advanced_internal(nbWorkers, cMem, pool);\n#else\n    (void)nbWorkers;\n    (void)cMem;\n    (void)pool;\n    return NULL;\n#endif\n}\n\n\n/* ZSTDMT_releaseAllJobResources() :\n * note : ensure all workers are killed first ! */\nstatic void ZSTDMT_releaseAllJobResources(ZSTDMT_CCtx* mtctx)\n{\n    unsigned jobID;\n    DEBUGLOG(3, \"ZSTDMT_releaseAllJobResources\");\n    if (mtctx->jobs) {\n        for (jobID=0; jobID <= mtctx->jobIDMask; jobID++) {\n            /* Copy the mutex/cond out */\n            ZSTD_pthread_mutex_t const mutex = mtctx->jobs[jobID].job_mutex;\n            ZSTD_pthread_cond_t const cond = mtctx->jobs[jobID].job_cond;\n            \n            DEBUGLOG(4, \"job%02u: release dst address %08X\", jobID, (U32)(size_t)mtctx->jobs[jobID].dstBuff.start);\n            ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[jobID].dstBuff);\n            \n            /* Clear the job description, but keep the mutex/cond */\n            ZSTD_memset(&mtctx->jobs[jobID], 0, sizeof(mtctx->jobs[jobID]));\n            mtctx->jobs[jobID].job_mutex = mutex;\n            mtctx->jobs[jobID].job_cond = cond;\n        }\n    }\n    mtctx->inBuff.buffer = g_nullBuffer;\n    mtctx->inBuff.filled = 0;\n    mtctx->allJobsCompleted = 1;\n}\n\nstatic void ZSTDMT_waitForAllJobsCompleted(ZSTDMT_CCtx* mtctx)\n{\n    DEBUGLOG(4, \"ZSTDMT_waitForAllJobsCompleted\");\n    while (mtctx->doneJobID < mtctx->nextJobID) {\n        unsigned const jobID = mtctx->doneJobID & mtctx->jobIDMask;\n        ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobs[jobID].job_mutex);\n        while (mtctx->jobs[jobID].consumed < mtctx->jobs[jobID].src.size) {\n            DEBUGLOG(4, \"waiting for jobCompleted signal from job %u\", mtctx->doneJobID);   /* we want to block when waiting for data to flush */\n            ZSTD_pthread_cond_wait(&mtctx->jobs[jobID].job_cond, &mtctx->jobs[jobID].job_mutex);\n        }\n        ZSTD_pthread_mutex_unlock(&mtctx->jobs[jobID].job_mutex);\n        mtctx->doneJobID++;\n    }\n}\n\nsize_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx)\n{\n    if (mtctx==NULL) return 0;   /* compatible with free on NULL */\n    if (!mtctx->providedFactory)\n        POOL_free(mtctx->factory);   /* stop and free worker threads */\n    ZSTDMT_releaseAllJobResources(mtctx);  /* release job resources into pools first */\n    ZSTDMT_freeJobsTable(mtctx->jobs, mtctx->jobIDMask+1, mtctx->cMem);\n    ZSTDMT_freeBufferPool(mtctx->bufPool);\n    ZSTDMT_freeCCtxPool(mtctx->cctxPool);\n    ZSTDMT_freeSeqPool(mtctx->seqPool);\n    ZSTDMT_serialState_free(&mtctx->serial);\n    ZSTD_freeCDict(mtctx->cdictLocal);\n    if (mtctx->roundBuff.buffer)\n        ZSTD_customFree(mtctx->roundBuff.buffer, mtctx->cMem);\n    ZSTD_customFree(mtctx, mtctx->cMem);\n    return 0;\n}\n\nsize_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx)\n{\n    if (mtctx == NULL) return 0;   /* supports sizeof NULL */\n    return sizeof(*mtctx)\n            + POOL_sizeof(mtctx->factory)\n            + ZSTDMT_sizeof_bufferPool(mtctx->bufPool)\n            + (mtctx->jobIDMask+1) * sizeof(ZSTDMT_jobDescription)\n            + ZSTDMT_sizeof_CCtxPool(mtctx->cctxPool)\n            + ZSTDMT_sizeof_seqPool(mtctx->seqPool)\n            + ZSTD_sizeof_CDict(mtctx->cdictLocal)\n            + mtctx->roundBuff.capacity;\n}\n\n\n/* ZSTDMT_resize() :\n * @return : error code if fails, 0 on success */\nstatic size_t ZSTDMT_resize(ZSTDMT_CCtx* mtctx, unsigned nbWorkers)\n{\n    if (POOL_resize(mtctx->factory, nbWorkers)) return ERROR(memory_allocation);\n    FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbWorkers) , \"\");\n    mtctx->bufPool = ZSTDMT_expandBufferPool(mtctx->bufPool, BUF_POOL_MAX_NB_BUFFERS(nbWorkers));\n    if (mtctx->bufPool == NULL) return ERROR(memory_allocation);\n    mtctx->cctxPool = ZSTDMT_expandCCtxPool(mtctx->cctxPool, nbWorkers);\n    if (mtctx->cctxPool == NULL) return ERROR(memory_allocation);\n    mtctx->seqPool = ZSTDMT_expandSeqPool(mtctx->seqPool, nbWorkers);\n    if (mtctx->seqPool == NULL) return ERROR(memory_allocation);\n    ZSTDMT_CCtxParam_setNbWorkers(&mtctx->params, nbWorkers);\n    return 0;\n}\n\n\n/*! ZSTDMT_updateCParams_whileCompressing() :\n *  Updates a selected set of compression parameters, remaining compatible with currently active frame.\n *  New parameters will be applied to next compression job. */\nvoid ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_params* cctxParams)\n{\n    U32 const saved_wlog = mtctx->params.cParams.windowLog;   /* Do not modify windowLog while compressing */\n    int const compressionLevel = cctxParams->compressionLevel;\n    DEBUGLOG(5, \"ZSTDMT_updateCParams_whileCompressing (level:%i)\",\n                compressionLevel);\n    mtctx->params.compressionLevel = compressionLevel;\n    {   ZSTD_compressionParameters cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);\n        cParams.windowLog = saved_wlog;\n        mtctx->params.cParams = cParams;\n    }\n}\n\n/* ZSTDMT_getFrameProgression():\n * tells how much data has been consumed (input) and produced (output) for current frame.\n * able to count progression inside worker threads.\n * Note : mutex will be acquired during statistics collection inside workers. */\nZSTD_frameProgression ZSTDMT_getFrameProgression(ZSTDMT_CCtx* mtctx)\n{\n    ZSTD_frameProgression fps;\n    DEBUGLOG(5, \"ZSTDMT_getFrameProgression\");\n    fps.ingested = mtctx->consumed + mtctx->inBuff.filled;\n    fps.consumed = mtctx->consumed;\n    fps.produced = fps.flushed = mtctx->produced;\n    fps.currentJobID = mtctx->nextJobID;\n    fps.nbActiveWorkers = 0;\n    {   unsigned jobNb;\n        unsigned lastJobNb = mtctx->nextJobID + mtctx->jobReady; assert(mtctx->jobReady <= 1);\n        DEBUGLOG(6, \"ZSTDMT_getFrameProgression: jobs: from %u to <%u (jobReady:%u)\",\n                    mtctx->doneJobID, lastJobNb, mtctx->jobReady);\n        for (jobNb = mtctx->doneJobID ; jobNb < lastJobNb ; jobNb++) {\n            unsigned const wJobID = jobNb & mtctx->jobIDMask;\n            ZSTDMT_jobDescription* jobPtr = &mtctx->jobs[wJobID];\n            ZSTD_pthread_mutex_lock(&jobPtr->job_mutex);\n            {   size_t const cResult = jobPtr->cSize;\n                size_t const produced = ZSTD_isError(cResult) ? 0 : cResult;\n                size_t const flushed = ZSTD_isError(cResult) ? 0 : jobPtr->dstFlushed;\n                assert(flushed <= produced);\n                fps.ingested += jobPtr->src.size;\n                fps.consumed += jobPtr->consumed;\n                fps.produced += produced;\n                fps.flushed  += flushed;\n                fps.nbActiveWorkers += (jobPtr->consumed < jobPtr->src.size);\n            }\n            ZSTD_pthread_mutex_unlock(&mtctx->jobs[wJobID].job_mutex);\n        }\n    }\n    return fps;\n}\n\n\nsize_t ZSTDMT_toFlushNow(ZSTDMT_CCtx* mtctx)\n{\n    size_t toFlush;\n    unsigned const jobID = mtctx->doneJobID;\n    assert(jobID <= mtctx->nextJobID);\n    if (jobID == mtctx->nextJobID) return 0;   /* no active job => nothing to flush */\n\n    /* look into oldest non-fully-flushed job */\n    {   unsigned const wJobID = jobID & mtctx->jobIDMask;\n        ZSTDMT_jobDescription* const jobPtr = &mtctx->jobs[wJobID];\n        ZSTD_pthread_mutex_lock(&jobPtr->job_mutex);\n        {   size_t const cResult = jobPtr->cSize;\n            size_t const produced = ZSTD_isError(cResult) ? 0 : cResult;\n            size_t const flushed = ZSTD_isError(cResult) ? 0 : jobPtr->dstFlushed;\n            assert(flushed <= produced);\n            assert(jobPtr->consumed <= jobPtr->src.size);\n            toFlush = produced - flushed;\n            /* if toFlush==0, nothing is available to flush.\n             * However, jobID is expected to still be active:\n             * if jobID was already completed and fully flushed,\n             * ZSTDMT_flushProduced() should have already moved onto next job.\n             * Therefore, some input has not yet been consumed. */\n            if (toFlush==0) {\n                assert(jobPtr->consumed < jobPtr->src.size);\n            }\n        }\n        ZSTD_pthread_mutex_unlock(&mtctx->jobs[wJobID].job_mutex);\n    }\n\n    return toFlush;\n}\n\n\n/* ------------------------------------------ */\n/* =====   Multi-threaded compression   ===== */\n/* ------------------------------------------ */\n\nstatic unsigned ZSTDMT_computeTargetJobLog(const ZSTD_CCtx_params* params)\n{\n    unsigned jobLog;\n    if (params->ldmParams.enableLdm == ZSTD_ps_enable) {\n        /* In Long Range Mode, the windowLog is typically oversized.\n         * In which case, it's preferable to determine the jobSize\n         * based on cycleLog instead. */\n        jobLog = MAX(21, ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy) + 3);\n    } else {\n        jobLog = MAX(20, params->cParams.windowLog + 2);\n    }\n    return MIN(jobLog, (unsigned)ZSTDMT_JOBLOG_MAX);\n}\n\nstatic int ZSTDMT_overlapLog_default(ZSTD_strategy strat)\n{\n    switch(strat)\n    {\n        case ZSTD_btultra2:\n            return 9;\n        case ZSTD_btultra:\n        case ZSTD_btopt:\n            return 8;\n        case ZSTD_btlazy2:\n        case ZSTD_lazy2:\n            return 7;\n        case ZSTD_lazy:\n        case ZSTD_greedy:\n        case ZSTD_dfast:\n        case ZSTD_fast:\n        default:;\n    }\n    return 6;\n}\n\nstatic int ZSTDMT_overlapLog(int ovlog, ZSTD_strategy strat)\n{\n    assert(0 <= ovlog && ovlog <= 9);\n    if (ovlog == 0) return ZSTDMT_overlapLog_default(strat);\n    return ovlog;\n}\n\nstatic size_t ZSTDMT_computeOverlapSize(const ZSTD_CCtx_params* params)\n{\n    int const overlapRLog = 9 - ZSTDMT_overlapLog(params->overlapLog, params->cParams.strategy);\n    int ovLog = (overlapRLog >= 8) ? 0 : (params->cParams.windowLog - overlapRLog);\n    assert(0 <= overlapRLog && overlapRLog <= 8);\n    if (params->ldmParams.enableLdm == ZSTD_ps_enable) {\n        /* In Long Range Mode, the windowLog is typically oversized.\n         * In which case, it's preferable to determine the jobSize\n         * based on chainLog instead.\n         * Then, ovLog becomes a fraction of the jobSize, rather than windowSize */\n        ovLog = MIN(params->cParams.windowLog, ZSTDMT_computeTargetJobLog(params) - 2)\n                - overlapRLog;\n    }\n    assert(0 <= ovLog && ovLog <= ZSTD_WINDOWLOG_MAX);\n    DEBUGLOG(4, \"overlapLog : %i\", params->overlapLog);\n    DEBUGLOG(4, \"overlap size : %i\", 1 << ovLog);\n    return (ovLog==0) ? 0 : (size_t)1 << ovLog;\n}\n\n/* ====================================== */\n/* =======      Streaming API     ======= */\n/* ====================================== */\n\nsize_t ZSTDMT_initCStream_internal(\n        ZSTDMT_CCtx* mtctx,\n        const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType,\n        const ZSTD_CDict* cdict, ZSTD_CCtx_params params,\n        unsigned long long pledgedSrcSize)\n{\n    DEBUGLOG(4, \"ZSTDMT_initCStream_internal (pledgedSrcSize=%u, nbWorkers=%u, cctxPool=%u)\",\n                (U32)pledgedSrcSize, params.nbWorkers, mtctx->cctxPool->totalCCtx);\n\n    /* params supposed partially fully validated at this point */\n    assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));\n    assert(!((dict) && (cdict)));  /* either dict or cdict, not both */\n\n    /* init */\n    if (params.nbWorkers != mtctx->params.nbWorkers)\n        FORWARD_IF_ERROR( ZSTDMT_resize(mtctx, (unsigned)params.nbWorkers) , \"\");\n\n    if (params.jobSize != 0 && params.jobSize < ZSTDMT_JOBSIZE_MIN) params.jobSize = ZSTDMT_JOBSIZE_MIN;\n    if (params.jobSize > (size_t)ZSTDMT_JOBSIZE_MAX) params.jobSize = (size_t)ZSTDMT_JOBSIZE_MAX;\n\n    if (mtctx->allJobsCompleted == 0) {   /* previous compression not correctly finished */\n        ZSTDMT_waitForAllJobsCompleted(mtctx);\n        ZSTDMT_releaseAllJobResources(mtctx); /* Will set allJobsCompleted to 1 */\n    }\n\n    mtctx->params = params;\n    mtctx->frameContentSize = pledgedSrcSize;\n    ZSTD_freeCDict(mtctx->cdictLocal);\n    if (dict) {\n        mtctx->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,\n                                                    ZSTD_dlm_byCopy, dictContentType, /* note : a loadPrefix becomes an internal CDict */\n                                                    params.cParams, mtctx->cMem);\n        mtctx->cdict = mtctx->cdictLocal;\n        if (mtctx->cdictLocal == NULL) return ERROR(memory_allocation);\n    } else {\n        mtctx->cdictLocal = NULL;\n        mtctx->cdict = cdict;\n    }\n\n    mtctx->targetPrefixSize = ZSTDMT_computeOverlapSize(&params);\n    DEBUGLOG(4, \"overlapLog=%i => %u KB\", params.overlapLog, (U32)(mtctx->targetPrefixSize>>10));\n    mtctx->targetSectionSize = params.jobSize;\n    if (mtctx->targetSectionSize == 0) {\n        mtctx->targetSectionSize = 1ULL << ZSTDMT_computeTargetJobLog(&params);\n    }\n    assert(mtctx->targetSectionSize <= (size_t)ZSTDMT_JOBSIZE_MAX);\n\n    if (params.rsyncable) {\n        /* Aim for the targetsectionSize as the average job size. */\n        U32 const jobSizeKB = (U32)(mtctx->targetSectionSize >> 10);\n        U32 const rsyncBits = (assert(jobSizeKB >= 1), ZSTD_highbit32(jobSizeKB) + 10);\n        /* We refuse to create jobs < RSYNC_MIN_BLOCK_SIZE bytes, so make sure our\n         * expected job size is at least 4x larger. */\n        assert(rsyncBits >= RSYNC_MIN_BLOCK_LOG + 2);\n        DEBUGLOG(4, \"rsyncLog = %u\", rsyncBits);\n        mtctx->rsync.hash = 0;\n        mtctx->rsync.hitMask = (1ULL << rsyncBits) - 1;\n        mtctx->rsync.primePower = ZSTD_rollingHash_primePower(RSYNC_LENGTH);\n    }\n    if (mtctx->targetSectionSize < mtctx->targetPrefixSize) mtctx->targetSectionSize = mtctx->targetPrefixSize;  /* job size must be >= overlap size */\n    DEBUGLOG(4, \"Job Size : %u KB (note : set to %u)\", (U32)(mtctx->targetSectionSize>>10), (U32)params.jobSize);\n    DEBUGLOG(4, \"inBuff Size : %u KB\", (U32)(mtctx->targetSectionSize>>10));\n    ZSTDMT_setBufferSize(mtctx->bufPool, ZSTD_compressBound(mtctx->targetSectionSize));\n    {\n        /* If ldm is enabled we need windowSize space. */\n        size_t const windowSize = mtctx->params.ldmParams.enableLdm == ZSTD_ps_enable ? (1U << mtctx->params.cParams.windowLog) : 0;\n        /* Two buffers of slack, plus extra space for the overlap\n         * This is the minimum slack that LDM works with. One extra because\n         * flush might waste up to targetSectionSize-1 bytes. Another extra\n         * for the overlap (if > 0), then one to fill which doesn't overlap\n         * with the LDM window.\n         */\n        size_t const nbSlackBuffers = 2 + (mtctx->targetPrefixSize > 0);\n        size_t const slackSize = mtctx->targetSectionSize * nbSlackBuffers;\n        /* Compute the total size, and always have enough slack */\n        size_t const nbWorkers = MAX(mtctx->params.nbWorkers, 1);\n        size_t const sectionsSize = mtctx->targetSectionSize * nbWorkers;\n        size_t const capacity = MAX(windowSize, sectionsSize) + slackSize;\n        if (mtctx->roundBuff.capacity < capacity) {\n            if (mtctx->roundBuff.buffer)\n                ZSTD_customFree(mtctx->roundBuff.buffer, mtctx->cMem);\n            mtctx->roundBuff.buffer = (BYTE*)ZSTD_customMalloc(capacity, mtctx->cMem);\n            if (mtctx->roundBuff.buffer == NULL) {\n                mtctx->roundBuff.capacity = 0;\n                return ERROR(memory_allocation);\n            }\n            mtctx->roundBuff.capacity = capacity;\n        }\n    }\n    DEBUGLOG(4, \"roundBuff capacity : %u KB\", (U32)(mtctx->roundBuff.capacity>>10));\n    mtctx->roundBuff.pos = 0;\n    mtctx->inBuff.buffer = g_nullBuffer;\n    mtctx->inBuff.filled = 0;\n    mtctx->inBuff.prefix = kNullRange;\n    mtctx->doneJobID = 0;\n    mtctx->nextJobID = 0;\n    mtctx->frameEnded = 0;\n    mtctx->allJobsCompleted = 0;\n    mtctx->consumed = 0;\n    mtctx->produced = 0;\n\n    /* update dictionary */\n    ZSTD_freeCDict(mtctx->cdictLocal);\n    mtctx->cdictLocal = NULL;\n    mtctx->cdict = NULL;\n    if (dict) {\n        if (dictContentType == ZSTD_dct_rawContent) {\n            mtctx->inBuff.prefix.start = (const BYTE*)dict;\n            mtctx->inBuff.prefix.size = dictSize;\n        } else {\n            /* note : a loadPrefix becomes an internal CDict */\n            mtctx->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,\n                                                        ZSTD_dlm_byRef, dictContentType,\n                                                        params.cParams, mtctx->cMem);\n            mtctx->cdict = mtctx->cdictLocal;\n            if (mtctx->cdictLocal == NULL) return ERROR(memory_allocation);\n        }\n    } else {\n        mtctx->cdict = cdict;\n    }\n\n    if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, mtctx->targetSectionSize,\n                                 dict, dictSize, dictContentType))\n        return ERROR(memory_allocation);\n\n\n    return 0;\n}\n\n\n/* ZSTDMT_writeLastEmptyBlock()\n * Write a single empty block with an end-of-frame to finish a frame.\n * Job must be created from streaming variant.\n * This function is always successful if expected conditions are fulfilled.\n */\nstatic void ZSTDMT_writeLastEmptyBlock(ZSTDMT_jobDescription* job)\n{\n    assert(job->lastJob == 1);\n    assert(job->src.size == 0);   /* last job is empty -> will be simplified into a last empty block */\n    assert(job->firstJob == 0);   /* cannot be first job, as it also needs to create frame header */\n    assert(job->dstBuff.start == NULL);   /* invoked from streaming variant only (otherwise, dstBuff might be user's output) */\n    job->dstBuff = ZSTDMT_getBuffer(job->bufPool);\n    if (job->dstBuff.start == NULL) {\n      job->cSize = ERROR(memory_allocation);\n      return;\n    }\n    assert(job->dstBuff.capacity >= ZSTD_blockHeaderSize);   /* no buffer should ever be that small */\n    job->src = kNullRange;\n    job->cSize = ZSTD_writeLastEmptyBlock(job->dstBuff.start, job->dstBuff.capacity);\n    assert(!ZSTD_isError(job->cSize));\n    assert(job->consumed == 0);\n}\n\nstatic size_t ZSTDMT_createCompressionJob(ZSTDMT_CCtx* mtctx, size_t srcSize, ZSTD_EndDirective endOp)\n{\n    unsigned const jobID = mtctx->nextJobID & mtctx->jobIDMask;\n    int const endFrame = (endOp == ZSTD_e_end);\n\n    if (mtctx->nextJobID > mtctx->doneJobID + mtctx->jobIDMask) {\n        DEBUGLOG(5, \"ZSTDMT_createCompressionJob: will not create new job : table is full\");\n        assert((mtctx->nextJobID & mtctx->jobIDMask) == (mtctx->doneJobID & mtctx->jobIDMask));\n        return 0;\n    }\n\n    if (!mtctx->jobReady) {\n        BYTE const* src = (BYTE const*)mtctx->inBuff.buffer.start;\n        DEBUGLOG(5, \"ZSTDMT_createCompressionJob: preparing job %u to compress %u bytes with %u preload \",\n                    mtctx->nextJobID, (U32)srcSize, (U32)mtctx->inBuff.prefix.size);\n        mtctx->jobs[jobID].src.start = src;\n        mtctx->jobs[jobID].src.size = srcSize;\n        assert(mtctx->inBuff.filled >= srcSize);\n        mtctx->jobs[jobID].prefix = mtctx->inBuff.prefix;\n        mtctx->jobs[jobID].consumed = 0;\n        mtctx->jobs[jobID].cSize = 0;\n        mtctx->jobs[jobID].params = mtctx->params;\n        mtctx->jobs[jobID].cdict = mtctx->nextJobID==0 ? mtctx->cdict : NULL;\n        mtctx->jobs[jobID].fullFrameSize = mtctx->frameContentSize;\n        mtctx->jobs[jobID].dstBuff = g_nullBuffer;\n        mtctx->jobs[jobID].cctxPool = mtctx->cctxPool;\n        mtctx->jobs[jobID].bufPool = mtctx->bufPool;\n        mtctx->jobs[jobID].seqPool = mtctx->seqPool;\n        mtctx->jobs[jobID].serial = &mtctx->serial;\n        mtctx->jobs[jobID].jobID = mtctx->nextJobID;\n        mtctx->jobs[jobID].firstJob = (mtctx->nextJobID==0);\n        mtctx->jobs[jobID].lastJob = endFrame;\n        mtctx->jobs[jobID].frameChecksumNeeded = mtctx->params.fParams.checksumFlag && endFrame && (mtctx->nextJobID>0);\n        mtctx->jobs[jobID].dstFlushed = 0;\n\n        /* Update the round buffer pos and clear the input buffer to be reset */\n        mtctx->roundBuff.pos += srcSize;\n        mtctx->inBuff.buffer = g_nullBuffer;\n        mtctx->inBuff.filled = 0;\n        /* Set the prefix for next job */\n        if (!endFrame) {\n            size_t const newPrefixSize = MIN(srcSize, mtctx->targetPrefixSize);\n            mtctx->inBuff.prefix.start = src + srcSize - newPrefixSize;\n            mtctx->inBuff.prefix.size = newPrefixSize;\n        } else {   /* endFrame==1 => no need for another input buffer */\n            mtctx->inBuff.prefix = kNullRange;\n            mtctx->frameEnded = endFrame;\n            if (mtctx->nextJobID == 0) {\n                /* single job exception : checksum is already calculated directly within worker thread */\n                mtctx->params.fParams.checksumFlag = 0;\n        }   }\n\n        if ( (srcSize == 0)\n          && (mtctx->nextJobID>0)/*single job must also write frame header*/ ) {\n            DEBUGLOG(5, \"ZSTDMT_createCompressionJob: creating a last empty block to end frame\");\n            assert(endOp == ZSTD_e_end);  /* only possible case : need to end the frame with an empty last block */\n            ZSTDMT_writeLastEmptyBlock(mtctx->jobs + jobID);\n            mtctx->nextJobID++;\n            return 0;\n        }\n    }\n\n    DEBUGLOG(5, \"ZSTDMT_createCompressionJob: posting job %u : %u bytes  (end:%u, jobNb == %u (mod:%u))\",\n                mtctx->nextJobID,\n                (U32)mtctx->jobs[jobID].src.size,\n                mtctx->jobs[jobID].lastJob,\n                mtctx->nextJobID,\n                jobID);\n    if (POOL_tryAdd(mtctx->factory, ZSTDMT_compressionJob, &mtctx->jobs[jobID])) {\n        mtctx->nextJobID++;\n        mtctx->jobReady = 0;\n    } else {\n        DEBUGLOG(5, \"ZSTDMT_createCompressionJob: no worker available for job %u\", mtctx->nextJobID);\n        mtctx->jobReady = 1;\n    }\n    return 0;\n}\n\n\n/*! ZSTDMT_flushProduced() :\n *  flush whatever data has been produced but not yet flushed in current job.\n *  move to next job if current one is fully flushed.\n * `output` : `pos` will be updated with amount of data flushed .\n * `blockToFlush` : if >0, the function will block and wait if there is no data available to flush .\n * @return : amount of data remaining within internal buffer, 0 if no more, 1 if unknown but > 0, or an error code */\nstatic size_t ZSTDMT_flushProduced(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, unsigned blockToFlush, ZSTD_EndDirective end)\n{\n    unsigned const wJobID = mtctx->doneJobID & mtctx->jobIDMask;\n    DEBUGLOG(5, \"ZSTDMT_flushProduced (blocking:%u , job %u <= %u)\",\n                blockToFlush, mtctx->doneJobID, mtctx->nextJobID);\n    assert(output->size >= output->pos);\n\n    ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobs[wJobID].job_mutex);\n    if (  blockToFlush\n      && (mtctx->doneJobID < mtctx->nextJobID) ) {\n        assert(mtctx->jobs[wJobID].dstFlushed <= mtctx->jobs[wJobID].cSize);\n        while (mtctx->jobs[wJobID].dstFlushed == mtctx->jobs[wJobID].cSize) {  /* nothing to flush */\n            if (mtctx->jobs[wJobID].consumed == mtctx->jobs[wJobID].src.size) {\n                DEBUGLOG(5, \"job %u is completely consumed (%u == %u) => don't wait for cond, there will be none\",\n                            mtctx->doneJobID, (U32)mtctx->jobs[wJobID].consumed, (U32)mtctx->jobs[wJobID].src.size);\n                break;\n            }\n            DEBUGLOG(5, \"waiting for something to flush from job %u (currently flushed: %u bytes)\",\n                        mtctx->doneJobID, (U32)mtctx->jobs[wJobID].dstFlushed);\n            ZSTD_pthread_cond_wait(&mtctx->jobs[wJobID].job_cond, &mtctx->jobs[wJobID].job_mutex);  /* block when nothing to flush but some to come */\n    }   }\n\n    /* try to flush something */\n    {   size_t cSize = mtctx->jobs[wJobID].cSize;                  /* shared */\n        size_t const srcConsumed = mtctx->jobs[wJobID].consumed;   /* shared */\n        size_t const srcSize = mtctx->jobs[wJobID].src.size;       /* read-only, could be done after mutex lock, but no-declaration-after-statement */\n        ZSTD_pthread_mutex_unlock(&mtctx->jobs[wJobID].job_mutex);\n        if (ZSTD_isError(cSize)) {\n            DEBUGLOG(5, \"ZSTDMT_flushProduced: job %u : compression error detected : %s\",\n                        mtctx->doneJobID, ZSTD_getErrorName(cSize));\n            ZSTDMT_waitForAllJobsCompleted(mtctx);\n            ZSTDMT_releaseAllJobResources(mtctx);\n            return cSize;\n        }\n        /* add frame checksum if necessary (can only happen once) */\n        assert(srcConsumed <= srcSize);\n        if ( (srcConsumed == srcSize)   /* job completed -> worker no longer active */\n          && mtctx->jobs[wJobID].frameChecksumNeeded ) {\n            U32 const checksum = (U32)XXH64_digest(&mtctx->serial.xxhState);\n            DEBUGLOG(4, \"ZSTDMT_flushProduced: writing checksum : %08X \\n\", checksum);\n            MEM_writeLE32((char*)mtctx->jobs[wJobID].dstBuff.start + mtctx->jobs[wJobID].cSize, checksum);\n            cSize += 4;\n            mtctx->jobs[wJobID].cSize += 4;  /* can write this shared value, as worker is no longer active */\n            mtctx->jobs[wJobID].frameChecksumNeeded = 0;\n        }\n\n        if (cSize > 0) {   /* compression is ongoing or completed */\n            size_t const toFlush = MIN(cSize - mtctx->jobs[wJobID].dstFlushed, output->size - output->pos);\n            DEBUGLOG(5, \"ZSTDMT_flushProduced: Flushing %u bytes from job %u (completion:%u/%u, generated:%u)\",\n                        (U32)toFlush, mtctx->doneJobID, (U32)srcConsumed, (U32)srcSize, (U32)cSize);\n            assert(mtctx->doneJobID < mtctx->nextJobID);\n            assert(cSize >= mtctx->jobs[wJobID].dstFlushed);\n            assert(mtctx->jobs[wJobID].dstBuff.start != NULL);\n            if (toFlush > 0) {\n                ZSTD_memcpy((char*)output->dst + output->pos,\n                    (const char*)mtctx->jobs[wJobID].dstBuff.start + mtctx->jobs[wJobID].dstFlushed,\n                    toFlush);\n            }\n            output->pos += toFlush;\n            mtctx->jobs[wJobID].dstFlushed += toFlush;  /* can write : this value is only used by mtctx */\n\n            if ( (srcConsumed == srcSize)    /* job is completed */\n              && (mtctx->jobs[wJobID].dstFlushed == cSize) ) {   /* output buffer fully flushed => free this job position */\n                DEBUGLOG(5, \"Job %u completed (%u bytes), moving to next one\",\n                        mtctx->doneJobID, (U32)mtctx->jobs[wJobID].dstFlushed);\n                ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[wJobID].dstBuff);\n                DEBUGLOG(5, \"dstBuffer released\");\n                mtctx->jobs[wJobID].dstBuff = g_nullBuffer;\n                mtctx->jobs[wJobID].cSize = 0;   /* ensure this job slot is considered \"not started\" in future check */\n                mtctx->consumed += srcSize;\n                mtctx->produced += cSize;\n                mtctx->doneJobID++;\n        }   }\n\n        /* return value : how many bytes left in buffer ; fake it to 1 when unknown but >0 */\n        if (cSize > mtctx->jobs[wJobID].dstFlushed) return (cSize - mtctx->jobs[wJobID].dstFlushed);\n        if (srcSize > srcConsumed) return 1;   /* current job not completely compressed */\n    }\n    if (mtctx->doneJobID < mtctx->nextJobID) return 1;   /* some more jobs ongoing */\n    if (mtctx->jobReady) return 1;      /* one job is ready to push, just not yet in the list */\n    if (mtctx->inBuff.filled > 0) return 1;   /* input is not empty, and still needs to be converted into a job */\n    mtctx->allJobsCompleted = mtctx->frameEnded;   /* all jobs are entirely flushed => if this one is last one, frame is completed */\n    if (end == ZSTD_e_end) return !mtctx->frameEnded;  /* for ZSTD_e_end, question becomes : is frame completed ? instead of : are internal buffers fully flushed ? */\n    return 0;   /* internal buffers fully flushed */\n}\n\n/**\n * Returns the range of data used by the earliest job that is not yet complete.\n * If the data of the first job is broken up into two segments, we cover both\n * sections.\n */\nstatic Range ZSTDMT_getInputDataInUse(ZSTDMT_CCtx* mtctx)\n{\n    unsigned const firstJobID = mtctx->doneJobID;\n    unsigned const lastJobID = mtctx->nextJobID;\n    unsigned jobID;\n\n    /* no need to check during first round */\n    size_t roundBuffCapacity = mtctx->roundBuff.capacity;\n    size_t nbJobs1stRoundMin = roundBuffCapacity / mtctx->targetSectionSize;\n    if (lastJobID < nbJobs1stRoundMin) return kNullRange;\n\n    for (jobID = firstJobID; jobID < lastJobID; ++jobID) {\n        unsigned const wJobID = jobID & mtctx->jobIDMask;\n        size_t consumed;\n\n        ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobs[wJobID].job_mutex);\n        consumed = mtctx->jobs[wJobID].consumed;\n        ZSTD_pthread_mutex_unlock(&mtctx->jobs[wJobID].job_mutex);\n\n        if (consumed < mtctx->jobs[wJobID].src.size) {\n            Range range = mtctx->jobs[wJobID].prefix;\n            if (range.size == 0) {\n                /* Empty prefix */\n                range = mtctx->jobs[wJobID].src;\n            }\n            /* Job source in multiple segments not supported yet */\n            assert(range.start <= mtctx->jobs[wJobID].src.start);\n            return range;\n        }\n    }\n    return kNullRange;\n}\n\n/**\n * Returns non-zero iff buffer and range overlap.\n */\nstatic int ZSTDMT_isOverlapped(Buffer buffer, Range range)\n{\n    BYTE const* const bufferStart = (BYTE const*)buffer.start;\n    BYTE const* const rangeStart = (BYTE const*)range.start;\n\n    if (rangeStart == NULL || bufferStart == NULL)\n        return 0;\n\n    {\n        BYTE const* const bufferEnd = bufferStart + buffer.capacity;\n        BYTE const* const rangeEnd = rangeStart + range.size;\n\n        /* Empty ranges cannot overlap */\n        if (bufferStart == bufferEnd || rangeStart == rangeEnd)\n            return 0;\n\n        return bufferStart < rangeEnd && rangeStart < bufferEnd;\n    }\n}\n\nstatic int ZSTDMT_doesOverlapWindow(Buffer buffer, ZSTD_window_t window)\n{\n    Range extDict;\n    Range prefix;\n\n    DEBUGLOG(5, \"ZSTDMT_doesOverlapWindow\");\n    extDict.start = window.dictBase + window.lowLimit;\n    extDict.size = window.dictLimit - window.lowLimit;\n\n    prefix.start = window.base + window.dictLimit;\n    prefix.size = window.nextSrc - (window.base + window.dictLimit);\n    DEBUGLOG(5, \"extDict [0x%zx, 0x%zx)\",\n                (size_t)extDict.start,\n                (size_t)extDict.start + extDict.size);\n    DEBUGLOG(5, \"prefix  [0x%zx, 0x%zx)\",\n                (size_t)prefix.start,\n                (size_t)prefix.start + prefix.size);\n\n    return ZSTDMT_isOverlapped(buffer, extDict)\n        || ZSTDMT_isOverlapped(buffer, prefix);\n}\n\nstatic void ZSTDMT_waitForLdmComplete(ZSTDMT_CCtx* mtctx, Buffer buffer)\n{\n    if (mtctx->params.ldmParams.enableLdm == ZSTD_ps_enable) {\n        ZSTD_pthread_mutex_t* mutex = &mtctx->serial.ldmWindowMutex;\n        DEBUGLOG(5, \"ZSTDMT_waitForLdmComplete\");\n        DEBUGLOG(5, \"source  [0x%zx, 0x%zx)\",\n                    (size_t)buffer.start,\n                    (size_t)buffer.start + buffer.capacity);\n        ZSTD_PTHREAD_MUTEX_LOCK(mutex);\n        while (ZSTDMT_doesOverlapWindow(buffer, mtctx->serial.ldmWindow)) {\n            DEBUGLOG(5, \"Waiting for LDM to finish...\");\n            ZSTD_pthread_cond_wait(&mtctx->serial.ldmWindowCond, mutex);\n        }\n        DEBUGLOG(6, \"Done waiting for LDM to finish\");\n        ZSTD_pthread_mutex_unlock(mutex);\n    }\n}\n\n/**\n * Attempts to set the inBuff to the next section to fill.\n * If any part of the new section is still in use we give up.\n * Returns non-zero if the buffer is filled.\n */\nstatic int ZSTDMT_tryGetInputRange(ZSTDMT_CCtx* mtctx)\n{\n    Range const inUse = ZSTDMT_getInputDataInUse(mtctx);\n    size_t const spaceLeft = mtctx->roundBuff.capacity - mtctx->roundBuff.pos;\n    size_t const spaceNeeded = mtctx->targetSectionSize;\n    Buffer buffer;\n\n    DEBUGLOG(5, \"ZSTDMT_tryGetInputRange\");\n    assert(mtctx->inBuff.buffer.start == NULL);\n    assert(mtctx->roundBuff.capacity >= spaceNeeded);\n\n    if (spaceLeft < spaceNeeded) {\n        /* ZSTD_invalidateRepCodes() doesn't work for extDict variants.\n         * Simply copy the prefix to the beginning in that case.\n         */\n        BYTE* const start = (BYTE*)mtctx->roundBuff.buffer;\n        size_t const prefixSize = mtctx->inBuff.prefix.size;\n\n        buffer.start = start;\n        buffer.capacity = prefixSize;\n        if (ZSTDMT_isOverlapped(buffer, inUse)) {\n            DEBUGLOG(5, \"Waiting for buffer...\");\n            return 0;\n        }\n        ZSTDMT_waitForLdmComplete(mtctx, buffer);\n        ZSTD_memmove(start, mtctx->inBuff.prefix.start, prefixSize);\n        mtctx->inBuff.prefix.start = start;\n        mtctx->roundBuff.pos = prefixSize;\n    }\n    buffer.start = mtctx->roundBuff.buffer + mtctx->roundBuff.pos;\n    buffer.capacity = spaceNeeded;\n\n    if (ZSTDMT_isOverlapped(buffer, inUse)) {\n        DEBUGLOG(5, \"Waiting for buffer...\");\n        return 0;\n    }\n    assert(!ZSTDMT_isOverlapped(buffer, mtctx->inBuff.prefix));\n\n    ZSTDMT_waitForLdmComplete(mtctx, buffer);\n\n    DEBUGLOG(5, \"Using prefix range [%zx, %zx)\",\n                (size_t)mtctx->inBuff.prefix.start,\n                (size_t)mtctx->inBuff.prefix.start + mtctx->inBuff.prefix.size);\n    DEBUGLOG(5, \"Using source range [%zx, %zx)\",\n                (size_t)buffer.start,\n                (size_t)buffer.start + buffer.capacity);\n\n\n    mtctx->inBuff.buffer = buffer;\n    mtctx->inBuff.filled = 0;\n    assert(mtctx->roundBuff.pos + buffer.capacity <= mtctx->roundBuff.capacity);\n    return 1;\n}\n\ntypedef struct {\n  size_t toLoad;  /* The number of bytes to load from the input. */\n  int flush;      /* Boolean declaring if we must flush because we found a synchronization point. */\n} SyncPoint;\n\n/**\n * Searches through the input for a synchronization point. If one is found, we\n * will instruct the caller to flush, and return the number of bytes to load.\n * Otherwise, we will load as many bytes as possible and instruct the caller\n * to continue as normal.\n */\nstatic SyncPoint\nfindSynchronizationPoint(ZSTDMT_CCtx const* mtctx, ZSTD_inBuffer const input)\n{\n    BYTE const* const istart = (BYTE const*)input.src + input.pos;\n    U64 const primePower = mtctx->rsync.primePower;\n    U64 const hitMask = mtctx->rsync.hitMask;\n\n    SyncPoint syncPoint;\n    U64 hash;\n    BYTE const* prev;\n    size_t pos;\n\n    syncPoint.toLoad = MIN(input.size - input.pos, mtctx->targetSectionSize - mtctx->inBuff.filled);\n    syncPoint.flush = 0;\n    if (!mtctx->params.rsyncable)\n        /* Rsync is disabled. */\n        return syncPoint;\n    if (mtctx->inBuff.filled + input.size - input.pos < RSYNC_MIN_BLOCK_SIZE)\n        /* We don't emit synchronization points if it would produce too small blocks.\n         * We don't have enough input to find a synchronization point, so don't look.\n         */\n        return syncPoint;\n    if (mtctx->inBuff.filled + syncPoint.toLoad < RSYNC_LENGTH)\n        /* Not enough to compute the hash.\n         * We will miss any synchronization points in this RSYNC_LENGTH byte\n         * window. However, since it depends only in the internal buffers, if the\n         * state is already synchronized, we will remain synchronized.\n         * Additionally, the probability that we miss a synchronization point is\n         * low: RSYNC_LENGTH / targetSectionSize.\n         */\n        return syncPoint;\n    /* Initialize the loop variables. */\n    if (mtctx->inBuff.filled < RSYNC_MIN_BLOCK_SIZE) {\n        /* We don't need to scan the first RSYNC_MIN_BLOCK_SIZE positions\n         * because they can't possibly be a sync point. So we can start\n         * part way through the input buffer.\n         */\n        pos = RSYNC_MIN_BLOCK_SIZE - mtctx->inBuff.filled;\n        if (pos >= RSYNC_LENGTH) {\n            prev = istart + pos - RSYNC_LENGTH;\n            hash = ZSTD_rollingHash_compute(prev, RSYNC_LENGTH);\n        } else {\n            assert(mtctx->inBuff.filled >= RSYNC_LENGTH);\n            prev = (BYTE const*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled - RSYNC_LENGTH;\n            hash = ZSTD_rollingHash_compute(prev + pos, (RSYNC_LENGTH - pos));\n            hash = ZSTD_rollingHash_append(hash, istart, pos);\n        }\n    } else {\n        /* We have enough bytes buffered to initialize the hash,\n         * and have processed enough bytes to find a sync point.\n         * Start scanning at the beginning of the input.\n         */\n        assert(mtctx->inBuff.filled >= RSYNC_MIN_BLOCK_SIZE);\n        assert(RSYNC_MIN_BLOCK_SIZE >= RSYNC_LENGTH);\n        pos = 0;\n        prev = (BYTE const*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled - RSYNC_LENGTH;\n        hash = ZSTD_rollingHash_compute(prev, RSYNC_LENGTH);\n        if ((hash & hitMask) == hitMask) {\n            /* We're already at a sync point so don't load any more until\n             * we're able to flush this sync point.\n             * This likely happened because the job table was full so we\n             * couldn't add our job.\n             */\n            syncPoint.toLoad = 0;\n            syncPoint.flush = 1;\n            return syncPoint;\n        }\n    }\n    /* Starting with the hash of the previous RSYNC_LENGTH bytes, roll\n     * through the input. If we hit a synchronization point, then cut the\n     * job off, and tell the compressor to flush the job. Otherwise, load\n     * all the bytes and continue as normal.\n     * If we go too long without a synchronization point (targetSectionSize)\n     * then a block will be emitted anyways, but this is okay, since if we\n     * are already synchronized we will remain synchronized.\n     */\n    assert(pos < RSYNC_LENGTH || ZSTD_rollingHash_compute(istart + pos - RSYNC_LENGTH, RSYNC_LENGTH) == hash);\n    for (; pos < syncPoint.toLoad; ++pos) {\n        BYTE const toRemove = pos < RSYNC_LENGTH ? prev[pos] : istart[pos - RSYNC_LENGTH];\n        /* This assert is very expensive, and Debian compiles with asserts enabled.\n         * So disable it for now. We can get similar coverage by checking it at the\n         * beginning & end of the loop.\n         * assert(pos < RSYNC_LENGTH || ZSTD_rollingHash_compute(istart + pos - RSYNC_LENGTH, RSYNC_LENGTH) == hash);\n         */\n        hash = ZSTD_rollingHash_rotate(hash, toRemove, istart[pos], primePower);\n        assert(mtctx->inBuff.filled + pos >= RSYNC_MIN_BLOCK_SIZE);\n        if ((hash & hitMask) == hitMask) {\n            syncPoint.toLoad = pos + 1;\n            syncPoint.flush = 1;\n            ++pos; /* for assert */\n            break;\n        }\n    }\n    assert(pos < RSYNC_LENGTH || ZSTD_rollingHash_compute(istart + pos - RSYNC_LENGTH, RSYNC_LENGTH) == hash);\n    return syncPoint;\n}\n\nsize_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx)\n{\n    size_t hintInSize = mtctx->targetSectionSize - mtctx->inBuff.filled;\n    if (hintInSize==0) hintInSize = mtctx->targetSectionSize;\n    return hintInSize;\n}\n\n/** ZSTDMT_compressStream_generic() :\n *  internal use only - exposed to be invoked from zstd_compress.c\n *  assumption : output and input are valid (pos <= size)\n * @return : minimum amount of data remaining to flush, 0 if none */\nsize_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,\n                                     ZSTD_outBuffer* output,\n                                     ZSTD_inBuffer* input,\n                                     ZSTD_EndDirective endOp)\n{\n    unsigned forwardInputProgress = 0;\n    DEBUGLOG(5, \"ZSTDMT_compressStream_generic (endOp=%u, srcSize=%u)\",\n                (U32)endOp, (U32)(input->size - input->pos));\n    assert(output->pos <= output->size);\n    assert(input->pos  <= input->size);\n\n    if ((mtctx->frameEnded) && (endOp==ZSTD_e_continue)) {\n        /* current frame being ended. Only flush/end are allowed */\n        return ERROR(stage_wrong);\n    }\n\n    /* fill input buffer */\n    if ( (!mtctx->jobReady)\n      && (input->size > input->pos) ) {   /* support NULL input */\n        if (mtctx->inBuff.buffer.start == NULL) {\n            assert(mtctx->inBuff.filled == 0); /* Can't fill an empty buffer */\n            if (!ZSTDMT_tryGetInputRange(mtctx)) {\n                /* It is only possible for this operation to fail if there are\n                 * still compression jobs ongoing.\n                 */\n                DEBUGLOG(5, \"ZSTDMT_tryGetInputRange failed\");\n                assert(mtctx->doneJobID != mtctx->nextJobID);\n            } else\n                DEBUGLOG(5, \"ZSTDMT_tryGetInputRange completed successfully : mtctx->inBuff.buffer.start = %p\", mtctx->inBuff.buffer.start);\n        }\n        if (mtctx->inBuff.buffer.start != NULL) {\n            SyncPoint const syncPoint = findSynchronizationPoint(mtctx, *input);\n            if (syncPoint.flush && endOp == ZSTD_e_continue) {\n                endOp = ZSTD_e_flush;\n            }\n            assert(mtctx->inBuff.buffer.capacity >= mtctx->targetSectionSize);\n            DEBUGLOG(5, \"ZSTDMT_compressStream_generic: adding %u bytes on top of %u to buffer of size %u\",\n                        (U32)syncPoint.toLoad, (U32)mtctx->inBuff.filled, (U32)mtctx->targetSectionSize);\n            ZSTD_memcpy((char*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled, (const char*)input->src + input->pos, syncPoint.toLoad);\n            input->pos += syncPoint.toLoad;\n            mtctx->inBuff.filled += syncPoint.toLoad;\n            forwardInputProgress = syncPoint.toLoad>0;\n        }\n    }\n    if ((input->pos < input->size) && (endOp == ZSTD_e_end)) {\n        /* Can't end yet because the input is not fully consumed.\n            * We are in one of these cases:\n            * - mtctx->inBuff is NULL & empty: we couldn't get an input buffer so don't create a new job.\n            * - We filled the input buffer: flush this job but don't end the frame.\n            * - We hit a synchronization point: flush this job but don't end the frame.\n            */\n        assert(mtctx->inBuff.filled == 0 || mtctx->inBuff.filled == mtctx->targetSectionSize || mtctx->params.rsyncable);\n        endOp = ZSTD_e_flush;\n    }\n\n    if ( (mtctx->jobReady)\n      || (mtctx->inBuff.filled >= mtctx->targetSectionSize)  /* filled enough : let's compress */\n      || ((endOp != ZSTD_e_continue) && (mtctx->inBuff.filled > 0))  /* something to flush : let's go */\n      || ((endOp == ZSTD_e_end) && (!mtctx->frameEnded)) ) {   /* must finish the frame with a zero-size block */\n        size_t const jobSize = mtctx->inBuff.filled;\n        assert(mtctx->inBuff.filled <= mtctx->targetSectionSize);\n        FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, jobSize, endOp) , \"\");\n    }\n\n    /* check for potential compressed data ready to be flushed */\n    {   size_t const remainingToFlush = ZSTDMT_flushProduced(mtctx, output, !forwardInputProgress, endOp); /* block if there was no forward input progress */\n        if (input->pos < input->size) return MAX(remainingToFlush, 1);  /* input not consumed : do not end flush yet */\n        DEBUGLOG(5, \"end of ZSTDMT_compressStream_generic: remainingToFlush = %u\", (U32)remainingToFlush);\n        return remainingToFlush;\n    }\n}\n"
  },
  {
    "path": "lib/compress/zstdmt_compress.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n #ifndef ZSTDMT_COMPRESS_H\n #define ZSTDMT_COMPRESS_H\n\n/* ===   Dependencies   === */\n#include \"../common/zstd_deps.h\"   /* size_t */\n#define ZSTD_STATIC_LINKING_ONLY   /* ZSTD_parameters */\n#include \"../zstd.h\"            /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTDLIB_API */\n\n/* Note : This is an internal API.\n *        These APIs used to be exposed with ZSTDLIB_API,\n *        because it used to be the only way to invoke MT compression.\n *        Now, you must use ZSTD_compress2 and ZSTD_compressStream2() instead.\n *\n *        This API requires ZSTD_MULTITHREAD to be defined during compilation,\n *        otherwise ZSTDMT_createCCtx*() will fail.\n */\n\n/* ===   Constants   === */\n#ifndef ZSTDMT_NBWORKERS_MAX /* a different value can be selected at compile time */\n#  define ZSTDMT_NBWORKERS_MAX ((sizeof(void*)==4) /*32-bit*/ ? 64 : 256)\n#endif\n#ifndef ZSTDMT_JOBSIZE_MIN   /* a different value can be selected at compile time */\n#  define ZSTDMT_JOBSIZE_MIN (512 KB)\n#endif\n#define ZSTDMT_JOBLOG_MAX   (MEM_32bits() ? 29 : 30)\n#define ZSTDMT_JOBSIZE_MAX  (MEM_32bits() ? (512 MB) : (1024 MB))\n\n\n/* ========================================================\n * ===  Private interface, for use by ZSTD_compress.c   ===\n * ===  Not exposed in libzstd. Never invoke directly   ===\n * ======================================================== */\n\n/* ===   Memory management   === */\ntypedef struct ZSTDMT_CCtx_s ZSTDMT_CCtx;\n/* Requires ZSTD_MULTITHREAD to be defined during compilation, otherwise it will return NULL. */\nZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers,\n                                        ZSTD_customMem cMem,\n\t\t\t\t\tZSTD_threadPool *pool);\nsize_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx);\n\nsize_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx);\n\n/* ===   Streaming functions   === */\n\nsize_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx);\n\n/*! ZSTDMT_initCStream_internal() :\n *  Private use only. Init streaming operation.\n *  expects params to be valid.\n *  must receive dict, or cdict, or none, but not both.\n *  mtctx can be freshly constructed or reused from a prior compression.\n *  If mtctx is reused, memory allocations from the prior compression may not be freed,\n *  even if they are not needed for the current compression.\n *  @return : 0, or an error code */\nsize_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* mtctx,\n                    const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType,\n                    const ZSTD_CDict* cdict,\n                    ZSTD_CCtx_params params, unsigned long long pledgedSrcSize);\n\n/*! ZSTDMT_compressStream_generic() :\n *  Combines ZSTDMT_compressStream() with optional ZSTDMT_flushStream() or ZSTDMT_endStream()\n *  depending on flush directive.\n * @return : minimum amount of data still to be flushed\n *           0 if fully flushed\n *           or an error code\n *  note : needs to be init using any ZSTD_initCStream*() variant */\nsize_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,\n                                     ZSTD_outBuffer* output,\n                                     ZSTD_inBuffer* input,\n                                     ZSTD_EndDirective endOp);\n\n /*! ZSTDMT_toFlushNow()\n  *  Tell how many bytes are ready to be flushed immediately.\n  *  Probe the oldest active job (not yet entirely flushed) and check its output buffer.\n  *  If return 0, it means there is no active job,\n  *  or, it means oldest job is still active, but everything produced has been flushed so far,\n  *  therefore flushing is limited by speed of oldest job. */\nsize_t ZSTDMT_toFlushNow(ZSTDMT_CCtx* mtctx);\n\n/*! ZSTDMT_updateCParams_whileCompressing() :\n *  Updates only a selected set of compression parameters, to remain compatible with current frame.\n *  New parameters will be applied to next compression job. */\nvoid ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_params* cctxParams);\n\n/*! ZSTDMT_getFrameProgression():\n *  tells how much data has been consumed (input) and produced (output) for current frame.\n *  able to count progression inside worker threads.\n */\nZSTD_frameProgression ZSTDMT_getFrameProgression(ZSTDMT_CCtx* mtctx);\n\n#endif   /* ZSTDMT_COMPRESS_H */\n"
  },
  {
    "path": "lib/decompress/huf_decompress.c",
    "content": "/* ******************************************************************\n * huff0 huffman decoder,\n * part of Finite State Entropy library\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n *  You can contact the author at :\n *  - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n/* **************************************************************\n*  Dependencies\n****************************************************************/\n#include <stddef.h>               /* size_t */\n#include \"../common/zstd_deps.h\"  /* ZSTD_memcpy, ZSTD_memset */\n#include \"../common/compiler.h\"\n#include \"../common/bitstream.h\"  /* BIT_* */\n#include \"../common/fse.h\"        /* to compress headers */\n#include \"../common/huf.h\"\n#include \"../common/error_private.h\"\n#include \"../common/zstd_internal.h\"\n#include \"../common/bits.h\"       /* ZSTD_highbit32, ZSTD_countTrailingZeros64 */\n\n/* **************************************************************\n*  Constants\n****************************************************************/\n\n#define HUF_DECODER_FAST_TABLELOG 11\n\n/* **************************************************************\n*  Macros\n****************************************************************/\n\n#ifdef HUF_DISABLE_FAST_DECODE\n# define HUF_ENABLE_FAST_DECODE 0\n#else\n# define HUF_ENABLE_FAST_DECODE 1\n#endif\n\n/* These two optional macros force the use one way or another of the two\n * Huffman decompression implementations. You can't force in both directions\n * at the same time.\n */\n#if defined(HUF_FORCE_DECOMPRESS_X1) && \\\n    defined(HUF_FORCE_DECOMPRESS_X2)\n#error \"Cannot force the use of the X1 and X2 decoders at the same time!\"\n#endif\n\n/* When DYNAMIC_BMI2 is enabled, fast decoders are only called when bmi2 is\n * supported at runtime, so we can add the BMI2 target attribute.\n * When it is disabled, we will still get BMI2 if it is enabled statically.\n */\n#if DYNAMIC_BMI2\n# define HUF_FAST_BMI2_ATTRS BMI2_TARGET_ATTRIBUTE\n#else\n# define HUF_FAST_BMI2_ATTRS\n#endif\n\n#ifdef __cplusplus\n# define HUF_EXTERN_C extern \"C\"\n#else\n# define HUF_EXTERN_C\n#endif\n#define HUF_ASM_DECL HUF_EXTERN_C\n\n#if DYNAMIC_BMI2\n# define HUF_NEED_BMI2_FUNCTION 1\n#else\n# define HUF_NEED_BMI2_FUNCTION 0\n#endif\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n#define HUF_isError ERR_isError\n\n\n/* **************************************************************\n*  Byte alignment for workSpace management\n****************************************************************/\n#define HUF_ALIGN(x, a)         HUF_ALIGN_MASK((x), (a) - 1)\n#define HUF_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))\n\n\n/* **************************************************************\n*  BMI2 Variant Wrappers\n****************************************************************/\ntypedef size_t (*HUF_DecompressUsingDTableFn)(void *dst, size_t dstSize,\n                                              const void *cSrc,\n                                              size_t cSrcSize,\n                                              const HUF_DTable *DTable);\n\n#if DYNAMIC_BMI2\n\n#define HUF_DGEN(fn)                                                        \\\n                                                                            \\\n    static size_t fn##_default(                                             \\\n                  void* dst,  size_t dstSize,                               \\\n            const void* cSrc, size_t cSrcSize,                              \\\n            const HUF_DTable* DTable)                                       \\\n    {                                                                       \\\n        return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable);             \\\n    }                                                                       \\\n                                                                            \\\n    static BMI2_TARGET_ATTRIBUTE size_t fn##_bmi2(                          \\\n                  void* dst,  size_t dstSize,                               \\\n            const void* cSrc, size_t cSrcSize,                              \\\n            const HUF_DTable* DTable)                                       \\\n    {                                                                       \\\n        return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable);             \\\n    }                                                                       \\\n                                                                            \\\n    static size_t fn(void* dst, size_t dstSize, void const* cSrc,           \\\n                     size_t cSrcSize, HUF_DTable const* DTable, int flags)  \\\n    {                                                                       \\\n        if (flags & HUF_flags_bmi2) {                                       \\\n            return fn##_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);         \\\n        }                                                                   \\\n        return fn##_default(dst, dstSize, cSrc, cSrcSize, DTable);          \\\n    }\n\n#else\n\n#define HUF_DGEN(fn)                                                        \\\n    static size_t fn(void* dst, size_t dstSize, void const* cSrc,           \\\n                     size_t cSrcSize, HUF_DTable const* DTable, int flags)  \\\n    {                                                                       \\\n        (void)flags;                                                        \\\n        return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable);             \\\n    }\n\n#endif\n\n\n/*-***************************/\n/*  generic DTableDesc       */\n/*-***************************/\ntypedef struct { BYTE maxTableLog; BYTE tableType; BYTE tableLog; BYTE reserved; } DTableDesc;\n\nstatic DTableDesc HUF_getDTableDesc(const HUF_DTable* table)\n{\n    DTableDesc dtd;\n    ZSTD_memcpy(&dtd, table, sizeof(dtd));\n    return dtd;\n}\n\nstatic size_t HUF_initFastDStream(BYTE const* ip) {\n    BYTE const lastByte = ip[7];\n    size_t const bitsConsumed = lastByte ? 8 - ZSTD_highbit32(lastByte) : 0;\n    size_t const value = MEM_readLEST(ip) | 1;\n    assert(bitsConsumed <= 8);\n    assert(sizeof(size_t) == 8);\n    return value << bitsConsumed;\n}\n\n\n/**\n * The input/output arguments to the Huffman fast decoding loop:\n *\n * ip [in/out] - The input pointers, must be updated to reflect what is consumed.\n * op [in/out] - The output pointers, must be updated to reflect what is written.\n * bits [in/out] - The bitstream containers, must be updated to reflect the current state.\n * dt [in] - The decoding table.\n * ilowest [in] - The beginning of the valid range of the input. Decoders may read\n *                down to this pointer. It may be below iend[0].\n * oend [in] - The end of the output stream. op[3] must not cross oend.\n * iend [in] - The end of each input stream. ip[i] may cross iend[i],\n *             as long as it is above ilowest, but that indicates corruption.\n */\ntypedef struct {\n    BYTE const* ip[4];\n    BYTE* op[4];\n    U64 bits[4];\n    void const* dt;\n    BYTE const* ilowest;\n    BYTE* oend;\n    BYTE const* iend[4];\n} HUF_DecompressFastArgs;\n\ntypedef void (*HUF_DecompressFastLoopFn)(HUF_DecompressFastArgs*);\n\n/**\n * Initializes args for the fast decoding loop.\n * @returns 1 on success\n *          0 if the fallback implementation should be used.\n *          Or an error code on failure.\n */\nstatic size_t HUF_DecompressFastArgs_init(HUF_DecompressFastArgs* args, void* dst, size_t dstSize, void const* src, size_t srcSize, const HUF_DTable* DTable)\n{\n    void const* dt = DTable + 1;\n    U32 const dtLog = HUF_getDTableDesc(DTable).tableLog;\n\n    const BYTE* const istart = (const BYTE*)src;\n\n    BYTE* const oend = (BYTE*)ZSTD_maybeNullPtrAdd(dst, (ptrdiff_t)dstSize);\n\n    /* The fast decoding loop assumes 64-bit little-endian.\n     * This condition is false on x32.\n     */\n    if (!MEM_isLittleEndian() || MEM_32bits())\n        return 0;\n\n    /* Avoid nullptr addition */\n    if (dstSize == 0)\n        return 0;\n    assert(dst != NULL);\n\n    /* strict minimum : jump table + 1 byte per stream */\n    if (srcSize < 10)\n        return ERROR(corruption_detected);\n\n    /* Must have at least 8 bytes per stream because we don't handle initializing smaller bit containers.\n     * If table log is not correct at this point, fallback to the old decoder.\n     * On small inputs we don't have enough data to trigger the fast loop, so use the old decoder.\n     */\n    if (dtLog != HUF_DECODER_FAST_TABLELOG)\n        return 0;\n\n    /* Read the jump table. */\n    {\n        size_t const length1 = MEM_readLE16(istart);\n        size_t const length2 = MEM_readLE16(istart+2);\n        size_t const length3 = MEM_readLE16(istart+4);\n        size_t const length4 = srcSize - (length1 + length2 + length3 + 6);\n        args->iend[0] = istart + 6;  /* jumpTable */\n        args->iend[1] = args->iend[0] + length1;\n        args->iend[2] = args->iend[1] + length2;\n        args->iend[3] = args->iend[2] + length3;\n\n        /* HUF_initFastDStream() requires this, and this small of an input\n         * won't benefit from the ASM loop anyways.\n         */\n        if (length1 < 8 || length2 < 8 || length3 < 8 || length4 < 8)\n            return 0;\n        if (length4 > srcSize) return ERROR(corruption_detected);   /* overflow */\n    }\n    /* ip[] contains the position that is currently loaded into bits[]. */\n    args->ip[0] = args->iend[1] - sizeof(U64);\n    args->ip[1] = args->iend[2] - sizeof(U64);\n    args->ip[2] = args->iend[3] - sizeof(U64);\n    args->ip[3] = (BYTE const*)src + srcSize - sizeof(U64);\n\n    /* op[] contains the output pointers. */\n    args->op[0] = (BYTE*)dst;\n    args->op[1] = args->op[0] + (dstSize+3)/4;\n    args->op[2] = args->op[1] + (dstSize+3)/4;\n    args->op[3] = args->op[2] + (dstSize+3)/4;\n\n    /* No point to call the ASM loop for tiny outputs. */\n    if (args->op[3] >= oend)\n        return 0;\n\n    /* bits[] is the bit container.\n        * It is read from the MSB down to the LSB.\n        * It is shifted left as it is read, and zeros are\n        * shifted in. After the lowest valid bit a 1 is\n        * set, so that CountTrailingZeros(bits[]) can be used\n        * to count how many bits we've consumed.\n        */\n    args->bits[0] = HUF_initFastDStream(args->ip[0]);\n    args->bits[1] = HUF_initFastDStream(args->ip[1]);\n    args->bits[2] = HUF_initFastDStream(args->ip[2]);\n    args->bits[3] = HUF_initFastDStream(args->ip[3]);\n\n    /* The decoders must be sure to never read beyond ilowest.\n     * This is lower than iend[0], but allowing decoders to read\n     * down to ilowest can allow an extra iteration or two in the\n     * fast loop.\n     */\n    args->ilowest = istart;\n\n    args->oend = oend;\n    args->dt = dt;\n\n    return 1;\n}\n\nstatic size_t HUF_initRemainingDStream(BIT_DStream_t* bit, HUF_DecompressFastArgs const* args, int stream, BYTE* segmentEnd)\n{\n    /* Validate that we haven't overwritten. */\n    if (args->op[stream] > segmentEnd)\n        return ERROR(corruption_detected);\n    /* Validate that we haven't read beyond iend[].\n        * Note that ip[] may be < iend[] because the MSB is\n        * the next bit to read, and we may have consumed 100%\n        * of the stream, so down to iend[i] - 8 is valid.\n        */\n    if (args->ip[stream] < args->iend[stream] - 8)\n        return ERROR(corruption_detected);\n\n    /* Construct the BIT_DStream_t. */\n    assert(sizeof(size_t) == 8);\n    bit->bitContainer = MEM_readLEST(args->ip[stream]);\n    bit->bitsConsumed = ZSTD_countTrailingZeros64(args->bits[stream]);\n    bit->start = (const char*)args->ilowest;\n    bit->limitPtr = bit->start + sizeof(size_t);\n    bit->ptr = (const char*)args->ip[stream];\n\n    return 0;\n}\n\n/* Calls X(N) for each stream 0, 1, 2, 3. */\n#define HUF_4X_FOR_EACH_STREAM(X) \\\n    do {                          \\\n        X(0);                     \\\n        X(1);                     \\\n        X(2);                     \\\n        X(3);                     \\\n    } while (0)\n\n/* Calls X(N, var) for each stream 0, 1, 2, 3. */\n#define HUF_4X_FOR_EACH_STREAM_WITH_VAR(X, var) \\\n    do {                                        \\\n        X(0, (var));                            \\\n        X(1, (var));                            \\\n        X(2, (var));                            \\\n        X(3, (var));                            \\\n    } while (0)\n\n\n#ifndef HUF_FORCE_DECOMPRESS_X2\n\n/*-***************************/\n/*  single-symbol decoding   */\n/*-***************************/\ntypedef struct { BYTE nbBits; BYTE byte; } HUF_DEltX1;   /* single-symbol decoding */\n\n/**\n * Packs 4 HUF_DEltX1 structs into a U64. This is used to lay down 4 entries at\n * a time.\n */\nstatic U64 HUF_DEltX1_set4(BYTE symbol, BYTE nbBits) {\n    U64 D4;\n    if (MEM_isLittleEndian()) {\n        D4 = (U64)((symbol << 8) + nbBits);\n    } else {\n        D4 = (U64)(symbol + (nbBits << 8));\n    }\n    assert(D4 < (1U << 16));\n    D4 *= 0x0001000100010001ULL;\n    return D4;\n}\n\n/**\n * Increase the tableLog to targetTableLog and rescales the stats.\n * If tableLog > targetTableLog this is a no-op.\n * @returns New tableLog\n */\nstatic U32 HUF_rescaleStats(BYTE* huffWeight, U32* rankVal, U32 nbSymbols, U32 tableLog, U32 targetTableLog)\n{\n    if (tableLog > targetTableLog)\n        return tableLog;\n    if (tableLog < targetTableLog) {\n        U32 const scale = targetTableLog - tableLog;\n        U32 s;\n        /* Increase the weight for all non-zero probability symbols by scale. */\n        for (s = 0; s < nbSymbols; ++s) {\n            huffWeight[s] += (BYTE)((huffWeight[s] == 0) ? 0 : scale);\n        }\n        /* Update rankVal to reflect the new weights.\n         * All weights except 0 get moved to weight + scale.\n         * Weights [1, scale] are empty.\n         */\n        for (s = targetTableLog; s > scale; --s) {\n            rankVal[s] = rankVal[s - scale];\n        }\n        for (s = scale; s > 0; --s) {\n            rankVal[s] = 0;\n        }\n    }\n    return targetTableLog;\n}\n\ntypedef struct {\n        U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1];\n        U32 rankStart[HUF_TABLELOG_ABSOLUTEMAX + 1];\n        U32 statsWksp[HUF_READ_STATS_WORKSPACE_SIZE_U32];\n        BYTE symbols[HUF_SYMBOLVALUE_MAX + 1];\n        BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1];\n} HUF_ReadDTableX1_Workspace;\n\nsize_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int flags)\n{\n    U32 tableLog = 0;\n    U32 nbSymbols = 0;\n    size_t iSize;\n    void* const dtPtr = DTable + 1;\n    HUF_DEltX1* const dt = (HUF_DEltX1*)dtPtr;\n    HUF_ReadDTableX1_Workspace* wksp = (HUF_ReadDTableX1_Workspace*)workSpace;\n\n    DEBUG_STATIC_ASSERT(HUF_DECOMPRESS_WORKSPACE_SIZE >= sizeof(*wksp));\n    if (sizeof(*wksp) > wkspSize) return ERROR(tableLog_tooLarge);\n\n    DEBUG_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUF_DTable));\n    /* ZSTD_memset(huffWeight, 0, sizeof(huffWeight)); */   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUF_readStats_wksp(wksp->huffWeight, HUF_SYMBOLVALUE_MAX + 1, wksp->rankVal, &nbSymbols, &tableLog, src, srcSize, wksp->statsWksp, sizeof(wksp->statsWksp), flags);\n    if (HUF_isError(iSize)) return iSize;\n\n\n    /* Table header */\n    {   DTableDesc dtd = HUF_getDTableDesc(DTable);\n        U32 const maxTableLog = dtd.maxTableLog + 1;\n        U32 const targetTableLog = MIN(maxTableLog, HUF_DECODER_FAST_TABLELOG);\n        tableLog = HUF_rescaleStats(wksp->huffWeight, wksp->rankVal, nbSymbols, tableLog, targetTableLog);\n        if (tableLog > (U32)(dtd.maxTableLog+1)) return ERROR(tableLog_tooLarge);   /* DTable too small, Huffman tree cannot fit in */\n        dtd.tableType = 0;\n        dtd.tableLog = (BYTE)tableLog;\n        ZSTD_memcpy(DTable, &dtd, sizeof(dtd));\n    }\n\n    /* Compute symbols and rankStart given rankVal:\n     *\n     * rankVal already contains the number of values of each weight.\n     *\n     * symbols contains the symbols ordered by weight. First are the rankVal[0]\n     * weight 0 symbols, followed by the rankVal[1] weight 1 symbols, and so on.\n     * symbols[0] is filled (but unused) to avoid a branch.\n     *\n     * rankStart contains the offset where each rank belongs in the DTable.\n     * rankStart[0] is not filled because there are no entries in the table for\n     * weight 0.\n     */\n    {   int n;\n        U32 nextRankStart = 0;\n        int const unroll = 4;\n        int const nLimit = (int)nbSymbols - unroll + 1;\n        for (n=0; n<(int)tableLog+1; n++) {\n            U32 const curr = nextRankStart;\n            nextRankStart += wksp->rankVal[n];\n            wksp->rankStart[n] = curr;\n        }\n        for (n=0; n < nLimit; n += unroll) {\n            int u;\n            for (u=0; u < unroll; ++u) {\n                size_t const w = wksp->huffWeight[n+u];\n                wksp->symbols[wksp->rankStart[w]++] = (BYTE)(n+u);\n            }\n        }\n        for (; n < (int)nbSymbols; ++n) {\n            size_t const w = wksp->huffWeight[n];\n            wksp->symbols[wksp->rankStart[w]++] = (BYTE)n;\n        }\n    }\n\n    /* fill DTable\n     * We fill all entries of each weight in order.\n     * That way length is a constant for each iteration of the outer loop.\n     * We can switch based on the length to a different inner loop which is\n     * optimized for that particular case.\n     */\n    {   U32 w;\n        int symbol = wksp->rankVal[0];\n        int rankStart = 0;\n        for (w=1; w<tableLog+1; ++w) {\n            int const symbolCount = wksp->rankVal[w];\n            int const length = (1 << w) >> 1;\n            int uStart = rankStart;\n            BYTE const nbBits = (BYTE)(tableLog + 1 - w);\n            int s;\n            int u;\n            switch (length) {\n            case 1:\n                for (s=0; s<symbolCount; ++s) {\n                    HUF_DEltX1 D;\n                    D.byte = wksp->symbols[symbol + s];\n                    D.nbBits = nbBits;\n                    dt[uStart] = D;\n                    uStart += 1;\n                }\n                break;\n            case 2:\n                for (s=0; s<symbolCount; ++s) {\n                    HUF_DEltX1 D;\n                    D.byte = wksp->symbols[symbol + s];\n                    D.nbBits = nbBits;\n                    dt[uStart+0] = D;\n                    dt[uStart+1] = D;\n                    uStart += 2;\n                }\n                break;\n            case 4:\n                for (s=0; s<symbolCount; ++s) {\n                    U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits);\n                    MEM_write64(dt + uStart, D4);\n                    uStart += 4;\n                }\n                break;\n            case 8:\n                for (s=0; s<symbolCount; ++s) {\n                    U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits);\n                    MEM_write64(dt + uStart, D4);\n                    MEM_write64(dt + uStart + 4, D4);\n                    uStart += 8;\n                }\n                break;\n            default:\n                for (s=0; s<symbolCount; ++s) {\n                    U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits);\n                    for (u=0; u < length; u += 16) {\n                        MEM_write64(dt + uStart + u + 0, D4);\n                        MEM_write64(dt + uStart + u + 4, D4);\n                        MEM_write64(dt + uStart + u + 8, D4);\n                        MEM_write64(dt + uStart + u + 12, D4);\n                    }\n                    assert(u == length);\n                    uStart += length;\n                }\n                break;\n            }\n            symbol += symbolCount;\n            rankStart += symbolCount * length;\n        }\n    }\n    return iSize;\n}\n\nFORCE_INLINE_TEMPLATE BYTE\nHUF_decodeSymbolX1(BIT_DStream_t* Dstream, const HUF_DEltX1* dt, const U32 dtLog)\n{\n    size_t const val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */\n    BYTE const c = dt[val].byte;\n    BIT_skipBits(Dstream, dt[val].nbBits);\n    return c;\n}\n\n#define HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr) \\\n    do { *ptr++ = HUF_decodeSymbolX1(DStreamPtr, dt, dtLog); } while (0)\n\n#define HUF_DECODE_SYMBOLX1_1(ptr, DStreamPtr)      \\\n    do {                                            \\\n        if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \\\n            HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr); \\\n    } while (0)\n\n#define HUF_DECODE_SYMBOLX1_2(ptr, DStreamPtr)      \\\n    do {                                            \\\n        if (MEM_64bits())                           \\\n            HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr); \\\n    } while (0)\n\nHINT_INLINE size_t\nHUF_decodeStreamX1(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX1* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 4 symbols at a time */\n    if ((pEnd - p) > 3) {\n        while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-3)) {\n            HUF_DECODE_SYMBOLX1_2(p, bitDPtr);\n            HUF_DECODE_SYMBOLX1_1(p, bitDPtr);\n            HUF_DECODE_SYMBOLX1_2(p, bitDPtr);\n            HUF_DECODE_SYMBOLX1_0(p, bitDPtr);\n        }\n    } else {\n        BIT_reloadDStream(bitDPtr);\n    }\n\n    /* [0-3] symbols remaining */\n    if (MEM_32bits())\n        while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd))\n            HUF_DECODE_SYMBOLX1_0(p, bitDPtr);\n\n    /* no more data to retrieve from bitstream, no need to reload */\n    while (p < pEnd)\n        HUF_DECODE_SYMBOLX1_0(p, bitDPtr);\n\n    return (size_t)(pEnd-pStart);\n}\n\nFORCE_INLINE_TEMPLATE size_t\nHUF_decompress1X1_usingDTable_internal_body(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUF_DTable* DTable)\n{\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = (BYTE*)ZSTD_maybeNullPtrAdd(op, (ptrdiff_t)dstSize);\n    const void* dtPtr = DTable + 1;\n    const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr;\n    BIT_DStream_t bitD;\n    DTableDesc const dtd = HUF_getDTableDesc(DTable);\n    U32 const dtLog = dtd.tableLog;\n\n    CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) );\n\n    HUF_decodeStreamX1(op, &bitD, oend, dt, dtLog);\n\n    if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);\n\n    return dstSize;\n}\n\n/* HUF_decompress4X1_usingDTable_internal_body():\n * Conditions :\n * @dstSize >= 6\n */\nFORCE_INLINE_TEMPLATE size_t\nHUF_decompress4X1_usingDTable_internal_body(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUF_DTable* DTable)\n{\n    /* Check */\n    if (cSrcSize < 10) return ERROR(corruption_detected);  /* strict minimum : jump table + 1 byte per stream */\n    if (dstSize < 6) return ERROR(corruption_detected);         /* stream 4-split doesn't work */\n\n    {   const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        BYTE* const olimit = oend - 3;\n        const void* const dtPtr = DTable + 1;\n        const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr;\n\n        /* Init */\n        BIT_DStream_t bitD1;\n        BIT_DStream_t bitD2;\n        BIT_DStream_t bitD3;\n        BIT_DStream_t bitD4;\n        size_t const length1 = MEM_readLE16(istart);\n        size_t const length2 = MEM_readLE16(istart+2);\n        size_t const length3 = MEM_readLE16(istart+4);\n        size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        DTableDesc const dtd = HUF_getDTableDesc(DTable);\n        U32 const dtLog = dtd.tableLog;\n        U32 endSignal = 1;\n\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        if (opStart4 > oend) return ERROR(corruption_detected);      /* overflow */\n        assert(dstSize >= 6); /* validated above */\n        CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );\n        CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );\n        CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );\n        CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );\n\n        /* up to 16 symbols per loop (4 symbols per stream) in 64-bit mode */\n        if ((size_t)(oend - op4) >= sizeof(size_t)) {\n            for ( ; (endSignal) & (op4 < olimit) ; ) {\n                HUF_DECODE_SYMBOLX1_2(op1, &bitD1);\n                HUF_DECODE_SYMBOLX1_2(op2, &bitD2);\n                HUF_DECODE_SYMBOLX1_2(op3, &bitD3);\n                HUF_DECODE_SYMBOLX1_2(op4, &bitD4);\n                HUF_DECODE_SYMBOLX1_1(op1, &bitD1);\n                HUF_DECODE_SYMBOLX1_1(op2, &bitD2);\n                HUF_DECODE_SYMBOLX1_1(op3, &bitD3);\n                HUF_DECODE_SYMBOLX1_1(op4, &bitD4);\n                HUF_DECODE_SYMBOLX1_2(op1, &bitD1);\n                HUF_DECODE_SYMBOLX1_2(op2, &bitD2);\n                HUF_DECODE_SYMBOLX1_2(op3, &bitD3);\n                HUF_DECODE_SYMBOLX1_2(op4, &bitD4);\n                HUF_DECODE_SYMBOLX1_0(op1, &bitD1);\n                HUF_DECODE_SYMBOLX1_0(op2, &bitD2);\n                HUF_DECODE_SYMBOLX1_0(op3, &bitD3);\n                HUF_DECODE_SYMBOLX1_0(op4, &bitD4);\n                endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished;\n                endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished;\n                endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished;\n                endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished;\n            }\n        }\n\n        /* check corruption */\n        /* note : should not be necessary : op# advance in lock step, and we control op4.\n         *        but curiously, binary generated by gcc 7.2 & 7.3 with -mbmi2 runs faster when >=1 test is present */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUF_decodeStreamX1(op1, &bitD1, opStart2, dt, dtLog);\n        HUF_decodeStreamX1(op2, &bitD2, opStart3, dt, dtLog);\n        HUF_decodeStreamX1(op3, &bitD3, opStart4, dt, dtLog);\n        HUF_decodeStreamX1(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);\n          if (!endCheck) return ERROR(corruption_detected); }\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n#if HUF_NEED_BMI2_FUNCTION\nstatic BMI2_TARGET_ATTRIBUTE\nsize_t HUF_decompress4X1_usingDTable_internal_bmi2(void* dst, size_t dstSize, void const* cSrc,\n                    size_t cSrcSize, HUF_DTable const* DTable) {\n    return HUF_decompress4X1_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);\n}\n#endif\n\nstatic\nsize_t HUF_decompress4X1_usingDTable_internal_default(void* dst, size_t dstSize, void const* cSrc,\n                    size_t cSrcSize, HUF_DTable const* DTable) {\n    return HUF_decompress4X1_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);\n}\n\n#if ZSTD_ENABLE_ASM_X86_64_BMI2\n\nHUF_ASM_DECL void HUF_decompress4X1_usingDTable_internal_fast_asm_loop(HUF_DecompressFastArgs* args) ZSTDLIB_HIDDEN;\n\n#endif\n\nstatic HUF_FAST_BMI2_ATTRS\nvoid HUF_decompress4X1_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs* args)\n{\n    U64 bits[4];\n    BYTE const* ip[4];\n    BYTE* op[4];\n    U16 const* const dtable = (U16 const*)args->dt;\n    BYTE* const oend = args->oend;\n    BYTE const* const ilowest = args->ilowest;\n\n    /* Copy the arguments to local variables */\n    ZSTD_memcpy(&bits, &args->bits, sizeof(bits));\n    ZSTD_memcpy((void*)(&ip), &args->ip, sizeof(ip));\n    ZSTD_memcpy(&op, &args->op, sizeof(op));\n\n    assert(MEM_isLittleEndian());\n    assert(!MEM_32bits());\n\n    for (;;) {\n        BYTE* olimit;\n        int stream;\n\n        /* Assert loop preconditions */\n#ifndef NDEBUG\n        for (stream = 0; stream < 4; ++stream) {\n            assert(op[stream] <= (stream == 3 ? oend : op[stream + 1]));\n            assert(ip[stream] >= ilowest);\n        }\n#endif\n        /* Compute olimit */\n        {\n            /* Each iteration produces 5 output symbols per stream */\n            size_t const oiters = (size_t)(oend - op[3]) / 5;\n            /* Each iteration consumes up to 11 bits * 5 = 55 bits < 7 bytes\n             * per stream.\n             */\n            size_t const iiters = (size_t)(ip[0] - ilowest) / 7;\n            /* We can safely run iters iterations before running bounds checks */\n            size_t const iters = MIN(oiters, iiters);\n            size_t const symbols = iters * 5;\n\n            /* We can simply check that op[3] < olimit, instead of checking all\n             * of our bounds, since we can't hit the other bounds until we've run\n             * iters iterations, which only happens when op[3] == olimit.\n             */\n            olimit = op[3] + symbols;\n\n            /* Exit fast decoding loop once we reach the end. */\n            if (op[3] == olimit)\n                break;\n\n            /* Exit the decoding loop if any input pointer has crossed the\n             * previous one. This indicates corruption, and a precondition\n             * to our loop is that ip[i] >= ip[0].\n             */\n            for (stream = 1; stream < 4; ++stream) {\n                if (ip[stream] < ip[stream - 1])\n                    goto _out;\n            }\n        }\n\n#ifndef NDEBUG\n        for (stream = 1; stream < 4; ++stream) {\n            assert(ip[stream] >= ip[stream - 1]);\n        }\n#endif\n\n#define HUF_4X1_DECODE_SYMBOL(_stream, _symbol)        \\\n    do {                                               \\\n        U64 const index = bits[(_stream)] >> 53;       \\\n        U16 const entry = dtable[index];               \\\n        bits[(_stream)] <<= entry & 0x3F;              \\\n        op[(_stream)][(_symbol)] = (BYTE)(entry >> 8); \\\n    } while (0)\n\n#define HUF_5X1_RELOAD_STREAM(_stream)                              \\\n    do {                                                            \\\n        U64 const ctz = ZSTD_countTrailingZeros64(bits[(_stream)]); \\\n        U64 const nbBits = ctz & 7;                                 \\\n        U64 const nbBytes = ctz >> 3;                               \\\n        op[(_stream)] += 5;                                         \\\n        ip[(_stream)] -= nbBytes;                                   \\\n        bits[(_stream)] = MEM_read64(ip[(_stream)]) | 1;            \\\n        bits[(_stream)] <<= nbBits;                                 \\\n    } while (0)\n\n        /* Manually unroll the loop because compilers don't consistently\n         * unroll the inner loops, which destroys performance.\n         */\n        do {\n            /* Decode 5 symbols in each of the 4 streams */\n            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 0);\n            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 1);\n            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 2);\n            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 3);\n            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 4);\n\n            /* Reload each of the 4 the bitstreams */\n            HUF_4X_FOR_EACH_STREAM(HUF_5X1_RELOAD_STREAM);\n        } while (op[3] < olimit);\n\n#undef HUF_4X1_DECODE_SYMBOL\n#undef HUF_5X1_RELOAD_STREAM\n    }\n\n_out:\n\n    /* Save the final values of each of the state variables back to args. */\n    ZSTD_memcpy(&args->bits, &bits, sizeof(bits));\n    ZSTD_memcpy((void*)(&args->ip), &ip, sizeof(ip));\n    ZSTD_memcpy(&args->op, &op, sizeof(op));\n}\n\n/**\n * @returns @p dstSize on success (>= 6)\n *          0 if the fallback implementation should be used\n *          An error if an error occurred\n */\nstatic HUF_FAST_BMI2_ATTRS\nsize_t\nHUF_decompress4X1_usingDTable_internal_fast(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUF_DTable* DTable,\n    HUF_DecompressFastLoopFn loopFn)\n{\n    void const* dt = DTable + 1;\n    BYTE const* const ilowest = (BYTE const*)cSrc;\n    BYTE* const oend = (BYTE*)ZSTD_maybeNullPtrAdd(dst, (ptrdiff_t)dstSize);\n    HUF_DecompressFastArgs args;\n    {   size_t const ret = HUF_DecompressFastArgs_init(&args, dst, dstSize, cSrc, cSrcSize, DTable);\n        FORWARD_IF_ERROR(ret, \"Failed to init fast loop args\");\n        if (ret == 0)\n            return 0;\n    }\n\n    assert(args.ip[0] >= args.ilowest);\n    loopFn(&args);\n\n    /* Our loop guarantees that ip[] >= ilowest and that we haven't\n    * overwritten any op[].\n    */\n    assert(args.ip[0] >= ilowest);\n    assert(args.ip[0] >= ilowest);\n    assert(args.ip[1] >= ilowest);\n    assert(args.ip[2] >= ilowest);\n    assert(args.ip[3] >= ilowest);\n    assert(args.op[3] <= oend);\n\n    assert(ilowest == args.ilowest);\n    assert(ilowest + 6 == args.iend[0]);\n    (void)ilowest;\n\n    /* finish bit streams one by one. */\n    {   size_t const segmentSize = (dstSize+3) / 4;\n        BYTE* segmentEnd = (BYTE*)dst;\n        int i;\n        for (i = 0; i < 4; ++i) {\n            BIT_DStream_t bit;\n            if (segmentSize <= (size_t)(oend - segmentEnd))\n                segmentEnd += segmentSize;\n            else\n                segmentEnd = oend;\n            FORWARD_IF_ERROR(HUF_initRemainingDStream(&bit, &args, i, segmentEnd), \"corruption\");\n            /* Decompress and validate that we've produced exactly the expected length. */\n            args.op[i] += HUF_decodeStreamX1(args.op[i], &bit, segmentEnd, (HUF_DEltX1 const*)dt, HUF_DECODER_FAST_TABLELOG);\n            if (args.op[i] != segmentEnd) return ERROR(corruption_detected);\n        }\n    }\n\n    /* decoded size */\n    assert(dstSize != 0);\n    return dstSize;\n}\n\nHUF_DGEN(HUF_decompress1X1_usingDTable_internal)\n\nstatic size_t HUF_decompress4X1_usingDTable_internal(void* dst, size_t dstSize, void const* cSrc,\n                    size_t cSrcSize, HUF_DTable const* DTable, int flags)\n{\n    HUF_DecompressUsingDTableFn fallbackFn = HUF_decompress4X1_usingDTable_internal_default;\n    HUF_DecompressFastLoopFn loopFn = HUF_decompress4X1_usingDTable_internal_fast_c_loop;\n\n#if DYNAMIC_BMI2\n    if (flags & HUF_flags_bmi2) {\n        fallbackFn = HUF_decompress4X1_usingDTable_internal_bmi2;\n# if ZSTD_ENABLE_ASM_X86_64_BMI2\n        if (!(flags & HUF_flags_disableAsm)) {\n            loopFn = HUF_decompress4X1_usingDTable_internal_fast_asm_loop;\n        }\n# endif\n    } else {\n        return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable);\n    }\n#endif\n\n#if ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__)\n    if (!(flags & HUF_flags_disableAsm)) {\n        loopFn = HUF_decompress4X1_usingDTable_internal_fast_asm_loop;\n    }\n#endif\n\n    if (HUF_ENABLE_FAST_DECODE && !(flags & HUF_flags_disableFast)) {\n        size_t const ret = HUF_decompress4X1_usingDTable_internal_fast(dst, dstSize, cSrc, cSrcSize, DTable, loopFn);\n        if (ret != 0)\n            return ret;\n    }\n    return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable);\n}\n\nstatic size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,\n                                   const void* cSrc, size_t cSrcSize,\n                                   void* workSpace, size_t wkspSize, int flags)\n{\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t const hSize = HUF_readDTableX1_wksp(dctx, cSrc, cSrcSize, workSpace, wkspSize, flags);\n    if (HUF_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize; cSrcSize -= hSize;\n\n    return HUF_decompress4X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, flags);\n}\n\n#endif /* HUF_FORCE_DECOMPRESS_X2 */\n\n\n#ifndef HUF_FORCE_DECOMPRESS_X1\n\n/* *************************/\n/* double-symbols decoding */\n/* *************************/\n\ntypedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX2;  /* double-symbols decoding */\ntypedef struct { BYTE symbol; } sortedSymbol_t;\ntypedef U32 rankValCol_t[HUF_TABLELOG_MAX + 1];\ntypedef rankValCol_t rankVal_t[HUF_TABLELOG_MAX];\n\n/**\n * Constructs a HUF_DEltX2 in a U32.\n */\nstatic U32 HUF_buildDEltX2U32(U32 symbol, U32 nbBits, U32 baseSeq, int level)\n{\n    U32 seq;\n    DEBUG_STATIC_ASSERT(offsetof(HUF_DEltX2, sequence) == 0);\n    DEBUG_STATIC_ASSERT(offsetof(HUF_DEltX2, nbBits) == 2);\n    DEBUG_STATIC_ASSERT(offsetof(HUF_DEltX2, length) == 3);\n    DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(U32));\n    if (MEM_isLittleEndian()) {\n        seq = level == 1 ? symbol : (baseSeq + (symbol << 8));\n        return seq + (nbBits << 16) + ((U32)level << 24);\n    } else {\n        seq = level == 1 ? (symbol << 8) : ((baseSeq << 8) + symbol);\n        return (seq << 16) + (nbBits << 8) + (U32)level;\n    }\n}\n\n/**\n * Constructs a HUF_DEltX2.\n */\nstatic HUF_DEltX2 HUF_buildDEltX2(U32 symbol, U32 nbBits, U32 baseSeq, int level)\n{\n    HUF_DEltX2 DElt;\n    U32 const val = HUF_buildDEltX2U32(symbol, nbBits, baseSeq, level);\n    DEBUG_STATIC_ASSERT(sizeof(DElt) == sizeof(val));\n    ZSTD_memcpy(&DElt, &val, sizeof(val));\n    return DElt;\n}\n\n/**\n * Constructs 2 HUF_DEltX2s and packs them into a U64.\n */\nstatic U64 HUF_buildDEltX2U64(U32 symbol, U32 nbBits, U16 baseSeq, int level)\n{\n    U32 DElt = HUF_buildDEltX2U32(symbol, nbBits, baseSeq, level);\n    return (U64)DElt + ((U64)DElt << 32);\n}\n\n/**\n * Fills the DTable rank with all the symbols from [begin, end) that are each\n * nbBits long.\n *\n * @param DTableRank The start of the rank in the DTable.\n * @param begin The first symbol to fill (inclusive).\n * @param end The last symbol to fill (exclusive).\n * @param nbBits Each symbol is nbBits long.\n * @param tableLog The table log.\n * @param baseSeq If level == 1 { 0 } else { the first level symbol }\n * @param level The level in the table. Must be 1 or 2.\n */\nstatic void HUF_fillDTableX2ForWeight(\n    HUF_DEltX2* DTableRank,\n    sortedSymbol_t const* begin, sortedSymbol_t const* end,\n    U32 nbBits, U32 tableLog,\n    U16 baseSeq, int const level)\n{\n    U32 const length = 1U << ((tableLog - nbBits) & 0x1F /* quiet static-analyzer */);\n    const sortedSymbol_t* ptr;\n    assert(level >= 1 && level <= 2);\n    switch (length) {\n    case 1:\n        for (ptr = begin; ptr != end; ++ptr) {\n            HUF_DEltX2 const DElt = HUF_buildDEltX2(ptr->symbol, nbBits, baseSeq, level);\n            *DTableRank++ = DElt;\n        }\n        break;\n    case 2:\n        for (ptr = begin; ptr != end; ++ptr) {\n            HUF_DEltX2 const DElt = HUF_buildDEltX2(ptr->symbol, nbBits, baseSeq, level);\n            DTableRank[0] = DElt;\n            DTableRank[1] = DElt;\n            DTableRank += 2;\n        }\n        break;\n    case 4:\n        for (ptr = begin; ptr != end; ++ptr) {\n            U64 const DEltX2 = HUF_buildDEltX2U64(ptr->symbol, nbBits, baseSeq, level);\n            ZSTD_memcpy(DTableRank + 0, &DEltX2, sizeof(DEltX2));\n            ZSTD_memcpy(DTableRank + 2, &DEltX2, sizeof(DEltX2));\n            DTableRank += 4;\n        }\n        break;\n    case 8:\n        for (ptr = begin; ptr != end; ++ptr) {\n            U64 const DEltX2 = HUF_buildDEltX2U64(ptr->symbol, nbBits, baseSeq, level);\n            ZSTD_memcpy(DTableRank + 0, &DEltX2, sizeof(DEltX2));\n            ZSTD_memcpy(DTableRank + 2, &DEltX2, sizeof(DEltX2));\n            ZSTD_memcpy(DTableRank + 4, &DEltX2, sizeof(DEltX2));\n            ZSTD_memcpy(DTableRank + 6, &DEltX2, sizeof(DEltX2));\n            DTableRank += 8;\n        }\n        break;\n    default:\n        for (ptr = begin; ptr != end; ++ptr) {\n            U64 const DEltX2 = HUF_buildDEltX2U64(ptr->symbol, nbBits, baseSeq, level);\n            HUF_DEltX2* const DTableRankEnd = DTableRank + length;\n            for (; DTableRank != DTableRankEnd; DTableRank += 8) {\n                ZSTD_memcpy(DTableRank + 0, &DEltX2, sizeof(DEltX2));\n                ZSTD_memcpy(DTableRank + 2, &DEltX2, sizeof(DEltX2));\n                ZSTD_memcpy(DTableRank + 4, &DEltX2, sizeof(DEltX2));\n                ZSTD_memcpy(DTableRank + 6, &DEltX2, sizeof(DEltX2));\n            }\n        }\n        break;\n    }\n}\n\n/* HUF_fillDTableX2Level2() :\n * `rankValOrigin` must be a table of at least (HUF_TABLELOG_MAX + 1) U32 */\nstatic void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 targetLog, const U32 consumedBits,\n                           const U32* rankVal, const int minWeight, const int maxWeight1,\n                           const sortedSymbol_t* sortedSymbols, U32 const* rankStart,\n                           U32 nbBitsBaseline, U16 baseSeq)\n{\n    /* Fill skipped values (all positions up to rankVal[minWeight]).\n     * These are positions only get a single symbol because the combined weight\n     * is too large.\n     */\n    if (minWeight>1) {\n        U32 const length = 1U << ((targetLog - consumedBits) & 0x1F /* quiet static-analyzer */);\n        U64 const DEltX2 = HUF_buildDEltX2U64(baseSeq, consumedBits, /* baseSeq */ 0, /* level */ 1);\n        int const skipSize = rankVal[minWeight];\n        assert(length > 1);\n        assert((U32)skipSize < length);\n        switch (length) {\n        case 2:\n            assert(skipSize == 1);\n            ZSTD_memcpy(DTable, &DEltX2, sizeof(DEltX2));\n            break;\n        case 4:\n            assert(skipSize <= 4);\n            ZSTD_memcpy(DTable + 0, &DEltX2, sizeof(DEltX2));\n            ZSTD_memcpy(DTable + 2, &DEltX2, sizeof(DEltX2));\n            break;\n        default:\n            {\n                int i;\n                for (i = 0; i < skipSize; i += 8) {\n                    ZSTD_memcpy(DTable + i + 0, &DEltX2, sizeof(DEltX2));\n                    ZSTD_memcpy(DTable + i + 2, &DEltX2, sizeof(DEltX2));\n                    ZSTD_memcpy(DTable + i + 4, &DEltX2, sizeof(DEltX2));\n                    ZSTD_memcpy(DTable + i + 6, &DEltX2, sizeof(DEltX2));\n                }\n            }\n        }\n    }\n\n    /* Fill each of the second level symbols by weight. */\n    {\n        int w;\n        for (w = minWeight; w < maxWeight1; ++w) {\n            int const begin = rankStart[w];\n            int const end = rankStart[w+1];\n            U32 const nbBits = nbBitsBaseline - w;\n            U32 const totalBits = nbBits + consumedBits;\n            HUF_fillDTableX2ForWeight(\n                DTable + rankVal[w],\n                sortedSymbols + begin, sortedSymbols + end,\n                totalBits, targetLog,\n                baseSeq, /* level */ 2);\n        }\n    }\n}\n\nstatic void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog,\n                           const sortedSymbol_t* sortedList,\n                           const U32* rankStart, rankValCol_t* rankValOrigin, const U32 maxWeight,\n                           const U32 nbBitsBaseline)\n{\n    U32* const rankVal = rankValOrigin[0];\n    const int scaleLog = nbBitsBaseline - targetLog;   /* note : targetLog >= srcLog, hence scaleLog <= 1 */\n    const U32 minBits  = nbBitsBaseline - maxWeight;\n    int w;\n    int const wEnd = (int)maxWeight + 1;\n\n    /* Fill DTable in order of weight. */\n    for (w = 1; w < wEnd; ++w) {\n        int const begin = (int)rankStart[w];\n        int const end = (int)rankStart[w+1];\n        U32 const nbBits = nbBitsBaseline - w;\n\n        if (targetLog-nbBits >= minBits) {\n            /* Enough room for a second symbol. */\n            int start = rankVal[w];\n            U32 const length = 1U << ((targetLog - nbBits) & 0x1F /* quiet static-analyzer */);\n            int minWeight = nbBits + scaleLog;\n            int s;\n            if (minWeight < 1) minWeight = 1;\n            /* Fill the DTable for every symbol of weight w.\n             * These symbols get at least 1 second symbol.\n             */\n            for (s = begin; s != end; ++s) {\n                HUF_fillDTableX2Level2(\n                    DTable + start, targetLog, nbBits,\n                    rankValOrigin[nbBits], minWeight, wEnd,\n                    sortedList, rankStart,\n                    nbBitsBaseline, sortedList[s].symbol);\n                start += length;\n            }\n        } else {\n            /* Only a single symbol. */\n            HUF_fillDTableX2ForWeight(\n                DTable + rankVal[w],\n                sortedList + begin, sortedList + end,\n                nbBits, targetLog,\n                /* baseSeq */ 0, /* level */ 1);\n        }\n    }\n}\n\ntypedef struct {\n    rankValCol_t rankVal[HUF_TABLELOG_MAX];\n    U32 rankStats[HUF_TABLELOG_MAX + 1];\n    U32 rankStart0[HUF_TABLELOG_MAX + 3];\n    sortedSymbol_t sortedSymbol[HUF_SYMBOLVALUE_MAX + 1];\n    BYTE weightList[HUF_SYMBOLVALUE_MAX + 1];\n    U32 calleeWksp[HUF_READ_STATS_WORKSPACE_SIZE_U32];\n} HUF_ReadDTableX2_Workspace;\n\nsize_t HUF_readDTableX2_wksp(HUF_DTable* DTable,\n                       const void* src, size_t srcSize,\n                             void* workSpace, size_t wkspSize, int flags)\n{\n    U32 tableLog, maxW, nbSymbols;\n    DTableDesc dtd = HUF_getDTableDesc(DTable);\n    U32 maxTableLog = dtd.maxTableLog;\n    size_t iSize;\n    void* dtPtr = DTable+1;   /* force compiler to avoid strict-aliasing */\n    HUF_DEltX2* const dt = (HUF_DEltX2*)dtPtr;\n    U32 *rankStart;\n\n    HUF_ReadDTableX2_Workspace* const wksp = (HUF_ReadDTableX2_Workspace*)workSpace;\n\n    if (sizeof(*wksp) > wkspSize) return ERROR(GENERIC);\n\n    rankStart = wksp->rankStart0 + 1;\n    ZSTD_memset(wksp->rankStats, 0, sizeof(wksp->rankStats));\n    ZSTD_memset(wksp->rankStart0, 0, sizeof(wksp->rankStart0));\n\n    DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(HUF_DTable));   /* if compiler fails here, assertion is wrong */\n    if (maxTableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);\n    /* ZSTD_memset(weightList, 0, sizeof(weightList)); */  /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUF_readStats_wksp(wksp->weightList, HUF_SYMBOLVALUE_MAX + 1, wksp->rankStats, &nbSymbols, &tableLog, src, srcSize, wksp->calleeWksp, sizeof(wksp->calleeWksp), flags);\n    if (HUF_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > maxTableLog) return ERROR(tableLog_tooLarge);   /* DTable can't fit code depth */\n    if (tableLog <= HUF_DECODER_FAST_TABLELOG && maxTableLog > HUF_DECODER_FAST_TABLELOG) maxTableLog = HUF_DECODER_FAST_TABLELOG;\n\n    /* find maxWeight */\n    for (maxW = tableLog; wksp->rankStats[maxW]==0; maxW--) {}  /* necessarily finds a solution before 0 */\n\n    /* Get start index of each weight */\n    {   U32 w, nextRankStart = 0;\n        for (w=1; w<maxW+1; w++) {\n            U32 curr = nextRankStart;\n            nextRankStart += wksp->rankStats[w];\n            rankStart[w] = curr;\n        }\n        rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/\n        rankStart[maxW+1] = nextRankStart;\n    }\n\n    /* sort symbols by weight */\n    {   U32 s;\n        for (s=0; s<nbSymbols; s++) {\n            U32 const w = wksp->weightList[s];\n            U32 const r = rankStart[w]++;\n            wksp->sortedSymbol[r].symbol = (BYTE)s;\n        }\n        rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */\n    }\n\n    /* Build rankVal */\n    {   U32* const rankVal0 = wksp->rankVal[0];\n        {   int const rescale = (maxTableLog-tableLog) - 1;   /* tableLog <= maxTableLog */\n            U32 nextRankVal = 0;\n            U32 w;\n            for (w=1; w<maxW+1; w++) {\n                U32 curr = nextRankVal;\n                nextRankVal += wksp->rankStats[w] << (w+rescale);\n                rankVal0[w] = curr;\n        }   }\n        {   U32 const minBits = tableLog+1 - maxW;\n            U32 consumed;\n            for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) {\n                U32* const rankValPtr = wksp->rankVal[consumed];\n                U32 w;\n                for (w = 1; w < maxW+1; w++) {\n                    rankValPtr[w] = rankVal0[w] >> consumed;\n    }   }   }   }\n\n    HUF_fillDTableX2(dt, maxTableLog,\n                   wksp->sortedSymbol,\n                   wksp->rankStart0, wksp->rankVal, maxW,\n                   tableLog+1);\n\n    dtd.tableLog = (BYTE)maxTableLog;\n    dtd.tableType = 1;\n    ZSTD_memcpy(DTable, &dtd, sizeof(dtd));\n    return iSize;\n}\n\n\nFORCE_INLINE_TEMPLATE U32\nHUF_decodeSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog)\n{\n    size_t const val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    ZSTD_memcpy(op, &dt[val].sequence, 2);\n    BIT_skipBits(DStream, dt[val].nbBits);\n    return dt[val].length;\n}\n\nFORCE_INLINE_TEMPLATE U32\nHUF_decodeLastSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog)\n{\n    size_t const val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    ZSTD_memcpy(op, &dt[val].sequence, 1);\n    if (dt[val].length==1) {\n        BIT_skipBits(DStream, dt[val].nbBits);\n    } else {\n        if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {\n            BIT_skipBits(DStream, dt[val].nbBits);\n            if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))\n                /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */\n                DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);\n        }\n    }\n    return 1;\n}\n\n#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \\\n    do { ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog); } while (0)\n\n#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr)                     \\\n    do {                                                           \\\n        if (MEM_64bits() || (HUF_TABLELOG_MAX<=12))                \\\n            ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog); \\\n    } while (0)\n\n#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr)                     \\\n    do {                                                           \\\n        if (MEM_64bits())                                          \\\n            ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog); \\\n    } while (0)\n\nHINT_INLINE size_t\nHUF_decodeStreamX2(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd,\n                const HUF_DEltX2* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 8 symbols at a time */\n    if ((size_t)(pEnd - p) >= sizeof(bitDPtr->bitContainer)) {\n        if (dtLog <= 11 && MEM_64bits()) {\n            /* up to 10 symbols at a time */\n            while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-9)) {\n                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n            }\n        } else {\n            /* up to 8 symbols at a time */\n            while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-(sizeof(bitDPtr->bitContainer)-1))) {\n                HUF_DECODE_SYMBOLX2_2(p, bitDPtr);\n                HUF_DECODE_SYMBOLX2_1(p, bitDPtr);\n                HUF_DECODE_SYMBOLX2_2(p, bitDPtr);\n                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n            }\n        }\n    } else {\n        BIT_reloadDStream(bitDPtr);\n    }\n\n    /* closer to end : up to 2 symbols at a time */\n    if ((size_t)(pEnd - p) >= 2) {\n        while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p <= pEnd-2))\n            HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n        while (p <= pEnd-2)\n            HUF_DECODE_SYMBOLX2_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */\n    }\n\n    if (p < pEnd)\n        p += HUF_decodeLastSymbolX2(p, bitDPtr, dt, dtLog);\n\n    return p-pStart;\n}\n\nFORCE_INLINE_TEMPLATE size_t\nHUF_decompress1X2_usingDTable_internal_body(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUF_DTable* DTable)\n{\n    BIT_DStream_t bitD;\n\n    /* Init */\n    CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) );\n\n    /* decode */\n    {   BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = (BYTE*)ZSTD_maybeNullPtrAdd(ostart, (ptrdiff_t)dstSize);\n        const void* const dtPtr = DTable+1;   /* force compiler to not use strict-aliasing */\n        const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;\n        DTableDesc const dtd = HUF_getDTableDesc(DTable);\n        HUF_decodeStreamX2(ostart, &bitD, oend, dt, dtd.tableLog);\n    }\n\n    /* check */\n    if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);\n\n    /* decoded size */\n    return dstSize;\n}\n\n/* HUF_decompress4X2_usingDTable_internal_body():\n * Conditions:\n * @dstSize >= 6\n */\nFORCE_INLINE_TEMPLATE size_t\nHUF_decompress4X2_usingDTable_internal_body(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUF_DTable* DTable)\n{\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n    if (dstSize < 6) return ERROR(corruption_detected);         /* stream 4-split doesn't work */\n\n    {   const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        BYTE* const olimit = oend - (sizeof(size_t)-1);\n        const void* const dtPtr = DTable+1;\n        const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;\n\n        /* Init */\n        BIT_DStream_t bitD1;\n        BIT_DStream_t bitD2;\n        BIT_DStream_t bitD3;\n        BIT_DStream_t bitD4;\n        size_t const length1 = MEM_readLE16(istart);\n        size_t const length2 = MEM_readLE16(istart+2);\n        size_t const length3 = MEM_readLE16(istart+4);\n        size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        size_t const segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal = 1;\n        DTableDesc const dtd = HUF_getDTableDesc(DTable);\n        U32 const dtLog = dtd.tableLog;\n\n        if (length4 > cSrcSize) return ERROR(corruption_detected);  /* overflow */\n        if (opStart4 > oend) return ERROR(corruption_detected);     /* overflow */\n        assert(dstSize >= 6 /* validated above */);\n        CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );\n        CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );\n        CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );\n        CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        if ((size_t)(oend - op4) >= sizeof(size_t)) {\n            for ( ; (endSignal) & (op4 < olimit); ) {\n#if defined(__clang__) && (defined(__x86_64__) || defined(__i386__))\n                HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n                HUF_DECODE_SYMBOLX2_1(op1, &bitD1);\n                HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n                HUF_DECODE_SYMBOLX2_0(op1, &bitD1);\n                HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n                HUF_DECODE_SYMBOLX2_1(op2, &bitD2);\n                HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n                HUF_DECODE_SYMBOLX2_0(op2, &bitD2);\n                endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished;\n                endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished;\n                HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n                HUF_DECODE_SYMBOLX2_1(op3, &bitD3);\n                HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n                HUF_DECODE_SYMBOLX2_0(op3, &bitD3);\n                HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n                HUF_DECODE_SYMBOLX2_1(op4, &bitD4);\n                HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n                HUF_DECODE_SYMBOLX2_0(op4, &bitD4);\n                endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished;\n                endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished;\n#else\n                HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n                HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n                HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n                HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n                HUF_DECODE_SYMBOLX2_1(op1, &bitD1);\n                HUF_DECODE_SYMBOLX2_1(op2, &bitD2);\n                HUF_DECODE_SYMBOLX2_1(op3, &bitD3);\n                HUF_DECODE_SYMBOLX2_1(op4, &bitD4);\n                HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n                HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n                HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n                HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n                HUF_DECODE_SYMBOLX2_0(op1, &bitD1);\n                HUF_DECODE_SYMBOLX2_0(op2, &bitD2);\n                HUF_DECODE_SYMBOLX2_0(op3, &bitD3);\n                HUF_DECODE_SYMBOLX2_0(op4, &bitD4);\n                endSignal = (U32)LIKELY((U32)\n                            (BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished)\n                        & (BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished)\n                        & (BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished)\n                        & (BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished));\n#endif\n            }\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);\n        HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);\n        HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);\n        HUF_decodeStreamX2(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);\n          if (!endCheck) return ERROR(corruption_detected); }\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n#if HUF_NEED_BMI2_FUNCTION\nstatic BMI2_TARGET_ATTRIBUTE\nsize_t HUF_decompress4X2_usingDTable_internal_bmi2(void* dst, size_t dstSize, void const* cSrc,\n                    size_t cSrcSize, HUF_DTable const* DTable) {\n    return HUF_decompress4X2_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);\n}\n#endif\n\nstatic\nsize_t HUF_decompress4X2_usingDTable_internal_default(void* dst, size_t dstSize, void const* cSrc,\n                    size_t cSrcSize, HUF_DTable const* DTable) {\n    return HUF_decompress4X2_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);\n}\n\n#if ZSTD_ENABLE_ASM_X86_64_BMI2\n\nHUF_ASM_DECL void HUF_decompress4X2_usingDTable_internal_fast_asm_loop(HUF_DecompressFastArgs* args) ZSTDLIB_HIDDEN;\n\n#endif\n\nstatic HUF_FAST_BMI2_ATTRS\nvoid HUF_decompress4X2_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs* args)\n{\n    U64 bits[4];\n    BYTE const* ip[4];\n    BYTE* op[4];\n    BYTE* oend[4];\n    HUF_DEltX2 const* const dtable = (HUF_DEltX2 const*)args->dt;\n    BYTE const* const ilowest = args->ilowest;\n\n    /* Copy the arguments to local registers. */\n    ZSTD_memcpy(&bits, &args->bits, sizeof(bits));\n    ZSTD_memcpy((void*)(&ip), &args->ip, sizeof(ip));\n    ZSTD_memcpy(&op, &args->op, sizeof(op));\n\n    oend[0] = op[1];\n    oend[1] = op[2];\n    oend[2] = op[3];\n    oend[3] = args->oend;\n\n    assert(MEM_isLittleEndian());\n    assert(!MEM_32bits());\n\n    for (;;) {\n        BYTE* olimit;\n        int stream;\n\n        /* Assert loop preconditions */\n#ifndef NDEBUG\n        for (stream = 0; stream < 4; ++stream) {\n            assert(op[stream] <= oend[stream]);\n            assert(ip[stream] >= ilowest);\n        }\n#endif\n        /* Compute olimit */\n        {\n            /* Each loop does 5 table lookups for each of the 4 streams.\n             * Each table lookup consumes up to 11 bits of input, and produces\n             * up to 2 bytes of output.\n             */\n            /* We can consume up to 7 bytes of input per iteration per stream.\n             * We also know that each input pointer is >= ip[0]. So we can run\n             * iters loops before running out of input.\n             */\n            size_t iters = (size_t)(ip[0] - ilowest) / 7;\n            /* Each iteration can produce up to 10 bytes of output per stream.\n             * Each output stream my advance at different rates. So take the\n             * minimum number of safe iterations among all the output streams.\n             */\n            for (stream = 0; stream < 4; ++stream) {\n                size_t const oiters = (size_t)(oend[stream] - op[stream]) / 10;\n                iters = MIN(iters, oiters);\n            }\n\n            /* Each iteration produces at least 5 output symbols. So until\n             * op[3] crosses olimit, we know we haven't executed iters\n             * iterations yet. This saves us maintaining an iters counter,\n             * at the expense of computing the remaining # of iterations\n             * more frequently.\n             */\n            olimit = op[3] + (iters * 5);\n\n            /* Exit the fast decoding loop once we reach the end. */\n            if (op[3] == olimit)\n                break;\n\n            /* Exit the decoding loop if any input pointer has crossed the\n             * previous one. This indicates corruption, and a precondition\n             * to our loop is that ip[i] >= ip[0].\n             */\n            for (stream = 1; stream < 4; ++stream) {\n                if (ip[stream] < ip[stream - 1])\n                    goto _out;\n            }\n        }\n\n#ifndef NDEBUG\n        for (stream = 1; stream < 4; ++stream) {\n            assert(ip[stream] >= ip[stream - 1]);\n        }\n#endif\n\n#define HUF_4X2_DECODE_SYMBOL(_stream, _decode3)               \\\n    do {                                                       \\\n        if ((_decode3) || (_stream) != 3) {                    \\\n            U64 const index = bits[(_stream)] >> 53;           \\\n            size_t const entry = MEM_readLE32(&dtable[index]); \\\n            MEM_write16(op[(_stream)], (U16)entry);            \\\n            bits[(_stream)] <<= (entry >> 16) & 0x3F;          \\\n            op[(_stream)] += entry >> 24;                      \\\n        }                                                      \\\n    } while (0)\n\n#define HUF_5X2_RELOAD_STREAM(_stream, _decode3)                        \\\n    do {                                                                \\\n        if (_decode3) HUF_4X2_DECODE_SYMBOL(3, 1);                      \\\n        {                                                               \\\n            U64 const ctz = ZSTD_countTrailingZeros64(bits[(_stream)]); \\\n            U64 const nbBits = ctz & 7;                                 \\\n            U64 const nbBytes = ctz >> 3;                               \\\n            ip[(_stream)] -= nbBytes;                                   \\\n            bits[(_stream)] = MEM_read64(ip[(_stream)]) | 1;            \\\n            bits[(_stream)] <<= nbBits;                                 \\\n        }                                                               \\\n    } while (0)\n\n#if defined(__aarch64__)\n#  define HUF_4X2_4WAY 1\n#else\n#  define HUF_4X2_4WAY 0\n#endif\n#define HUF_4X2_3WAY !HUF_4X2_4WAY\n\n        /* Manually unroll the loop because compilers don't consistently\n         * unroll the inner loops, which destroys performance.\n         */\n        do {\n            /* Decode 5 symbols from each of the first 3 or 4 streams.\n             * In the 3-way case the final stream will be decoded during\n             * the reload phase to reduce register pressure.\n             */\n            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, HUF_4X2_4WAY);\n            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, HUF_4X2_4WAY);\n            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, HUF_4X2_4WAY);\n            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, HUF_4X2_4WAY);\n            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, HUF_4X2_4WAY);\n\n            /* In the 3-way case decode one symbol from the final stream. */\n            HUF_4X2_DECODE_SYMBOL(3, HUF_4X2_3WAY);\n\n            /* In the 3-way case decode 4 symbols from the final stream &\n             * reload bitstreams. The final stream is reloaded last, meaning\n             * that all 5 symbols are decoded from the final stream before\n             * it is reloaded.\n             */\n            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_5X2_RELOAD_STREAM, HUF_4X2_3WAY);\n        } while (op[3] < olimit);\n    }\n\n#undef HUF_4X2_DECODE_SYMBOL\n#undef HUF_5X2_RELOAD_STREAM\n\n_out:\n\n    /* Save the final values of each of the state variables back to args. */\n    ZSTD_memcpy(&args->bits, &bits, sizeof(bits));\n    ZSTD_memcpy((void*)(&args->ip), &ip, sizeof(ip));\n    ZSTD_memcpy(&args->op, &op, sizeof(op));\n}\n\n\nstatic HUF_FAST_BMI2_ATTRS size_t\nHUF_decompress4X2_usingDTable_internal_fast(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUF_DTable* DTable,\n    HUF_DecompressFastLoopFn loopFn) {\n    void const* dt = DTable + 1;\n    const BYTE* const ilowest = (const BYTE*)cSrc;\n    BYTE* const oend = (BYTE*)ZSTD_maybeNullPtrAdd(dst, (ptrdiff_t)dstSize);\n    HUF_DecompressFastArgs args;\n    {\n        size_t const ret = HUF_DecompressFastArgs_init(&args, dst, dstSize, cSrc, cSrcSize, DTable);\n        FORWARD_IF_ERROR(ret, \"Failed to init asm args\");\n        if (ret == 0)\n            return 0;\n    }\n\n    assert(args.ip[0] >= args.ilowest);\n    loopFn(&args);\n\n    /* note : op4 already verified within main loop */\n    assert(args.ip[0] >= ilowest);\n    assert(args.ip[1] >= ilowest);\n    assert(args.ip[2] >= ilowest);\n    assert(args.ip[3] >= ilowest);\n    assert(args.op[3] <= oend);\n\n    assert(ilowest == args.ilowest);\n    assert(ilowest + 6 == args.iend[0]);\n    (void)ilowest;\n\n    /* finish bitStreams one by one */\n    {\n        size_t const segmentSize = (dstSize+3) / 4;\n        BYTE* segmentEnd = (BYTE*)dst;\n        int i;\n        for (i = 0; i < 4; ++i) {\n            BIT_DStream_t bit;\n            if (segmentSize <= (size_t)(oend - segmentEnd))\n                segmentEnd += segmentSize;\n            else\n                segmentEnd = oend;\n            FORWARD_IF_ERROR(HUF_initRemainingDStream(&bit, &args, i, segmentEnd), \"corruption\");\n            args.op[i] += HUF_decodeStreamX2(args.op[i], &bit, segmentEnd, (HUF_DEltX2 const*)dt, HUF_DECODER_FAST_TABLELOG);\n            if (args.op[i] != segmentEnd)\n                return ERROR(corruption_detected);\n        }\n    }\n\n    /* decoded size */\n    return dstSize;\n}\n\nstatic size_t HUF_decompress4X2_usingDTable_internal(void* dst, size_t dstSize, void const* cSrc,\n                    size_t cSrcSize, HUF_DTable const* DTable, int flags)\n{\n    HUF_DecompressUsingDTableFn fallbackFn = HUF_decompress4X2_usingDTable_internal_default;\n    HUF_DecompressFastLoopFn loopFn = HUF_decompress4X2_usingDTable_internal_fast_c_loop;\n\n#if DYNAMIC_BMI2\n    if (flags & HUF_flags_bmi2) {\n        fallbackFn = HUF_decompress4X2_usingDTable_internal_bmi2;\n# if ZSTD_ENABLE_ASM_X86_64_BMI2\n        if (!(flags & HUF_flags_disableAsm)) {\n            loopFn = HUF_decompress4X2_usingDTable_internal_fast_asm_loop;\n        }\n# endif\n    } else {\n        return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable);\n    }\n#endif\n\n#if ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__)\n    if (!(flags & HUF_flags_disableAsm)) {\n        loopFn = HUF_decompress4X2_usingDTable_internal_fast_asm_loop;\n    }\n#endif\n\n    if (HUF_ENABLE_FAST_DECODE && !(flags & HUF_flags_disableFast)) {\n        size_t const ret = HUF_decompress4X2_usingDTable_internal_fast(dst, dstSize, cSrc, cSrcSize, DTable, loopFn);\n        if (ret != 0)\n            return ret;\n    }\n    return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable);\n}\n\nHUF_DGEN(HUF_decompress1X2_usingDTable_internal)\n\nsize_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,\n                                   const void* cSrc, size_t cSrcSize,\n                                   void* workSpace, size_t wkspSize, int flags)\n{\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t const hSize = HUF_readDTableX2_wksp(DCtx, cSrc, cSrcSize,\n                                               workSpace, wkspSize, flags);\n    if (HUF_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize; cSrcSize -= hSize;\n\n    return HUF_decompress1X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, flags);\n}\n\nstatic size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,\n                                   const void* cSrc, size_t cSrcSize,\n                                   void* workSpace, size_t wkspSize, int flags)\n{\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t hSize = HUF_readDTableX2_wksp(dctx, cSrc, cSrcSize,\n                                         workSpace, wkspSize, flags);\n    if (HUF_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize; cSrcSize -= hSize;\n\n    return HUF_decompress4X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, flags);\n}\n\n#endif /* HUF_FORCE_DECOMPRESS_X1 */\n\n\n/* ***********************************/\n/* Universal decompression selectors */\n/* ***********************************/\n\n\n#if !defined(HUF_FORCE_DECOMPRESS_X1) && !defined(HUF_FORCE_DECOMPRESS_X2)\ntypedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;\nstatic const algo_time_t algoTime[16 /* Quantization */][2 /* single, double */] =\n{\n    /* single, double, quad */\n    {{0,0}, {1,1}},  /* Q==0 : impossible */\n    {{0,0}, {1,1}},  /* Q==1 : impossible */\n    {{ 150,216}, { 381,119}},   /* Q == 2 : 12-18% */\n    {{ 170,205}, { 514,112}},   /* Q == 3 : 18-25% */\n    {{ 177,199}, { 539,110}},   /* Q == 4 : 25-32% */\n    {{ 197,194}, { 644,107}},   /* Q == 5 : 32-38% */\n    {{ 221,192}, { 735,107}},   /* Q == 6 : 38-44% */\n    {{ 256,189}, { 881,106}},   /* Q == 7 : 44-50% */\n    {{ 359,188}, {1167,109}},   /* Q == 8 : 50-56% */\n    {{ 582,187}, {1570,114}},   /* Q == 9 : 56-62% */\n    {{ 688,187}, {1712,122}},   /* Q ==10 : 62-69% */\n    {{ 825,186}, {1965,136}},   /* Q ==11 : 69-75% */\n    {{ 976,185}, {2131,150}},   /* Q ==12 : 75-81% */\n    {{1180,186}, {2070,175}},   /* Q ==13 : 81-87% */\n    {{1377,185}, {1731,202}},   /* Q ==14 : 87-93% */\n    {{1412,185}, {1695,202}},   /* Q ==15 : 93-99% */\n};\n#endif\n\n/** HUF_selectDecoder() :\n *  Tells which decoder is likely to decode faster,\n *  based on a set of pre-computed metrics.\n * @return : 0==HUF_decompress4X1, 1==HUF_decompress4X2 .\n *  Assumption : 0 < dstSize <= 128 KB */\nU32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize)\n{\n    assert(dstSize > 0);\n    assert(dstSize <= 128*1024);\n#if defined(HUF_FORCE_DECOMPRESS_X1)\n    (void)dstSize;\n    (void)cSrcSize;\n    return 0;\n#elif defined(HUF_FORCE_DECOMPRESS_X2)\n    (void)dstSize;\n    (void)cSrcSize;\n    return 1;\n#else\n    /* decoder timing evaluation */\n    {   U32 const Q = (cSrcSize >= dstSize) ? 15 : (U32)(cSrcSize * 16 / dstSize);   /* Q < 16 */\n        U32 const D256 = (U32)(dstSize >> 8);\n        U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256);\n        U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256);\n        DTime1 += DTime1 >> 5;  /* small advantage to algorithm using less memory, to reduce cache eviction */\n        return DTime1 < DTime0;\n    }\n#endif\n}\n\nsize_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,\n                                  const void* cSrc, size_t cSrcSize,\n                                  void* workSpace, size_t wkspSize, int flags)\n{\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */\n    if (cSrcSize == dstSize) { ZSTD_memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */\n    if (cSrcSize == 1) { ZSTD_memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */\n\n    {   U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);\n#if defined(HUF_FORCE_DECOMPRESS_X1)\n        (void)algoNb;\n        assert(algoNb == 0);\n        return HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc,\n                                cSrcSize, workSpace, wkspSize, flags);\n#elif defined(HUF_FORCE_DECOMPRESS_X2)\n        (void)algoNb;\n        assert(algoNb == 1);\n        return HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc,\n                                cSrcSize, workSpace, wkspSize, flags);\n#else\n        return algoNb ? HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc,\n                                cSrcSize, workSpace, wkspSize, flags):\n                        HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc,\n                                cSrcSize, workSpace, wkspSize, flags);\n#endif\n    }\n}\n\n\nsize_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int flags)\n{\n    DTableDesc const dtd = HUF_getDTableDesc(DTable);\n#if defined(HUF_FORCE_DECOMPRESS_X1)\n    (void)dtd;\n    assert(dtd.tableType == 0);\n    return HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);\n#elif defined(HUF_FORCE_DECOMPRESS_X2)\n    (void)dtd;\n    assert(dtd.tableType == 1);\n    return HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);\n#else\n    return dtd.tableType ? HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags) :\n                           HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);\n#endif\n}\n\n#ifndef HUF_FORCE_DECOMPRESS_X2\nsize_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags)\n{\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t const hSize = HUF_readDTableX1_wksp(dctx, cSrc, cSrcSize, workSpace, wkspSize, flags);\n    if (HUF_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize; cSrcSize -= hSize;\n\n    return HUF_decompress1X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, flags);\n}\n#endif\n\nsize_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int flags)\n{\n    DTableDesc const dtd = HUF_getDTableDesc(DTable);\n#if defined(HUF_FORCE_DECOMPRESS_X1)\n    (void)dtd;\n    assert(dtd.tableType == 0);\n    return HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);\n#elif defined(HUF_FORCE_DECOMPRESS_X2)\n    (void)dtd;\n    assert(dtd.tableType == 1);\n    return HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);\n#else\n    return dtd.tableType ? HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags) :\n                           HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);\n#endif\n}\n\nsize_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags)\n{\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize == 0) return ERROR(corruption_detected);\n\n    {   U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);\n#if defined(HUF_FORCE_DECOMPRESS_X1)\n        (void)algoNb;\n        assert(algoNb == 0);\n        return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags);\n#elif defined(HUF_FORCE_DECOMPRESS_X2)\n        (void)algoNb;\n        assert(algoNb == 1);\n        return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags);\n#else\n        return algoNb ? HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags) :\n                        HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags);\n#endif\n    }\n}\n"
  },
  {
    "path": "lib/decompress/huf_decompress_amd64.S",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"../common/portability_macros.h\"\n\n#if defined(__ELF__) && defined(__GNUC__)\n/* Stack marking\n * ref: https://wiki.gentoo.org/wiki/Hardened/GNU_stack_quickstart\n */\n.section .note.GNU-stack,\"\",%progbits\n\n#if defined(__aarch64__)\n/* Mark that this assembly supports BTI & PAC, because it is empty for aarch64.\n * See: https://github.com/facebook/zstd/issues/3841\n * See: https://gcc.godbolt.org/z/sqr5T4ffK\n * See: https://lore.kernel.org/linux-arm-kernel/20200429211641.9279-8-broonie@kernel.org/\n * See: https://reviews.llvm.org/D62609\n */\n.pushsection .note.gnu.property, \"a\"\n.p2align 3\n.long 4                 /* size of the name - \"GNU\\0\" */\n.long 0x10              /* size of descriptor */\n.long 0x5               /* NT_GNU_PROPERTY_TYPE_0 */\n.asciz \"GNU\"\n.long 0xc0000000        /* pr_type - GNU_PROPERTY_AARCH64_FEATURE_1_AND */\n.long 4                 /* pr_datasz - 4 bytes */\n.long 3                 /* pr_data - GNU_PROPERTY_AARCH64_FEATURE_1_BTI | GNU_PROPERTY_AARCH64_FEATURE_1_PAC */\n.p2align 3              /* pr_padding - bring everything to 8 byte alignment */\n.popsection\n#endif\n\n#endif\n\n// There appears to be an unreconcilable syntax difference between Linux and Darwin assemblers.\n// Name of a private label (i.e. not exported to symbol table) on Darwin has to start with \"L\",\n// on Linux has to start with \".\". There's no way to have a name start with both \".\" and \"L\", so\n// we have to use a macro.\n#if defined(__APPLE__)\n#define LOCAL_LABEL(label) L_ ## label\n#else\n#define LOCAL_LABEL(label) .L_ ## label\n#endif\n\n#if ZSTD_ENABLE_ASM_X86_64_BMI2\n\n/* Calling convention:\n *\n * %rdi (or %rcx on Windows) contains the first argument: HUF_DecompressAsmArgs*.\n * %rbp isn't maintained (no frame pointer).\n * %rsp contains the stack pointer that grows down.\n *      No red-zone is assumed, only addresses >= %rsp are used.\n * All register contents are preserved.\n */\n\nZSTD_HIDE_ASM_FUNCTION(HUF_decompress4X1_usingDTable_internal_fast_asm_loop)\nZSTD_HIDE_ASM_FUNCTION(HUF_decompress4X2_usingDTable_internal_fast_asm_loop)\nZSTD_HIDE_ASM_FUNCTION(_HUF_decompress4X2_usingDTable_internal_fast_asm_loop)\nZSTD_HIDE_ASM_FUNCTION(_HUF_decompress4X1_usingDTable_internal_fast_asm_loop)\n.global HUF_decompress4X1_usingDTable_internal_fast_asm_loop\n.global HUF_decompress4X2_usingDTable_internal_fast_asm_loop\n.global _HUF_decompress4X1_usingDTable_internal_fast_asm_loop\n.global _HUF_decompress4X2_usingDTable_internal_fast_asm_loop\n.text\n\n/* Sets up register mappings for clarity.\n * op[], bits[], dtable & ip[0] each get their own register.\n * ip[1,2,3] & olimit alias var[].\n * %rax is a scratch register.\n */\n\n#define op0    rsi\n#define op1    rbx\n#define op2    rcx\n#define op3    rdi\n\n#define ip0    r8\n#define ip1    r9\n#define ip2    r10\n#define ip3    r11\n\n#define bits0  rbp\n#define bits1  rdx\n#define bits2  r12\n#define bits3  r13\n#define dtable r14\n#define olimit r15\n\n/* var[] aliases ip[1,2,3] & olimit\n * ip[1,2,3] are saved every iteration.\n * olimit is only used in compute_olimit.\n */\n#define var0   r15\n#define var1   r9\n#define var2   r10\n#define var3   r11\n\n/* 32-bit var registers */\n#define vard0  r15d\n#define vard1  r9d\n#define vard2  r10d\n#define vard3  r11d\n\n/* Calls X(N) for each stream 0, 1, 2, 3. */\n#define FOR_EACH_STREAM(X) \\\n    X(0);                  \\\n    X(1);                  \\\n    X(2);                  \\\n    X(3)\n\n/* Calls X(N, idx) for each stream 0, 1, 2, 3. */\n#define FOR_EACH_STREAM_WITH_INDEX(X, idx) \\\n    X(0, idx);                             \\\n    X(1, idx);                             \\\n    X(2, idx);                             \\\n    X(3, idx)\n\n/* Define both _HUF_* & HUF_* symbols because MacOS\n * C symbols are prefixed with '_' & Linux symbols aren't.\n */\n_HUF_decompress4X1_usingDTable_internal_fast_asm_loop:\nHUF_decompress4X1_usingDTable_internal_fast_asm_loop:\n    ZSTD_CET_ENDBRANCH\n    .cfi_startproc\n    .cfi_def_cfa_offset 8\n    .cfi_offset %rip, -8\n    /* Save all registers - even if they are callee saved for simplicity. */\n    push %rax\n    .cfi_def_cfa_offset 16\n    .cfi_offset rax, -16\n    push %rbx\n    .cfi_def_cfa_offset 24\n    .cfi_offset rbx, -24\n    push %rcx\n    .cfi_def_cfa_offset 32\n    .cfi_offset rcx, -32\n    push %rdx\n    .cfi_def_cfa_offset 40\n    .cfi_offset rdx, -40\n    push %rbp\n    .cfi_def_cfa_offset 48\n    .cfi_offset rbp, -48\n    push %rsi\n    .cfi_def_cfa_offset 56\n    .cfi_offset rsi, -56\n    push %rdi\n    .cfi_def_cfa_offset 64\n    .cfi_offset rdi, -64\n    push %r8\n    .cfi_def_cfa_offset 72\n    .cfi_offset r8, -72\n    push %r9\n    .cfi_def_cfa_offset 80\n    .cfi_offset r9, -80\n    push %r10\n    .cfi_def_cfa_offset 88\n    .cfi_offset r10, -88\n    push %r11\n    .cfi_def_cfa_offset 96\n    .cfi_offset r11, -96\n    push %r12\n    .cfi_def_cfa_offset 104\n    .cfi_offset r12, -104\n    push %r13\n    .cfi_def_cfa_offset 112\n    .cfi_offset r13, -112\n    push %r14\n    .cfi_def_cfa_offset 120\n    .cfi_offset r14, -120\n    push %r15\n    .cfi_def_cfa_offset 128\n    .cfi_offset r15, -128\n\n    /* Read HUF_DecompressAsmArgs* args from %rax */\n#if defined(_WIN32)\n    movq %rcx, %rax\n#else\n    movq %rdi, %rax\n#endif\n    movq  0(%rax), %ip0\n    movq  8(%rax), %ip1\n    movq 16(%rax), %ip2\n    movq 24(%rax), %ip3\n    movq 32(%rax), %op0\n    movq 40(%rax), %op1\n    movq 48(%rax), %op2\n    movq 56(%rax), %op3\n    movq 64(%rax), %bits0\n    movq 72(%rax), %bits1\n    movq 80(%rax), %bits2\n    movq 88(%rax), %bits3\n    movq 96(%rax), %dtable\n    push %rax      /* argument */\n    .cfi_def_cfa_offset 136\n    push 104(%rax) /* ilowest */\n    .cfi_def_cfa_offset 144\n    push 112(%rax) /* oend */\n    .cfi_def_cfa_offset 152\n    push %olimit   /* olimit space */\n    .cfi_def_cfa_offset 160\n\n    subq $24, %rsp\n    .cfi_def_cfa_offset 184\n\nLOCAL_LABEL(4X1_compute_olimit):\n    /* Computes how many iterations we can do safely\n     * %r15, %rax may be clobbered\n     * rbx, rdx must be saved\n     * op3 & ip0 mustn't be clobbered\n     */\n    movq %rbx, 0(%rsp)\n    movq %rdx, 8(%rsp)\n\n    movq 32(%rsp), %rax /* rax = oend */\n    subq %op3,    %rax  /* rax = oend - op3 */\n\n    /* r15 = (oend - op3) / 5 */\n    movabsq $-3689348814741910323, %rdx\n    mulq %rdx\n    movq %rdx, %r15\n    shrq $2, %r15\n\n    movq %ip0,     %rax /* rax = ip0 */\n    movq 40(%rsp), %rdx /* rdx = ilowest */\n    subq %rdx,     %rax /* rax = ip0 - ilowest */\n    movq %rax,     %rbx /* rbx = ip0 - ilowest */\n\n    /* rdx = (ip0 - ilowest) / 7 */\n    movabsq $2635249153387078803, %rdx\n    mulq %rdx\n    subq %rdx, %rbx\n    shrq %rbx\n    addq %rbx, %rdx\n    shrq $2, %rdx\n\n    /* r15 = min(%rdx, %r15) */\n    cmpq %rdx, %r15\n    cmova %rdx, %r15\n\n    /* r15 = r15 * 5 */\n    leaq (%r15, %r15, 4), %r15\n\n    /* olimit = op3 + r15 */\n    addq %op3, %olimit\n\n    movq 8(%rsp), %rdx\n    movq 0(%rsp), %rbx\n\n    /* If (op3 + 20 > olimit) */\n    movq %op3, %rax    /* rax = op3 */\n    cmpq %rax, %olimit /* op3 == olimit */\n    je LOCAL_LABEL(4X1_exit)\n\n    /* If (ip1 < ip0) go to exit */\n    cmpq %ip0, %ip1\n    jb LOCAL_LABEL(4X1_exit)\n\n    /* If (ip2 < ip1) go to exit */\n    cmpq %ip1, %ip2\n    jb LOCAL_LABEL(4X1_exit)\n\n    /* If (ip3 < ip2) go to exit */\n    cmpq %ip2, %ip3\n    jb LOCAL_LABEL(4X1_exit)\n\n/* Reads top 11 bits from bits[n]\n * Loads dt[bits[n]] into var[n]\n */\n#define GET_NEXT_DELT(n)                \\\n    movq $53, %var##n;                  \\\n    shrxq %var##n, %bits##n, %var##n;   \\\n    movzwl (%dtable,%var##n,2),%vard##n\n\n/* var[n] must contain the DTable entry computed with GET_NEXT_DELT\n * Moves var[n] to %rax\n * bits[n] <<= var[n] & 63\n * op[n][idx] = %rax >> 8\n * %ah is a way to access bits [8, 16) of %rax\n */\n#define DECODE_FROM_DELT(n, idx)       \\\n    movq %var##n, %rax;                \\\n    shlxq %var##n, %bits##n, %bits##n; \\\n    movb %ah, idx(%op##n)\n\n/* Assumes GET_NEXT_DELT has been called.\n * Calls DECODE_FROM_DELT then GET_NEXT_DELT\n */\n#define DECODE_AND_GET_NEXT(n, idx) \\\n    DECODE_FROM_DELT(n, idx);       \\\n    GET_NEXT_DELT(n)                \\\n\n/* // ctz & nbBytes is stored in bits[n]\n * // nbBits is stored in %rax\n * ctz  = CTZ[bits[n]]\n * nbBits  = ctz & 7\n * nbBytes = ctz >> 3\n * op[n]  += 5\n * ip[n]  -= nbBytes\n * // Note: x86-64 is little-endian ==> no bswap\n * bits[n] = MEM_readST(ip[n]) | 1\n * bits[n] <<= nbBits\n */\n#define RELOAD_BITS(n)             \\\n    bsfq %bits##n, %bits##n;       \\\n    movq %bits##n, %rax;           \\\n    andq $7, %rax;                 \\\n    shrq $3, %bits##n;             \\\n    leaq 5(%op##n), %op##n;        \\\n    subq %bits##n, %ip##n;         \\\n    movq (%ip##n), %bits##n;       \\\n    orq $1, %bits##n;              \\\n    shlx %rax, %bits##n, %bits##n\n\n    /* Store clobbered variables on the stack */\n    movq %olimit, 24(%rsp)\n    movq %ip1, 0(%rsp)\n    movq %ip2, 8(%rsp)\n    movq %ip3, 16(%rsp)\n\n    /* Call GET_NEXT_DELT for each stream */\n    FOR_EACH_STREAM(GET_NEXT_DELT)\n\n    .p2align 6\n\nLOCAL_LABEL(4X1_loop_body):\n    /* Decode 5 symbols in each of the 4 streams (20 total)\n     * Must have called GET_NEXT_DELT for each stream\n     */\n    FOR_EACH_STREAM_WITH_INDEX(DECODE_AND_GET_NEXT, 0)\n    FOR_EACH_STREAM_WITH_INDEX(DECODE_AND_GET_NEXT, 1)\n    FOR_EACH_STREAM_WITH_INDEX(DECODE_AND_GET_NEXT, 2)\n    FOR_EACH_STREAM_WITH_INDEX(DECODE_AND_GET_NEXT, 3)\n    FOR_EACH_STREAM_WITH_INDEX(DECODE_FROM_DELT, 4)\n\n    /* Load ip[1,2,3] from stack (var[] aliases them)\n     * ip[] is needed for RELOAD_BITS\n     * Each will be stored back to the stack after RELOAD\n     */\n    movq 0(%rsp), %ip1\n    movq 8(%rsp), %ip2\n    movq 16(%rsp), %ip3\n\n    /* Reload each stream & fetch the next table entry\n     * to prepare for the next iteration\n     */\n    RELOAD_BITS(0)\n    GET_NEXT_DELT(0)\n\n    RELOAD_BITS(1)\n    movq %ip1, 0(%rsp)\n    GET_NEXT_DELT(1)\n\n    RELOAD_BITS(2)\n    movq %ip2, 8(%rsp)\n    GET_NEXT_DELT(2)\n\n    RELOAD_BITS(3)\n    movq %ip3, 16(%rsp)\n    GET_NEXT_DELT(3)\n\n    /* If op3 < olimit: continue the loop */\n    cmp %op3, 24(%rsp)\n    ja LOCAL_LABEL(4X1_loop_body)\n\n    /* Reload ip[1,2,3] from stack */\n    movq 0(%rsp), %ip1\n    movq 8(%rsp), %ip2\n    movq 16(%rsp), %ip3\n\n    /* Re-compute olimit */\n    jmp LOCAL_LABEL(4X1_compute_olimit)\n\n#undef GET_NEXT_DELT\n#undef DECODE_FROM_DELT\n#undef DECODE\n#undef RELOAD_BITS\nLOCAL_LABEL(4X1_exit):\n    addq $24, %rsp\n    .cfi_def_cfa_offset 160\n\n    /* Restore stack (oend & olimit) */\n    pop %rax /* olimit */\n    .cfi_def_cfa_offset 152\n    pop %rax /* oend */\n    .cfi_def_cfa_offset 144\n    pop %rax /* ilowest */\n    .cfi_def_cfa_offset 136\n    pop %rax /* arg */\n    .cfi_def_cfa_offset 128\n\n    /* Save ip / op / bits */\n    movq %ip0,  0(%rax)\n    movq %ip1,  8(%rax)\n    movq %ip2, 16(%rax)\n    movq %ip3, 24(%rax)\n    movq %op0, 32(%rax)\n    movq %op1, 40(%rax)\n    movq %op2, 48(%rax)\n    movq %op3, 56(%rax)\n    movq %bits0, 64(%rax)\n    movq %bits1, 72(%rax)\n    movq %bits2, 80(%rax)\n    movq %bits3, 88(%rax)\n\n    /* Restore registers */\n    pop %r15\n    .cfi_restore r15\n    .cfi_def_cfa_offset 120\n    pop %r14\n    .cfi_restore r14\n    .cfi_def_cfa_offset 112\n    pop %r13\n    .cfi_restore r13\n    .cfi_def_cfa_offset 104\n    pop %r12\n    .cfi_restore r12\n    .cfi_def_cfa_offset 96\n    pop %r11\n    .cfi_restore r11\n    .cfi_def_cfa_offset 88\n    pop %r10\n    .cfi_restore r10\n    .cfi_def_cfa_offset 80\n    pop %r9\n    .cfi_restore r9\n    .cfi_def_cfa_offset 72\n    pop %r8\n    .cfi_restore r8\n    .cfi_def_cfa_offset 64\n    pop %rdi\n    .cfi_restore rdi\n    .cfi_def_cfa_offset 56\n    pop %rsi\n    .cfi_restore rsi\n    .cfi_def_cfa_offset 48\n    pop %rbp\n    .cfi_restore rbp\n    .cfi_def_cfa_offset 40\n    pop %rdx\n    .cfi_restore rdx\n    .cfi_def_cfa_offset 32\n    pop %rcx\n    .cfi_restore rcx\n    .cfi_def_cfa_offset 24\n    pop %rbx\n    .cfi_restore rbx\n    .cfi_def_cfa_offset 16\n    pop %rax\n    .cfi_restore rax\n    .cfi_def_cfa_offset 8\n    ret\n    .cfi_endproc\n\n_HUF_decompress4X2_usingDTable_internal_fast_asm_loop:\nHUF_decompress4X2_usingDTable_internal_fast_asm_loop:\n    ZSTD_CET_ENDBRANCH\n    .cfi_startproc\n    .cfi_def_cfa_offset 8\n    .cfi_offset %rip, -8\n    /* Save all registers - even if they are callee saved for simplicity. */\n    push %rax\n    .cfi_def_cfa_offset 16\n    .cfi_offset rax, -16\n    push %rbx\n    .cfi_def_cfa_offset 24\n    .cfi_offset rbx, -24\n    push %rcx\n    .cfi_def_cfa_offset 32\n    .cfi_offset rcx, -32\n    push %rdx\n    .cfi_def_cfa_offset 40\n    .cfi_offset rdx, -40\n    push %rbp\n    .cfi_def_cfa_offset 48\n    .cfi_offset rbp, -48\n    push %rsi\n    .cfi_def_cfa_offset 56\n    .cfi_offset rsi, -56\n    push %rdi\n    .cfi_def_cfa_offset 64\n    .cfi_offset rdi, -64\n    push %r8\n    .cfi_def_cfa_offset 72\n    .cfi_offset r8, -72\n    push %r9\n    .cfi_def_cfa_offset 80\n    .cfi_offset r9, -80\n    push %r10\n    .cfi_def_cfa_offset 88\n    .cfi_offset r10, -88\n    push %r11\n    .cfi_def_cfa_offset 96\n    .cfi_offset r11, -96\n    push %r12\n    .cfi_def_cfa_offset 104\n    .cfi_offset r12, -104\n    push %r13\n    .cfi_def_cfa_offset 112\n    .cfi_offset r13, -112\n    push %r14\n    .cfi_def_cfa_offset 120\n    .cfi_offset r14, -120\n    push %r15\n    .cfi_def_cfa_offset 128\n    .cfi_offset r15, -128\n\n    /* Read HUF_DecompressAsmArgs* args from %rax */\n#if defined(_WIN32)\n    movq %rcx, %rax\n#else\n    movq %rdi, %rax\n#endif\n    movq  0(%rax), %ip0\n    movq  8(%rax), %ip1\n    movq 16(%rax), %ip2\n    movq 24(%rax), %ip3\n    movq 32(%rax), %op0\n    movq 40(%rax), %op1\n    movq 48(%rax), %op2\n    movq 56(%rax), %op3\n    movq 64(%rax), %bits0\n    movq 72(%rax), %bits1\n    movq 80(%rax), %bits2\n    movq 88(%rax), %bits3\n    movq 96(%rax), %dtable\n    push %rax      /* argument */\n    .cfi_def_cfa_offset 136\n    push %rax      /* olimit */\n    .cfi_def_cfa_offset 144\n    push 104(%rax) /* ilowest */\n    .cfi_def_cfa_offset 152\n\n    movq 112(%rax), %rax\n    push %rax /* oend3 */\n    .cfi_def_cfa_offset 160\n\n    movq %op3, %rax\n    push %rax /* oend2 */\n    .cfi_def_cfa_offset 168\n\n    movq %op2, %rax\n    push %rax /* oend1 */\n    .cfi_def_cfa_offset 176\n\n    movq %op1, %rax\n    push %rax /* oend0 */\n    .cfi_def_cfa_offset 184\n\n    /* Scratch space */\n    subq $8, %rsp\n    .cfi_def_cfa_offset 192\n\nLOCAL_LABEL(4X2_compute_olimit):\n    /* Computes how many iterations we can do safely\n     * %r15, %rax may be clobbered\n     * rdx must be saved\n     * op[1,2,3,4] & ip0 mustn't be clobbered\n     */\n    movq %rdx, 0(%rsp)\n\n    /* We can consume up to 7 input bytes each iteration. */\n    movq %ip0,     %rax  /* rax = ip0 */\n    movq 40(%rsp), %rdx  /* rdx = ilowest */\n    subq %rdx,     %rax  /* rax = ip0 - ilowest */\n    movq %rax,    %r15   /* r15 = ip0 - ilowest */\n\n    /* rdx = rax / 7 */\n    movabsq $2635249153387078803, %rdx\n    mulq %rdx\n    subq %rdx, %r15\n    shrq %r15\n    addq %r15, %rdx\n    shrq $2, %rdx\n\n    /* r15 = (ip0 - ilowest) / 7 */\n    movq %rdx, %r15\n\n    /* r15 = min(r15, min(oend0 - op0, oend1 - op1, oend2 - op2, oend3 - op3) / 10) */\n    movq 8(%rsp),  %rax /* rax = oend0 */\n    subq %op0,     %rax /* rax = oend0 - op0 */\n    movq 16(%rsp), %rdx /* rdx = oend1 */\n    subq %op1,     %rdx /* rdx = oend1 - op1 */\n\n    cmpq  %rax,    %rdx\n    cmova %rax,    %rdx /* rdx = min(%rdx, %rax) */\n\n    movq 24(%rsp), %rax /* rax = oend2 */\n    subq %op2,     %rax /* rax = oend2 - op2 */\n\n    cmpq  %rax,    %rdx\n    cmova %rax,    %rdx /* rdx = min(%rdx, %rax) */\n\n    movq 32(%rsp), %rax /* rax = oend3 */\n    subq %op3,     %rax /* rax = oend3 - op3 */\n\n    cmpq  %rax,    %rdx\n    cmova %rax,    %rdx /* rdx = min(%rdx, %rax) */\n\n    movabsq $-3689348814741910323, %rax\n    mulq %rdx\n    shrq $3,       %rdx /* rdx = rdx / 10 */\n\n    /* r15 = min(%rdx, %r15) */\n    cmpq  %rdx, %r15\n    cmova %rdx, %r15\n\n    /* olimit = op3 + 5 * r15 */\n    movq %r15, %rax\n    leaq (%op3, %rax, 4), %olimit\n    addq %rax, %olimit\n\n    movq 0(%rsp), %rdx\n\n    /* If (op3 + 10 > olimit) */\n    movq %op3, %rax    /* rax = op3 */\n    cmpq %rax, %olimit /* op3 == olimit */\n    je LOCAL_LABEL(4X2_exit)\n\n    /* If (ip1 < ip0) go to exit */\n    cmpq %ip0, %ip1\n    jb LOCAL_LABEL(4X2_exit)\n\n    /* If (ip2 < ip1) go to exit */\n    cmpq %ip1, %ip2\n    jb LOCAL_LABEL(4X2_exit)\n\n    /* If (ip3 < ip2) go to exit */\n    cmpq %ip2, %ip3\n    jb LOCAL_LABEL(4X2_exit)\n\n#define DECODE(n, idx)              \\\n    movq %bits##n, %rax;            \\\n    shrq $53, %rax;                 \\\n    movzwl 0(%dtable,%rax,4),%r8d;  \\\n    movzbl 2(%dtable,%rax,4),%r15d; \\\n    movzbl 3(%dtable,%rax,4),%eax;  \\\n    movw %r8w, (%op##n);            \\\n    shlxq %r15, %bits##n, %bits##n; \\\n    addq %rax, %op##n\n\n#define RELOAD_BITS(n)              \\\n    bsfq %bits##n, %bits##n;        \\\n    movq %bits##n, %rax;            \\\n    shrq $3, %bits##n;              \\\n    andq $7, %rax;                  \\\n    subq %bits##n, %ip##n;          \\\n    movq (%ip##n), %bits##n;        \\\n    orq $1, %bits##n;               \\\n    shlxq %rax, %bits##n, %bits##n\n\n\n    movq %olimit, 48(%rsp)\n\n    .p2align 6\n\nLOCAL_LABEL(4X2_loop_body):\n    /* We clobber r8, so store it on the stack */\n    movq %r8, 0(%rsp)\n\n    /* Decode 5 symbols from each of the 4 streams (20 symbols total). */\n    FOR_EACH_STREAM_WITH_INDEX(DECODE, 0)\n    FOR_EACH_STREAM_WITH_INDEX(DECODE, 1)\n    FOR_EACH_STREAM_WITH_INDEX(DECODE, 2)\n    FOR_EACH_STREAM_WITH_INDEX(DECODE, 3)\n    FOR_EACH_STREAM_WITH_INDEX(DECODE, 4)\n\n    /* Reload r8 */\n    movq 0(%rsp), %r8\n\n    FOR_EACH_STREAM(RELOAD_BITS)\n\n    cmp %op3, 48(%rsp)\n    ja LOCAL_LABEL(4X2_loop_body)\n    jmp LOCAL_LABEL(4X2_compute_olimit)\n\n#undef DECODE\n#undef RELOAD_BITS\nLOCAL_LABEL(4X2_exit):\n    addq $8, %rsp\n    .cfi_def_cfa_offset 184\n    /* Restore stack (oend & olimit) */\n    pop %rax /* oend0 */\n    .cfi_def_cfa_offset 176\n    pop %rax /* oend1 */\n    .cfi_def_cfa_offset 168\n    pop %rax /* oend2 */\n    .cfi_def_cfa_offset 160\n    pop %rax /* oend3 */\n    .cfi_def_cfa_offset 152\n    pop %rax /* ilowest */\n    .cfi_def_cfa_offset 144\n    pop %rax /* olimit */\n    .cfi_def_cfa_offset 136\n    pop %rax /* arg */\n    .cfi_def_cfa_offset 128\n\n    /* Save ip / op / bits */\n    movq %ip0,  0(%rax)\n    movq %ip1,  8(%rax)\n    movq %ip2, 16(%rax)\n    movq %ip3, 24(%rax)\n    movq %op0, 32(%rax)\n    movq %op1, 40(%rax)\n    movq %op2, 48(%rax)\n    movq %op3, 56(%rax)\n    movq %bits0, 64(%rax)\n    movq %bits1, 72(%rax)\n    movq %bits2, 80(%rax)\n    movq %bits3, 88(%rax)\n\n    /* Restore registers */\n    pop %r15\n    .cfi_restore r15\n    .cfi_def_cfa_offset 120\n    pop %r14\n    .cfi_restore r14\n    .cfi_def_cfa_offset 112\n    pop %r13\n    .cfi_restore r13\n    .cfi_def_cfa_offset 104\n    pop %r12\n    .cfi_restore r12\n    .cfi_def_cfa_offset 96\n    pop %r11\n    .cfi_restore r11\n    .cfi_def_cfa_offset 88\n    pop %r10\n    .cfi_restore r10\n    .cfi_def_cfa_offset 80\n    pop %r9\n    .cfi_restore r9\n    .cfi_def_cfa_offset 72\n    pop %r8\n    .cfi_restore r8\n    .cfi_def_cfa_offset 64\n    pop %rdi\n    .cfi_restore rdi\n    .cfi_def_cfa_offset 56\n    pop %rsi\n    .cfi_restore rsi\n    .cfi_def_cfa_offset 48\n    pop %rbp\n    .cfi_restore rbp\n    .cfi_def_cfa_offset 40\n    pop %rdx\n    .cfi_restore rdx\n    .cfi_def_cfa_offset 32\n    pop %rcx\n    .cfi_restore rcx\n    .cfi_def_cfa_offset 24\n    pop %rbx\n    .cfi_restore rbx\n    .cfi_def_cfa_offset 16\n    pop %rax\n    .cfi_restore rax\n    .cfi_def_cfa_offset 8\n    ret\n    .cfi_endproc\n\n#endif\n"
  },
  {
    "path": "lib/decompress/zstd_ddict.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* zstd_ddict.c :\n * concentrates all logic that needs to know the internals of ZSTD_DDict object */\n\n/*-*******************************************************\n*  Dependencies\n*********************************************************/\n#include \"../common/allocations.h\"  /* ZSTD_customMalloc, ZSTD_customFree */\n#include \"../common/zstd_deps.h\"   /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */\n#include \"../common/cpu.h\"         /* bmi2 */\n#include \"../common/mem.h\"         /* low level memory routines */\n#define FSE_STATIC_LINKING_ONLY\n#include \"../common/fse.h\"\n#include \"../common/huf.h\"\n#include \"zstd_decompress_internal.h\"\n#include \"zstd_ddict.h\"\n\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)\n#  include \"../legacy/zstd_legacy.h\"\n#endif\n\n\n\n/*-*******************************************************\n*  Types\n*********************************************************/\nstruct ZSTD_DDict_s {\n    void* dictBuffer;\n    const void* dictContent;\n    size_t dictSize;\n    ZSTD_entropyDTables_t entropy;\n    U32 dictID;\n    U32 entropyPresent;\n    ZSTD_customMem cMem;\n};  /* typedef'd to ZSTD_DDict within \"zstd.h\" */\n\nconst void* ZSTD_DDict_dictContent(const ZSTD_DDict* ddict)\n{\n    assert(ddict != NULL);\n    return ddict->dictContent;\n}\n\nsize_t ZSTD_DDict_dictSize(const ZSTD_DDict* ddict)\n{\n    assert(ddict != NULL);\n    return ddict->dictSize;\n}\n\nvoid ZSTD_copyDDictParameters(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)\n{\n    DEBUGLOG(4, \"ZSTD_copyDDictParameters\");\n    assert(dctx != NULL);\n    assert(ddict != NULL);\n    dctx->dictID = ddict->dictID;\n    dctx->prefixStart = ddict->dictContent;\n    dctx->virtualStart = ddict->dictContent;\n    dctx->dictEnd = (const BYTE*)ddict->dictContent + ddict->dictSize;\n    dctx->previousDstEnd = dctx->dictEnd;\n#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION\n    dctx->dictContentBeginForFuzzing = dctx->prefixStart;\n    dctx->dictContentEndForFuzzing = dctx->previousDstEnd;\n#endif\n    if (ddict->entropyPresent) {\n        dctx->litEntropy = 1;\n        dctx->fseEntropy = 1;\n        dctx->LLTptr = ddict->entropy.LLTable;\n        dctx->MLTptr = ddict->entropy.MLTable;\n        dctx->OFTptr = ddict->entropy.OFTable;\n        dctx->HUFptr = ddict->entropy.hufTable;\n        dctx->entropy.rep[0] = ddict->entropy.rep[0];\n        dctx->entropy.rep[1] = ddict->entropy.rep[1];\n        dctx->entropy.rep[2] = ddict->entropy.rep[2];\n    } else {\n        dctx->litEntropy = 0;\n        dctx->fseEntropy = 0;\n    }\n}\n\n\nstatic size_t\nZSTD_loadEntropy_intoDDict(ZSTD_DDict* ddict,\n                           ZSTD_dictContentType_e dictContentType)\n{\n    ddict->dictID = 0;\n    ddict->entropyPresent = 0;\n    if (dictContentType == ZSTD_dct_rawContent) return 0;\n\n    if (ddict->dictSize < 8) {\n        if (dictContentType == ZSTD_dct_fullDict)\n            return ERROR(dictionary_corrupted);   /* only accept specified dictionaries */\n        return 0;   /* pure content mode */\n    }\n    {   U32 const magic = MEM_readLE32(ddict->dictContent);\n        if (magic != ZSTD_MAGIC_DICTIONARY) {\n            if (dictContentType == ZSTD_dct_fullDict)\n                return ERROR(dictionary_corrupted);   /* only accept specified dictionaries */\n            return 0;   /* pure content mode */\n        }\n    }\n    ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + ZSTD_FRAMEIDSIZE);\n\n    /* load entropy tables */\n    RETURN_ERROR_IF(ZSTD_isError(ZSTD_loadDEntropy(\n            &ddict->entropy, ddict->dictContent, ddict->dictSize)),\n        dictionary_corrupted, \"\");\n    ddict->entropyPresent = 1;\n    return 0;\n}\n\n\nstatic size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict,\n                                      const void* dict, size_t dictSize,\n                                      ZSTD_dictLoadMethod_e dictLoadMethod,\n                                      ZSTD_dictContentType_e dictContentType)\n{\n    if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dict) || (!dictSize)) {\n        ddict->dictBuffer = NULL;\n        ddict->dictContent = dict;\n        if (!dict) dictSize = 0;\n    } else {\n        void* const internalBuffer = ZSTD_customMalloc(dictSize, ddict->cMem);\n        ddict->dictBuffer = internalBuffer;\n        ddict->dictContent = internalBuffer;\n        if (!internalBuffer) return ERROR(memory_allocation);\n        ZSTD_memcpy(internalBuffer, dict, dictSize);\n    }\n    ddict->dictSize = dictSize;\n    ddict->entropy.hufTable[0] = (HUF_DTable)((ZSTD_HUFFDTABLE_CAPACITY_LOG)*0x1000001);  /* cover both little and big endian */\n\n    /* parse dictionary content */\n    FORWARD_IF_ERROR( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) , \"\");\n\n    return 0;\n}\n\nZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize,\n                                      ZSTD_dictLoadMethod_e dictLoadMethod,\n                                      ZSTD_dictContentType_e dictContentType,\n                                      ZSTD_customMem customMem)\n{\n    if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;\n\n    {   ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_customMalloc(sizeof(ZSTD_DDict), customMem);\n        if (ddict == NULL) return NULL;\n        ddict->cMem = customMem;\n        {   size_t const initResult = ZSTD_initDDict_internal(ddict,\n                                            dict, dictSize,\n                                            dictLoadMethod, dictContentType);\n            if (ZSTD_isError(initResult)) {\n                ZSTD_freeDDict(ddict);\n                return NULL;\n        }   }\n        return ddict;\n    }\n}\n\n/*! ZSTD_createDDict() :\n*   Create a digested dictionary, to start decompression without startup delay.\n*   `dict` content is copied inside DDict.\n*   Consequently, `dict` can be released after `ZSTD_DDict` creation */\nZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)\n{\n    ZSTD_customMem const allocator = { NULL, NULL, NULL };\n    return ZSTD_createDDict_advanced(dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto, allocator);\n}\n\n/*! ZSTD_createDDict_byReference() :\n *  Create a digested dictionary, to start decompression without startup delay.\n *  Dictionary content is simply referenced, it will be accessed during decompression.\n *  Warning : dictBuffer must outlive DDict (DDict must be freed before dictBuffer) */\nZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize)\n{\n    ZSTD_customMem const allocator = { NULL, NULL, NULL };\n    return ZSTD_createDDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, allocator);\n}\n\n\nconst ZSTD_DDict* ZSTD_initStaticDDict(\n                                void* sBuffer, size_t sBufferSize,\n                                const void* dict, size_t dictSize,\n                                ZSTD_dictLoadMethod_e dictLoadMethod,\n                                ZSTD_dictContentType_e dictContentType)\n{\n    size_t const neededSpace = sizeof(ZSTD_DDict)\n                             + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);\n    ZSTD_DDict* const ddict = (ZSTD_DDict*)sBuffer;\n    assert(sBuffer != NULL);\n    assert(dict != NULL);\n    if ((size_t)sBuffer & 7) return NULL;   /* 8-aligned */\n    if (sBufferSize < neededSpace) return NULL;\n    if (dictLoadMethod == ZSTD_dlm_byCopy) {\n        ZSTD_memcpy(ddict+1, dict, dictSize);  /* local copy */\n        dict = ddict+1;\n    }\n    if (ZSTD_isError( ZSTD_initDDict_internal(ddict,\n                                              dict, dictSize,\n                                              ZSTD_dlm_byRef, dictContentType) ))\n        return NULL;\n    return ddict;\n}\n\n\nsize_t ZSTD_freeDDict(ZSTD_DDict* ddict)\n{\n    if (ddict==NULL) return 0;   /* support free on NULL */\n    {   ZSTD_customMem const cMem = ddict->cMem;\n        ZSTD_customFree(ddict->dictBuffer, cMem);\n        ZSTD_customFree(ddict, cMem);\n        return 0;\n    }\n}\n\n/*! ZSTD_estimateDDictSize() :\n *  Estimate amount of memory that will be needed to create a dictionary for decompression.\n *  Note : dictionary created by reference using ZSTD_dlm_byRef are smaller */\nsize_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod)\n{\n    return sizeof(ZSTD_DDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);\n}\n\nsize_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict)\n{\n    if (ddict==NULL) return 0;   /* support sizeof on NULL */\n    return sizeof(*ddict) + (ddict->dictBuffer ? ddict->dictSize : 0) ;\n}\n\n/*! ZSTD_getDictID_fromDDict() :\n *  Provides the dictID of the dictionary loaded into `ddict`.\n *  If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.\n *  Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */\nunsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict)\n{\n    if (ddict==NULL) return 0;\n    return ddict->dictID;\n}\n"
  },
  {
    "path": "lib/decompress/zstd_ddict.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n#ifndef ZSTD_DDICT_H\n#define ZSTD_DDICT_H\n\n/*-*******************************************************\n *  Dependencies\n *********************************************************/\n#include \"../common/zstd_deps.h\"   /* size_t */\n#include \"../zstd.h\"     /* ZSTD_DDict, and several public functions */\n\n\n/*-*******************************************************\n *  Interface\n *********************************************************/\n\n/* note: several prototypes are already published in `zstd.h` :\n * ZSTD_createDDict()\n * ZSTD_createDDict_byReference()\n * ZSTD_createDDict_advanced()\n * ZSTD_freeDDict()\n * ZSTD_initStaticDDict()\n * ZSTD_sizeof_DDict()\n * ZSTD_estimateDDictSize()\n * ZSTD_getDictID_fromDict()\n */\n\nconst void* ZSTD_DDict_dictContent(const ZSTD_DDict* ddict);\nsize_t ZSTD_DDict_dictSize(const ZSTD_DDict* ddict);\n\nvoid ZSTD_copyDDictParameters(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);\n\n\n\n#endif /* ZSTD_DDICT_H */\n"
  },
  {
    "path": "lib/decompress/zstd_decompress.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/* ***************************************************************\n*  Tuning parameters\n*****************************************************************/\n/*!\n * HEAPMODE :\n * Select how default decompression function ZSTD_decompress() allocates its context,\n * on stack (0), or into heap (1, default; requires malloc()).\n * Note that functions with explicit context such as ZSTD_decompressDCtx() are unaffected.\n */\n#ifndef ZSTD_HEAPMODE\n#  define ZSTD_HEAPMODE 1\n#endif\n\n/*!\n*  LEGACY_SUPPORT :\n*  if set to 1+, ZSTD_decompress() can decode older formats (v0.1+)\n*/\n#ifndef ZSTD_LEGACY_SUPPORT\n#  define ZSTD_LEGACY_SUPPORT 0\n#endif\n\n/*!\n *  MAXWINDOWSIZE_DEFAULT :\n *  maximum window size accepted by DStream __by default__.\n *  Frames requiring more memory will be rejected.\n *  It's possible to set a different limit using ZSTD_DCtx_setMaxWindowSize().\n */\n#ifndef ZSTD_MAXWINDOWSIZE_DEFAULT\n#  define ZSTD_MAXWINDOWSIZE_DEFAULT (((U32)1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT) + 1)\n#endif\n\n/*!\n *  NO_FORWARD_PROGRESS_MAX :\n *  maximum allowed nb of calls to ZSTD_decompressStream()\n *  without any forward progress\n *  (defined as: no byte read from input, and no byte flushed to output)\n *  before triggering an error.\n */\n#ifndef ZSTD_NO_FORWARD_PROGRESS_MAX\n#  define ZSTD_NO_FORWARD_PROGRESS_MAX 16\n#endif\n\n\n/*-*******************************************************\n*  Dependencies\n*********************************************************/\n#include \"../common/zstd_deps.h\"   /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */\n#include \"../common/allocations.h\"  /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */\n#include \"../common/error_private.h\"\n#include \"../common/zstd_internal.h\"  /* blockProperties_t */\n#include \"../common/mem.h\"         /* low level memory routines */\n#include \"../common/bits.h\"  /* ZSTD_highbit32 */\n#define FSE_STATIC_LINKING_ONLY\n#include \"../common/fse.h\"\n#include \"../common/huf.h\"\n#include \"../common/xxhash.h\" /* XXH64_reset, XXH64_update, XXH64_digest, XXH64 */\n#include \"zstd_decompress_internal.h\"   /* ZSTD_DCtx */\n#include \"zstd_ddict.h\"  /* ZSTD_DDictDictContent */\n#include \"zstd_decompress_block.h\"   /* ZSTD_decompressBlock_internal */\n\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)\n#  include \"../legacy/zstd_legacy.h\"\n#endif\n\n\n\n/*************************************\n * Multiple DDicts Hashset internals *\n *************************************/\n\n#define DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT 4\n#define DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT 3  /* These two constants represent SIZE_MULT/COUNT_MULT load factor without using a float.\n                                                    * Currently, that means a 0.75 load factor.\n                                                    * So, if count * COUNT_MULT / size * SIZE_MULT != 0, then we've exceeded\n                                                    * the load factor of the ddict hash set.\n                                                    */\n\n#define DDICT_HASHSET_TABLE_BASE_SIZE 64\n#define DDICT_HASHSET_RESIZE_FACTOR 2\n\n/* Hash function to determine starting position of dict insertion within the table\n * Returns an index between [0, hashSet->ddictPtrTableSize]\n */\nstatic size_t ZSTD_DDictHashSet_getIndex(const ZSTD_DDictHashSet* hashSet, U32 dictID) {\n    const U64 hash = XXH64(&dictID, sizeof(U32), 0);\n    /* DDict ptr table size is a multiple of 2, use size - 1 as mask to get index within [0, hashSet->ddictPtrTableSize) */\n    return hash & (hashSet->ddictPtrTableSize - 1);\n}\n\n/* Adds DDict to a hashset without resizing it.\n * If inserting a DDict with a dictID that already exists in the set, replaces the one in the set.\n * Returns 0 if successful, or a zstd error code if something went wrong.\n */\nstatic size_t ZSTD_DDictHashSet_emplaceDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict) {\n    const U32 dictID = ZSTD_getDictID_fromDDict(ddict);\n    size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);\n    const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;\n    RETURN_ERROR_IF(hashSet->ddictPtrCount == hashSet->ddictPtrTableSize, GENERIC, \"Hash set is full!\");\n    DEBUGLOG(4, \"Hashed index: for dictID: %u is %zu\", dictID, idx);\n    while (hashSet->ddictPtrTable[idx] != NULL) {\n        /* Replace existing ddict if inserting ddict with same dictID */\n        if (ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]) == dictID) {\n            DEBUGLOG(4, \"DictID already exists, replacing rather than adding\");\n            hashSet->ddictPtrTable[idx] = ddict;\n            return 0;\n        }\n        idx &= idxRangeMask;\n        idx++;\n    }\n    DEBUGLOG(4, \"Final idx after probing for dictID %u is: %zu\", dictID, idx);\n    hashSet->ddictPtrTable[idx] = ddict;\n    hashSet->ddictPtrCount++;\n    return 0;\n}\n\n/* Expands hash table by factor of DDICT_HASHSET_RESIZE_FACTOR and\n * rehashes all values, allocates new table, frees old table.\n * Returns 0 on success, otherwise a zstd error code.\n */\nstatic size_t ZSTD_DDictHashSet_expand(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {\n    size_t newTableSize = hashSet->ddictPtrTableSize * DDICT_HASHSET_RESIZE_FACTOR;\n    const ZSTD_DDict** newTable = (const ZSTD_DDict**)ZSTD_customCalloc(sizeof(ZSTD_DDict*) * newTableSize, customMem);\n    const ZSTD_DDict** oldTable = hashSet->ddictPtrTable;\n    size_t oldTableSize = hashSet->ddictPtrTableSize;\n    size_t i;\n\n    DEBUGLOG(4, \"Expanding DDict hash table! Old size: %zu new size: %zu\", oldTableSize, newTableSize);\n    RETURN_ERROR_IF(!newTable, memory_allocation, \"Expanded hashset allocation failed!\");\n    hashSet->ddictPtrTable = newTable;\n    hashSet->ddictPtrTableSize = newTableSize;\n    hashSet->ddictPtrCount = 0;\n    for (i = 0; i < oldTableSize; ++i) {\n        if (oldTable[i] != NULL) {\n            FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, oldTable[i]), \"\");\n        }\n    }\n    ZSTD_customFree((void*)oldTable, customMem);\n    DEBUGLOG(4, \"Finished re-hash\");\n    return 0;\n}\n\n/* Fetches a DDict with the given dictID\n * Returns the ZSTD_DDict* with the requested dictID. If it doesn't exist, then returns NULL.\n */\nstatic const ZSTD_DDict* ZSTD_DDictHashSet_getDDict(ZSTD_DDictHashSet* hashSet, U32 dictID) {\n    size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);\n    const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;\n    DEBUGLOG(4, \"Hashed index: for dictID: %u is %zu\", dictID, idx);\n    for (;;) {\n        size_t currDictID = ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]);\n        if (currDictID == dictID || currDictID == 0) {\n            /* currDictID == 0 implies a NULL ddict entry */\n            break;\n        } else {\n            idx &= idxRangeMask;    /* Goes to start of table when we reach the end */\n            idx++;\n        }\n    }\n    DEBUGLOG(4, \"Final idx after probing for dictID %u is: %zu\", dictID, idx);\n    return hashSet->ddictPtrTable[idx];\n}\n\n/* Allocates space for and returns a ddict hash set\n * The hash set's ZSTD_DDict* table has all values automatically set to NULL to begin with.\n * Returns NULL if allocation failed.\n */\nstatic ZSTD_DDictHashSet* ZSTD_createDDictHashSet(ZSTD_customMem customMem) {\n    ZSTD_DDictHashSet* ret = (ZSTD_DDictHashSet*)ZSTD_customMalloc(sizeof(ZSTD_DDictHashSet), customMem);\n    DEBUGLOG(4, \"Allocating new hash set\");\n    if (!ret)\n        return NULL;\n    ret->ddictPtrTable = (const ZSTD_DDict**)ZSTD_customCalloc(DDICT_HASHSET_TABLE_BASE_SIZE * sizeof(ZSTD_DDict*), customMem);\n    if (!ret->ddictPtrTable) {\n        ZSTD_customFree(ret, customMem);\n        return NULL;\n    }\n    ret->ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE;\n    ret->ddictPtrCount = 0;\n    return ret;\n}\n\n/* Frees the table of ZSTD_DDict* within a hashset, then frees the hashset itself.\n * Note: The ZSTD_DDict* within the table are NOT freed.\n */\nstatic void ZSTD_freeDDictHashSet(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {\n    DEBUGLOG(4, \"Freeing ddict hash set\");\n    if (hashSet && hashSet->ddictPtrTable) {\n        ZSTD_customFree((void*)hashSet->ddictPtrTable, customMem);\n    }\n    if (hashSet) {\n        ZSTD_customFree(hashSet, customMem);\n    }\n}\n\n/* Public function: Adds a DDict into the ZSTD_DDictHashSet, possibly triggering a resize of the hash set.\n * Returns 0 on success, or a ZSTD error.\n */\nstatic size_t ZSTD_DDictHashSet_addDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict, ZSTD_customMem customMem) {\n    DEBUGLOG(4, \"Adding dict ID: %u to hashset with - Count: %zu Tablesize: %zu\", ZSTD_getDictID_fromDDict(ddict), hashSet->ddictPtrCount, hashSet->ddictPtrTableSize);\n    if (hashSet->ddictPtrCount * DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT / hashSet->ddictPtrTableSize * DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT != 0) {\n        FORWARD_IF_ERROR(ZSTD_DDictHashSet_expand(hashSet, customMem), \"\");\n    }\n    FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, ddict), \"\");\n    return 0;\n}\n\n/*-*************************************************************\n*   Context management\n***************************************************************/\nsize_t ZSTD_sizeof_DCtx (const ZSTD_DCtx* dctx)\n{\n    if (dctx==NULL) return 0;   /* support sizeof NULL */\n    return sizeof(*dctx)\n           + ZSTD_sizeof_DDict(dctx->ddictLocal)\n           + dctx->inBuffSize + dctx->outBuffSize;\n}\n\nsize_t ZSTD_estimateDCtxSize(void) { return sizeof(ZSTD_DCtx); }\n\n\nstatic size_t ZSTD_startingInputLength(ZSTD_format_e format)\n{\n    size_t const startingInputLength = ZSTD_FRAMEHEADERSIZE_PREFIX(format);\n    /* only supports formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless */\n    assert( (format == ZSTD_f_zstd1) || (format == ZSTD_f_zstd1_magicless) );\n    return startingInputLength;\n}\n\nstatic void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx)\n{\n    assert(dctx->streamStage == zdss_init);\n    dctx->format = ZSTD_f_zstd1;\n    dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;\n    dctx->outBufferMode = ZSTD_bm_buffered;\n    dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;\n    dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict;\n    dctx->disableHufAsm = 0;\n    dctx->maxBlockSizeParam = 0;\n}\n\nstatic void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)\n{\n    dctx->staticSize  = 0;\n    dctx->ddict       = NULL;\n    dctx->ddictLocal  = NULL;\n    dctx->dictEnd     = NULL;\n    dctx->ddictIsCold = 0;\n    dctx->dictUses = ZSTD_dont_use;\n    dctx->inBuff      = NULL;\n    dctx->inBuffSize  = 0;\n    dctx->outBuffSize = 0;\n    dctx->streamStage = zdss_init;\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)\n    dctx->legacyContext = NULL;\n    dctx->previousLegacyVersion = 0;\n#endif\n    dctx->noForwardProgress = 0;\n    dctx->oversizedDuration = 0;\n    dctx->isFrameDecompression = 1;\n#if DYNAMIC_BMI2\n    dctx->bmi2 = ZSTD_cpuSupportsBmi2();\n#endif\n    dctx->ddictSet = NULL;\n    ZSTD_DCtx_resetParameters(dctx);\n#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION\n    dctx->dictContentEndForFuzzing = NULL;\n#endif\n}\n\nZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)\n{\n    ZSTD_DCtx* const dctx = (ZSTD_DCtx*) workspace;\n\n    if ((size_t)workspace & 7) return NULL;  /* 8-aligned */\n    if (workspaceSize < sizeof(ZSTD_DCtx)) return NULL;  /* minimum size */\n\n    ZSTD_initDCtx_internal(dctx);\n    dctx->staticSize = workspaceSize;\n    dctx->inBuff = (char*)(dctx+1);\n    return dctx;\n}\n\nstatic ZSTD_DCtx* ZSTD_createDCtx_internal(ZSTD_customMem customMem) {\n    if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;\n\n    {   ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_customMalloc(sizeof(*dctx), customMem);\n        if (!dctx) return NULL;\n        dctx->customMem = customMem;\n        ZSTD_initDCtx_internal(dctx);\n        return dctx;\n    }\n}\n\nZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)\n{\n    return ZSTD_createDCtx_internal(customMem);\n}\n\nZSTD_DCtx* ZSTD_createDCtx(void)\n{\n    DEBUGLOG(3, \"ZSTD_createDCtx\");\n    return ZSTD_createDCtx_internal(ZSTD_defaultCMem);\n}\n\nstatic void ZSTD_clearDict(ZSTD_DCtx* dctx)\n{\n    ZSTD_freeDDict(dctx->ddictLocal);\n    dctx->ddictLocal = NULL;\n    dctx->ddict = NULL;\n    dctx->dictUses = ZSTD_dont_use;\n}\n\nsize_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)\n{\n    if (dctx==NULL) return 0;   /* support free on NULL */\n    RETURN_ERROR_IF(dctx->staticSize, memory_allocation, \"not compatible with static DCtx\");\n    {   ZSTD_customMem const cMem = dctx->customMem;\n        ZSTD_clearDict(dctx);\n        ZSTD_customFree(dctx->inBuff, cMem);\n        dctx->inBuff = NULL;\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)\n        if (dctx->legacyContext)\n            ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion);\n#endif\n        if (dctx->ddictSet) {\n            ZSTD_freeDDictHashSet(dctx->ddictSet, cMem);\n            dctx->ddictSet = NULL;\n        }\n        ZSTD_customFree(dctx, cMem);\n        return 0;\n    }\n}\n\n/* no longer useful */\nvoid ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)\n{\n    size_t const toCopy = (size_t)((char*)(&dstDCtx->inBuff) - (char*)dstDCtx);\n    ZSTD_memcpy(dstDCtx, srcDCtx, toCopy);  /* no need to copy workspace */\n}\n\n/* Given a dctx with a digested frame params, re-selects the correct ZSTD_DDict based on\n * the requested dict ID from the frame. If there exists a reference to the correct ZSTD_DDict, then\n * accordingly sets the ddict to be used to decompress the frame.\n *\n * If no DDict is found, then no action is taken, and the ZSTD_DCtx::ddict remains as-is.\n *\n * ZSTD_d_refMultipleDDicts must be enabled for this function to be called.\n */\nstatic void ZSTD_DCtx_selectFrameDDict(ZSTD_DCtx* dctx) {\n    assert(dctx->refMultipleDDicts && dctx->ddictSet);\n    DEBUGLOG(4, \"Adjusting DDict based on requested dict ID from frame\");\n    if (dctx->ddict) {\n        const ZSTD_DDict* frameDDict = ZSTD_DDictHashSet_getDDict(dctx->ddictSet, dctx->fParams.dictID);\n        if (frameDDict) {\n            DEBUGLOG(4, \"DDict found!\");\n            ZSTD_clearDict(dctx);\n            dctx->dictID = dctx->fParams.dictID;\n            dctx->ddict = frameDDict;\n            dctx->dictUses = ZSTD_use_indefinitely;\n        }\n    }\n}\n\n\n/*-*************************************************************\n *   Frame header decoding\n ***************************************************************/\n\n/*! ZSTD_isFrame() :\n *  Tells if the content of `buffer` starts with a valid Frame Identifier.\n *  Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.\n *  Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled.\n *  Note 3 : Skippable Frame Identifiers are considered valid. */\nunsigned ZSTD_isFrame(const void* buffer, size_t size)\n{\n    if (size < ZSTD_FRAMEIDSIZE) return 0;\n    {   U32 const magic = MEM_readLE32(buffer);\n        if (magic == ZSTD_MAGICNUMBER) return 1;\n        if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) return 1;\n    }\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)\n    if (ZSTD_isLegacy(buffer, size)) return 1;\n#endif\n    return 0;\n}\n\n/*! ZSTD_isSkippableFrame() :\n *  Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame.\n *  Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.\n */\nunsigned ZSTD_isSkippableFrame(const void* buffer, size_t size)\n{\n    if (size < ZSTD_FRAMEIDSIZE) return 0;\n    {   U32 const magic = MEM_readLE32(buffer);\n        if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) return 1;\n    }\n    return 0;\n}\n\n/** ZSTD_frameHeaderSize_internal() :\n *  srcSize must be large enough to reach header size fields.\n *  note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless.\n * @return : size of the Frame Header\n *           or an error code, which can be tested with ZSTD_isError() */\nstatic size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)\n{\n    size_t const minInputSize = ZSTD_startingInputLength(format);\n    RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong, \"\");\n\n    {   BYTE const fhd = ((const BYTE*)src)[minInputSize-1];\n        U32 const dictID= fhd & 3;\n        U32 const singleSegment = (fhd >> 5) & 1;\n        U32 const fcsId = fhd >> 6;\n        return minInputSize + !singleSegment\n             + ZSTD_did_fieldSize[dictID] + ZSTD_fcs_fieldSize[fcsId]\n             + (singleSegment && !fcsId);\n    }\n}\n\n/** ZSTD_frameHeaderSize() :\n *  srcSize must be >= ZSTD_frameHeaderSize_prefix.\n * @return : size of the Frame Header,\n *           or an error code (if srcSize is too small) */\nsize_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)\n{\n    return ZSTD_frameHeaderSize_internal(src, srcSize, ZSTD_f_zstd1);\n}\n\n\n/** ZSTD_getFrameHeader_advanced() :\n *  decode Frame Header, or require larger `srcSize`.\n *  note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless\n * @return : 0, `zfhPtr` is correctly filled,\n *          >0, `srcSize` is too small, value is wanted `srcSize` amount,\n**           or an error code, which can be tested using ZSTD_isError() */\nsize_t ZSTD_getFrameHeader_advanced(ZSTD_FrameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format)\n{\n    const BYTE* ip = (const BYTE*)src;\n    size_t const minInputSize = ZSTD_startingInputLength(format);\n\n    DEBUGLOG(5, \"ZSTD_getFrameHeader_advanced: minInputSize = %zu, srcSize = %zu\", minInputSize, srcSize);\n\n    if (srcSize > 0) {\n        /* note : technically could be considered an assert(), since it's an invalid entry */\n        RETURN_ERROR_IF(src==NULL, GENERIC, \"invalid parameter : src==NULL, but srcSize>0\");\n    }\n    if (srcSize < minInputSize) {\n        if (srcSize > 0 && format != ZSTD_f_zstd1_magicless) {\n            /* when receiving less than @minInputSize bytes,\n             * control these bytes at least correspond to a supported magic number\n             * in order to error out early if they don't.\n            **/\n            size_t const toCopy = MIN(4, srcSize);\n            unsigned char hbuf[4]; MEM_writeLE32(hbuf, ZSTD_MAGICNUMBER);\n            assert(src != NULL);\n            ZSTD_memcpy(hbuf, src, toCopy);\n            if ( MEM_readLE32(hbuf) != ZSTD_MAGICNUMBER ) {\n                /* not a zstd frame : let's check if it's a skippable frame */\n                MEM_writeLE32(hbuf, ZSTD_MAGIC_SKIPPABLE_START);\n                ZSTD_memcpy(hbuf, src, toCopy);\n                if ((MEM_readLE32(hbuf) & ZSTD_MAGIC_SKIPPABLE_MASK) != ZSTD_MAGIC_SKIPPABLE_START) {\n                    RETURN_ERROR(prefix_unknown,\n                                \"first bytes don't correspond to any supported magic number\");\n        }   }   }\n        return minInputSize;\n    }\n\n    ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr));   /* not strictly necessary, but static analyzers may not understand that zfhPtr will be read only if return value is zero, since they are 2 different signals */\n    if ( (format != ZSTD_f_zstd1_magicless)\n      && (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {\n        if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {\n            /* skippable frame */\n            if (srcSize < ZSTD_SKIPPABLEHEADERSIZE)\n                return ZSTD_SKIPPABLEHEADERSIZE; /* magic number + frame length */\n            ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr));\n            zfhPtr->frameType = ZSTD_skippableFrame;\n            zfhPtr->dictID = MEM_readLE32(src) - ZSTD_MAGIC_SKIPPABLE_START;\n            zfhPtr->headerSize = ZSTD_SKIPPABLEHEADERSIZE;\n            zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE);\n            return 0;\n        }\n        RETURN_ERROR(prefix_unknown, \"\");\n    }\n\n    /* ensure there is enough `srcSize` to fully read/decode frame header */\n    {   size_t const fhsize = ZSTD_frameHeaderSize_internal(src, srcSize, format);\n        if (srcSize < fhsize) return fhsize;\n        zfhPtr->headerSize = (U32)fhsize;\n    }\n\n    {   BYTE const fhdByte = ip[minInputSize-1];\n        size_t pos = minInputSize;\n        U32 const dictIDSizeCode = fhdByte&3;\n        U32 const checksumFlag = (fhdByte>>2)&1;\n        U32 const singleSegment = (fhdByte>>5)&1;\n        U32 const fcsID = fhdByte>>6;\n        U64 windowSize = 0;\n        U32 dictID = 0;\n        U64 frameContentSize = ZSTD_CONTENTSIZE_UNKNOWN;\n        RETURN_ERROR_IF((fhdByte & 0x08) != 0, frameParameter_unsupported,\n                        \"reserved bits, must be zero\");\n\n        if (!singleSegment) {\n            BYTE const wlByte = ip[pos++];\n            U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;\n            RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge, \"\");\n            windowSize = (1ULL << windowLog);\n            windowSize += (windowSize >> 3) * (wlByte&7);\n        }\n        switch(dictIDSizeCode)\n        {\n            default:\n                assert(0);  /* impossible */\n                ZSTD_FALLTHROUGH;\n            case 0 : break;\n            case 1 : dictID = ip[pos]; pos++; break;\n            case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break;\n            case 3 : dictID = MEM_readLE32(ip+pos); pos+=4; break;\n        }\n        switch(fcsID)\n        {\n            default:\n                assert(0);  /* impossible */\n                ZSTD_FALLTHROUGH;\n            case 0 : if (singleSegment) frameContentSize = ip[pos]; break;\n            case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break;\n            case 2 : frameContentSize = MEM_readLE32(ip+pos); break;\n            case 3 : frameContentSize = MEM_readLE64(ip+pos); break;\n        }\n        if (singleSegment) windowSize = frameContentSize;\n\n        zfhPtr->frameType = ZSTD_frame;\n        zfhPtr->frameContentSize = frameContentSize;\n        zfhPtr->windowSize = windowSize;\n        zfhPtr->blockSizeMax = (unsigned) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);\n        zfhPtr->dictID = dictID;\n        zfhPtr->checksumFlag = checksumFlag;\n    }\n    return 0;\n}\n\n/** ZSTD_getFrameHeader() :\n *  decode Frame Header, or require larger `srcSize`.\n *  note : this function does not consume input, it only reads it.\n * @return : 0, `zfhPtr` is correctly filled,\n *          >0, `srcSize` is too small, value is wanted `srcSize` amount,\n *           or an error code, which can be tested using ZSTD_isError() */\nsize_t ZSTD_getFrameHeader(ZSTD_FrameHeader* zfhPtr, const void* src, size_t srcSize)\n{\n    return ZSTD_getFrameHeader_advanced(zfhPtr, src, srcSize, ZSTD_f_zstd1);\n}\n\n/** ZSTD_getFrameContentSize() :\n *  compatible with legacy mode\n * @return : decompressed size of the single frame pointed to be `src` if known, otherwise\n *         - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined\n *         - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) */\nunsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize)\n{\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)\n    if (ZSTD_isLegacy(src, srcSize)) {\n        unsigned long long const ret = ZSTD_getDecompressedSize_legacy(src, srcSize);\n        return ret == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : ret;\n    }\n#endif\n    {   ZSTD_FrameHeader zfh;\n        if (ZSTD_getFrameHeader(&zfh, src, srcSize) != 0)\n            return ZSTD_CONTENTSIZE_ERROR;\n        if (zfh.frameType == ZSTD_skippableFrame) {\n            return 0;\n        } else {\n            return zfh.frameContentSize;\n    }   }\n}\n\nstatic size_t readSkippableFrameSize(void const* src, size_t srcSize)\n{\n    size_t const skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE;\n    U32 sizeU32;\n\n    RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, \"\");\n\n    sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);\n    RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,\n                    frameParameter_unsupported, \"\");\n    {   size_t const skippableSize = skippableHeaderSize + sizeU32;\n        RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, \"\");\n        return skippableSize;\n    }\n}\n\n/*! ZSTD_readSkippableFrame() :\n * Retrieves content of a skippable frame, and writes it to dst buffer.\n *\n * The parameter magicVariant will receive the magicVariant that was supplied when the frame was written,\n * i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START.  This can be NULL if the caller is not interested\n * in the magicVariant.\n *\n * Returns an error if destination buffer is not large enough, or if this is not a valid skippable frame.\n *\n * @return : number of bytes written or a ZSTD error.\n */\nsize_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity,\n                               unsigned* magicVariant,  /* optional, can be NULL */\n                         const void* src, size_t srcSize)\n{\n    RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, \"\");\n\n    {   U32 const magicNumber = MEM_readLE32(src);\n        size_t skippableFrameSize = readSkippableFrameSize(src, srcSize);\n        size_t skippableContentSize = skippableFrameSize - ZSTD_SKIPPABLEHEADERSIZE;\n\n        /* check input validity */\n        RETURN_ERROR_IF(!ZSTD_isSkippableFrame(src, srcSize), frameParameter_unsupported, \"\");\n        RETURN_ERROR_IF(skippableFrameSize < ZSTD_SKIPPABLEHEADERSIZE || skippableFrameSize > srcSize, srcSize_wrong, \"\");\n        RETURN_ERROR_IF(skippableContentSize > dstCapacity, dstSize_tooSmall, \"\");\n\n        /* deliver payload */\n        if (skippableContentSize > 0  && dst != NULL)\n            ZSTD_memcpy(dst, (const BYTE *)src + ZSTD_SKIPPABLEHEADERSIZE, skippableContentSize);\n        if (magicVariant != NULL)\n            *magicVariant = magicNumber - ZSTD_MAGIC_SKIPPABLE_START;\n        return skippableContentSize;\n    }\n}\n\n/** ZSTD_findDecompressedSize() :\n *  `srcSize` must be the exact length of some number of ZSTD compressed and/or\n *      skippable frames\n *  note: compatible with legacy mode\n * @return : decompressed size of the frames contained */\nunsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)\n{\n    unsigned long long totalDstSize = 0;\n\n    while (srcSize >= ZSTD_startingInputLength(ZSTD_f_zstd1)) {\n        U32 const magicNumber = MEM_readLE32(src);\n\n        if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {\n            size_t const skippableSize = readSkippableFrameSize(src, srcSize);\n            if (ZSTD_isError(skippableSize)) return ZSTD_CONTENTSIZE_ERROR;\n            assert(skippableSize <= srcSize);\n\n            src = (const BYTE *)src + skippableSize;\n            srcSize -= skippableSize;\n            continue;\n        }\n\n        {   unsigned long long const fcs = ZSTD_getFrameContentSize(src, srcSize);\n            if (fcs >= ZSTD_CONTENTSIZE_ERROR) return fcs;\n\n            if (totalDstSize + fcs < totalDstSize)\n                return ZSTD_CONTENTSIZE_ERROR; /* check for overflow */\n            totalDstSize += fcs;\n        }\n        /* skip to next frame */\n        {   size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);\n            if (ZSTD_isError(frameSrcSize)) return ZSTD_CONTENTSIZE_ERROR;\n            assert(frameSrcSize <= srcSize);\n\n            src = (const BYTE *)src + frameSrcSize;\n            srcSize -= frameSrcSize;\n        }\n    }  /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */\n\n    if (srcSize) return ZSTD_CONTENTSIZE_ERROR;\n\n    return totalDstSize;\n}\n\n/** ZSTD_getDecompressedSize() :\n *  compatible with legacy mode\n * @return : decompressed size if known, 0 otherwise\n             note : 0 can mean any of the following :\n                   - frame content is empty\n                   - decompressed size field is not present in frame header\n                   - frame header unknown / not supported\n                   - frame header not complete (`srcSize` too small) */\nunsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)\n{\n    unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);\n    ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_ERROR < ZSTD_CONTENTSIZE_UNKNOWN);\n    return (ret >= ZSTD_CONTENTSIZE_ERROR) ? 0 : ret;\n}\n\n\n/** ZSTD_decodeFrameHeader() :\n * `headerSize` must be the size provided by ZSTD_frameHeaderSize().\n * If multiple DDict references are enabled, also will choose the correct DDict to use.\n * @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */\nstatic size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)\n{\n    size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);\n    if (ZSTD_isError(result)) return result;    /* invalid header */\n    RETURN_ERROR_IF(result>0, srcSize_wrong, \"headerSize too small\");\n\n    /* Reference DDict requested by frame if dctx references multiple ddicts */\n    if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts && dctx->ddictSet) {\n        ZSTD_DCtx_selectFrameDDict(dctx);\n    }\n\n#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION\n    /* Skip the dictID check in fuzzing mode, because it makes the search\n     * harder.\n     */\n    RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),\n                    dictionary_wrong, \"\");\n#endif\n    dctx->validateChecksum = (dctx->fParams.checksumFlag && !dctx->forceIgnoreChecksum) ? 1 : 0;\n    if (dctx->validateChecksum) XXH64_reset(&dctx->xxhState, 0);\n    dctx->processedCSize += headerSize;\n    return 0;\n}\n\nstatic ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)\n{\n    ZSTD_frameSizeInfo frameSizeInfo;\n    frameSizeInfo.compressedSize = ret;\n    frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;\n    return frameSizeInfo;\n}\n\nstatic ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize, ZSTD_format_e format)\n{\n    ZSTD_frameSizeInfo frameSizeInfo;\n    ZSTD_memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));\n\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)\n    if (format == ZSTD_f_zstd1 && ZSTD_isLegacy(src, srcSize))\n        return ZSTD_findFrameSizeInfoLegacy(src, srcSize);\n#endif\n\n    if (format == ZSTD_f_zstd1 && (srcSize >= ZSTD_SKIPPABLEHEADERSIZE)\n        && (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {\n        frameSizeInfo.compressedSize = readSkippableFrameSize(src, srcSize);\n        assert(ZSTD_isError(frameSizeInfo.compressedSize) ||\n               frameSizeInfo.compressedSize <= srcSize);\n        return frameSizeInfo;\n    } else {\n        const BYTE* ip = (const BYTE*)src;\n        const BYTE* const ipstart = ip;\n        size_t remainingSize = srcSize;\n        size_t nbBlocks = 0;\n        ZSTD_FrameHeader zfh;\n\n        /* Extract Frame Header */\n        {   size_t const ret = ZSTD_getFrameHeader_advanced(&zfh, src, srcSize, format);\n            if (ZSTD_isError(ret))\n                return ZSTD_errorFrameSizeInfo(ret);\n            if (ret > 0)\n                return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));\n        }\n\n        ip += zfh.headerSize;\n        remainingSize -= zfh.headerSize;\n\n        /* Iterate over each block */\n        while (1) {\n            blockProperties_t blockProperties;\n            size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);\n            if (ZSTD_isError(cBlockSize))\n                return ZSTD_errorFrameSizeInfo(cBlockSize);\n\n            if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)\n                return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));\n\n            ip += ZSTD_blockHeaderSize + cBlockSize;\n            remainingSize -= ZSTD_blockHeaderSize + cBlockSize;\n            nbBlocks++;\n\n            if (blockProperties.lastBlock) break;\n        }\n\n        /* Final frame content checksum */\n        if (zfh.checksumFlag) {\n            if (remainingSize < 4)\n                return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));\n            ip += 4;\n        }\n\n        frameSizeInfo.nbBlocks = nbBlocks;\n        frameSizeInfo.compressedSize = (size_t)(ip - ipstart);\n        frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)\n                                        ? zfh.frameContentSize\n                                        : (unsigned long long)nbBlocks * zfh.blockSizeMax;\n        return frameSizeInfo;\n    }\n}\n\nstatic size_t ZSTD_findFrameCompressedSize_advanced(const void *src, size_t srcSize, ZSTD_format_e format) {\n    ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize, format);\n    return frameSizeInfo.compressedSize;\n}\n\n/** ZSTD_findFrameCompressedSize() :\n * See docs in zstd.h\n * Note: compatible with legacy mode */\nsize_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)\n{\n    return ZSTD_findFrameCompressedSize_advanced(src, srcSize, ZSTD_f_zstd1);\n}\n\n/** ZSTD_decompressBound() :\n *  compatible with legacy mode\n *  `src` must point to the start of a ZSTD frame or a skippable frame\n *  `srcSize` must be at least as large as the frame contained\n *  @return : the maximum decompressed size of the compressed source\n */\nunsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)\n{\n    unsigned long long bound = 0;\n    /* Iterate over each frame */\n    while (srcSize > 0) {\n        ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize, ZSTD_f_zstd1);\n        size_t const compressedSize = frameSizeInfo.compressedSize;\n        unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;\n        if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)\n            return ZSTD_CONTENTSIZE_ERROR;\n        assert(srcSize >= compressedSize);\n        src = (const BYTE*)src + compressedSize;\n        srcSize -= compressedSize;\n        bound += decompressedBound;\n    }\n    return bound;\n}\n\nsize_t ZSTD_decompressionMargin(void const* src, size_t srcSize)\n{\n    size_t margin = 0;\n    unsigned maxBlockSize = 0;\n\n    /* Iterate over each frame */\n    while (srcSize > 0) {\n        ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize, ZSTD_f_zstd1);\n        size_t const compressedSize = frameSizeInfo.compressedSize;\n        unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;\n        ZSTD_FrameHeader zfh;\n\n        FORWARD_IF_ERROR(ZSTD_getFrameHeader(&zfh, src, srcSize), \"\");\n        if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)\n            return ERROR(corruption_detected);\n\n        if (zfh.frameType == ZSTD_frame) {\n            /* Add the frame header to our margin */\n            margin += zfh.headerSize;\n            /* Add the checksum to our margin */\n            margin += zfh.checksumFlag ? 4 : 0;\n            /* Add 3 bytes per block */\n            margin += 3 * frameSizeInfo.nbBlocks;\n\n            /* Compute the max block size */\n            maxBlockSize = MAX(maxBlockSize, zfh.blockSizeMax);\n        } else {\n            assert(zfh.frameType == ZSTD_skippableFrame);\n            /* Add the entire skippable frame size to our margin. */\n            margin += compressedSize;\n        }\n\n        assert(srcSize >= compressedSize);\n        src = (const BYTE*)src + compressedSize;\n        srcSize -= compressedSize;\n    }\n\n    /* Add the max block size back to the margin. */\n    margin += maxBlockSize;\n\n    return margin;\n}\n\n/*-*************************************************************\n *   Frame decoding\n ***************************************************************/\n\n/** ZSTD_insertBlock() :\n *  insert `src` block into `dctx` history. Useful to track uncompressed blocks. */\nsize_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)\n{\n    DEBUGLOG(5, \"ZSTD_insertBlock: %u bytes\", (unsigned)blockSize);\n    ZSTD_checkContinuity(dctx, blockStart, blockSize);\n    dctx->previousDstEnd = (const char*)blockStart + blockSize;\n    return blockSize;\n}\n\n\nstatic size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,\n                          const void* src, size_t srcSize)\n{\n    DEBUGLOG(5, \"ZSTD_copyRawBlock\");\n    RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, \"\");\n    if (dst == NULL) {\n        if (srcSize == 0) return 0;\n        RETURN_ERROR(dstBuffer_null, \"\");\n    }\n    ZSTD_memmove(dst, src, srcSize);\n    return srcSize;\n}\n\nstatic size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,\n                               BYTE b,\n                               size_t regenSize)\n{\n    RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, \"\");\n    if (dst == NULL) {\n        if (regenSize == 0) return 0;\n        RETURN_ERROR(dstBuffer_null, \"\");\n    }\n    ZSTD_memset(dst, b, regenSize);\n    return regenSize;\n}\n\nstatic void ZSTD_DCtx_trace_end(ZSTD_DCtx const* dctx, U64 uncompressedSize, U64 compressedSize, int streaming)\n{\n#if ZSTD_TRACE\n    if (dctx->traceCtx && ZSTD_trace_decompress_end != NULL) {\n        ZSTD_Trace trace;\n        ZSTD_memset(&trace, 0, sizeof(trace));\n        trace.version = ZSTD_VERSION_NUMBER;\n        trace.streaming = streaming;\n        if (dctx->ddict) {\n            trace.dictionaryID = ZSTD_getDictID_fromDDict(dctx->ddict);\n            trace.dictionarySize = ZSTD_DDict_dictSize(dctx->ddict);\n            trace.dictionaryIsCold = dctx->ddictIsCold;\n        }\n        trace.uncompressedSize = (size_t)uncompressedSize;\n        trace.compressedSize = (size_t)compressedSize;\n        trace.dctx = dctx;\n        ZSTD_trace_decompress_end(dctx->traceCtx, &trace);\n    }\n#else\n    (void)dctx;\n    (void)uncompressedSize;\n    (void)compressedSize;\n    (void)streaming;\n#endif\n}\n\n\n/*! ZSTD_decompressFrame() :\n * @dctx must be properly initialized\n *  will update *srcPtr and *srcSizePtr,\n *  to make *srcPtr progress by one frame. */\nstatic size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,\n                                   void* dst, size_t dstCapacity,\n                             const void** srcPtr, size_t *srcSizePtr)\n{\n    const BYTE* const istart = (const BYTE*)(*srcPtr);\n    const BYTE* ip = istart;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart;\n    BYTE* op = ostart;\n    size_t remainingSrcSize = *srcSizePtr;\n\n    DEBUGLOG(4, \"ZSTD_decompressFrame (srcSize:%i)\", (int)*srcSizePtr);\n\n    /* check */\n    RETURN_ERROR_IF(\n        remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN(dctx->format)+ZSTD_blockHeaderSize,\n        srcSize_wrong, \"\");\n\n    /* Frame Header */\n    {   size_t const frameHeaderSize = ZSTD_frameHeaderSize_internal(\n                ip, ZSTD_FRAMEHEADERSIZE_PREFIX(dctx->format), dctx->format);\n        if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;\n        RETURN_ERROR_IF(remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize,\n                        srcSize_wrong, \"\");\n        FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) , \"\");\n        ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize;\n    }\n\n    /* Shrink the blockSizeMax if enabled */\n    if (dctx->maxBlockSizeParam != 0)\n        dctx->fParams.blockSizeMax = MIN(dctx->fParams.blockSizeMax, (unsigned)dctx->maxBlockSizeParam);\n\n    /* Loop on each block */\n    while (1) {\n        BYTE* oBlockEnd = oend;\n        size_t decodedSize;\n        blockProperties_t blockProperties;\n        size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSrcSize, &blockProperties);\n        if (ZSTD_isError(cBlockSize)) return cBlockSize;\n\n        ip += ZSTD_blockHeaderSize;\n        remainingSrcSize -= ZSTD_blockHeaderSize;\n        RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, \"\");\n\n        if (ip >= op && ip < oBlockEnd) {\n            /* We are decompressing in-place. Limit the output pointer so that we\n             * don't overwrite the block that we are currently reading. This will\n             * fail decompression if the input & output pointers aren't spaced\n             * far enough apart.\n             *\n             * This is important to set, even when the pointers are far enough\n             * apart, because ZSTD_decompressBlock_internal() can decide to store\n             * literals in the output buffer, after the block it is decompressing.\n             * Since we don't want anything to overwrite our input, we have to tell\n             * ZSTD_decompressBlock_internal to never write past ip.\n             *\n             * See ZSTD_allocateLiteralsBuffer() for reference.\n             */\n            oBlockEnd = op + (ip - op);\n        }\n\n        switch(blockProperties.blockType)\n        {\n        case bt_compressed:\n            assert(dctx->isFrameDecompression == 1);\n            decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oBlockEnd-op), ip, cBlockSize, not_streaming);\n            break;\n        case bt_raw :\n            /* Use oend instead of oBlockEnd because this function is safe to overlap. It uses memmove. */\n            decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize);\n            break;\n        case bt_rle :\n            decodedSize = ZSTD_setRleBlock(op, (size_t)(oBlockEnd-op), *ip, blockProperties.origSize);\n            break;\n        case bt_reserved :\n        default:\n            RETURN_ERROR(corruption_detected, \"invalid block type\");\n        }\n        FORWARD_IF_ERROR(decodedSize, \"Block decompression failure\");\n        DEBUGLOG(5, \"Decompressed block of dSize = %u\", (unsigned)decodedSize);\n        if (dctx->validateChecksum) {\n            XXH64_update(&dctx->xxhState, op, decodedSize);\n        }\n        if (decodedSize) /* support dst = NULL,0 */ {\n            op += decodedSize;\n        }\n        assert(ip != NULL);\n        ip += cBlockSize;\n        remainingSrcSize -= cBlockSize;\n        if (blockProperties.lastBlock) break;\n    }\n\n    if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {\n        RETURN_ERROR_IF((U64)(op-ostart) != dctx->fParams.frameContentSize,\n                        corruption_detected, \"\");\n    }\n    if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */\n        RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong, \"\");\n        if (!dctx->forceIgnoreChecksum) {\n            U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);\n            U32 checkRead;\n            checkRead = MEM_readLE32(ip);\n            RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, \"\");\n        }\n        ip += 4;\n        remainingSrcSize -= 4;\n    }\n    ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0);\n    /* Allow caller to get size read */\n    DEBUGLOG(4, \"ZSTD_decompressFrame: decompressed frame of size %i, consuming %i bytes of input\", (int)(op-ostart), (int)(ip - (const BYTE*)*srcPtr));\n    *srcPtr = ip;\n    *srcSizePtr = remainingSrcSize;\n    return (size_t)(op-ostart);\n}\n\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,\n                                        void* dst, size_t dstCapacity,\n                                  const void* src, size_t srcSize,\n                                  const void* dict, size_t dictSize,\n                                  const ZSTD_DDict* ddict)\n{\n    void* const dststart = dst;\n    int moreThan1Frame = 0;\n\n    DEBUGLOG(5, \"ZSTD_decompressMultiFrame\");\n    assert(dict==NULL || ddict==NULL);  /* either dict or ddict set, not both */\n\n    if (ddict) {\n        dict = ZSTD_DDict_dictContent(ddict);\n        dictSize = ZSTD_DDict_dictSize(ddict);\n    }\n\n    while (srcSize >= ZSTD_startingInputLength(dctx->format)) {\n\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)\n        if (dctx->format == ZSTD_f_zstd1 && ZSTD_isLegacy(src, srcSize)) {\n            size_t decodedSize;\n            size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize);\n            if (ZSTD_isError(frameSize)) return frameSize;\n            RETURN_ERROR_IF(dctx->staticSize, memory_allocation,\n                \"legacy support is not compatible with static dctx\");\n\n            decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);\n            if (ZSTD_isError(decodedSize)) return decodedSize;\n\n            {\n                unsigned long long const expectedSize = ZSTD_getFrameContentSize(src, srcSize);\n                RETURN_ERROR_IF(expectedSize == ZSTD_CONTENTSIZE_ERROR, corruption_detected, \"Corrupted frame header!\");\n                if (expectedSize != ZSTD_CONTENTSIZE_UNKNOWN) {\n                    RETURN_ERROR_IF(expectedSize != decodedSize, corruption_detected,\n                        \"Frame header size does not match decoded size!\");\n                }\n            }\n\n            assert(decodedSize <= dstCapacity);\n            dst = (BYTE*)dst + decodedSize;\n            dstCapacity -= decodedSize;\n\n            src = (const BYTE*)src + frameSize;\n            srcSize -= frameSize;\n\n            continue;\n        }\n#endif\n\n        if (dctx->format == ZSTD_f_zstd1 && srcSize >= 4) {\n            U32 const magicNumber = MEM_readLE32(src);\n            DEBUGLOG(5, \"reading magic number %08X\", (unsigned)magicNumber);\n            if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {\n                /* skippable frame detected : skip it */\n                size_t const skippableSize = readSkippableFrameSize(src, srcSize);\n                FORWARD_IF_ERROR(skippableSize, \"invalid skippable frame\");\n                assert(skippableSize <= srcSize);\n\n                src = (const BYTE *)src + skippableSize;\n                srcSize -= skippableSize;\n                continue; /* check next frame */\n        }   }\n\n        if (ddict) {\n            /* we were called from ZSTD_decompress_usingDDict */\n            FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict), \"\");\n        } else {\n            /* this will initialize correctly with no dict if dict == NULL, so\n             * use this in all cases but ddict */\n            FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), \"\");\n        }\n        ZSTD_checkContinuity(dctx, dst, dstCapacity);\n\n        {   const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,\n                                                    &src, &srcSize);\n            RETURN_ERROR_IF(\n                (ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)\n             && (moreThan1Frame==1),\n                srcSize_wrong,\n                \"At least one frame successfully completed, \"\n                \"but following bytes are garbage: \"\n                \"it's more likely to be a srcSize error, \"\n                \"specifying more input bytes than size of frame(s). \"\n                \"Note: one could be unlucky, it might be a corruption error instead, \"\n                \"happening right at the place where we expect zstd magic bytes. \"\n                \"But this is _much_ less likely than a srcSize field error.\");\n            if (ZSTD_isError(res)) return res;\n            assert(res <= dstCapacity);\n            if (res != 0)\n                dst = (BYTE*)dst + res;\n            dstCapacity -= res;\n        }\n        moreThan1Frame = 1;\n    }  /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */\n\n    RETURN_ERROR_IF(srcSize, srcSize_wrong, \"input not entirely consumed\");\n\n    return (size_t)((BYTE*)dst - (BYTE*)dststart);\n}\n\nsize_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,\n                                 void* dst, size_t dstCapacity,\n                           const void* src, size_t srcSize,\n                           const void* dict, size_t dictSize)\n{\n    return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize, dict, dictSize, NULL);\n}\n\n\nstatic ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx)\n{\n    switch (dctx->dictUses) {\n    default:\n        assert(0 /* Impossible */);\n        ZSTD_FALLTHROUGH;\n    case ZSTD_dont_use:\n        ZSTD_clearDict(dctx);\n        return NULL;\n    case ZSTD_use_indefinitely:\n        return dctx->ddict;\n    case ZSTD_use_once:\n        dctx->dictUses = ZSTD_dont_use;\n        return dctx->ddict;\n    }\n}\n\nsize_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    return ZSTD_decompress_usingDDict(dctx, dst, dstCapacity, src, srcSize, ZSTD_getDDict(dctx));\n}\n\n\nsize_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)\n    size_t regenSize;\n    ZSTD_DCtx* const dctx =  ZSTD_createDCtx_internal(ZSTD_defaultCMem);\n    RETURN_ERROR_IF(dctx==NULL, memory_allocation, \"NULL pointer!\");\n    regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);\n    ZSTD_freeDCtx(dctx);\n    return regenSize;\n#else   /* stack mode */\n    ZSTD_DCtx dctx;\n    ZSTD_initDCtx_internal(&dctx);\n    return ZSTD_decompressDCtx(&dctx, dst, dstCapacity, src, srcSize);\n#endif\n}\n\n\n/*-**************************************\n*   Advanced Streaming Decompression API\n*   Bufferless and synchronous\n****************************************/\nsize_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; }\n\n/**\n * Similar to ZSTD_nextSrcSizeToDecompress(), but when a block input can be streamed, we\n * allow taking a partial block as the input. Currently only raw uncompressed blocks can\n * be streamed.\n *\n * For blocks that can be streamed, this allows us to reduce the latency until we produce\n * output, and avoid copying the input.\n *\n * @param inputSize - The total amount of input that the caller currently has.\n */\nstatic size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t inputSize) {\n    if (!(dctx->stage == ZSTDds_decompressBlock || dctx->stage == ZSTDds_decompressLastBlock))\n        return dctx->expected;\n    if (dctx->bType != bt_raw)\n        return dctx->expected;\n    return BOUNDED(1, inputSize, dctx->expected);\n}\n\nZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {\n    switch(dctx->stage)\n    {\n    default:   /* should not happen */\n        assert(0);\n        ZSTD_FALLTHROUGH;\n    case ZSTDds_getFrameHeaderSize:\n        ZSTD_FALLTHROUGH;\n    case ZSTDds_decodeFrameHeader:\n        return ZSTDnit_frameHeader;\n    case ZSTDds_decodeBlockHeader:\n        return ZSTDnit_blockHeader;\n    case ZSTDds_decompressBlock:\n        return ZSTDnit_block;\n    case ZSTDds_decompressLastBlock:\n        return ZSTDnit_lastBlock;\n    case ZSTDds_checkChecksum:\n        return ZSTDnit_checksum;\n    case ZSTDds_decodeSkippableHeader:\n        ZSTD_FALLTHROUGH;\n    case ZSTDds_skipFrame:\n        return ZSTDnit_skippableFrame;\n    }\n}\n\nstatic int ZSTD_isSkipFrame(ZSTD_DCtx* dctx) { return dctx->stage == ZSTDds_skipFrame; }\n\n/** ZSTD_decompressContinue() :\n *  srcSize : must be the exact nb of bytes expected (see ZSTD_nextSrcSizeToDecompress())\n *  @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity)\n *            or an error code, which can be tested using ZSTD_isError() */\nsize_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    DEBUGLOG(5, \"ZSTD_decompressContinue (srcSize:%u)\", (unsigned)srcSize);\n    /* Sanity check */\n    RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, \"not allowed\");\n    ZSTD_checkContinuity(dctx, dst, dstCapacity);\n\n    dctx->processedCSize += srcSize;\n\n    switch (dctx->stage)\n    {\n    case ZSTDds_getFrameHeaderSize :\n        assert(src != NULL);\n        if (dctx->format == ZSTD_f_zstd1) {  /* allows header */\n            assert(srcSize >= ZSTD_FRAMEIDSIZE);  /* to read skippable magic number */\n            if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {        /* skippable frame */\n                ZSTD_memcpy(dctx->headerBuffer, src, srcSize);\n                dctx->expected = ZSTD_SKIPPABLEHEADERSIZE - srcSize;  /* remaining to load to get full skippable frame header */\n                dctx->stage = ZSTDds_decodeSkippableHeader;\n                return 0;\n        }   }\n        dctx->headerSize = ZSTD_frameHeaderSize_internal(src, srcSize, dctx->format);\n        if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;\n        ZSTD_memcpy(dctx->headerBuffer, src, srcSize);\n        dctx->expected = dctx->headerSize - srcSize;\n        dctx->stage = ZSTDds_decodeFrameHeader;\n        return 0;\n\n    case ZSTDds_decodeFrameHeader:\n        assert(src != NULL);\n        ZSTD_memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);\n        FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize), \"\");\n        dctx->expected = ZSTD_blockHeaderSize;\n        dctx->stage = ZSTDds_decodeBlockHeader;\n        return 0;\n\n    case ZSTDds_decodeBlockHeader:\n        {   blockProperties_t bp;\n            size_t const cBlockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);\n            if (ZSTD_isError(cBlockSize)) return cBlockSize;\n            RETURN_ERROR_IF(cBlockSize > dctx->fParams.blockSizeMax, corruption_detected, \"Block Size Exceeds Maximum\");\n            dctx->expected = cBlockSize;\n            dctx->bType = bp.blockType;\n            dctx->rleSize = bp.origSize;\n            if (cBlockSize) {\n                dctx->stage = bp.lastBlock ? ZSTDds_decompressLastBlock : ZSTDds_decompressBlock;\n                return 0;\n            }\n            /* empty block */\n            if (bp.lastBlock) {\n                if (dctx->fParams.checksumFlag) {\n                    dctx->expected = 4;\n                    dctx->stage = ZSTDds_checkChecksum;\n                } else {\n                    dctx->expected = 0; /* end of frame */\n                    dctx->stage = ZSTDds_getFrameHeaderSize;\n                }\n            } else {\n                dctx->expected = ZSTD_blockHeaderSize;  /* jump to next header */\n                dctx->stage = ZSTDds_decodeBlockHeader;\n            }\n            return 0;\n        }\n\n    case ZSTDds_decompressLastBlock:\n    case ZSTDds_decompressBlock:\n        DEBUGLOG(5, \"ZSTD_decompressContinue: case ZSTDds_decompressBlock\");\n        {   size_t rSize;\n            switch(dctx->bType)\n            {\n            case bt_compressed:\n                DEBUGLOG(5, \"ZSTD_decompressContinue: case bt_compressed\");\n                assert(dctx->isFrameDecompression == 1);\n                rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, is_streaming);\n                dctx->expected = 0;  /* Streaming not supported */\n                break;\n            case bt_raw :\n                assert(srcSize <= dctx->expected);\n                rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize);\n                FORWARD_IF_ERROR(rSize, \"ZSTD_copyRawBlock failed\");\n                assert(rSize == srcSize);\n                dctx->expected -= rSize;\n                break;\n            case bt_rle :\n                rSize = ZSTD_setRleBlock(dst, dstCapacity, *(const BYTE*)src, dctx->rleSize);\n                dctx->expected = 0;  /* Streaming not supported */\n                break;\n            case bt_reserved :   /* should never happen */\n            default:\n                RETURN_ERROR(corruption_detected, \"invalid block type\");\n            }\n            FORWARD_IF_ERROR(rSize, \"\");\n            RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, \"Decompressed Block Size Exceeds Maximum\");\n            DEBUGLOG(5, \"ZSTD_decompressContinue: decoded size from block : %u\", (unsigned)rSize);\n            dctx->decodedSize += rSize;\n            if (dctx->validateChecksum) XXH64_update(&dctx->xxhState, dst, rSize);\n            dctx->previousDstEnd = (char*)dst + rSize;\n\n            /* Stay on the same stage until we are finished streaming the block. */\n            if (dctx->expected > 0) {\n                return rSize;\n            }\n\n            if (dctx->stage == ZSTDds_decompressLastBlock) {   /* end of frame */\n                DEBUGLOG(4, \"ZSTD_decompressContinue: decoded size from frame : %u\", (unsigned)dctx->decodedSize);\n                RETURN_ERROR_IF(\n                    dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN\n                 && dctx->decodedSize != dctx->fParams.frameContentSize,\n                    corruption_detected, \"\");\n                if (dctx->fParams.checksumFlag) {  /* another round for frame checksum */\n                    dctx->expected = 4;\n                    dctx->stage = ZSTDds_checkChecksum;\n                } else {\n                    ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);\n                    dctx->expected = 0;   /* ends here */\n                    dctx->stage = ZSTDds_getFrameHeaderSize;\n                }\n            } else {\n                dctx->stage = ZSTDds_decodeBlockHeader;\n                dctx->expected = ZSTD_blockHeaderSize;\n            }\n            return rSize;\n        }\n\n    case ZSTDds_checkChecksum:\n        assert(srcSize == 4);  /* guaranteed by dctx->expected */\n        {\n            if (dctx->validateChecksum) {\n                U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);\n                U32 const check32 = MEM_readLE32(src);\n                DEBUGLOG(4, \"ZSTD_decompressContinue: checksum : calculated %08X :: %08X read\", (unsigned)h32, (unsigned)check32);\n                RETURN_ERROR_IF(check32 != h32, checksum_wrong, \"\");\n            }\n            ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);\n            dctx->expected = 0;\n            dctx->stage = ZSTDds_getFrameHeaderSize;\n            return 0;\n        }\n\n    case ZSTDds_decodeSkippableHeader:\n        assert(src != NULL);\n        assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE);\n        assert(dctx->format != ZSTD_f_zstd1_magicless);\n        ZSTD_memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize);   /* complete skippable header */\n        dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE);   /* note : dctx->expected can grow seriously large, beyond local buffer size */\n        dctx->stage = ZSTDds_skipFrame;\n        return 0;\n\n    case ZSTDds_skipFrame:\n        dctx->expected = 0;\n        dctx->stage = ZSTDds_getFrameHeaderSize;\n        return 0;\n\n    default:\n        assert(0);   /* impossible */\n        RETURN_ERROR(GENERIC, \"impossible to reach\");   /* some compilers require default to do something */\n    }\n}\n\n\nstatic size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    dctx->dictEnd = dctx->previousDstEnd;\n    dctx->virtualStart = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));\n    dctx->prefixStart = dict;\n    dctx->previousDstEnd = (const char*)dict + dictSize;\n#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION\n    dctx->dictContentBeginForFuzzing = dctx->prefixStart;\n    dctx->dictContentEndForFuzzing = dctx->previousDstEnd;\n#endif\n    return 0;\n}\n\n/*! ZSTD_loadDEntropy() :\n *  dict : must point at beginning of a valid zstd dictionary.\n * @return : size of entropy tables read */\nsize_t\nZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,\n                  const void* const dict, size_t const dictSize)\n{\n    const BYTE* dictPtr = (const BYTE*)dict;\n    const BYTE* const dictEnd = dictPtr + dictSize;\n\n    RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted, \"dict is too small\");\n    assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY);   /* dict must be valid */\n    dictPtr += 8;   /* skip header = magic + dictID */\n\n    ZSTD_STATIC_ASSERT(offsetof(ZSTD_entropyDTables_t, OFTable) == offsetof(ZSTD_entropyDTables_t, LLTable) + sizeof(entropy->LLTable));\n    ZSTD_STATIC_ASSERT(offsetof(ZSTD_entropyDTables_t, MLTable) == offsetof(ZSTD_entropyDTables_t, OFTable) + sizeof(entropy->OFTable));\n    ZSTD_STATIC_ASSERT(sizeof(entropy->LLTable) + sizeof(entropy->OFTable) + sizeof(entropy->MLTable) >= HUF_DECOMPRESS_WORKSPACE_SIZE);\n    {   void* const workspace = &entropy->LLTable;   /* use fse tables as temporary workspace; implies fse tables are grouped together */\n        size_t const workspaceSize = sizeof(entropy->LLTable) + sizeof(entropy->OFTable) + sizeof(entropy->MLTable);\n#ifdef HUF_FORCE_DECOMPRESS_X1\n        /* in minimal huffman, we always use X1 variants */\n        size_t const hSize = HUF_readDTableX1_wksp(entropy->hufTable,\n                                                dictPtr, dictEnd - dictPtr,\n                                                workspace, workspaceSize, /* flags */ 0);\n#else\n        size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,\n                                                dictPtr, (size_t)(dictEnd - dictPtr),\n                                                workspace, workspaceSize, /* flags */ 0);\n#endif\n        RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, \"\");\n        dictPtr += hSize;\n    }\n\n    {   short offcodeNCount[MaxOff+1];\n        unsigned offcodeMaxValue = MaxOff, offcodeLog;\n        size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, (size_t)(dictEnd-dictPtr));\n        RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, \"\");\n        RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted, \"\");\n        RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, \"\");\n        ZSTD_buildFSETable( entropy->OFTable,\n                            offcodeNCount, offcodeMaxValue,\n                            OF_base, OF_bits,\n                            offcodeLog,\n                            entropy->workspace, sizeof(entropy->workspace),\n                            /* bmi2 */0);\n        dictPtr += offcodeHeaderSize;\n    }\n\n    {   short matchlengthNCount[MaxML+1];\n        unsigned matchlengthMaxValue = MaxML, matchlengthLog;\n        size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));\n        RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, \"\");\n        RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted, \"\");\n        RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, \"\");\n        ZSTD_buildFSETable( entropy->MLTable,\n                            matchlengthNCount, matchlengthMaxValue,\n                            ML_base, ML_bits,\n                            matchlengthLog,\n                            entropy->workspace, sizeof(entropy->workspace),\n                            /* bmi2 */ 0);\n        dictPtr += matchlengthHeaderSize;\n    }\n\n    {   short litlengthNCount[MaxLL+1];\n        unsigned litlengthMaxValue = MaxLL, litlengthLog;\n        size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));\n        RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, \"\");\n        RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted, \"\");\n        RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, \"\");\n        ZSTD_buildFSETable( entropy->LLTable,\n                            litlengthNCount, litlengthMaxValue,\n                            LL_base, LL_bits,\n                            litlengthLog,\n                            entropy->workspace, sizeof(entropy->workspace),\n                            /* bmi2 */ 0);\n        dictPtr += litlengthHeaderSize;\n    }\n\n    RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, \"\");\n    {   int i;\n        size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));\n        for (i=0; i<3; i++) {\n            U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;\n            RETURN_ERROR_IF(rep==0 || rep > dictContentSize,\n                            dictionary_corrupted, \"\");\n            entropy->rep[i] = rep;\n    }   }\n\n    return (size_t)(dictPtr - (const BYTE*)dict);\n}\n\nstatic size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    if (dictSize < 8) return ZSTD_refDictContent(dctx, dict, dictSize);\n    {   U32 const magic = MEM_readLE32(dict);\n        if (magic != ZSTD_MAGIC_DICTIONARY) {\n            return ZSTD_refDictContent(dctx, dict, dictSize);   /* pure content mode */\n    }   }\n    dctx->dictID = MEM_readLE32((const char*)dict + ZSTD_FRAMEIDSIZE);\n\n    /* load entropy tables */\n    {   size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize);\n        RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted, \"\");\n        dict = (const char*)dict + eSize;\n        dictSize -= eSize;\n    }\n    dctx->litEntropy = dctx->fseEntropy = 1;\n\n    /* reference dictionary content */\n    return ZSTD_refDictContent(dctx, dict, dictSize);\n}\n\nsize_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)\n{\n    assert(dctx != NULL);\n#if ZSTD_TRACE\n    dctx->traceCtx = (ZSTD_trace_decompress_begin != NULL) ? ZSTD_trace_decompress_begin(dctx) : 0;\n#endif\n    dctx->expected = ZSTD_startingInputLength(dctx->format);  /* dctx->format must be properly set */\n    dctx->stage = ZSTDds_getFrameHeaderSize;\n    dctx->processedCSize = 0;\n    dctx->decodedSize = 0;\n    dctx->previousDstEnd = NULL;\n    dctx->prefixStart = NULL;\n    dctx->virtualStart = NULL;\n    dctx->dictEnd = NULL;\n    dctx->entropy.hufTable[0] = (HUF_DTable)((ZSTD_HUFFDTABLE_CAPACITY_LOG)*0x1000001);  /* cover both little and big endian */\n    dctx->litEntropy = dctx->fseEntropy = 0;\n    dctx->dictID = 0;\n    dctx->bType = bt_reserved;\n    dctx->isFrameDecompression = 1;\n    ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));\n    ZSTD_memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue));  /* initial repcodes */\n    dctx->LLTptr = dctx->entropy.LLTable;\n    dctx->MLTptr = dctx->entropy.MLTable;\n    dctx->OFTptr = dctx->entropy.OFTable;\n    dctx->HUFptr = dctx->entropy.hufTable;\n    return 0;\n}\n\nsize_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , \"\");\n    if (dict && dictSize)\n        RETURN_ERROR_IF(\n            ZSTD_isError(ZSTD_decompress_insertDictionary(dctx, dict, dictSize)),\n            dictionary_corrupted, \"\");\n    return 0;\n}\n\n\n/* ======   ZSTD_DDict   ====== */\n\nsize_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)\n{\n    DEBUGLOG(4, \"ZSTD_decompressBegin_usingDDict\");\n    assert(dctx != NULL);\n    if (ddict) {\n        const char* const dictStart = (const char*)ZSTD_DDict_dictContent(ddict);\n        size_t const dictSize = ZSTD_DDict_dictSize(ddict);\n        const void* const dictEnd = dictStart + dictSize;\n        dctx->ddictIsCold = (dctx->dictEnd != dictEnd);\n        DEBUGLOG(4, \"DDict is %s\",\n                    dctx->ddictIsCold ? \"~cold~\" : \"hot!\");\n    }\n    FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , \"\");\n    if (ddict) {   /* NULL ddict is equivalent to no dictionary */\n        ZSTD_copyDDictParameters(dctx, ddict);\n    }\n    return 0;\n}\n\n/*! ZSTD_getDictID_fromDict() :\n *  Provides the dictID stored within dictionary.\n *  if @return == 0, the dictionary is not conformant with Zstandard specification.\n *  It can still be loaded, but as a content-only dictionary. */\nunsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)\n{\n    if (dictSize < 8) return 0;\n    if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) return 0;\n    return MEM_readLE32((const char*)dict + ZSTD_FRAMEIDSIZE);\n}\n\n/*! ZSTD_getDictID_fromFrame() :\n *  Provides the dictID required to decompress frame stored within `src`.\n *  If @return == 0, the dictID could not be decoded.\n *  This could for one of the following reasons :\n *  - The frame does not require a dictionary (most common case).\n *  - The frame was built with dictID intentionally removed.\n *    Needed dictionary is a hidden piece of information.\n *    Note : this use case also happens when using a non-conformant dictionary.\n *  - `srcSize` is too small, and as a result, frame header could not be decoded.\n *    Note : possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`.\n *  - This is not a Zstandard frame.\n *  When identifying the exact failure cause, it's possible to use\n *  ZSTD_getFrameHeader(), which will provide a more precise error code. */\nunsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize)\n{\n    ZSTD_FrameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0, 0, 0 };\n    size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize);\n    if (ZSTD_isError(hError)) return 0;\n    return zfp.dictID;\n}\n\n\n/*! ZSTD_decompress_usingDDict() :\n*   Decompression using a pre-digested Dictionary\n*   Use dictionary without significant overhead. */\nsize_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,\n                                  void* dst, size_t dstCapacity,\n                            const void* src, size_t srcSize,\n                            const ZSTD_DDict* ddict)\n{\n    /* pass content and size in case legacy frames are encountered */\n    return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize,\n                                     NULL, 0,\n                                     ddict);\n}\n\n\n/*=====================================\n*   Streaming decompression\n*====================================*/\n\nZSTD_DStream* ZSTD_createDStream(void)\n{\n    DEBUGLOG(3, \"ZSTD_createDStream\");\n    return ZSTD_createDCtx_internal(ZSTD_defaultCMem);\n}\n\nZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)\n{\n    return ZSTD_initStaticDCtx(workspace, workspaceSize);\n}\n\nZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem)\n{\n    return ZSTD_createDCtx_internal(customMem);\n}\n\nsize_t ZSTD_freeDStream(ZSTD_DStream* zds)\n{\n    return ZSTD_freeDCtx(zds);\n}\n\n\n/* ***  Initialization  *** */\n\nsize_t ZSTD_DStreamInSize(void)  { return ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize; }\nsize_t ZSTD_DStreamOutSize(void) { return ZSTD_BLOCKSIZE_MAX; }\n\nsize_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx,\n                                   const void* dict, size_t dictSize,\n                                         ZSTD_dictLoadMethod_e dictLoadMethod,\n                                         ZSTD_dictContentType_e dictContentType)\n{\n    RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, \"\");\n    ZSTD_clearDict(dctx);\n    if (dict && dictSize != 0) {\n        dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem);\n        RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation, \"NULL pointer!\");\n        dctx->ddict = dctx->ddictLocal;\n        dctx->dictUses = ZSTD_use_indefinitely;\n    }\n    return 0;\n}\n\nsize_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    return ZSTD_DCtx_loadDictionary_advanced(dctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto);\n}\n\nsize_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    return ZSTD_DCtx_loadDictionary_advanced(dctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto);\n}\n\nsize_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)\n{\n    FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType), \"\");\n    dctx->dictUses = ZSTD_use_once;\n    return 0;\n}\n\nsize_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize)\n{\n    return ZSTD_DCtx_refPrefix_advanced(dctx, prefix, prefixSize, ZSTD_dct_rawContent);\n}\n\n\n/* ZSTD_initDStream_usingDict() :\n * return : expected size, aka ZSTD_startingInputLength().\n * this function cannot fail */\nsize_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)\n{\n    DEBUGLOG(4, \"ZSTD_initDStream_usingDict\");\n    FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) , \"\");\n    FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) , \"\");\n    return ZSTD_startingInputLength(zds->format);\n}\n\n/* note : this variant can't fail */\nsize_t ZSTD_initDStream(ZSTD_DStream* zds)\n{\n    DEBUGLOG(4, \"ZSTD_initDStream\");\n    FORWARD_IF_ERROR(ZSTD_DCtx_reset(zds, ZSTD_reset_session_only), \"\");\n    FORWARD_IF_ERROR(ZSTD_DCtx_refDDict(zds, NULL), \"\");\n    return ZSTD_startingInputLength(zds->format);\n}\n\n/* ZSTD_initDStream_usingDDict() :\n * ddict will just be referenced, and must outlive decompression session\n * this function cannot fail */\nsize_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)\n{\n    DEBUGLOG(4, \"ZSTD_initDStream_usingDDict\");\n    FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , \"\");\n    FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , \"\");\n    return ZSTD_startingInputLength(dctx->format);\n}\n\n/* ZSTD_resetDStream() :\n * return : expected size, aka ZSTD_startingInputLength().\n * this function cannot fail */\nsize_t ZSTD_resetDStream(ZSTD_DStream* dctx)\n{\n    DEBUGLOG(4, \"ZSTD_resetDStream\");\n    FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), \"\");\n    return ZSTD_startingInputLength(dctx->format);\n}\n\n\nsize_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)\n{\n    RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, \"\");\n    ZSTD_clearDict(dctx);\n    if (ddict) {\n        dctx->ddict = ddict;\n        dctx->dictUses = ZSTD_use_indefinitely;\n        if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts) {\n            if (dctx->ddictSet == NULL) {\n                dctx->ddictSet = ZSTD_createDDictHashSet(dctx->customMem);\n                if (!dctx->ddictSet) {\n                    RETURN_ERROR(memory_allocation, \"Failed to allocate memory for hash set!\");\n                }\n            }\n            assert(!dctx->staticSize);  /* Impossible: ddictSet cannot have been allocated if static dctx */\n            FORWARD_IF_ERROR(ZSTD_DDictHashSet_addDDict(dctx->ddictSet, ddict, dctx->customMem), \"\");\n        }\n    }\n    return 0;\n}\n\n/* ZSTD_DCtx_setMaxWindowSize() :\n * note : no direct equivalence in ZSTD_DCtx_setParameter,\n * since this version sets windowSize, and the other sets windowLog */\nsize_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)\n{\n    ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);\n    size_t const min = (size_t)1 << bounds.lowerBound;\n    size_t const max = (size_t)1 << bounds.upperBound;\n    RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, \"\");\n    RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound, \"\");\n    RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound, \"\");\n    dctx->maxWindowSize = maxWindowSize;\n    return 0;\n}\n\nsize_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)\n{\n    return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (int)format);\n}\n\nZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)\n{\n    ZSTD_bounds bounds = { 0, 0, 0 };\n    switch(dParam) {\n        case ZSTD_d_windowLogMax:\n            bounds.lowerBound = ZSTD_WINDOWLOG_ABSOLUTEMIN;\n            bounds.upperBound = ZSTD_WINDOWLOG_MAX;\n            return bounds;\n        case ZSTD_d_format:\n            bounds.lowerBound = (int)ZSTD_f_zstd1;\n            bounds.upperBound = (int)ZSTD_f_zstd1_magicless;\n            ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);\n            return bounds;\n        case ZSTD_d_stableOutBuffer:\n            bounds.lowerBound = (int)ZSTD_bm_buffered;\n            bounds.upperBound = (int)ZSTD_bm_stable;\n            return bounds;\n        case ZSTD_d_forceIgnoreChecksum:\n            bounds.lowerBound = (int)ZSTD_d_validateChecksum;\n            bounds.upperBound = (int)ZSTD_d_ignoreChecksum;\n            return bounds;\n        case ZSTD_d_refMultipleDDicts:\n            bounds.lowerBound = (int)ZSTD_rmd_refSingleDDict;\n            bounds.upperBound = (int)ZSTD_rmd_refMultipleDDicts;\n            return bounds;\n        case ZSTD_d_disableHuffmanAssembly:\n            bounds.lowerBound = 0;\n            bounds.upperBound = 1;\n            return bounds;\n        case ZSTD_d_maxBlockSize:\n            bounds.lowerBound = ZSTD_BLOCKSIZE_MAX_MIN;\n            bounds.upperBound = ZSTD_BLOCKSIZE_MAX;\n            return bounds;\n\n        default:;\n    }\n    bounds.error = ERROR(parameter_unsupported);\n    return bounds;\n}\n\n/* ZSTD_dParam_withinBounds:\n * @return 1 if value is within dParam bounds,\n * 0 otherwise */\nstatic int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)\n{\n    ZSTD_bounds const bounds = ZSTD_dParam_getBounds(dParam);\n    if (ZSTD_isError(bounds.error)) return 0;\n    if (value < bounds.lowerBound) return 0;\n    if (value > bounds.upperBound) return 0;\n    return 1;\n}\n\n#define CHECK_DBOUNDS(p,v) {                \\\n    RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, \"\"); \\\n}\n\nsize_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value)\n{\n    switch (param) {\n        case ZSTD_d_windowLogMax:\n            *value = (int)ZSTD_highbit32((U32)dctx->maxWindowSize);\n            return 0;\n        case ZSTD_d_format:\n            *value = (int)dctx->format;\n            return 0;\n        case ZSTD_d_stableOutBuffer:\n            *value = (int)dctx->outBufferMode;\n            return 0;\n        case ZSTD_d_forceIgnoreChecksum:\n            *value = (int)dctx->forceIgnoreChecksum;\n            return 0;\n        case ZSTD_d_refMultipleDDicts:\n            *value = (int)dctx->refMultipleDDicts;\n            return 0;\n        case ZSTD_d_disableHuffmanAssembly:\n            *value = (int)dctx->disableHufAsm;\n            return 0;\n        case ZSTD_d_maxBlockSize:\n            *value = dctx->maxBlockSizeParam;\n            return 0;\n        default:;\n    }\n    RETURN_ERROR(parameter_unsupported, \"\");\n}\n\nsize_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)\n{\n    RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, \"\");\n    switch(dParam) {\n        case ZSTD_d_windowLogMax:\n            if (value == 0) value = ZSTD_WINDOWLOG_LIMIT_DEFAULT;\n            CHECK_DBOUNDS(ZSTD_d_windowLogMax, value);\n            dctx->maxWindowSize = ((size_t)1) << value;\n            return 0;\n        case ZSTD_d_format:\n            CHECK_DBOUNDS(ZSTD_d_format, value);\n            dctx->format = (ZSTD_format_e)value;\n            return 0;\n        case ZSTD_d_stableOutBuffer:\n            CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value);\n            dctx->outBufferMode = (ZSTD_bufferMode_e)value;\n            return 0;\n        case ZSTD_d_forceIgnoreChecksum:\n            CHECK_DBOUNDS(ZSTD_d_forceIgnoreChecksum, value);\n            dctx->forceIgnoreChecksum = (ZSTD_forceIgnoreChecksum_e)value;\n            return 0;\n        case ZSTD_d_refMultipleDDicts:\n            CHECK_DBOUNDS(ZSTD_d_refMultipleDDicts, value);\n            if (dctx->staticSize != 0) {\n                RETURN_ERROR(parameter_unsupported, \"Static dctx does not support multiple DDicts!\");\n            }\n            dctx->refMultipleDDicts = (ZSTD_refMultipleDDicts_e)value;\n            return 0;\n        case ZSTD_d_disableHuffmanAssembly:\n            CHECK_DBOUNDS(ZSTD_d_disableHuffmanAssembly, value);\n            dctx->disableHufAsm = value != 0;\n            return 0;\n        case ZSTD_d_maxBlockSize:\n            if (value != 0) CHECK_DBOUNDS(ZSTD_d_maxBlockSize, value);\n            dctx->maxBlockSizeParam = value;\n            return 0;\n        default:;\n    }\n    RETURN_ERROR(parameter_unsupported, \"\");\n}\n\nsize_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)\n{\n    if ( (reset == ZSTD_reset_session_only)\n      || (reset == ZSTD_reset_session_and_parameters) ) {\n        dctx->streamStage = zdss_init;\n        dctx->noForwardProgress = 0;\n        dctx->isFrameDecompression = 1;\n    }\n    if ( (reset == ZSTD_reset_parameters)\n      || (reset == ZSTD_reset_session_and_parameters) ) {\n        RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, \"\");\n        ZSTD_clearDict(dctx);\n        ZSTD_DCtx_resetParameters(dctx);\n    }\n    return 0;\n}\n\n\nsize_t ZSTD_sizeof_DStream(const ZSTD_DStream* dctx)\n{\n    return ZSTD_sizeof_DCtx(dctx);\n}\n\nstatic size_t ZSTD_decodingBufferSize_internal(unsigned long long windowSize, unsigned long long frameContentSize, size_t blockSizeMax)\n{\n    size_t const blockSize = MIN((size_t)MIN(windowSize, ZSTD_BLOCKSIZE_MAX), blockSizeMax);\n    /* We need blockSize + WILDCOPY_OVERLENGTH worth of buffer so that if a block\n     * ends at windowSize + WILDCOPY_OVERLENGTH + 1 bytes, we can start writing\n     * the block at the beginning of the output buffer, and maintain a full window.\n     *\n     * We need another blockSize worth of buffer so that we can store split\n     * literals at the end of the block without overwriting the extDict window.\n     */\n    unsigned long long const neededRBSize = windowSize + (blockSize * 2) + (WILDCOPY_OVERLENGTH * 2);\n    unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);\n    size_t const minRBSize = (size_t) neededSize;\n    RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,\n                    frameParameter_windowTooLarge, \"\");\n    return minRBSize;\n}\n\nsize_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)\n{\n    return ZSTD_decodingBufferSize_internal(windowSize, frameContentSize, ZSTD_BLOCKSIZE_MAX);\n}\n\nsize_t ZSTD_estimateDStreamSize(size_t windowSize)\n{\n    size_t const blockSize = MIN(windowSize, ZSTD_BLOCKSIZE_MAX);\n    size_t const inBuffSize = blockSize;  /* no block can be larger */\n    size_t const outBuffSize = ZSTD_decodingBufferSize_min(windowSize, ZSTD_CONTENTSIZE_UNKNOWN);\n    return ZSTD_estimateDCtxSize() + inBuffSize + outBuffSize;\n}\n\nsize_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)\n{\n    U32 const windowSizeMax = 1U << ZSTD_WINDOWLOG_MAX;   /* note : should be user-selectable, but requires an additional parameter (or a dctx) */\n    ZSTD_FrameHeader zfh;\n    size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);\n    if (ZSTD_isError(err)) return err;\n    RETURN_ERROR_IF(err>0, srcSize_wrong, \"\");\n    RETURN_ERROR_IF(zfh.windowSize > windowSizeMax,\n                    frameParameter_windowTooLarge, \"\");\n    return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);\n}\n\n\n/* *****   Decompression   ***** */\n\nstatic int ZSTD_DCtx_isOverflow(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)\n{\n    return (zds->inBuffSize + zds->outBuffSize) >= (neededInBuffSize + neededOutBuffSize) * ZSTD_WORKSPACETOOLARGE_FACTOR;\n}\n\nstatic void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)\n{\n    if (ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize))\n        zds->oversizedDuration++;\n    else\n        zds->oversizedDuration = 0;\n}\n\nstatic int ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream* zds)\n{\n    return zds->oversizedDuration >= ZSTD_WORKSPACETOOLARGE_MAXDURATION;\n}\n\n/* Checks that the output buffer hasn't changed if ZSTD_obm_stable is used. */\nstatic size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* output)\n{\n    ZSTD_outBuffer const expect = zds->expectedOutBuffer;\n    /* No requirement when ZSTD_obm_stable is not enabled. */\n    if (zds->outBufferMode != ZSTD_bm_stable)\n        return 0;\n    /* Any buffer is allowed in zdss_init, this must be the same for every other call until\n     * the context is reset.\n     */\n    if (zds->streamStage == zdss_init)\n        return 0;\n    /* The buffer must match our expectation exactly. */\n    if (expect.dst == output->dst && expect.pos == output->pos && expect.size == output->size)\n        return 0;\n    RETURN_ERROR(dstBuffer_wrong, \"ZSTD_d_stableOutBuffer enabled but output differs!\");\n}\n\n/* Calls ZSTD_decompressContinue() with the right parameters for ZSTD_decompressStream()\n * and updates the stage and the output buffer state. This call is extracted so it can be\n * used both when reading directly from the ZSTD_inBuffer, and in buffered input mode.\n * NOTE: You must break after calling this function since the streamStage is modified.\n */\nstatic size_t ZSTD_decompressContinueStream(\n            ZSTD_DStream* zds, char** op, char* oend,\n            void const* src, size_t srcSize) {\n    int const isSkipFrame = ZSTD_isSkipFrame(zds);\n    if (zds->outBufferMode == ZSTD_bm_buffered) {\n        size_t const dstSize = isSkipFrame ? 0 : zds->outBuffSize - zds->outStart;\n        size_t const decodedSize = ZSTD_decompressContinue(zds,\n                zds->outBuff + zds->outStart, dstSize, src, srcSize);\n        FORWARD_IF_ERROR(decodedSize, \"\");\n        if (!decodedSize && !isSkipFrame) {\n            zds->streamStage = zdss_read;\n        } else {\n            zds->outEnd = zds->outStart + decodedSize;\n            zds->streamStage = zdss_flush;\n        }\n    } else {\n        /* Write directly into the output buffer */\n        size_t const dstSize = isSkipFrame ? 0 : (size_t)(oend - *op);\n        size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize);\n        FORWARD_IF_ERROR(decodedSize, \"\");\n        *op += decodedSize;\n        /* Flushing is not needed. */\n        zds->streamStage = zdss_read;\n        assert(*op <= oend);\n        assert(zds->outBufferMode == ZSTD_bm_stable);\n    }\n    return 0;\n}\n\nsize_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input)\n{\n    const char* const src = (const char*)input->src;\n    const char* const istart = input->pos != 0 ? src + input->pos : src;\n    const char* const iend = input->size != 0 ? src + input->size : src;\n    const char* ip = istart;\n    char* const dst = (char*)output->dst;\n    char* const ostart = output->pos != 0 ? dst + output->pos : dst;\n    char* const oend = output->size != 0 ? dst + output->size : dst;\n    char* op = ostart;\n    U32 someMoreWork = 1;\n\n    DEBUGLOG(5, \"ZSTD_decompressStream\");\n    assert(zds != NULL);\n    RETURN_ERROR_IF(\n        input->pos > input->size,\n        srcSize_wrong,\n        \"forbidden. in: pos: %u   vs size: %u\",\n        (U32)input->pos, (U32)input->size);\n    RETURN_ERROR_IF(\n        output->pos > output->size,\n        dstSize_tooSmall,\n        \"forbidden. out: pos: %u   vs size: %u\",\n        (U32)output->pos, (U32)output->size);\n    DEBUGLOG(5, \"input size : %u\", (U32)(input->size - input->pos));\n    FORWARD_IF_ERROR(ZSTD_checkOutBuffer(zds, output), \"\");\n\n    while (someMoreWork) {\n        switch(zds->streamStage)\n        {\n        case zdss_init :\n            DEBUGLOG(5, \"stage zdss_init => transparent reset \");\n            zds->streamStage = zdss_loadHeader;\n            zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)\n            zds->legacyVersion = 0;\n#endif\n            zds->hostageByte = 0;\n            zds->expectedOutBuffer = *output;\n            ZSTD_FALLTHROUGH;\n\n        case zdss_loadHeader :\n            DEBUGLOG(5, \"stage zdss_loadHeader (srcSize : %u)\", (U32)(iend - ip));\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)\n            if (zds->legacyVersion) {\n                RETURN_ERROR_IF(zds->staticSize, memory_allocation,\n                    \"legacy support is incompatible with static dctx\");\n                {   size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input);\n                    if (hint==0) zds->streamStage = zdss_init;\n                    return hint;\n            }   }\n#endif\n            {   size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);\n                if (zds->refMultipleDDicts && zds->ddictSet) {\n                    ZSTD_DCtx_selectFrameDDict(zds);\n                }\n                if (ZSTD_isError(hSize)) {\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)\n                    U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);\n                    if (legacyVersion) {\n                        ZSTD_DDict const* const ddict = ZSTD_getDDict(zds);\n                        const void* const dict = ddict ? ZSTD_DDict_dictContent(ddict) : NULL;\n                        size_t const dictSize = ddict ? ZSTD_DDict_dictSize(ddict) : 0;\n                        DEBUGLOG(5, \"ZSTD_decompressStream: detected legacy version v0.%u\", legacyVersion);\n                        RETURN_ERROR_IF(zds->staticSize, memory_allocation,\n                            \"legacy support is incompatible with static dctx\");\n                        FORWARD_IF_ERROR(ZSTD_initLegacyStream(&zds->legacyContext,\n                                    zds->previousLegacyVersion, legacyVersion,\n                                    dict, dictSize), \"\");\n                        zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;\n                        {   size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, input);\n                            if (hint==0) zds->streamStage = zdss_init;   /* or stay in stage zdss_loadHeader */\n                            return hint;\n                    }   }\n#endif\n                    return hSize;   /* error */\n                }\n                if (hSize != 0) {   /* need more input */\n                    size_t const toLoad = hSize - zds->lhSize;   /* if hSize!=0, hSize > zds->lhSize */\n                    size_t const remainingInput = (size_t)(iend-ip);\n                    assert(iend >= ip);\n                    if (toLoad > remainingInput) {   /* not enough input to load full header */\n                        if (remainingInput > 0) {\n                            ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);\n                            zds->lhSize += remainingInput;\n                        }\n                        input->pos = input->size;\n                        /* check first few bytes */\n                        FORWARD_IF_ERROR(\n                            ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format),\n                            \"First few bytes detected incorrect\" );\n                        /* return hint input size */\n                        return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize;   /* remaining header bytes + next block header */\n                    }\n                    assert(ip != NULL);\n                    ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;\n                    break;\n            }   }\n\n            /* check for single-pass mode opportunity */\n            if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN\n                && zds->fParams.frameType != ZSTD_skippableFrame\n                && (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {\n                size_t const cSize = ZSTD_findFrameCompressedSize_advanced(istart, (size_t)(iend-istart), zds->format);\n                if (cSize <= (size_t)(iend-istart)) {\n                    /* shortcut : using single-pass mode */\n                    size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds));\n                    if (ZSTD_isError(decompressedSize)) return decompressedSize;\n                    DEBUGLOG(4, \"shortcut to single-pass ZSTD_decompress_usingDDict()\");\n                    assert(istart != NULL);\n                    ip = istart + cSize;\n                    op = op ? op + decompressedSize : op; /* can occur if frameContentSize = 0 (empty frame) */\n                    zds->expected = 0;\n                    zds->streamStage = zdss_init;\n                    someMoreWork = 0;\n                    break;\n            }   }\n\n            /* Check output buffer is large enough for ZSTD_odm_stable. */\n            if (zds->outBufferMode == ZSTD_bm_stable\n                && zds->fParams.frameType != ZSTD_skippableFrame\n                && zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN\n                && (U64)(size_t)(oend-op) < zds->fParams.frameContentSize) {\n                RETURN_ERROR(dstSize_tooSmall, \"ZSTD_obm_stable passed but ZSTD_outBuffer is too small\");\n            }\n\n            /* Consume header (see ZSTDds_decodeFrameHeader) */\n            DEBUGLOG(4, \"Consume header\");\n            FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)), \"\");\n\n            if (zds->format == ZSTD_f_zstd1\n                && (MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {  /* skippable frame */\n                zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);\n                zds->stage = ZSTDds_skipFrame;\n            } else {\n                FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize), \"\");\n                zds->expected = ZSTD_blockHeaderSize;\n                zds->stage = ZSTDds_decodeBlockHeader;\n            }\n\n            /* control buffer memory usage */\n            DEBUGLOG(4, \"Control max memory usage (%u KB <= max %u KB)\",\n                        (U32)(zds->fParams.windowSize >>10),\n                        (U32)(zds->maxWindowSize >> 10) );\n            zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);\n            RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize,\n                            frameParameter_windowTooLarge, \"\");\n            if (zds->maxBlockSizeParam != 0)\n                zds->fParams.blockSizeMax = MIN(zds->fParams.blockSizeMax, (unsigned)zds->maxBlockSizeParam);\n\n            /* Adapt buffer sizes to frame header instructions */\n            {   size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);\n                size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_bm_buffered\n                        ? ZSTD_decodingBufferSize_internal(zds->fParams.windowSize, zds->fParams.frameContentSize, zds->fParams.blockSizeMax)\n                        : 0;\n\n                ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize);\n\n                {   int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize);\n                    int const tooLarge = ZSTD_DCtx_isOversizedTooLong(zds);\n\n                    if (tooSmall || tooLarge) {\n                        size_t const bufferSize = neededInBuffSize + neededOutBuffSize;\n                        DEBUGLOG(4, \"inBuff  : from %u to %u\",\n                                    (U32)zds->inBuffSize, (U32)neededInBuffSize);\n                        DEBUGLOG(4, \"outBuff : from %u to %u\",\n                                    (U32)zds->outBuffSize, (U32)neededOutBuffSize);\n                        if (zds->staticSize) {  /* static DCtx */\n                            DEBUGLOG(4, \"staticSize : %u\", (U32)zds->staticSize);\n                            assert(zds->staticSize >= sizeof(ZSTD_DCtx));  /* controlled at init */\n                            RETURN_ERROR_IF(\n                                bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),\n                                memory_allocation, \"\");\n                        } else {\n                            ZSTD_customFree(zds->inBuff, zds->customMem);\n                            zds->inBuffSize = 0;\n                            zds->outBuffSize = 0;\n                            zds->inBuff = (char*)ZSTD_customMalloc(bufferSize, zds->customMem);\n                            RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation, \"\");\n                        }\n                        zds->inBuffSize = neededInBuffSize;\n                        zds->outBuff = zds->inBuff + zds->inBuffSize;\n                        zds->outBuffSize = neededOutBuffSize;\n            }   }   }\n            zds->streamStage = zdss_read;\n            ZSTD_FALLTHROUGH;\n\n        case zdss_read:\n            DEBUGLOG(5, \"stage zdss_read\");\n            {   size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip));\n                DEBUGLOG(5, \"neededInSize = %u\", (U32)neededInSize);\n                if (neededInSize==0) {  /* end of frame */\n                    zds->streamStage = zdss_init;\n                    someMoreWork = 0;\n                    break;\n                }\n                if ((size_t)(iend-ip) >= neededInSize) {  /* decode directly from src */\n                    FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), \"\");\n                    assert(ip != NULL);\n                    ip += neededInSize;\n                    /* Function modifies the stage so we must break */\n                    break;\n            }   }\n            if (ip==iend) { someMoreWork = 0; break; }   /* no more input */\n            zds->streamStage = zdss_load;\n            ZSTD_FALLTHROUGH;\n\n        case zdss_load:\n            {   size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);\n                size_t const toLoad = neededInSize - zds->inPos;\n                int const isSkipFrame = ZSTD_isSkipFrame(zds);\n                size_t loadedSize;\n                /* At this point we shouldn't be decompressing a block that we can stream. */\n                assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip)));\n                if (isSkipFrame) {\n                    loadedSize = MIN(toLoad, (size_t)(iend-ip));\n                } else {\n                    RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,\n                                    corruption_detected,\n                                    \"should never happen\");\n                    loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, (size_t)(iend-ip));\n                }\n                if (loadedSize != 0) {\n                    /* ip may be NULL */\n                    ip += loadedSize;\n                    zds->inPos += loadedSize;\n                }\n                if (loadedSize < toLoad) { someMoreWork = 0; break; }   /* not enough input, wait for more */\n\n                /* decode loaded input */\n                zds->inPos = 0;   /* input is consumed */\n                FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, zds->inBuff, neededInSize), \"\");\n                /* Function modifies the stage so we must break */\n                break;\n            }\n        case zdss_flush:\n            {\n                size_t const toFlushSize = zds->outEnd - zds->outStart;\n                size_t const flushedSize = ZSTD_limitCopy(op, (size_t)(oend-op), zds->outBuff + zds->outStart, toFlushSize);\n\n                op = op ? op + flushedSize : op;\n\n                zds->outStart += flushedSize;\n                if (flushedSize == toFlushSize) {  /* flush completed */\n                    zds->streamStage = zdss_read;\n                    if ( (zds->outBuffSize < zds->fParams.frameContentSize)\n                        && (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) {\n                        DEBUGLOG(5, \"restart filling outBuff from beginning (left:%i, needed:%u)\",\n                                (int)(zds->outBuffSize - zds->outStart),\n                                (U32)zds->fParams.blockSizeMax);\n                        zds->outStart = zds->outEnd = 0;\n                    }\n                    break;\n            }   }\n            /* cannot complete flush */\n            someMoreWork = 0;\n            break;\n\n        default:\n            assert(0);    /* impossible */\n            RETURN_ERROR(GENERIC, \"impossible to reach\");   /* some compilers require default to do something */\n    }   }\n\n    /* result */\n    input->pos = (size_t)(ip - (const char*)(input->src));\n    output->pos = (size_t)(op - (char*)(output->dst));\n\n    /* Update the expected output buffer for ZSTD_obm_stable. */\n    zds->expectedOutBuffer = *output;\n\n    if ((ip==istart) && (op==ostart)) {  /* no forward progress */\n        zds->noForwardProgress ++;\n        if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {\n            RETURN_ERROR_IF(op==oend, noForwardProgress_destFull, \"\");\n            RETURN_ERROR_IF(ip==iend, noForwardProgress_inputEmpty, \"\");\n            assert(0);\n        }\n    } else {\n        zds->noForwardProgress = 0;\n    }\n    {   size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds);\n        if (!nextSrcSizeHint) {   /* frame fully decoded */\n            if (zds->outEnd == zds->outStart) {  /* output fully flushed */\n                if (zds->hostageByte) {\n                    if (input->pos >= input->size) {\n                        /* can't release hostage (not present) */\n                        zds->streamStage = zdss_read;\n                        return 1;\n                    }\n                    input->pos++;  /* release hostage */\n                }   /* zds->hostageByte */\n                return 0;\n            }  /* zds->outEnd == zds->outStart */\n            if (!zds->hostageByte) { /* output not fully flushed; keep last byte as hostage; will be released when all output is flushed */\n                input->pos--;   /* note : pos > 0, otherwise, impossible to finish reading last block */\n                zds->hostageByte=1;\n            }\n            return 1;\n        }  /* nextSrcSizeHint==0 */\n        nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds) == ZSTDnit_block);   /* preload header of next block */\n        assert(zds->inPos <= nextSrcSizeHint);\n        nextSrcSizeHint -= zds->inPos;   /* part already loaded*/\n        return nextSrcSizeHint;\n    }\n}\n\nsize_t ZSTD_decompressStream_simpleArgs (\n                            ZSTD_DCtx* dctx,\n                            void* dst, size_t dstCapacity, size_t* dstPos,\n                      const void* src, size_t srcSize, size_t* srcPos)\n{\n    ZSTD_outBuffer output;\n    ZSTD_inBuffer  input;\n    output.dst = dst;\n    output.size = dstCapacity;\n    output.pos = *dstPos;\n    input.src = src;\n    input.size = srcSize;\n    input.pos = *srcPos;\n    {   size_t const cErr = ZSTD_decompressStream(dctx, &output, &input);\n        *dstPos = output.pos;\n        *srcPos = input.pos;\n        return cErr;\n    }\n}\n"
  },
  {
    "path": "lib/decompress/zstd_decompress_block.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* zstd_decompress_block :\n * this module takes care of decompressing _compressed_ block */\n\n/*-*******************************************************\n*  Dependencies\n*********************************************************/\n#include \"../common/zstd_deps.h\"   /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */\n#include \"../common/compiler.h\"    /* prefetch */\n#include \"../common/mem.h\"         /* low level memory routines */\n#include <stddef.h>\n#define FSE_STATIC_LINKING_ONLY\n#include \"../common/fse.h\"\n#include \"../common/huf.h\"\n#include \"../common/zstd_internal.h\"\n#include \"zstd_decompress_internal.h\"   /* ZSTD_DCtx */\n#include \"zstd_decompress_block.h\"\n#include \"../common/bits.h\"  /* ZSTD_highbit32 */\n\n/*_*******************************************************\n*  Macros\n**********************************************************/\n\n/* These two optional macros force the use one way or another of the two\n * ZSTD_decompressSequences implementations. You can't force in both directions\n * at the same time.\n */\n#if defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \\\n    defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)\n#error \"Cannot force the use of the short and the long ZSTD_decompressSequences variants!\"\n#endif\n\n\n/*_*******************************************************\n*  Memory operations\n**********************************************************/\nstatic void ZSTD_copy4(void* dst, const void* src) { ZSTD_memcpy(dst, src, 4); }\n\n\n/*-*************************************************************\n *   Block decoding\n ***************************************************************/\n\nstatic size_t ZSTD_blockSizeMax(ZSTD_DCtx const* dctx)\n{\n    size_t const blockSizeMax = dctx->isFrameDecompression ? dctx->fParams.blockSizeMax : ZSTD_BLOCKSIZE_MAX;\n    assert(blockSizeMax <= ZSTD_BLOCKSIZE_MAX);\n    return blockSizeMax;\n}\n\n/*! ZSTD_getcBlockSize() :\n *  Provides the size of compressed block from block header `src` */\nsize_t ZSTD_getcBlockSize(const void* src, size_t srcSize,\n                          blockProperties_t* bpPtr)\n{\n    RETURN_ERROR_IF(srcSize < ZSTD_blockHeaderSize, srcSize_wrong, \"\");\n\n    {   U32 const cBlockHeader = MEM_readLE24(src);\n        U32 const cSize = cBlockHeader >> 3;\n        bpPtr->lastBlock = cBlockHeader & 1;\n        bpPtr->blockType = (blockType_e)((cBlockHeader >> 1) & 3);\n        bpPtr->origSize = cSize;   /* only useful for RLE */\n        if (bpPtr->blockType == bt_rle) return 1;\n        RETURN_ERROR_IF(bpPtr->blockType == bt_reserved, corruption_detected, \"\");\n        return cSize;\n    }\n}\n\n/* Allocate buffer for literals, either overlapping current dst, or split between dst and litExtraBuffer, or stored entirely within litExtraBuffer */\nstatic void ZSTD_allocateLiteralsBuffer(ZSTD_DCtx* dctx, void* const dst, const size_t dstCapacity, const size_t litSize,\n    const streaming_operation streaming, const size_t expectedWriteSize, const unsigned splitImmediately)\n{\n    size_t const blockSizeMax = ZSTD_blockSizeMax(dctx);\n    assert(litSize <= blockSizeMax);\n    assert(dctx->isFrameDecompression || streaming == not_streaming);\n    assert(expectedWriteSize <= blockSizeMax);\n    if (streaming == not_streaming && dstCapacity > blockSizeMax + WILDCOPY_OVERLENGTH + litSize + WILDCOPY_OVERLENGTH) {\n        /* If we aren't streaming, we can just put the literals after the output\n         * of the current block. We don't need to worry about overwriting the\n         * extDict of our window, because it doesn't exist.\n         * So if we have space after the end of the block, just put it there.\n         */\n        dctx->litBuffer = (BYTE*)dst + blockSizeMax + WILDCOPY_OVERLENGTH;\n        dctx->litBufferEnd = dctx->litBuffer + litSize;\n        dctx->litBufferLocation = ZSTD_in_dst;\n    } else if (litSize <= ZSTD_LITBUFFEREXTRASIZE) {\n        /* Literals fit entirely within the extra buffer, put them there to avoid\n         * having to split the literals.\n         */\n        dctx->litBuffer = dctx->litExtraBuffer;\n        dctx->litBufferEnd = dctx->litBuffer + litSize;\n        dctx->litBufferLocation = ZSTD_not_in_dst;\n    } else {\n        assert(blockSizeMax > ZSTD_LITBUFFEREXTRASIZE);\n        /* Literals must be split between the output block and the extra lit\n         * buffer. We fill the extra lit buffer with the tail of the literals,\n         * and put the rest of the literals at the end of the block, with\n         * WILDCOPY_OVERLENGTH of buffer room to allow for overreads.\n         * This MUST not write more than our maxBlockSize beyond dst, because in\n         * streaming mode, that could overwrite part of our extDict window.\n         */\n        if (splitImmediately) {\n            /* won't fit in litExtraBuffer, so it will be split between end of dst and extra buffer */\n            dctx->litBuffer = (BYTE*)dst + expectedWriteSize - litSize + ZSTD_LITBUFFEREXTRASIZE - WILDCOPY_OVERLENGTH;\n            dctx->litBufferEnd = dctx->litBuffer + litSize - ZSTD_LITBUFFEREXTRASIZE;\n        } else {\n            /* initially this will be stored entirely in dst during huffman decoding, it will partially be shifted to litExtraBuffer after */\n            dctx->litBuffer = (BYTE*)dst + expectedWriteSize - litSize;\n            dctx->litBufferEnd = (BYTE*)dst + expectedWriteSize;\n        }\n        dctx->litBufferLocation = ZSTD_split;\n        assert(dctx->litBufferEnd <= (BYTE*)dst + expectedWriteSize);\n    }\n}\n\n/*! ZSTD_decodeLiteralsBlock() :\n * Where it is possible to do so without being stomped by the output during decompression, the literals block will be stored\n * in the dstBuffer.  If there is room to do so, it will be stored in full in the excess dst space after where the current\n * block will be output.  Otherwise it will be stored at the end of the current dst blockspace, with a small portion being\n * stored in dctx->litExtraBuffer to help keep it \"ahead\" of the current output write.\n *\n * @return : nb of bytes read from src (< srcSize )\n *  note : symbol not declared but exposed for fullbench */\nstatic size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,\n                          const void* src, size_t srcSize,   /* note : srcSize < BLOCKSIZE */\n                          void* dst, size_t dstCapacity, const streaming_operation streaming)\n{\n    DEBUGLOG(5, \"ZSTD_decodeLiteralsBlock\");\n    RETURN_ERROR_IF(srcSize < MIN_CBLOCK_SIZE, corruption_detected, \"\");\n\n    {   const BYTE* const istart = (const BYTE*) src;\n        SymbolEncodingType_e const litEncType = (SymbolEncodingType_e)(istart[0] & 3);\n        size_t const blockSizeMax = ZSTD_blockSizeMax(dctx);\n\n        switch(litEncType)\n        {\n        case set_repeat:\n            DEBUGLOG(5, \"set_repeat flag : re-using stats from previous compressed literals block\");\n            RETURN_ERROR_IF(dctx->litEntropy==0, dictionary_corrupted, \"\");\n            ZSTD_FALLTHROUGH;\n\n        case set_compressed:\n            RETURN_ERROR_IF(srcSize < 5, corruption_detected, \"srcSize >= MIN_CBLOCK_SIZE == 2; here we need up to 5 for case 3\");\n            {   size_t lhSize, litSize, litCSize;\n                U32 singleStream=0;\n                U32 const lhlCode = (istart[0] >> 2) & 3;\n                U32 const lhc = MEM_readLE32(istart);\n                size_t hufSuccess;\n                size_t expectedWriteSize = MIN(blockSizeMax, dstCapacity);\n                int const flags = 0\n                    | (ZSTD_DCtx_get_bmi2(dctx) ? HUF_flags_bmi2 : 0)\n                    | (dctx->disableHufAsm ? HUF_flags_disableAsm : 0);\n                switch(lhlCode)\n                {\n                case 0: case 1: default:   /* note : default is impossible, since lhlCode into [0..3] */\n                    /* 2 - 2 - 10 - 10 */\n                    singleStream = !lhlCode;\n                    lhSize = 3;\n                    litSize  = (lhc >> 4) & 0x3FF;\n                    litCSize = (lhc >> 14) & 0x3FF;\n                    break;\n                case 2:\n                    /* 2 - 2 - 14 - 14 */\n                    lhSize = 4;\n                    litSize  = (lhc >> 4) & 0x3FFF;\n                    litCSize = lhc >> 18;\n                    break;\n                case 3:\n                    /* 2 - 2 - 18 - 18 */\n                    lhSize = 5;\n                    litSize  = (lhc >> 4) & 0x3FFFF;\n                    litCSize = (lhc >> 22) + ((size_t)istart[4] << 10);\n                    break;\n                }\n                RETURN_ERROR_IF(litSize > 0 && dst == NULL, dstSize_tooSmall, \"NULL not handled\");\n                RETURN_ERROR_IF(litSize > blockSizeMax, corruption_detected, \"\");\n                if (!singleStream)\n                    RETURN_ERROR_IF(litSize < MIN_LITERALS_FOR_4_STREAMS, literals_headerWrong,\n                        \"Not enough literals (%zu) for the 4-streams mode (min %u)\",\n                        litSize, MIN_LITERALS_FOR_4_STREAMS);\n                RETURN_ERROR_IF(litCSize + lhSize > srcSize, corruption_detected, \"\");\n                RETURN_ERROR_IF(expectedWriteSize < litSize , dstSize_tooSmall, \"\");\n                ZSTD_allocateLiteralsBuffer(dctx, dst, dstCapacity, litSize, streaming, expectedWriteSize, 0);\n\n                /* prefetch huffman table if cold */\n                if (dctx->ddictIsCold && (litSize > 768 /* heuristic */)) {\n                    PREFETCH_AREA(dctx->HUFptr, sizeof(dctx->entropy.hufTable));\n                }\n\n                if (litEncType==set_repeat) {\n                    if (singleStream) {\n                        hufSuccess = HUF_decompress1X_usingDTable(\n                            dctx->litBuffer, litSize, istart+lhSize, litCSize,\n                            dctx->HUFptr, flags);\n                    } else {\n                        assert(litSize >= MIN_LITERALS_FOR_4_STREAMS);\n                        hufSuccess = HUF_decompress4X_usingDTable(\n                            dctx->litBuffer, litSize, istart+lhSize, litCSize,\n                            dctx->HUFptr, flags);\n                    }\n                } else {\n                    if (singleStream) {\n#if defined(HUF_FORCE_DECOMPRESS_X2)\n                        hufSuccess = HUF_decompress1X_DCtx_wksp(\n                            dctx->entropy.hufTable, dctx->litBuffer, litSize,\n                            istart+lhSize, litCSize, dctx->workspace,\n                            sizeof(dctx->workspace), flags);\n#else\n                        hufSuccess = HUF_decompress1X1_DCtx_wksp(\n                            dctx->entropy.hufTable, dctx->litBuffer, litSize,\n                            istart+lhSize, litCSize, dctx->workspace,\n                            sizeof(dctx->workspace), flags);\n#endif\n                    } else {\n                        hufSuccess = HUF_decompress4X_hufOnly_wksp(\n                            dctx->entropy.hufTable, dctx->litBuffer, litSize,\n                            istart+lhSize, litCSize, dctx->workspace,\n                            sizeof(dctx->workspace), flags);\n                    }\n                }\n                if (dctx->litBufferLocation == ZSTD_split)\n                {\n                    assert(litSize > ZSTD_LITBUFFEREXTRASIZE);\n                    ZSTD_memcpy(dctx->litExtraBuffer, dctx->litBufferEnd - ZSTD_LITBUFFEREXTRASIZE, ZSTD_LITBUFFEREXTRASIZE);\n                    ZSTD_memmove(dctx->litBuffer + ZSTD_LITBUFFEREXTRASIZE - WILDCOPY_OVERLENGTH, dctx->litBuffer, litSize - ZSTD_LITBUFFEREXTRASIZE);\n                    dctx->litBuffer += ZSTD_LITBUFFEREXTRASIZE - WILDCOPY_OVERLENGTH;\n                    dctx->litBufferEnd -= WILDCOPY_OVERLENGTH;\n                    assert(dctx->litBufferEnd <= (BYTE*)dst + blockSizeMax);\n                }\n\n                RETURN_ERROR_IF(HUF_isError(hufSuccess), corruption_detected, \"\");\n\n                dctx->litPtr = dctx->litBuffer;\n                dctx->litSize = litSize;\n                dctx->litEntropy = 1;\n                if (litEncType==set_compressed) dctx->HUFptr = dctx->entropy.hufTable;\n                return litCSize + lhSize;\n            }\n\n        case set_basic:\n            {   size_t litSize, lhSize;\n                U32 const lhlCode = ((istart[0]) >> 2) & 3;\n                size_t expectedWriteSize = MIN(blockSizeMax, dstCapacity);\n                switch(lhlCode)\n                {\n                case 0: case 2: default:   /* note : default is impossible, since lhlCode into [0..3] */\n                    lhSize = 1;\n                    litSize = istart[0] >> 3;\n                    break;\n                case 1:\n                    lhSize = 2;\n                    litSize = MEM_readLE16(istart) >> 4;\n                    break;\n                case 3:\n                    lhSize = 3;\n                    RETURN_ERROR_IF(srcSize<3, corruption_detected, \"srcSize >= MIN_CBLOCK_SIZE == 2; here we need lhSize = 3\");\n                    litSize = MEM_readLE24(istart) >> 4;\n                    break;\n                }\n\n                RETURN_ERROR_IF(litSize > 0 && dst == NULL, dstSize_tooSmall, \"NULL not handled\");\n                RETURN_ERROR_IF(litSize > blockSizeMax, corruption_detected, \"\");\n                RETURN_ERROR_IF(expectedWriteSize < litSize, dstSize_tooSmall, \"\");\n                ZSTD_allocateLiteralsBuffer(dctx, dst, dstCapacity, litSize, streaming, expectedWriteSize, 1);\n                if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) {  /* risk reading beyond src buffer with wildcopy */\n                    RETURN_ERROR_IF(litSize+lhSize > srcSize, corruption_detected, \"\");\n                    if (dctx->litBufferLocation == ZSTD_split)\n                    {\n                        ZSTD_memcpy(dctx->litBuffer, istart + lhSize, litSize - ZSTD_LITBUFFEREXTRASIZE);\n                        ZSTD_memcpy(dctx->litExtraBuffer, istart + lhSize + litSize - ZSTD_LITBUFFEREXTRASIZE, ZSTD_LITBUFFEREXTRASIZE);\n                    }\n                    else\n                    {\n                        ZSTD_memcpy(dctx->litBuffer, istart + lhSize, litSize);\n                    }\n                    dctx->litPtr = dctx->litBuffer;\n                    dctx->litSize = litSize;\n                    return lhSize+litSize;\n                }\n                /* direct reference into compressed stream */\n                dctx->litPtr = istart+lhSize;\n                dctx->litSize = litSize;\n                dctx->litBufferEnd = dctx->litPtr + litSize;\n                dctx->litBufferLocation = ZSTD_not_in_dst;\n                return lhSize+litSize;\n            }\n\n        case set_rle:\n            {   U32 const lhlCode = ((istart[0]) >> 2) & 3;\n                size_t litSize, lhSize;\n                size_t expectedWriteSize = MIN(blockSizeMax, dstCapacity);\n                switch(lhlCode)\n                {\n                case 0: case 2: default:   /* note : default is impossible, since lhlCode into [0..3] */\n                    lhSize = 1;\n                    litSize = istart[0] >> 3;\n                    break;\n                case 1:\n                    lhSize = 2;\n                    RETURN_ERROR_IF(srcSize<3, corruption_detected, \"srcSize >= MIN_CBLOCK_SIZE == 2; here we need lhSize+1 = 3\");\n                    litSize = MEM_readLE16(istart) >> 4;\n                    break;\n                case 3:\n                    lhSize = 3;\n                    RETURN_ERROR_IF(srcSize<4, corruption_detected, \"srcSize >= MIN_CBLOCK_SIZE == 2; here we need lhSize+1 = 4\");\n                    litSize = MEM_readLE24(istart) >> 4;\n                    break;\n                }\n                RETURN_ERROR_IF(litSize > 0 && dst == NULL, dstSize_tooSmall, \"NULL not handled\");\n                RETURN_ERROR_IF(litSize > blockSizeMax, corruption_detected, \"\");\n                RETURN_ERROR_IF(expectedWriteSize < litSize, dstSize_tooSmall, \"\");\n                ZSTD_allocateLiteralsBuffer(dctx, dst, dstCapacity, litSize, streaming, expectedWriteSize, 1);\n                if (dctx->litBufferLocation == ZSTD_split)\n                {\n                    ZSTD_memset(dctx->litBuffer, istart[lhSize], litSize - ZSTD_LITBUFFEREXTRASIZE);\n                    ZSTD_memset(dctx->litExtraBuffer, istart[lhSize], ZSTD_LITBUFFEREXTRASIZE);\n                }\n                else\n                {\n                    ZSTD_memset(dctx->litBuffer, istart[lhSize], litSize);\n                }\n                dctx->litPtr = dctx->litBuffer;\n                dctx->litSize = litSize;\n                return lhSize+1;\n            }\n        default:\n            RETURN_ERROR(corruption_detected, \"impossible\");\n        }\n    }\n}\n\n/* Hidden declaration for fullbench */\nsize_t ZSTD_decodeLiteralsBlock_wrapper(ZSTD_DCtx* dctx,\n                          const void* src, size_t srcSize,\n                          void* dst, size_t dstCapacity);\nsize_t ZSTD_decodeLiteralsBlock_wrapper(ZSTD_DCtx* dctx,\n                          const void* src, size_t srcSize,\n                          void* dst, size_t dstCapacity)\n{\n    dctx->isFrameDecompression = 0;\n    return ZSTD_decodeLiteralsBlock(dctx, src, srcSize, dst, dstCapacity, not_streaming);\n}\n\n/* Default FSE distribution tables.\n * These are pre-calculated FSE decoding tables using default distributions as defined in specification :\n * https://github.com/facebook/zstd/blob/release/doc/zstd_compression_format.md#default-distributions\n * They were generated programmatically with following method :\n * - start from default distributions, present in /lib/common/zstd_internal.h\n * - generate tables normally, using ZSTD_buildFSETable()\n * - printout the content of tables\n * - prettify output, report below, test with fuzzer to ensure it's correct */\n\n/* Default FSE distribution table for Literal Lengths */\nstatic const ZSTD_seqSymbol LL_defaultDTable[(1<<LL_DEFAULTNORMLOG)+1] = {\n     {  1,  1,  1, LL_DEFAULTNORMLOG},  /* header : fastMode, tableLog */\n     /* nextState, nbAddBits, nbBits, baseVal */\n     {  0,  0,  4,    0},  { 16,  0,  4,    0},\n     { 32,  0,  5,    1},  {  0,  0,  5,    3},\n     {  0,  0,  5,    4},  {  0,  0,  5,    6},\n     {  0,  0,  5,    7},  {  0,  0,  5,    9},\n     {  0,  0,  5,   10},  {  0,  0,  5,   12},\n     {  0,  0,  6,   14},  {  0,  1,  5,   16},\n     {  0,  1,  5,   20},  {  0,  1,  5,   22},\n     {  0,  2,  5,   28},  {  0,  3,  5,   32},\n     {  0,  4,  5,   48},  { 32,  6,  5,   64},\n     {  0,  7,  5,  128},  {  0,  8,  6,  256},\n     {  0, 10,  6, 1024},  {  0, 12,  6, 4096},\n     { 32,  0,  4,    0},  {  0,  0,  4,    1},\n     {  0,  0,  5,    2},  { 32,  0,  5,    4},\n     {  0,  0,  5,    5},  { 32,  0,  5,    7},\n     {  0,  0,  5,    8},  { 32,  0,  5,   10},\n     {  0,  0,  5,   11},  {  0,  0,  6,   13},\n     { 32,  1,  5,   16},  {  0,  1,  5,   18},\n     { 32,  1,  5,   22},  {  0,  2,  5,   24},\n     { 32,  3,  5,   32},  {  0,  3,  5,   40},\n     {  0,  6,  4,   64},  { 16,  6,  4,   64},\n     { 32,  7,  5,  128},  {  0,  9,  6,  512},\n     {  0, 11,  6, 2048},  { 48,  0,  4,    0},\n     { 16,  0,  4,    1},  { 32,  0,  5,    2},\n     { 32,  0,  5,    3},  { 32,  0,  5,    5},\n     { 32,  0,  5,    6},  { 32,  0,  5,    8},\n     { 32,  0,  5,    9},  { 32,  0,  5,   11},\n     { 32,  0,  5,   12},  {  0,  0,  6,   15},\n     { 32,  1,  5,   18},  { 32,  1,  5,   20},\n     { 32,  2,  5,   24},  { 32,  2,  5,   28},\n     { 32,  3,  5,   40},  { 32,  4,  5,   48},\n     {  0, 16,  6,65536},  {  0, 15,  6,32768},\n     {  0, 14,  6,16384},  {  0, 13,  6, 8192},\n};   /* LL_defaultDTable */\n\n/* Default FSE distribution table for Offset Codes */\nstatic const ZSTD_seqSymbol OF_defaultDTable[(1<<OF_DEFAULTNORMLOG)+1] = {\n    {  1,  1,  1, OF_DEFAULTNORMLOG},  /* header : fastMode, tableLog */\n    /* nextState, nbAddBits, nbBits, baseVal */\n    {  0,  0,  5,    0},     {  0,  6,  4,   61},\n    {  0,  9,  5,  509},     {  0, 15,  5,32765},\n    {  0, 21,  5,2097149},   {  0,  3,  5,    5},\n    {  0,  7,  4,  125},     {  0, 12,  5, 4093},\n    {  0, 18,  5,262141},    {  0, 23,  5,8388605},\n    {  0,  5,  5,   29},     {  0,  8,  4,  253},\n    {  0, 14,  5,16381},     {  0, 20,  5,1048573},\n    {  0,  2,  5,    1},     { 16,  7,  4,  125},\n    {  0, 11,  5, 2045},     {  0, 17,  5,131069},\n    {  0, 22,  5,4194301},   {  0,  4,  5,   13},\n    { 16,  8,  4,  253},     {  0, 13,  5, 8189},\n    {  0, 19,  5,524285},    {  0,  1,  5,    1},\n    { 16,  6,  4,   61},     {  0, 10,  5, 1021},\n    {  0, 16,  5,65533},     {  0, 28,  5,268435453},\n    {  0, 27,  5,134217725}, {  0, 26,  5,67108861},\n    {  0, 25,  5,33554429},  {  0, 24,  5,16777213},\n};   /* OF_defaultDTable */\n\n\n/* Default FSE distribution table for Match Lengths */\nstatic const ZSTD_seqSymbol ML_defaultDTable[(1<<ML_DEFAULTNORMLOG)+1] = {\n    {  1,  1,  1, ML_DEFAULTNORMLOG},  /* header : fastMode, tableLog */\n    /* nextState, nbAddBits, nbBits, baseVal */\n    {  0,  0,  6,    3},  {  0,  0,  4,    4},\n    { 32,  0,  5,    5},  {  0,  0,  5,    6},\n    {  0,  0,  5,    8},  {  0,  0,  5,    9},\n    {  0,  0,  5,   11},  {  0,  0,  6,   13},\n    {  0,  0,  6,   16},  {  0,  0,  6,   19},\n    {  0,  0,  6,   22},  {  0,  0,  6,   25},\n    {  0,  0,  6,   28},  {  0,  0,  6,   31},\n    {  0,  0,  6,   34},  {  0,  1,  6,   37},\n    {  0,  1,  6,   41},  {  0,  2,  6,   47},\n    {  0,  3,  6,   59},  {  0,  4,  6,   83},\n    {  0,  7,  6,  131},  {  0,  9,  6,  515},\n    { 16,  0,  4,    4},  {  0,  0,  4,    5},\n    { 32,  0,  5,    6},  {  0,  0,  5,    7},\n    { 32,  0,  5,    9},  {  0,  0,  5,   10},\n    {  0,  0,  6,   12},  {  0,  0,  6,   15},\n    {  0,  0,  6,   18},  {  0,  0,  6,   21},\n    {  0,  0,  6,   24},  {  0,  0,  6,   27},\n    {  0,  0,  6,   30},  {  0,  0,  6,   33},\n    {  0,  1,  6,   35},  {  0,  1,  6,   39},\n    {  0,  2,  6,   43},  {  0,  3,  6,   51},\n    {  0,  4,  6,   67},  {  0,  5,  6,   99},\n    {  0,  8,  6,  259},  { 32,  0,  4,    4},\n    { 48,  0,  4,    4},  { 16,  0,  4,    5},\n    { 32,  0,  5,    7},  { 32,  0,  5,    8},\n    { 32,  0,  5,   10},  { 32,  0,  5,   11},\n    {  0,  0,  6,   14},  {  0,  0,  6,   17},\n    {  0,  0,  6,   20},  {  0,  0,  6,   23},\n    {  0,  0,  6,   26},  {  0,  0,  6,   29},\n    {  0,  0,  6,   32},  {  0, 16,  6,65539},\n    {  0, 15,  6,32771},  {  0, 14,  6,16387},\n    {  0, 13,  6, 8195},  {  0, 12,  6, 4099},\n    {  0, 11,  6, 2051},  {  0, 10,  6, 1027},\n};   /* ML_defaultDTable */\n\n\nstatic void ZSTD_buildSeqTable_rle(ZSTD_seqSymbol* dt, U32 baseValue, U8 nbAddBits)\n{\n    void* ptr = dt;\n    ZSTD_seqSymbol_header* const DTableH = (ZSTD_seqSymbol_header*)ptr;\n    ZSTD_seqSymbol* const cell = dt + 1;\n\n    DTableH->tableLog = 0;\n    DTableH->fastMode = 0;\n\n    cell->nbBits = 0;\n    cell->nextState = 0;\n    assert(nbAddBits < 255);\n    cell->nbAdditionalBits = nbAddBits;\n    cell->baseValue = baseValue;\n}\n\n\n/* ZSTD_buildFSETable() :\n * generate FSE decoding table for one symbol (ll, ml or off)\n * cannot fail if input is valid =>\n * all inputs are presumed validated at this stage */\nFORCE_INLINE_TEMPLATE\nvoid ZSTD_buildFSETable_body(ZSTD_seqSymbol* dt,\n            const short* normalizedCounter, unsigned maxSymbolValue,\n            const U32* baseValue, const U8* nbAdditionalBits,\n            unsigned tableLog, void* wksp, size_t wkspSize)\n{\n    ZSTD_seqSymbol* const tableDecode = dt+1;\n    U32 const maxSV1 = maxSymbolValue + 1;\n    U32 const tableSize = 1 << tableLog;\n\n    U16* symbolNext = (U16*)wksp;\n    BYTE* spread = (BYTE*)(symbolNext + MaxSeq + 1);\n    U32 highThreshold = tableSize - 1;\n\n\n    /* Sanity Checks */\n    assert(maxSymbolValue <= MaxSeq);\n    assert(tableLog <= MaxFSELog);\n    assert(wkspSize >= ZSTD_BUILD_FSE_TABLE_WKSP_SIZE);\n    (void)wkspSize;\n    /* Init, lay down lowprob symbols */\n    {   ZSTD_seqSymbol_header DTableH;\n        DTableH.tableLog = tableLog;\n        DTableH.fastMode = 1;\n        {   S16 const largeLimit= (S16)(1 << (tableLog-1));\n            U32 s;\n            for (s=0; s<maxSV1; s++) {\n                if (normalizedCounter[s]==-1) {\n                    tableDecode[highThreshold--].baseValue = s;\n                    symbolNext[s] = 1;\n                } else {\n                    if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;\n                    assert(normalizedCounter[s]>=0);\n                    symbolNext[s] = (U16)normalizedCounter[s];\n        }   }   }\n        ZSTD_memcpy(dt, &DTableH, sizeof(DTableH));\n    }\n\n    /* Spread symbols */\n    assert(tableSize <= 512);\n    /* Specialized symbol spreading for the case when there are\n     * no low probability (-1 count) symbols. When compressing\n     * small blocks we avoid low probability symbols to hit this\n     * case, since header decoding speed matters more.\n     */\n    if (highThreshold == tableSize - 1) {\n        size_t const tableMask = tableSize-1;\n        size_t const step = FSE_TABLESTEP(tableSize);\n        /* First lay down the symbols in order.\n         * We use a uint64_t to lay down 8 bytes at a time. This reduces branch\n         * misses since small blocks generally have small table logs, so nearly\n         * all symbols have counts <= 8. We ensure we have 8 bytes at the end of\n         * our buffer to handle the over-write.\n         */\n        {\n            U64 const add = 0x0101010101010101ull;\n            size_t pos = 0;\n            U64 sv = 0;\n            U32 s;\n            for (s=0; s<maxSV1; ++s, sv += add) {\n                int i;\n                int const n = normalizedCounter[s];\n                MEM_write64(spread + pos, sv);\n                for (i = 8; i < n; i += 8) {\n                    MEM_write64(spread + pos + i, sv);\n                }\n                assert(n>=0);\n                pos += (size_t)n;\n            }\n        }\n        /* Now we spread those positions across the table.\n         * The benefit of doing it in two stages is that we avoid the\n         * variable size inner loop, which caused lots of branch misses.\n         * Now we can run through all the positions without any branch misses.\n         * We unroll the loop twice, since that is what empirically worked best.\n         */\n        {\n            size_t position = 0;\n            size_t s;\n            size_t const unroll = 2;\n            assert(tableSize % unroll == 0); /* FSE_MIN_TABLELOG is 5 */\n            for (s = 0; s < (size_t)tableSize; s += unroll) {\n                size_t u;\n                for (u = 0; u < unroll; ++u) {\n                    size_t const uPosition = (position + (u * step)) & tableMask;\n                    tableDecode[uPosition].baseValue = spread[s + u];\n                }\n                position = (position + (unroll * step)) & tableMask;\n            }\n            assert(position == 0);\n        }\n    } else {\n        U32 const tableMask = tableSize-1;\n        U32 const step = FSE_TABLESTEP(tableSize);\n        U32 s, position = 0;\n        for (s=0; s<maxSV1; s++) {\n            int i;\n            int const n = normalizedCounter[s];\n            for (i=0; i<n; i++) {\n                tableDecode[position].baseValue = s;\n                position = (position + step) & tableMask;\n                while (UNLIKELY(position > highThreshold)) position = (position + step) & tableMask;   /* lowprob area */\n        }   }\n        assert(position == 0); /* position must reach all cells once, otherwise normalizedCounter is incorrect */\n    }\n\n    /* Build Decoding table */\n    {\n        U32 u;\n        for (u=0; u<tableSize; u++) {\n            U32 const symbol = tableDecode[u].baseValue;\n            U32 const nextState = symbolNext[symbol]++;\n            tableDecode[u].nbBits = (BYTE) (tableLog - ZSTD_highbit32(nextState) );\n            tableDecode[u].nextState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);\n            assert(nbAdditionalBits[symbol] < 255);\n            tableDecode[u].nbAdditionalBits = nbAdditionalBits[symbol];\n            tableDecode[u].baseValue = baseValue[symbol];\n        }\n    }\n}\n\n/* Avoids the FORCE_INLINE of the _body() function. */\nstatic void ZSTD_buildFSETable_body_default(ZSTD_seqSymbol* dt,\n            const short* normalizedCounter, unsigned maxSymbolValue,\n            const U32* baseValue, const U8* nbAdditionalBits,\n            unsigned tableLog, void* wksp, size_t wkspSize)\n{\n    ZSTD_buildFSETable_body(dt, normalizedCounter, maxSymbolValue,\n            baseValue, nbAdditionalBits, tableLog, wksp, wkspSize);\n}\n\n#if DYNAMIC_BMI2\nBMI2_TARGET_ATTRIBUTE static void ZSTD_buildFSETable_body_bmi2(ZSTD_seqSymbol* dt,\n            const short* normalizedCounter, unsigned maxSymbolValue,\n            const U32* baseValue, const U8* nbAdditionalBits,\n            unsigned tableLog, void* wksp, size_t wkspSize)\n{\n    ZSTD_buildFSETable_body(dt, normalizedCounter, maxSymbolValue,\n            baseValue, nbAdditionalBits, tableLog, wksp, wkspSize);\n}\n#endif\n\nvoid ZSTD_buildFSETable(ZSTD_seqSymbol* dt,\n            const short* normalizedCounter, unsigned maxSymbolValue,\n            const U32* baseValue, const U8* nbAdditionalBits,\n            unsigned tableLog, void* wksp, size_t wkspSize, int bmi2)\n{\n#if DYNAMIC_BMI2\n    if (bmi2) {\n        ZSTD_buildFSETable_body_bmi2(dt, normalizedCounter, maxSymbolValue,\n                baseValue, nbAdditionalBits, tableLog, wksp, wkspSize);\n        return;\n    }\n#endif\n    (void)bmi2;\n    ZSTD_buildFSETable_body_default(dt, normalizedCounter, maxSymbolValue,\n            baseValue, nbAdditionalBits, tableLog, wksp, wkspSize);\n}\n\n\n/*! ZSTD_buildSeqTable() :\n * @return : nb bytes read from src,\n *           or an error code if it fails */\nstatic size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymbol** DTablePtr,\n                                 SymbolEncodingType_e type, unsigned max, U32 maxLog,\n                                 const void* src, size_t srcSize,\n                                 const U32* baseValue, const U8* nbAdditionalBits,\n                                 const ZSTD_seqSymbol* defaultTable, U32 flagRepeatTable,\n                                 int ddictIsCold, int nbSeq, U32* wksp, size_t wkspSize,\n                                 int bmi2)\n{\n    switch(type)\n    {\n    case set_rle :\n        RETURN_ERROR_IF(!srcSize, srcSize_wrong, \"\");\n        RETURN_ERROR_IF((*(const BYTE*)src) > max, corruption_detected, \"\");\n        {   U32 const symbol = *(const BYTE*)src;\n            U32 const baseline = baseValue[symbol];\n            U8 const nbBits = nbAdditionalBits[symbol];\n            ZSTD_buildSeqTable_rle(DTableSpace, baseline, nbBits);\n        }\n        *DTablePtr = DTableSpace;\n        return 1;\n    case set_basic :\n        *DTablePtr = defaultTable;\n        return 0;\n    case set_repeat:\n        RETURN_ERROR_IF(!flagRepeatTable, corruption_detected, \"\");\n        /* prefetch FSE table if used */\n        if (ddictIsCold && (nbSeq > 24 /* heuristic */)) {\n            const void* const pStart = *DTablePtr;\n            size_t const pSize = sizeof(ZSTD_seqSymbol) * (SEQSYMBOL_TABLE_SIZE(maxLog));\n            PREFETCH_AREA(pStart, pSize);\n        }\n        return 0;\n    case set_compressed :\n        {   unsigned tableLog;\n            S16 norm[MaxSeq+1];\n            size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize);\n            RETURN_ERROR_IF(FSE_isError(headerSize), corruption_detected, \"\");\n            RETURN_ERROR_IF(tableLog > maxLog, corruption_detected, \"\");\n            ZSTD_buildFSETable(DTableSpace, norm, max, baseValue, nbAdditionalBits, tableLog, wksp, wkspSize, bmi2);\n            *DTablePtr = DTableSpace;\n            return headerSize;\n        }\n    default :\n        assert(0);\n        RETURN_ERROR(GENERIC, \"impossible\");\n    }\n}\n\nsize_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,\n                             const void* src, size_t srcSize)\n{\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* ip = istart;\n    int nbSeq;\n    DEBUGLOG(5, \"ZSTD_decodeSeqHeaders\");\n\n    /* check */\n    RETURN_ERROR_IF(srcSize < MIN_SEQUENCES_SIZE, srcSize_wrong, \"\");\n\n    /* SeqHead */\n    nbSeq = *ip++;\n    if (nbSeq > 0x7F) {\n        if (nbSeq == 0xFF) {\n            RETURN_ERROR_IF(ip+2 > iend, srcSize_wrong, \"\");\n            nbSeq = MEM_readLE16(ip) + LONGNBSEQ;\n            ip+=2;\n        } else {\n            RETURN_ERROR_IF(ip >= iend, srcSize_wrong, \"\");\n            nbSeq = ((nbSeq-0x80)<<8) + *ip++;\n        }\n    }\n    *nbSeqPtr = nbSeq;\n\n    if (nbSeq == 0) {\n        /* No sequence : section ends immediately */\n        RETURN_ERROR_IF(ip != iend, corruption_detected,\n            \"extraneous data present in the Sequences section\");\n        return (size_t)(ip - istart);\n    }\n\n    /* FSE table descriptors */\n    RETURN_ERROR_IF(ip+1 > iend, srcSize_wrong, \"\"); /* minimum possible size: 1 byte for symbol encoding types */\n    RETURN_ERROR_IF(*ip & 3, corruption_detected, \"\"); /* The last field, Reserved, must be all-zeroes. */\n    {   SymbolEncodingType_e const LLtype = (SymbolEncodingType_e)(*ip >> 6);\n        SymbolEncodingType_e const OFtype = (SymbolEncodingType_e)((*ip >> 4) & 3);\n        SymbolEncodingType_e const MLtype = (SymbolEncodingType_e)((*ip >> 2) & 3);\n        ip++;\n\n        /* Build DTables */\n        assert(ip <= iend);\n        {   size_t const llhSize = ZSTD_buildSeqTable(dctx->entropy.LLTable, &dctx->LLTptr,\n                                                      LLtype, MaxLL, LLFSELog,\n                                                      ip, (size_t)(iend-ip),\n                                                      LL_base, LL_bits,\n                                                      LL_defaultDTable, dctx->fseEntropy,\n                                                      dctx->ddictIsCold, nbSeq,\n                                                      dctx->workspace, sizeof(dctx->workspace),\n                                                      ZSTD_DCtx_get_bmi2(dctx));\n            RETURN_ERROR_IF(ZSTD_isError(llhSize), corruption_detected, \"ZSTD_buildSeqTable failed\");\n            ip += llhSize;\n        }\n\n        assert(ip <= iend);\n        {   size_t const ofhSize = ZSTD_buildSeqTable(dctx->entropy.OFTable, &dctx->OFTptr,\n                                                      OFtype, MaxOff, OffFSELog,\n                                                      ip, (size_t)(iend-ip),\n                                                      OF_base, OF_bits,\n                                                      OF_defaultDTable, dctx->fseEntropy,\n                                                      dctx->ddictIsCold, nbSeq,\n                                                      dctx->workspace, sizeof(dctx->workspace),\n                                                      ZSTD_DCtx_get_bmi2(dctx));\n            RETURN_ERROR_IF(ZSTD_isError(ofhSize), corruption_detected, \"ZSTD_buildSeqTable failed\");\n            ip += ofhSize;\n        }\n\n        assert(ip <= iend);\n        {   size_t const mlhSize = ZSTD_buildSeqTable(dctx->entropy.MLTable, &dctx->MLTptr,\n                                                      MLtype, MaxML, MLFSELog,\n                                                      ip, (size_t)(iend-ip),\n                                                      ML_base, ML_bits,\n                                                      ML_defaultDTable, dctx->fseEntropy,\n                                                      dctx->ddictIsCold, nbSeq,\n                                                      dctx->workspace, sizeof(dctx->workspace),\n                                                      ZSTD_DCtx_get_bmi2(dctx));\n            RETURN_ERROR_IF(ZSTD_isError(mlhSize), corruption_detected, \"ZSTD_buildSeqTable failed\");\n            ip += mlhSize;\n        }\n    }\n\n    return (size_t)(ip-istart);\n}\n\n\ntypedef struct {\n    size_t litLength;\n    size_t matchLength;\n    size_t offset;\n} seq_t;\n\ntypedef struct {\n    size_t state;\n    const ZSTD_seqSymbol* table;\n} ZSTD_fseState;\n\ntypedef struct {\n    BIT_DStream_t DStream;\n    ZSTD_fseState stateLL;\n    ZSTD_fseState stateOffb;\n    ZSTD_fseState stateML;\n    size_t prevOffset[ZSTD_REP_NUM];\n} seqState_t;\n\n/*! ZSTD_overlapCopy8() :\n *  Copies 8 bytes from ip to op and updates op and ip where ip <= op.\n *  If the offset is < 8 then the offset is spread to at least 8 bytes.\n *\n *  Precondition: *ip <= *op\n *  Postcondition: *op - *op >= 8\n */\nHINT_INLINE void ZSTD_overlapCopy8(BYTE** op, BYTE const** ip, size_t offset)\n{\n    assert(*ip <= *op);\n    if (offset < 8) {\n        /* close range match, overlap */\n        static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 };   /* added */\n        static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 };   /* subtracted */\n        int const sub2 = dec64table[offset];\n        (*op)[0] = (*ip)[0];\n        (*op)[1] = (*ip)[1];\n        (*op)[2] = (*ip)[2];\n        (*op)[3] = (*ip)[3];\n        *ip += dec32table[offset];\n        ZSTD_copy4(*op+4, *ip);\n        *ip -= sub2;\n    } else {\n        ZSTD_copy8(*op, *ip);\n    }\n    *ip += 8;\n    *op += 8;\n    assert(*op - *ip >= 8);\n}\n\n/*! ZSTD_safecopy() :\n *  Specialized version of memcpy() that is allowed to READ up to WILDCOPY_OVERLENGTH past the input buffer\n *  and write up to 16 bytes past oend_w (op >= oend_w is allowed).\n *  This function is only called in the uncommon case where the sequence is near the end of the block. It\n *  should be fast for a single long sequence, but can be slow for several short sequences.\n *\n *  @param ovtype controls the overlap detection\n *         - ZSTD_no_overlap: The source and destination are guaranteed to be at least WILDCOPY_VECLEN bytes apart.\n *         - ZSTD_overlap_src_before_dst: The src and dst may overlap and may be any distance apart.\n *           The src buffer must be before the dst buffer.\n */\nstatic void\nZSTD_safecopy(BYTE* op, const BYTE* const oend_w, BYTE const* ip, size_t length, ZSTD_overlap_e ovtype)\n{\n    ptrdiff_t const diff = op - ip;\n    BYTE* const oend = op + length;\n\n    assert((ovtype == ZSTD_no_overlap && (diff <= -8 || diff >= 8 || op >= oend_w)) ||\n           (ovtype == ZSTD_overlap_src_before_dst && diff >= 0));\n\n    if (length < 8) {\n        /* Handle short lengths. */\n        while (op < oend) *op++ = *ip++;\n        return;\n    }\n    if (ovtype == ZSTD_overlap_src_before_dst) {\n        /* Copy 8 bytes and ensure the offset >= 8 when there can be overlap. */\n        assert(length >= 8);\n        assert(diff > 0);\n        ZSTD_overlapCopy8(&op, &ip, (size_t)diff);\n        length -= 8;\n        assert(op - ip >= 8);\n        assert(op <= oend);\n    }\n\n    if (oend <= oend_w) {\n        /* No risk of overwrite. */\n        ZSTD_wildcopy(op, ip, length, ovtype);\n        return;\n    }\n    if (op <= oend_w) {\n        /* Wildcopy until we get close to the end. */\n        assert(oend > oend_w);\n        ZSTD_wildcopy(op, ip, (size_t)(oend_w - op), ovtype);\n        ip += oend_w - op;\n        op += oend_w - op;\n    }\n    /* Handle the leftovers. */\n    while (op < oend) *op++ = *ip++;\n}\n\n/* ZSTD_safecopyDstBeforeSrc():\n * This version allows overlap with dst before src, or handles the non-overlap case with dst after src\n * Kept separate from more common ZSTD_safecopy case to avoid performance impact to the safecopy common case */\nstatic void ZSTD_safecopyDstBeforeSrc(BYTE* op, const BYTE* ip, size_t length)\n{\n    ptrdiff_t const diff = op - ip;\n    BYTE* const oend = op + length;\n\n    if (length < 8 || diff > -8) {\n        /* Handle short lengths, close overlaps, and dst not before src. */\n        while (op < oend) *op++ = *ip++;\n        return;\n    }\n\n    if (op <= oend - WILDCOPY_OVERLENGTH && diff < -WILDCOPY_VECLEN) {\n        ZSTD_wildcopy(op, ip, (size_t)(oend - WILDCOPY_OVERLENGTH - op), ZSTD_no_overlap);\n        ip += oend - WILDCOPY_OVERLENGTH - op;\n        op += oend - WILDCOPY_OVERLENGTH - op;\n    }\n\n    /* Handle the leftovers. */\n    while (op < oend) *op++ = *ip++;\n}\n\n/* ZSTD_execSequenceEnd():\n * This version handles cases that are near the end of the output buffer. It requires\n * more careful checks to make sure there is no overflow. By separating out these hard\n * and unlikely cases, we can speed up the common cases.\n *\n * NOTE: This function needs to be fast for a single long sequence, but doesn't need\n * to be optimized for many small sequences, since those fall into ZSTD_execSequence().\n */\nFORCE_NOINLINE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_execSequenceEnd(BYTE* op,\n    BYTE* const oend, seq_t sequence,\n    const BYTE** litPtr, const BYTE* const litLimit,\n    const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd)\n{\n    BYTE* const oLitEnd = op + sequence.litLength;\n    size_t const sequenceLength = sequence.litLength + sequence.matchLength;\n    const BYTE* const iLitEnd = *litPtr + sequence.litLength;\n    const BYTE* match = oLitEnd - sequence.offset;\n    BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH;\n\n    /* bounds checks : careful of address space overflow in 32-bit mode */\n    RETURN_ERROR_IF(sequenceLength > (size_t)(oend - op), dstSize_tooSmall, \"last match must fit within dstBuffer\");\n    RETURN_ERROR_IF(sequence.litLength > (size_t)(litLimit - *litPtr), corruption_detected, \"try to read beyond literal buffer\");\n    assert(op < op + sequenceLength);\n    assert(oLitEnd < op + sequenceLength);\n\n    /* copy literals */\n    ZSTD_safecopy(op, oend_w, *litPtr, sequence.litLength, ZSTD_no_overlap);\n    op = oLitEnd;\n    *litPtr = iLitEnd;\n\n    /* copy Match */\n    if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {\n        /* offset beyond prefix */\n        RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - virtualStart), corruption_detected, \"\");\n        match = dictEnd - (prefixStart - match);\n        if (match + sequence.matchLength <= dictEnd) {\n            ZSTD_memmove(oLitEnd, match, sequence.matchLength);\n            return sequenceLength;\n        }\n        /* span extDict & currentPrefixSegment */\n        {   size_t const length1 = (size_t)(dictEnd - match);\n            ZSTD_memmove(oLitEnd, match, length1);\n            op = oLitEnd + length1;\n            sequence.matchLength -= length1;\n            match = prefixStart;\n        }\n    }\n    ZSTD_safecopy(op, oend_w, match, sequence.matchLength, ZSTD_overlap_src_before_dst);\n    return sequenceLength;\n}\n\n/* ZSTD_execSequenceEndSplitLitBuffer():\n * This version is intended to be used during instances where the litBuffer is still split.  It is kept separate to avoid performance impact for the good case.\n */\nFORCE_NOINLINE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_execSequenceEndSplitLitBuffer(BYTE* op,\n    BYTE* const oend, const BYTE* const oend_w, seq_t sequence,\n    const BYTE** litPtr, const BYTE* const litLimit,\n    const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd)\n{\n    BYTE* const oLitEnd = op + sequence.litLength;\n    size_t const sequenceLength = sequence.litLength + sequence.matchLength;\n    const BYTE* const iLitEnd = *litPtr + sequence.litLength;\n    const BYTE* match = oLitEnd - sequence.offset;\n\n\n    /* bounds checks : careful of address space overflow in 32-bit mode */\n    RETURN_ERROR_IF(sequenceLength > (size_t)(oend - op), dstSize_tooSmall, \"last match must fit within dstBuffer\");\n    RETURN_ERROR_IF(sequence.litLength > (size_t)(litLimit - *litPtr), corruption_detected, \"try to read beyond literal buffer\");\n    assert(op < op + sequenceLength);\n    assert(oLitEnd < op + sequenceLength);\n\n    /* copy literals */\n    RETURN_ERROR_IF(op > *litPtr && op < *litPtr + sequence.litLength, dstSize_tooSmall, \"output should not catch up to and overwrite literal buffer\");\n    ZSTD_safecopyDstBeforeSrc(op, *litPtr, sequence.litLength);\n    op = oLitEnd;\n    *litPtr = iLitEnd;\n\n    /* copy Match */\n    if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {\n        /* offset beyond prefix */\n        RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - virtualStart), corruption_detected, \"\");\n        match = dictEnd - (prefixStart - match);\n        if (match + sequence.matchLength <= dictEnd) {\n            ZSTD_memmove(oLitEnd, match, sequence.matchLength);\n            return sequenceLength;\n        }\n        /* span extDict & currentPrefixSegment */\n        {   size_t const length1 = (size_t)(dictEnd - match);\n            ZSTD_memmove(oLitEnd, match, length1);\n            op = oLitEnd + length1;\n            sequence.matchLength -= length1;\n            match = prefixStart;\n        }\n    }\n    ZSTD_safecopy(op, oend_w, match, sequence.matchLength, ZSTD_overlap_src_before_dst);\n    return sequenceLength;\n}\n\nHINT_INLINE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_execSequence(BYTE* op,\n    BYTE* const oend, seq_t sequence,\n    const BYTE** litPtr, const BYTE* const litLimit,\n    const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd)\n{\n    BYTE* const oLitEnd = op + sequence.litLength;\n    size_t const sequenceLength = sequence.litLength + sequence.matchLength;\n    BYTE* const oMatchEnd = op + sequenceLength;   /* risk : address space overflow (32-bits) */\n    BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH;   /* risk : address space underflow on oend=NULL */\n    const BYTE* const iLitEnd = *litPtr + sequence.litLength;\n    const BYTE* match = oLitEnd - sequence.offset;\n\n    assert(op != NULL /* Precondition */);\n    assert(oend_w < oend /* No underflow */);\n\n#if defined(__aarch64__)\n    /* prefetch sequence starting from match that will be used for copy later */\n    PREFETCH_L1(match);\n#endif\n    /* Handle edge cases in a slow path:\n     *   - Read beyond end of literals\n     *   - Match end is within WILDCOPY_OVERLIMIT of oend\n     *   - 32-bit mode and the match length overflows\n     */\n    if (UNLIKELY(\n        iLitEnd > litLimit ||\n        oMatchEnd > oend_w ||\n        (MEM_32bits() && (size_t)(oend - op) < sequenceLength + WILDCOPY_OVERLENGTH)))\n        return ZSTD_execSequenceEnd(op, oend, sequence, litPtr, litLimit, prefixStart, virtualStart, dictEnd);\n\n    /* Assumptions (everything else goes into ZSTD_execSequenceEnd()) */\n    assert(op <= oLitEnd /* No overflow */);\n    assert(oLitEnd < oMatchEnd /* Non-zero match & no overflow */);\n    assert(oMatchEnd <= oend /* No underflow */);\n    assert(iLitEnd <= litLimit /* Literal length is in bounds */);\n    assert(oLitEnd <= oend_w /* Can wildcopy literals */);\n    assert(oMatchEnd <= oend_w /* Can wildcopy matches */);\n\n    /* Copy Literals:\n     * Split out litLength <= 16 since it is nearly always true. +1.6% on gcc-9.\n     * We likely don't need the full 32-byte wildcopy.\n     */\n    assert(WILDCOPY_OVERLENGTH >= 16);\n    ZSTD_copy16(op, (*litPtr));\n    if (UNLIKELY(sequence.litLength > 16)) {\n        ZSTD_wildcopy(op + 16, (*litPtr) + 16, sequence.litLength - 16, ZSTD_no_overlap);\n    }\n    op = oLitEnd;\n    *litPtr = iLitEnd;   /* update for next sequence */\n\n    /* Copy Match */\n    if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {\n        /* offset beyond prefix -> go into extDict */\n        RETURN_ERROR_IF(UNLIKELY(sequence.offset > (size_t)(oLitEnd - virtualStart)), corruption_detected, \"\");\n        match = dictEnd + (match - prefixStart);\n        if (match + sequence.matchLength <= dictEnd) {\n            ZSTD_memmove(oLitEnd, match, sequence.matchLength);\n            return sequenceLength;\n        }\n        /* span extDict & currentPrefixSegment */\n        {   size_t const length1 = (size_t)(dictEnd - match);\n            ZSTD_memmove(oLitEnd, match, length1);\n            op = oLitEnd + length1;\n            sequence.matchLength -= length1;\n            match = prefixStart;\n        }\n    }\n    /* Match within prefix of 1 or more bytes */\n    assert(op <= oMatchEnd);\n    assert(oMatchEnd <= oend_w);\n    assert(match >= prefixStart);\n    assert(sequence.matchLength >= 1);\n\n    /* Nearly all offsets are >= WILDCOPY_VECLEN bytes, which means we can use wildcopy\n     * without overlap checking.\n     */\n    if (LIKELY(sequence.offset >= WILDCOPY_VECLEN)) {\n        /* We bet on a full wildcopy for matches, since we expect matches to be\n         * longer than literals (in general). In silesia, ~10% of matches are longer\n         * than 16 bytes.\n         */\n        ZSTD_wildcopy(op, match, sequence.matchLength, ZSTD_no_overlap);\n        return sequenceLength;\n    }\n    assert(sequence.offset < WILDCOPY_VECLEN);\n\n    /* Copy 8 bytes and spread the offset to be >= 8. */\n    ZSTD_overlapCopy8(&op, &match, sequence.offset);\n\n    /* If the match length is > 8 bytes, then continue with the wildcopy. */\n    if (sequence.matchLength > 8) {\n        assert(op < oMatchEnd);\n        ZSTD_wildcopy(op, match, sequence.matchLength - 8, ZSTD_overlap_src_before_dst);\n    }\n    return sequenceLength;\n}\n\nHINT_INLINE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_execSequenceSplitLitBuffer(BYTE* op,\n    BYTE* const oend, const BYTE* const oend_w, seq_t sequence,\n    const BYTE** litPtr, const BYTE* const litLimit,\n    const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd)\n{\n    BYTE* const oLitEnd = op + sequence.litLength;\n    size_t const sequenceLength = sequence.litLength + sequence.matchLength;\n    BYTE* const oMatchEnd = op + sequenceLength;   /* risk : address space overflow (32-bits) */\n    const BYTE* const iLitEnd = *litPtr + sequence.litLength;\n    const BYTE* match = oLitEnd - sequence.offset;\n\n    assert(op != NULL /* Precondition */);\n    assert(oend_w < oend /* No underflow */);\n    /* Handle edge cases in a slow path:\n     *   - Read beyond end of literals\n     *   - Match end is within WILDCOPY_OVERLIMIT of oend\n     *   - 32-bit mode and the match length overflows\n     */\n    if (UNLIKELY(\n            iLitEnd > litLimit ||\n            oMatchEnd > oend_w ||\n            (MEM_32bits() && (size_t)(oend - op) < sequenceLength + WILDCOPY_OVERLENGTH)))\n        return ZSTD_execSequenceEndSplitLitBuffer(op, oend, oend_w, sequence, litPtr, litLimit, prefixStart, virtualStart, dictEnd);\n\n    /* Assumptions (everything else goes into ZSTD_execSequenceEnd()) */\n    assert(op <= oLitEnd /* No overflow */);\n    assert(oLitEnd < oMatchEnd /* Non-zero match & no overflow */);\n    assert(oMatchEnd <= oend /* No underflow */);\n    assert(iLitEnd <= litLimit /* Literal length is in bounds */);\n    assert(oLitEnd <= oend_w /* Can wildcopy literals */);\n    assert(oMatchEnd <= oend_w /* Can wildcopy matches */);\n\n    /* Copy Literals:\n     * Split out litLength <= 16 since it is nearly always true. +1.6% on gcc-9.\n     * We likely don't need the full 32-byte wildcopy.\n     */\n    assert(WILDCOPY_OVERLENGTH >= 16);\n    ZSTD_copy16(op, (*litPtr));\n    if (UNLIKELY(sequence.litLength > 16)) {\n        ZSTD_wildcopy(op+16, (*litPtr)+16, sequence.litLength-16, ZSTD_no_overlap);\n    }\n    op = oLitEnd;\n    *litPtr = iLitEnd;   /* update for next sequence */\n\n    /* Copy Match */\n    if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {\n        /* offset beyond prefix -> go into extDict */\n        RETURN_ERROR_IF(UNLIKELY(sequence.offset > (size_t)(oLitEnd - virtualStart)), corruption_detected, \"\");\n        match = dictEnd + (match - prefixStart);\n        if (match + sequence.matchLength <= dictEnd) {\n            ZSTD_memmove(oLitEnd, match, sequence.matchLength);\n            return sequenceLength;\n        }\n        /* span extDict & currentPrefixSegment */\n        {   size_t const length1 = (size_t)(dictEnd - match);\n            ZSTD_memmove(oLitEnd, match, length1);\n            op = oLitEnd + length1;\n            sequence.matchLength -= length1;\n            match = prefixStart;\n    }   }\n    /* Match within prefix of 1 or more bytes */\n    assert(op <= oMatchEnd);\n    assert(oMatchEnd <= oend_w);\n    assert(match >= prefixStart);\n    assert(sequence.matchLength >= 1);\n\n    /* Nearly all offsets are >= WILDCOPY_VECLEN bytes, which means we can use wildcopy\n     * without overlap checking.\n     */\n    if (LIKELY(sequence.offset >= WILDCOPY_VECLEN)) {\n        /* We bet on a full wildcopy for matches, since we expect matches to be\n         * longer than literals (in general). In silesia, ~10% of matches are longer\n         * than 16 bytes.\n         */\n        ZSTD_wildcopy(op, match, sequence.matchLength, ZSTD_no_overlap);\n        return sequenceLength;\n    }\n    assert(sequence.offset < WILDCOPY_VECLEN);\n\n    /* Copy 8 bytes and spread the offset to be >= 8. */\n    ZSTD_overlapCopy8(&op, &match, sequence.offset);\n\n    /* If the match length is > 8 bytes, then continue with the wildcopy. */\n    if (sequence.matchLength > 8) {\n        assert(op < oMatchEnd);\n        ZSTD_wildcopy(op, match, sequence.matchLength-8, ZSTD_overlap_src_before_dst);\n    }\n    return sequenceLength;\n}\n\n\nstatic void\nZSTD_initFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, const ZSTD_seqSymbol* dt)\n{\n    const void* ptr = dt;\n    const ZSTD_seqSymbol_header* const DTableH = (const ZSTD_seqSymbol_header*)ptr;\n    DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog);\n    DEBUGLOG(6, \"ZSTD_initFseState : val=%u using %u bits\",\n                (U32)DStatePtr->state, DTableH->tableLog);\n    BIT_reloadDStream(bitD);\n    DStatePtr->table = dt + 1;\n}\n\nFORCE_INLINE_TEMPLATE void\nZSTD_updateFseStateWithDInfo(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, U16 nextState, U32 nbBits)\n{\n    size_t const lowBits = BIT_readBits(bitD, nbBits);\n    DStatePtr->state = nextState + lowBits;\n}\n\n/* We need to add at most (ZSTD_WINDOWLOG_MAX_32 - 1) bits to read the maximum\n * offset bits. But we can only read at most STREAM_ACCUMULATOR_MIN_32\n * bits before reloading. This value is the maximum number of bytes we read\n * after reloading when we are decoding long offsets.\n */\n#define LONG_OFFSETS_MAX_EXTRA_BITS_32                       \\\n    (ZSTD_WINDOWLOG_MAX_32 > STREAM_ACCUMULATOR_MIN_32       \\\n        ? ZSTD_WINDOWLOG_MAX_32 - STREAM_ACCUMULATOR_MIN_32  \\\n        : 0)\n\ntypedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset_e;\n\n/**\n * ZSTD_decodeSequence():\n * @p longOffsets : tells the decoder to reload more bit while decoding large offsets\n *                  only used in 32-bit mode\n * @return : Sequence (litL + matchL + offset)\n */\nFORCE_INLINE_TEMPLATE seq_t\nZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, const int isLastSeq)\n{\n    seq_t seq;\n#if defined(__aarch64__)\n    size_t prevOffset0 = seqState->prevOffset[0];\n    size_t prevOffset1 = seqState->prevOffset[1];\n    size_t prevOffset2 = seqState->prevOffset[2];\n    /*\n     * ZSTD_seqSymbol is a 64 bits wide structure.\n     * It can be loaded in one operation\n     * and its fields extracted by simply shifting or bit-extracting on aarch64.\n     * GCC doesn't recognize this and generates more unnecessary ldr/ldrb/ldrh\n     * operations that cause performance drop. This can be avoided by using this\n     * ZSTD_memcpy hack.\n     */\n#  if defined(__GNUC__) && !defined(__clang__)\n    ZSTD_seqSymbol llDInfoS, mlDInfoS, ofDInfoS;\n    ZSTD_seqSymbol* const llDInfo = &llDInfoS;\n    ZSTD_seqSymbol* const mlDInfo = &mlDInfoS;\n    ZSTD_seqSymbol* const ofDInfo = &ofDInfoS;\n    ZSTD_memcpy(llDInfo, seqState->stateLL.table + seqState->stateLL.state, sizeof(ZSTD_seqSymbol));\n    ZSTD_memcpy(mlDInfo, seqState->stateML.table + seqState->stateML.state, sizeof(ZSTD_seqSymbol));\n    ZSTD_memcpy(ofDInfo, seqState->stateOffb.table + seqState->stateOffb.state, sizeof(ZSTD_seqSymbol));\n#  else\n    const ZSTD_seqSymbol* const llDInfo = seqState->stateLL.table + seqState->stateLL.state;\n    const ZSTD_seqSymbol* const mlDInfo = seqState->stateML.table + seqState->stateML.state;\n    const ZSTD_seqSymbol* const ofDInfo = seqState->stateOffb.table + seqState->stateOffb.state;\n#  endif\n    (void)longOffsets;\n    seq.matchLength = mlDInfo->baseValue;\n    seq.litLength = llDInfo->baseValue;\n    {   U32 const ofBase = ofDInfo->baseValue;\n        BYTE const llBits = llDInfo->nbAdditionalBits;\n        BYTE const mlBits = mlDInfo->nbAdditionalBits;\n        BYTE const ofBits = ofDInfo->nbAdditionalBits;\n        BYTE const totalBits = llBits+mlBits+ofBits;\n\n        U16 const llNext = llDInfo->nextState;\n        U16 const mlNext = mlDInfo->nextState;\n        U16 const ofNext = ofDInfo->nextState;\n        U32 const llnbBits = llDInfo->nbBits;\n        U32 const mlnbBits = mlDInfo->nbBits;\n        U32 const ofnbBits = ofDInfo->nbBits;\n\n        assert(llBits <= MaxLLBits);\n        assert(mlBits <= MaxMLBits);\n        assert(ofBits <= MaxOff);\n        /* As GCC has better branch and block analyzers, sometimes it is only\n         * valuable to mark likeliness for Clang.\n         */\n\n        /* sequence */\n        {   size_t offset;\n            if (ofBits > 1) {\n                ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);\n                ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5);\n                ZSTD_STATIC_ASSERT(STREAM_ACCUMULATOR_MIN_32 > LONG_OFFSETS_MAX_EXTRA_BITS_32);\n                ZSTD_STATIC_ASSERT(STREAM_ACCUMULATOR_MIN_32 - LONG_OFFSETS_MAX_EXTRA_BITS_32 >= MaxMLBits);\n                offset = ofBase + BIT_readBitsFast(&seqState->DStream, ofBits/*>0*/);   /* <=  (ZSTD_WINDOWLOG_MAX-1) bits */\n                prevOffset2 = prevOffset1;\n                prevOffset1 = prevOffset0;\n                prevOffset0 = offset;\n            } else {\n                U32 const ll0 = (llDInfo->baseValue == 0);\n                if (LIKELY((ofBits == 0))) {\n                    if (ll0) {\n                        offset = prevOffset1;\n                        prevOffset1 = prevOffset0;\n                        prevOffset0 = offset;\n                    } else {\n                        offset = prevOffset0;\n                    }\n                } else {\n                    offset = ofBase + ll0 + BIT_readBitsFast(&seqState->DStream, 1);\n                    {   size_t temp = (offset == 1)   ? prevOffset1\n                                      : (offset == 3) ? prevOffset0 - 1\n                                      : (offset >= 2) ? prevOffset2\n                                      : prevOffset0;\n                        /* 0 is not valid: input corrupted => force offset to -1 =>\n                         * corruption detected at execSequence.\n                         */\n                        temp -= !temp;\n                        prevOffset2 = (offset == 1) ? prevOffset2 : prevOffset1;\n                        prevOffset1 = prevOffset0;\n                        prevOffset0 = offset = temp;\n            }   }   }\n            seq.offset = offset;\n        }\n\n        if (mlBits > 0)\n            seq.matchLength += BIT_readBitsFast(&seqState->DStream, mlBits/*>0*/);\n\n        if (UNLIKELY(totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog)))\n            BIT_reloadDStream(&seqState->DStream);\n\n        /* Ensure there are enough bits to read the rest of data in 64-bit mode. */\n        ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64);\n\n        if (llBits > 0)\n            seq.litLength += BIT_readBitsFast(&seqState->DStream, llBits/*>0*/);\n\n        DEBUGLOG(6, \"seq: litL=%u, matchL=%u, offset=%u\",\n                    (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);\n\n        if (!isLastSeq) {\n            /* Don't update FSE state for last sequence. */\n            ZSTD_updateFseStateWithDInfo(&seqState->stateLL, &seqState->DStream, llNext, llnbBits);    /* <=  9 bits */\n            ZSTD_updateFseStateWithDInfo(&seqState->stateML, &seqState->DStream, mlNext, mlnbBits);    /* <=  9 bits */\n            ZSTD_updateFseStateWithDInfo(&seqState->stateOffb, &seqState->DStream, ofNext, ofnbBits);  /* <=  8 bits */\n            BIT_reloadDStream(&seqState->DStream);\n        }\n    }\n    seqState->prevOffset[0] = prevOffset0;\n    seqState->prevOffset[1] = prevOffset1;\n    seqState->prevOffset[2] = prevOffset2;\n#else   /* !defined(__aarch64__) */\n    const ZSTD_seqSymbol* const llDInfo = seqState->stateLL.table + seqState->stateLL.state;\n    const ZSTD_seqSymbol* const mlDInfo = seqState->stateML.table + seqState->stateML.state;\n    const ZSTD_seqSymbol* const ofDInfo = seqState->stateOffb.table + seqState->stateOffb.state;\n    seq.matchLength = mlDInfo->baseValue;\n    seq.litLength = llDInfo->baseValue;\n    {   U32 const ofBase = ofDInfo->baseValue;\n        BYTE const llBits = llDInfo->nbAdditionalBits;\n        BYTE const mlBits = mlDInfo->nbAdditionalBits;\n        BYTE const ofBits = ofDInfo->nbAdditionalBits;\n        BYTE const totalBits = llBits+mlBits+ofBits;\n\n        U16 const llNext = llDInfo->nextState;\n        U16 const mlNext = mlDInfo->nextState;\n        U16 const ofNext = ofDInfo->nextState;\n        U32 const llnbBits = llDInfo->nbBits;\n        U32 const mlnbBits = mlDInfo->nbBits;\n        U32 const ofnbBits = ofDInfo->nbBits;\n\n        assert(llBits <= MaxLLBits);\n        assert(mlBits <= MaxMLBits);\n        assert(ofBits <= MaxOff);\n        /* As GCC has better branch and block analyzers, sometimes it is only\n         * valuable to mark likeliness for Clang.\n         */\n\n        /* sequence */\n        {   size_t offset;\n            if (ofBits > 1) {\n                ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);\n                ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5);\n                ZSTD_STATIC_ASSERT(STREAM_ACCUMULATOR_MIN_32 > LONG_OFFSETS_MAX_EXTRA_BITS_32);\n                ZSTD_STATIC_ASSERT(STREAM_ACCUMULATOR_MIN_32 - LONG_OFFSETS_MAX_EXTRA_BITS_32 >= MaxMLBits);\n                if (MEM_32bits() && longOffsets && (ofBits >= STREAM_ACCUMULATOR_MIN_32)) {\n                    /* Always read extra bits, this keeps the logic simple,\n                     * avoids branches, and avoids accidentally reading 0 bits.\n                     */\n                    U32 const extraBits = LONG_OFFSETS_MAX_EXTRA_BITS_32;\n                    offset = ofBase + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);\n                    BIT_reloadDStream(&seqState->DStream);\n                    offset += BIT_readBitsFast(&seqState->DStream, extraBits);\n                } else {\n                    offset = ofBase + BIT_readBitsFast(&seqState->DStream, ofBits/*>0*/);   /* <=  (ZSTD_WINDOWLOG_MAX-1) bits */\n                    if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);\n                }\n                seqState->prevOffset[2] = seqState->prevOffset[1];\n                seqState->prevOffset[1] = seqState->prevOffset[0];\n                seqState->prevOffset[0] = offset;\n            } else {\n                U32 const ll0 = (llDInfo->baseValue == 0);\n                if (LIKELY((ofBits == 0))) {\n                    offset = seqState->prevOffset[ll0];\n                    seqState->prevOffset[1] = seqState->prevOffset[!ll0];\n                    seqState->prevOffset[0] = offset;\n                } else {\n                    offset = ofBase + ll0 + BIT_readBitsFast(&seqState->DStream, 1);\n                    {   size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset];\n                        temp -= !temp; /* 0 is not valid: input corrupted => force offset to -1 => corruption detected at execSequence */\n                        if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1];\n                        seqState->prevOffset[1] = seqState->prevOffset[0];\n                        seqState->prevOffset[0] = offset = temp;\n            }   }   }\n            seq.offset = offset;\n        }\n\n        if (mlBits > 0)\n            seq.matchLength += BIT_readBitsFast(&seqState->DStream, mlBits/*>0*/);\n\n        if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32))\n            BIT_reloadDStream(&seqState->DStream);\n        if (MEM_64bits() && UNLIKELY(totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog)))\n            BIT_reloadDStream(&seqState->DStream);\n        /* Ensure there are enough bits to read the rest of data in 64-bit mode. */\n        ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64);\n\n        if (llBits > 0)\n            seq.litLength += BIT_readBitsFast(&seqState->DStream, llBits/*>0*/);\n\n        if (MEM_32bits())\n            BIT_reloadDStream(&seqState->DStream);\n\n        DEBUGLOG(6, \"seq: litL=%u, matchL=%u, offset=%u\",\n                    (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);\n\n        if (!isLastSeq) {\n            /* Don't update FSE state for last sequence. */\n            ZSTD_updateFseStateWithDInfo(&seqState->stateLL, &seqState->DStream, llNext, llnbBits);    /* <=  9 bits */\n            ZSTD_updateFseStateWithDInfo(&seqState->stateML, &seqState->DStream, mlNext, mlnbBits);    /* <=  9 bits */\n            if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);    /* <= 18 bits */\n            ZSTD_updateFseStateWithDInfo(&seqState->stateOffb, &seqState->DStream, ofNext, ofnbBits);  /* <=  8 bits */\n            BIT_reloadDStream(&seqState->DStream);\n        }\n    }\n#endif  /* defined(__aarch64__) */\n\n    return seq;\n}\n\n#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)\n#if DEBUGLEVEL >= 1\nstatic int ZSTD_dictionaryIsActive(ZSTD_DCtx const* dctx, BYTE const* prefixStart, BYTE const* oLitEnd)\n{\n    size_t const windowSize = dctx->fParams.windowSize;\n    /* No dictionary used. */\n    if (dctx->dictContentEndForFuzzing == NULL) return 0;\n    /* Dictionary is our prefix. */\n    if (prefixStart == dctx->dictContentBeginForFuzzing) return 1;\n    /* Dictionary is not our ext-dict. */\n    if (dctx->dictEnd != dctx->dictContentEndForFuzzing) return 0;\n    /* Dictionary is not within our window size. */\n    if ((size_t)(oLitEnd - prefixStart) >= windowSize) return 0;\n    /* Dictionary is active. */\n    return 1;\n}\n#endif\n\nstatic void ZSTD_assertValidSequence(\n        ZSTD_DCtx const* dctx,\n        BYTE const* op, BYTE const* oend,\n        seq_t const seq,\n        BYTE const* prefixStart, BYTE const* virtualStart)\n{\n#if DEBUGLEVEL >= 1\n    if (dctx->isFrameDecompression) {\n        size_t const windowSize = dctx->fParams.windowSize;\n        size_t const sequenceSize = seq.litLength + seq.matchLength;\n        BYTE const* const oLitEnd = op + seq.litLength;\n        DEBUGLOG(6, \"Checking sequence: litL=%u matchL=%u offset=%u\",\n                (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);\n        assert(op <= oend);\n        assert((size_t)(oend - op) >= sequenceSize);\n        assert(sequenceSize <= ZSTD_blockSizeMax(dctx));\n        if (ZSTD_dictionaryIsActive(dctx, prefixStart, oLitEnd)) {\n            size_t const dictSize = (size_t)((char const*)dctx->dictContentEndForFuzzing - (char const*)dctx->dictContentBeginForFuzzing);\n            /* Offset must be within the dictionary. */\n            assert(seq.offset <= (size_t)(oLitEnd - virtualStart));\n            assert(seq.offset <= windowSize + dictSize);\n        } else {\n            /* Offset must be within our window. */\n            assert(seq.offset <= windowSize);\n        }\n    }\n#else\n    (void)dctx, (void)op, (void)oend, (void)seq, (void)prefixStart, (void)virtualStart;\n#endif\n}\n#endif\n\n#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG\n\n\nFORCE_INLINE_TEMPLATE size_t\nDONT_VECTORIZE\nZSTD_decompressSequences_bodySplitLitBuffer( ZSTD_DCtx* dctx,\n                               void* dst, size_t maxDstSize,\n                         const void* seqStart, size_t seqSize, int nbSeq,\n                         const ZSTD_longOffset_e isLongOffset)\n{\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = (BYTE*)ZSTD_maybeNullPtrAdd(ostart, (ptrdiff_t)maxDstSize);\n    BYTE* op = ostart;\n    const BYTE* litPtr = dctx->litPtr;\n    const BYTE* litBufferEnd = dctx->litBufferEnd;\n    const BYTE* const prefixStart = (const BYTE*) (dctx->prefixStart);\n    const BYTE* const vBase = (const BYTE*) (dctx->virtualStart);\n    const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);\n    DEBUGLOG(5, \"ZSTD_decompressSequences_bodySplitLitBuffer (%i seqs)\", nbSeq);\n\n    /* Literals are split between internal buffer & output buffer */\n    if (nbSeq) {\n        seqState_t seqState;\n        dctx->fseEntropy = 1;\n        { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }\n        RETURN_ERROR_IF(\n            ERR_isError(BIT_initDStream(&seqState.DStream, seqStart, seqSize)),\n            corruption_detected, \"\");\n        ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);\n        ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);\n        ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);\n        assert(dst != NULL);\n\n        ZSTD_STATIC_ASSERT(\n                BIT_DStream_unfinished < BIT_DStream_completed &&\n                BIT_DStream_endOfBuffer < BIT_DStream_completed &&\n                BIT_DStream_completed < BIT_DStream_overflow);\n\n        /* decompress without overrunning litPtr begins */\n        {   seq_t sequence = {0,0,0};  /* some static analyzer believe that @sequence is not initialized (it necessarily is, since for(;;) loop as at least one iteration) */\n            /* Align the decompression loop to 32 + 16 bytes.\n                *\n                * zstd compiled with gcc-9 on an Intel i9-9900k shows 10% decompression\n                * speed swings based on the alignment of the decompression loop. This\n                * performance swing is caused by parts of the decompression loop falling\n                * out of the DSB. The entire decompression loop should fit in the DSB,\n                * when it can't we get much worse performance. You can measure if you've\n                * hit the good case or the bad case with this perf command for some\n                * compressed file test.zst:\n                *\n                *   perf stat -e cycles -e instructions -e idq.all_dsb_cycles_any_uops \\\n                *             -e idq.all_mite_cycles_any_uops -- ./zstd -tq test.zst\n                *\n                * If you see most cycles served out of the MITE you've hit the bad case.\n                * If you see most cycles served out of the DSB you've hit the good case.\n                * If it is pretty even then you may be in an okay case.\n                *\n                * This issue has been reproduced on the following CPUs:\n                *   - Kabylake: Macbook Pro (15-inch, 2019) 2.4 GHz Intel Core i9\n                *               Use Instruments->Counters to get DSB/MITE cycles.\n                *               I never got performance swings, but I was able to\n                *               go from the good case of mostly DSB to half of the\n                *               cycles served from MITE.\n                *   - Coffeelake: Intel i9-9900k\n                *   - Coffeelake: Intel i7-9700k\n                *\n                * I haven't been able to reproduce the instability or DSB misses on any\n                * of the following CPUS:\n                *   - Haswell\n                *   - Broadwell: Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GH\n                *   - Skylake\n                *\n                * Alignment is done for each of the three major decompression loops:\n                *   - ZSTD_decompressSequences_bodySplitLitBuffer - presplit section of the literal buffer\n                *   - ZSTD_decompressSequences_bodySplitLitBuffer - postsplit section of the literal buffer\n                *   - ZSTD_decompressSequences_body\n                * Alignment choices are made to minimize large swings on bad cases and influence on performance\n                * from changes external to this code, rather than to overoptimize on the current commit.\n                *\n                * If you are seeing performance stability this script can help test.\n                * It tests on 4 commits in zstd where I saw performance change.\n                *\n                *   https://gist.github.com/terrelln/9889fc06a423fd5ca6e99351564473f4\n                */\n#if defined(__GNUC__) && defined(__x86_64__)\n            __asm__(\".p2align 6\");\n#  if __GNUC__ >= 7\n\t    /* good for gcc-7, gcc-9, and gcc-11 */\n            __asm__(\"nop\");\n            __asm__(\".p2align 5\");\n            __asm__(\"nop\");\n            __asm__(\".p2align 4\");\n#    if __GNUC__ == 8 || __GNUC__ == 10\n\t    /* good for gcc-8 and gcc-10 */\n            __asm__(\"nop\");\n            __asm__(\".p2align 3\");\n#    endif\n#  endif\n#endif\n\n            /* Handle the initial state where litBuffer is currently split between dst and litExtraBuffer */\n            for ( ; nbSeq; nbSeq--) {\n                sequence = ZSTD_decodeSequence(&seqState, isLongOffset, nbSeq==1);\n                if (litPtr + sequence.litLength > dctx->litBufferEnd) break;\n                {   size_t const oneSeqSize = ZSTD_execSequenceSplitLitBuffer(op, oend, litPtr + sequence.litLength - WILDCOPY_OVERLENGTH, sequence, &litPtr, litBufferEnd, prefixStart, vBase, dictEnd);\n#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)\n                    assert(!ZSTD_isError(oneSeqSize));\n                    ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase);\n#endif\n                    if (UNLIKELY(ZSTD_isError(oneSeqSize)))\n                        return oneSeqSize;\n                    DEBUGLOG(6, \"regenerated sequence size : %u\", (U32)oneSeqSize);\n                    op += oneSeqSize;\n            }   }\n            DEBUGLOG(6, \"reached: (litPtr + sequence.litLength > dctx->litBufferEnd)\");\n\n            /* If there are more sequences, they will need to read literals from litExtraBuffer; copy over the remainder from dst and update litPtr and litEnd */\n            if (nbSeq > 0) {\n                const size_t leftoverLit = (size_t)(dctx->litBufferEnd - litPtr);\n                assert(dctx->litBufferEnd >= litPtr);\n                DEBUGLOG(6, \"There are %i sequences left, and %zu/%zu literals left in buffer\", nbSeq, leftoverLit, sequence.litLength);\n                if (leftoverLit) {\n                    RETURN_ERROR_IF(leftoverLit > (size_t)(oend - op), dstSize_tooSmall, \"remaining lit must fit within dstBuffer\");\n                    ZSTD_safecopyDstBeforeSrc(op, litPtr, leftoverLit);\n                    sequence.litLength -= leftoverLit;\n                    op += leftoverLit;\n                }\n                litPtr = dctx->litExtraBuffer;\n                litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE;\n                dctx->litBufferLocation = ZSTD_not_in_dst;\n                {   size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litBufferEnd, prefixStart, vBase, dictEnd);\n#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)\n                    assert(!ZSTD_isError(oneSeqSize));\n                    ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase);\n#endif\n                    if (UNLIKELY(ZSTD_isError(oneSeqSize)))\n                        return oneSeqSize;\n                    DEBUGLOG(6, \"regenerated sequence size : %u\", (U32)oneSeqSize);\n                    op += oneSeqSize;\n                }\n                nbSeq--;\n            }\n        }\n\n        if (nbSeq > 0) {\n            /* there is remaining lit from extra buffer */\n\n#if defined(__GNUC__) && defined(__x86_64__)\n            __asm__(\".p2align 6\");\n            __asm__(\"nop\");\n#  if __GNUC__ != 7\n            /* worse for gcc-7 better for gcc-8, gcc-9, and gcc-10 and clang */\n            __asm__(\".p2align 4\");\n            __asm__(\"nop\");\n            __asm__(\".p2align 3\");\n#  elif __GNUC__ >= 11\n            __asm__(\".p2align 3\");\n#  else\n            __asm__(\".p2align 5\");\n            __asm__(\"nop\");\n            __asm__(\".p2align 3\");\n#  endif\n#endif\n\n            for ( ; nbSeq ; nbSeq--) {\n                seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, nbSeq==1);\n                size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litBufferEnd, prefixStart, vBase, dictEnd);\n#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)\n                assert(!ZSTD_isError(oneSeqSize));\n                ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase);\n#endif\n                if (UNLIKELY(ZSTD_isError(oneSeqSize)))\n                    return oneSeqSize;\n                DEBUGLOG(6, \"regenerated sequence size : %u\", (U32)oneSeqSize);\n                op += oneSeqSize;\n            }\n        }\n\n        /* check if reached exact end */\n        DEBUGLOG(5, \"ZSTD_decompressSequences_bodySplitLitBuffer: after decode loop, remaining nbSeq : %i\", nbSeq);\n        RETURN_ERROR_IF(nbSeq, corruption_detected, \"\");\n        DEBUGLOG(5, \"bitStream : start=%p, ptr=%p, bitsConsumed=%u\", seqState.DStream.start, seqState.DStream.ptr, seqState.DStream.bitsConsumed);\n        RETURN_ERROR_IF(!BIT_endOfDStream(&seqState.DStream), corruption_detected, \"\");\n        /* save reps for next block */\n        { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }\n    }\n\n    /* last literal segment */\n    if (dctx->litBufferLocation == ZSTD_split) {\n        /* split hasn't been reached yet, first get dst then copy litExtraBuffer */\n        size_t const lastLLSize = (size_t)(litBufferEnd - litPtr);\n        DEBUGLOG(6, \"copy last literals from segment : %u\", (U32)lastLLSize);\n        RETURN_ERROR_IF(lastLLSize > (size_t)(oend - op), dstSize_tooSmall, \"\");\n        if (op != NULL) {\n            ZSTD_memmove(op, litPtr, lastLLSize);\n            op += lastLLSize;\n        }\n        litPtr = dctx->litExtraBuffer;\n        litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE;\n        dctx->litBufferLocation = ZSTD_not_in_dst;\n    }\n    /* copy last literals from internal buffer */\n    {   size_t const lastLLSize = (size_t)(litBufferEnd - litPtr);\n        DEBUGLOG(6, \"copy last literals from internal buffer : %u\", (U32)lastLLSize);\n        RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, \"\");\n        if (op != NULL) {\n            ZSTD_memcpy(op, litPtr, lastLLSize);\n            op += lastLLSize;\n    }   }\n\n    DEBUGLOG(6, \"decoded block of size %u bytes\", (U32)(op - ostart));\n    return (size_t)(op - ostart);\n}\n\nFORCE_INLINE_TEMPLATE size_t\nDONT_VECTORIZE\nZSTD_decompressSequences_body(ZSTD_DCtx* dctx,\n    void* dst, size_t maxDstSize,\n    const void* seqStart, size_t seqSize, int nbSeq,\n    const ZSTD_longOffset_e isLongOffset)\n{\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = (dctx->litBufferLocation == ZSTD_not_in_dst) ?\n                        (BYTE*)ZSTD_maybeNullPtrAdd(ostart, (ptrdiff_t)maxDstSize) :\n                        dctx->litBuffer;\n    BYTE* op = ostart;\n    const BYTE* litPtr = dctx->litPtr;\n    const BYTE* const litEnd = litPtr + dctx->litSize;\n    const BYTE* const prefixStart = (const BYTE*)(dctx->prefixStart);\n    const BYTE* const vBase = (const BYTE*)(dctx->virtualStart);\n    const BYTE* const dictEnd = (const BYTE*)(dctx->dictEnd);\n    DEBUGLOG(5, \"ZSTD_decompressSequences_body: nbSeq = %d\", nbSeq);\n\n    /* Regen sequences */\n    if (nbSeq) {\n        seqState_t seqState;\n        dctx->fseEntropy = 1;\n        { U32 i; for (i = 0; i < ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }\n        RETURN_ERROR_IF(\n            ERR_isError(BIT_initDStream(&seqState.DStream, seqStart, seqSize)),\n            corruption_detected, \"\");\n        ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);\n        ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);\n        ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);\n        assert(dst != NULL);\n\n#if defined(__GNUC__) && defined(__x86_64__)\n            __asm__(\".p2align 6\");\n            __asm__(\"nop\");\n#  if __GNUC__ >= 7\n            __asm__(\".p2align 5\");\n            __asm__(\"nop\");\n            __asm__(\".p2align 3\");\n#  else\n            __asm__(\".p2align 4\");\n            __asm__(\"nop\");\n            __asm__(\".p2align 3\");\n#  endif\n#endif\n\n        for ( ; nbSeq ; nbSeq--) {\n            seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, nbSeq==1);\n            size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, prefixStart, vBase, dictEnd);\n#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)\n            assert(!ZSTD_isError(oneSeqSize));\n            ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase);\n#endif\n            if (UNLIKELY(ZSTD_isError(oneSeqSize)))\n                return oneSeqSize;\n            DEBUGLOG(6, \"regenerated sequence size : %u\", (U32)oneSeqSize);\n            op += oneSeqSize;\n        }\n\n        /* check if reached exact end */\n        assert(nbSeq == 0);\n        RETURN_ERROR_IF(!BIT_endOfDStream(&seqState.DStream), corruption_detected, \"\");\n        /* save reps for next block */\n        { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }\n    }\n\n    /* last literal segment */\n    {   size_t const lastLLSize = (size_t)(litEnd - litPtr);\n        DEBUGLOG(6, \"copy last literals : %u\", (U32)lastLLSize);\n        RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, \"\");\n        if (op != NULL) {\n            ZSTD_memcpy(op, litPtr, lastLLSize);\n            op += lastLLSize;\n    }   }\n\n    DEBUGLOG(6, \"decoded block of size %u bytes\", (U32)(op - ostart));\n    return (size_t)(op - ostart);\n}\n\nstatic size_t\nZSTD_decompressSequences_default(ZSTD_DCtx* dctx,\n                                 void* dst, size_t maxDstSize,\n                           const void* seqStart, size_t seqSize, int nbSeq,\n                           const ZSTD_longOffset_e isLongOffset)\n{\n    return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n}\n\nstatic size_t\nZSTD_decompressSequencesSplitLitBuffer_default(ZSTD_DCtx* dctx,\n                                               void* dst, size_t maxDstSize,\n                                         const void* seqStart, size_t seqSize, int nbSeq,\n                                         const ZSTD_longOffset_e isLongOffset)\n{\n    return ZSTD_decompressSequences_bodySplitLitBuffer(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n}\n#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */\n\n#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT\n\nFORCE_INLINE_TEMPLATE\n\nsize_t ZSTD_prefetchMatch(size_t prefetchPos, seq_t const sequence,\n                   const BYTE* const prefixStart, const BYTE* const dictEnd)\n{\n    prefetchPos += sequence.litLength;\n    {   const BYTE* const matchBase = (sequence.offset > prefetchPos) ? dictEnd : prefixStart;\n        /* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted.\n         * No consequence though : memory address is only used for prefetching, not for dereferencing */\n        const BYTE* const match = (const BYTE*)ZSTD_wrappedPtrSub(ZSTD_wrappedPtrAdd(matchBase, (ptrdiff_t)prefetchPos), (ptrdiff_t)sequence.offset);\n        PREFETCH_L1(match); PREFETCH_L1(ZSTD_wrappedPtrAdd(match, CACHELINE_SIZE));   /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */\n    }\n    return prefetchPos + sequence.matchLength;\n}\n\n/* This decoding function employs prefetching\n * to reduce latency impact of cache misses.\n * It's generally employed when block contains a significant portion of long-distance matches\n * or when coupled with a \"cold\" dictionary */\nFORCE_INLINE_TEMPLATE size_t\nZSTD_decompressSequencesLong_body(\n                               ZSTD_DCtx* dctx,\n                               void* dst, size_t maxDstSize,\n                         const void* seqStart, size_t seqSize, int nbSeq,\n                         const ZSTD_longOffset_e isLongOffset)\n{\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = (dctx->litBufferLocation == ZSTD_in_dst) ?\n                        dctx->litBuffer :\n                        (BYTE*)ZSTD_maybeNullPtrAdd(ostart, (ptrdiff_t)maxDstSize);\n    BYTE* op = ostart;\n    const BYTE* litPtr = dctx->litPtr;\n    const BYTE* litBufferEnd = dctx->litBufferEnd;\n    const BYTE* const prefixStart = (const BYTE*) (dctx->prefixStart);\n    const BYTE* const dictStart = (const BYTE*) (dctx->virtualStart);\n    const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);\n\n    /* Regen sequences */\n    if (nbSeq) {\n#define STORED_SEQS 8\n#define STORED_SEQS_MASK (STORED_SEQS-1)\n#define ADVANCED_SEQS STORED_SEQS\n        seq_t sequences[STORED_SEQS];\n        int const seqAdvance = MIN(nbSeq, ADVANCED_SEQS);\n        seqState_t seqState;\n        int seqNb;\n        size_t prefetchPos = (size_t)(op-prefixStart); /* track position relative to prefixStart */\n\n        dctx->fseEntropy = 1;\n        { int i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }\n        assert(dst != NULL);\n        RETURN_ERROR_IF(\n            ERR_isError(BIT_initDStream(&seqState.DStream, seqStart, seqSize)),\n            corruption_detected, \"\");\n        ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);\n        ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);\n        ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);\n\n        /* prepare in advance */\n        for (seqNb=0; seqNb<seqAdvance; seqNb++) {\n            seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, seqNb == nbSeq-1);\n            prefetchPos = ZSTD_prefetchMatch(prefetchPos, sequence, prefixStart, dictEnd);\n            sequences[seqNb] = sequence;\n        }\n\n        /* decompress without stomping litBuffer */\n        for (; seqNb < nbSeq; seqNb++) {\n            seq_t sequence = ZSTD_decodeSequence(&seqState, isLongOffset, seqNb == nbSeq-1);\n\n            if (dctx->litBufferLocation == ZSTD_split && litPtr + sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK].litLength > dctx->litBufferEnd) {\n                /* lit buffer is reaching split point, empty out the first buffer and transition to litExtraBuffer */\n                const size_t leftoverLit = (size_t)(dctx->litBufferEnd - litPtr);\n                assert(dctx->litBufferEnd >= litPtr);\n                if (leftoverLit) {\n                    RETURN_ERROR_IF(leftoverLit > (size_t)(oend - op), dstSize_tooSmall, \"remaining lit must fit within dstBuffer\");\n                    ZSTD_safecopyDstBeforeSrc(op, litPtr, leftoverLit);\n                    sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK].litLength -= leftoverLit;\n                    op += leftoverLit;\n                }\n                litPtr = dctx->litExtraBuffer;\n                litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE;\n                dctx->litBufferLocation = ZSTD_not_in_dst;\n                {   size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd);\n#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)\n                    assert(!ZSTD_isError(oneSeqSize));\n                    ZSTD_assertValidSequence(dctx, op, oend, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], prefixStart, dictStart);\n#endif\n                    if (ZSTD_isError(oneSeqSize)) return oneSeqSize;\n\n                    prefetchPos = ZSTD_prefetchMatch(prefetchPos, sequence, prefixStart, dictEnd);\n                    sequences[seqNb & STORED_SEQS_MASK] = sequence;\n                    op += oneSeqSize;\n            }   }\n            else\n            {\n                /* lit buffer is either wholly contained in first or second split, or not split at all*/\n                size_t const oneSeqSize = dctx->litBufferLocation == ZSTD_split ?\n                    ZSTD_execSequenceSplitLitBuffer(op, oend, litPtr + sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK].litLength - WILDCOPY_OVERLENGTH, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd) :\n                    ZSTD_execSequence(op, oend, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd);\n#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)\n                assert(!ZSTD_isError(oneSeqSize));\n                ZSTD_assertValidSequence(dctx, op, oend, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], prefixStart, dictStart);\n#endif\n                if (ZSTD_isError(oneSeqSize)) return oneSeqSize;\n\n                prefetchPos = ZSTD_prefetchMatch(prefetchPos, sequence, prefixStart, dictEnd);\n                sequences[seqNb & STORED_SEQS_MASK] = sequence;\n                op += oneSeqSize;\n            }\n        }\n        RETURN_ERROR_IF(!BIT_endOfDStream(&seqState.DStream), corruption_detected, \"\");\n\n        /* finish queue */\n        seqNb -= seqAdvance;\n        for ( ; seqNb<nbSeq ; seqNb++) {\n            seq_t *sequence = &(sequences[seqNb&STORED_SEQS_MASK]);\n            if (dctx->litBufferLocation == ZSTD_split && litPtr + sequence->litLength > dctx->litBufferEnd) {\n                const size_t leftoverLit = (size_t)(dctx->litBufferEnd - litPtr);\n                assert(dctx->litBufferEnd >= litPtr);\n                if (leftoverLit) {\n                    RETURN_ERROR_IF(leftoverLit > (size_t)(oend - op), dstSize_tooSmall, \"remaining lit must fit within dstBuffer\");\n                    ZSTD_safecopyDstBeforeSrc(op, litPtr, leftoverLit);\n                    sequence->litLength -= leftoverLit;\n                    op += leftoverLit;\n                }\n                litPtr = dctx->litExtraBuffer;\n                litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE;\n                dctx->litBufferLocation = ZSTD_not_in_dst;\n                {   size_t const oneSeqSize = ZSTD_execSequence(op, oend, *sequence, &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd);\n#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)\n                    assert(!ZSTD_isError(oneSeqSize));\n                    ZSTD_assertValidSequence(dctx, op, oend, sequences[seqNb&STORED_SEQS_MASK], prefixStart, dictStart);\n#endif\n                    if (ZSTD_isError(oneSeqSize)) return oneSeqSize;\n                    op += oneSeqSize;\n                }\n            }\n            else\n            {\n                size_t const oneSeqSize = dctx->litBufferLocation == ZSTD_split ?\n                    ZSTD_execSequenceSplitLitBuffer(op, oend, litPtr + sequence->litLength - WILDCOPY_OVERLENGTH, *sequence, &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd) :\n                    ZSTD_execSequence(op, oend, *sequence, &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd);\n#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)\n                assert(!ZSTD_isError(oneSeqSize));\n                ZSTD_assertValidSequence(dctx, op, oend, sequences[seqNb&STORED_SEQS_MASK], prefixStart, dictStart);\n#endif\n                if (ZSTD_isError(oneSeqSize)) return oneSeqSize;\n                op += oneSeqSize;\n            }\n        }\n\n        /* save reps for next block */\n        { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }\n    }\n\n    /* last literal segment */\n    if (dctx->litBufferLocation == ZSTD_split) { /* first deplete literal buffer in dst, then copy litExtraBuffer */\n        size_t const lastLLSize = (size_t)(litBufferEnd - litPtr);\n        assert(litBufferEnd >= litPtr);\n        RETURN_ERROR_IF(lastLLSize > (size_t)(oend - op), dstSize_tooSmall, \"\");\n        if (op != NULL) {\n            ZSTD_memmove(op, litPtr, lastLLSize);\n            op += lastLLSize;\n        }\n        litPtr = dctx->litExtraBuffer;\n        litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE;\n    }\n    {   size_t const lastLLSize = (size_t)(litBufferEnd - litPtr);\n        assert(litBufferEnd >= litPtr);\n        RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, \"\");\n        if (op != NULL) {\n            ZSTD_memmove(op, litPtr, lastLLSize);\n            op += lastLLSize;\n        }\n    }\n\n    return (size_t)(op - ostart);\n}\n\nstatic size_t\nZSTD_decompressSequencesLong_default(ZSTD_DCtx* dctx,\n                                 void* dst, size_t maxDstSize,\n                           const void* seqStart, size_t seqSize, int nbSeq,\n                           const ZSTD_longOffset_e isLongOffset)\n{\n    return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n}\n#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */\n\n\n\n#if DYNAMIC_BMI2\n\n#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG\nstatic BMI2_TARGET_ATTRIBUTE size_t\nDONT_VECTORIZE\nZSTD_decompressSequences_bmi2(ZSTD_DCtx* dctx,\n                                 void* dst, size_t maxDstSize,\n                           const void* seqStart, size_t seqSize, int nbSeq,\n                           const ZSTD_longOffset_e isLongOffset)\n{\n    return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n}\nstatic BMI2_TARGET_ATTRIBUTE size_t\nDONT_VECTORIZE\nZSTD_decompressSequencesSplitLitBuffer_bmi2(ZSTD_DCtx* dctx,\n                                 void* dst, size_t maxDstSize,\n                           const void* seqStart, size_t seqSize, int nbSeq,\n                           const ZSTD_longOffset_e isLongOffset)\n{\n    return ZSTD_decompressSequences_bodySplitLitBuffer(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n}\n#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */\n\n#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT\nstatic BMI2_TARGET_ATTRIBUTE size_t\nZSTD_decompressSequencesLong_bmi2(ZSTD_DCtx* dctx,\n                                 void* dst, size_t maxDstSize,\n                           const void* seqStart, size_t seqSize, int nbSeq,\n                           const ZSTD_longOffset_e isLongOffset)\n{\n    return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n}\n#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */\n\n#endif /* DYNAMIC_BMI2 */\n\n#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG\nstatic size_t\nZSTD_decompressSequences(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize,\n                   const void* seqStart, size_t seqSize, int nbSeq,\n                   const ZSTD_longOffset_e isLongOffset)\n{\n    DEBUGLOG(5, \"ZSTD_decompressSequences\");\n#if DYNAMIC_BMI2\n    if (ZSTD_DCtx_get_bmi2(dctx)) {\n        return ZSTD_decompressSequences_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n    }\n#endif\n    return ZSTD_decompressSequences_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n}\nstatic size_t\nZSTD_decompressSequencesSplitLitBuffer(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize,\n                                 const void* seqStart, size_t seqSize, int nbSeq,\n                                 const ZSTD_longOffset_e isLongOffset)\n{\n    DEBUGLOG(5, \"ZSTD_decompressSequencesSplitLitBuffer\");\n#if DYNAMIC_BMI2\n    if (ZSTD_DCtx_get_bmi2(dctx)) {\n        return ZSTD_decompressSequencesSplitLitBuffer_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n    }\n#endif\n    return ZSTD_decompressSequencesSplitLitBuffer_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n}\n#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */\n\n\n#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT\n/* ZSTD_decompressSequencesLong() :\n * decompression function triggered when a minimum share of offsets is considered \"long\",\n * aka out of cache.\n * note : \"long\" definition seems overloaded here, sometimes meaning \"wider than bitstream register\", and sometimes meaning \"farther than memory cache distance\".\n * This function will try to mitigate main memory latency through the use of prefetching */\nstatic size_t\nZSTD_decompressSequencesLong(ZSTD_DCtx* dctx,\n                             void* dst, size_t maxDstSize,\n                             const void* seqStart, size_t seqSize, int nbSeq,\n                             const ZSTD_longOffset_e isLongOffset)\n{\n    DEBUGLOG(5, \"ZSTD_decompressSequencesLong\");\n#if DYNAMIC_BMI2\n    if (ZSTD_DCtx_get_bmi2(dctx)) {\n        return ZSTD_decompressSequencesLong_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n    }\n#endif\n  return ZSTD_decompressSequencesLong_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n}\n#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */\n\n\n/**\n * @returns The total size of the history referenceable by zstd, including\n * both the prefix and the extDict. At @p op any offset larger than this\n * is invalid.\n */\nstatic size_t ZSTD_totalHistorySize(void* curPtr, const void* virtualStart)\n{\n    return (size_t)((char*)curPtr - (const char*)virtualStart);\n}\n\ntypedef struct {\n    unsigned longOffsetShare;\n    unsigned maxNbAdditionalBits;\n} ZSTD_OffsetInfo;\n\n/* ZSTD_getOffsetInfo() :\n * condition : offTable must be valid\n * @return : \"share\" of long offsets (arbitrarily defined as > (1<<23))\n *           compared to maximum possible of (1<<OffFSELog),\n *           as well as the maximum number additional bits required.\n */\nstatic ZSTD_OffsetInfo\nZSTD_getOffsetInfo(const ZSTD_seqSymbol* offTable, int nbSeq)\n{\n    ZSTD_OffsetInfo info = {0, 0};\n    /* If nbSeq == 0, then the offTable is uninitialized, but we have\n     * no sequences, so both values should be 0.\n     */\n    if (nbSeq != 0) {\n        const void* ptr = offTable;\n        U32 const tableLog = ((const ZSTD_seqSymbol_header*)ptr)[0].tableLog;\n        const ZSTD_seqSymbol* table = offTable + 1;\n        U32 const max = 1 << tableLog;\n        U32 u;\n        DEBUGLOG(5, \"ZSTD_getLongOffsetsShare: (tableLog=%u)\", tableLog);\n\n        assert(max <= (1 << OffFSELog));  /* max not too large */\n        for (u=0; u<max; u++) {\n            info.maxNbAdditionalBits = MAX(info.maxNbAdditionalBits, table[u].nbAdditionalBits);\n            if (table[u].nbAdditionalBits > 22) info.longOffsetShare += 1;\n        }\n\n        assert(tableLog <= OffFSELog);\n        info.longOffsetShare <<= (OffFSELog - tableLog);  /* scale to OffFSELog */\n    }\n\n    return info;\n}\n\n/**\n * @returns The maximum offset we can decode in one read of our bitstream, without\n * reloading more bits in the middle of the offset bits read. Any offsets larger\n * than this must use the long offset decoder.\n */\nstatic size_t ZSTD_maxShortOffset(void)\n{\n    if (MEM_64bits()) {\n        /* We can decode any offset without reloading bits.\n         * This might change if the max window size grows.\n         */\n        ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);\n        return (size_t)-1;\n    } else {\n        /* The maximum offBase is (1 << (STREAM_ACCUMULATOR_MIN + 1)) - 1.\n         * This offBase would require STREAM_ACCUMULATOR_MIN extra bits.\n         * Then we have to subtract ZSTD_REP_NUM to get the maximum possible offset.\n         */\n        size_t const maxOffbase = ((size_t)1 << (STREAM_ACCUMULATOR_MIN + 1)) - 1;\n        size_t const maxOffset = maxOffbase - ZSTD_REP_NUM;\n        assert(ZSTD_highbit32((U32)maxOffbase) == STREAM_ACCUMULATOR_MIN);\n        return maxOffset;\n    }\n}\n\nsize_t\nZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,\n                              void* dst, size_t dstCapacity,\n                        const void* src, size_t srcSize, const streaming_operation streaming)\n{   /* blockType == blockCompressed */\n    const BYTE* ip = (const BYTE*)src;\n    DEBUGLOG(5, \"ZSTD_decompressBlock_internal (cSize : %u)\", (unsigned)srcSize);\n\n    /* Note : the wording of the specification\n     * allows compressed block to be sized exactly ZSTD_blockSizeMax(dctx).\n     * This generally does not happen, as it makes little sense,\n     * since an uncompressed block would feature same size and have no decompression cost.\n     * Also, note that decoder from reference libzstd before < v1.5.4\n     * would consider this edge case as an error.\n     * As a consequence, avoid generating compressed blocks of size ZSTD_blockSizeMax(dctx)\n     * for broader compatibility with the deployed ecosystem of zstd decoders */\n    RETURN_ERROR_IF(srcSize > ZSTD_blockSizeMax(dctx), srcSize_wrong, \"\");\n\n    /* Decode literals section */\n    {   size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize, dst, dstCapacity, streaming);\n        DEBUGLOG(5, \"ZSTD_decodeLiteralsBlock : cSize=%u, nbLiterals=%zu\", (U32)litCSize, dctx->litSize);\n        if (ZSTD_isError(litCSize)) return litCSize;\n        ip += litCSize;\n        srcSize -= litCSize;\n    }\n\n    /* Build Decoding Tables */\n    {\n        /* Compute the maximum block size, which must also work when !frame and fParams are unset.\n         * Additionally, take the min with dstCapacity to ensure that the totalHistorySize fits in a size_t.\n         */\n        size_t const blockSizeMax = MIN(dstCapacity, ZSTD_blockSizeMax(dctx));\n        size_t const totalHistorySize = ZSTD_totalHistorySize(ZSTD_maybeNullPtrAdd(dst, (ptrdiff_t)blockSizeMax), (BYTE const*)dctx->virtualStart);\n        /* isLongOffset must be true if there are long offsets.\n         * Offsets are long if they are larger than ZSTD_maxShortOffset().\n         * We don't expect that to be the case in 64-bit mode.\n         *\n         * We check here to see if our history is large enough to allow long offsets.\n         * If it isn't, then we can't possible have (valid) long offsets. If the offset\n         * is invalid, then it is okay to read it incorrectly.\n         *\n         * If isLongOffsets is true, then we will later check our decoding table to see\n         * if it is even possible to generate long offsets.\n         */\n        ZSTD_longOffset_e isLongOffset = (ZSTD_longOffset_e)(MEM_32bits() && (totalHistorySize > ZSTD_maxShortOffset()));\n        /* These macros control at build-time which decompressor implementation\n         * we use. If neither is defined, we do some inspection and dispatch at\n         * runtime.\n         */\n#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \\\n    !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)\n        int usePrefetchDecoder = dctx->ddictIsCold;\n#else\n        /* Set to 1 to avoid computing offset info if we don't need to.\n         * Otherwise this value is ignored.\n         */\n        int usePrefetchDecoder = 1;\n#endif\n        int nbSeq;\n        size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, srcSize);\n        if (ZSTD_isError(seqHSize)) return seqHSize;\n        ip += seqHSize;\n        srcSize -= seqHSize;\n\n        RETURN_ERROR_IF((dst == NULL || dstCapacity == 0) && nbSeq > 0, dstSize_tooSmall, \"NULL not handled\");\n        RETURN_ERROR_IF(MEM_64bits() && sizeof(size_t) == sizeof(void*) && (size_t)(-1) - (size_t)dst < (size_t)(1 << 20), dstSize_tooSmall,\n                \"invalid dst\");\n\n        /* If we could potentially have long offsets, or we might want to use the prefetch decoder,\n         * compute information about the share of long offsets, and the maximum nbAdditionalBits.\n         * NOTE: could probably use a larger nbSeq limit\n         */\n        if (isLongOffset || (!usePrefetchDecoder && (totalHistorySize > (1u << 24)) && (nbSeq > 8))) {\n            ZSTD_OffsetInfo const info = ZSTD_getOffsetInfo(dctx->OFTptr, nbSeq);\n            if (isLongOffset && info.maxNbAdditionalBits <= STREAM_ACCUMULATOR_MIN) {\n                /* If isLongOffset, but the maximum number of additional bits that we see in our table is small\n                 * enough, then we know it is impossible to have too long an offset in this block, so we can\n                 * use the regular offset decoder.\n                 */\n                isLongOffset = ZSTD_lo_isRegularOffset;\n            }\n            if (!usePrefetchDecoder) {\n                U32 const minShare = MEM_64bits() ? 7 : 20; /* heuristic values, correspond to 2.73% and 7.81% */\n                usePrefetchDecoder = (info.longOffsetShare >= minShare);\n            }\n        }\n\n        dctx->ddictIsCold = 0;\n\n#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \\\n    !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)\n        if (usePrefetchDecoder) {\n#else\n        (void)usePrefetchDecoder;\n        {\n#endif\n#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT\n            return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset);\n#endif\n        }\n\n#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG\n        /* else */\n        if (dctx->litBufferLocation == ZSTD_split)\n            return ZSTD_decompressSequencesSplitLitBuffer(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset);\n        else\n            return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset);\n#endif\n    }\n}\n\n\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst, size_t dstSize)\n{\n    if (dst != dctx->previousDstEnd && dstSize > 0) {   /* not contiguous */\n        dctx->dictEnd = dctx->previousDstEnd;\n        dctx->virtualStart = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));\n        dctx->prefixStart = dst;\n        dctx->previousDstEnd = dst;\n    }\n}\n\n\nsize_t ZSTD_decompressBlock_deprecated(ZSTD_DCtx* dctx,\n                                       void* dst, size_t dstCapacity,\n                                 const void* src, size_t srcSize)\n{\n    size_t dSize;\n    dctx->isFrameDecompression = 0;\n    ZSTD_checkContinuity(dctx, dst, dstCapacity);\n    dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, not_streaming);\n    FORWARD_IF_ERROR(dSize, \"\");\n    dctx->previousDstEnd = (char*)dst + dSize;\n    return dSize;\n}\n\n\n/* NOTE: Must just wrap ZSTD_decompressBlock_deprecated() */\nsize_t ZSTD_decompressBlock(ZSTD_DCtx* dctx,\n                            void* dst, size_t dstCapacity,\n                      const void* src, size_t srcSize)\n{\n    return ZSTD_decompressBlock_deprecated(dctx, dst, dstCapacity, src, srcSize);\n}\n"
  },
  {
    "path": "lib/decompress/zstd_decompress_block.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n#ifndef ZSTD_DEC_BLOCK_H\n#define ZSTD_DEC_BLOCK_H\n\n/*-*******************************************************\n *  Dependencies\n *********************************************************/\n#include \"../common/zstd_deps.h\"   /* size_t */\n#include \"../zstd.h\"    /* DCtx, and some public functions */\n#include \"../common/zstd_internal.h\"  /* blockProperties_t, and some public functions */\n#include \"zstd_decompress_internal.h\"  /* ZSTD_seqSymbol */\n\n\n/* ===   Prototypes   === */\n\n/* note: prototypes already published within `zstd.h` :\n * ZSTD_decompressBlock()\n */\n\n/* note: prototypes already published within `zstd_internal.h` :\n * ZSTD_getcBlockSize()\n * ZSTD_decodeSeqHeaders()\n */\n\n\n /* Streaming state is used to inform allocation of the literal buffer */\ntypedef enum {\n    not_streaming = 0,\n    is_streaming = 1\n} streaming_operation;\n\n/* ZSTD_decompressBlock_internal() :\n * decompress block, starting at `src`,\n * into destination buffer `dst`.\n * @return : decompressed block size,\n *           or an error code (which can be tested using ZSTD_isError())\n */\nsize_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,\n                               void* dst, size_t dstCapacity,\n                         const void* src, size_t srcSize, const streaming_operation streaming);\n\n/* ZSTD_buildFSETable() :\n * generate FSE decoding table for one symbol (ll, ml or off)\n * this function must be called with valid parameters only\n * (dt is large enough, normalizedCounter distribution total is a power of 2, max is within range, etc.)\n * in which case it cannot fail.\n * The workspace must be 4-byte aligned and at least ZSTD_BUILD_FSE_TABLE_WKSP_SIZE bytes, which is\n * defined in zstd_decompress_internal.h.\n * Internal use only.\n */\nvoid ZSTD_buildFSETable(ZSTD_seqSymbol* dt,\n             const short* normalizedCounter, unsigned maxSymbolValue,\n             const U32* baseValue, const U8* nbAdditionalBits,\n                   unsigned tableLog, void* wksp, size_t wkspSize,\n                   int bmi2);\n\n/* Internal definition of ZSTD_decompressBlock() to avoid deprecation warnings. */\nsize_t ZSTD_decompressBlock_deprecated(ZSTD_DCtx* dctx,\n                            void* dst, size_t dstCapacity,\n                      const void* src, size_t srcSize);\n\n\n#endif /* ZSTD_DEC_BLOCK_H */\n"
  },
  {
    "path": "lib/decompress/zstd_decompress_internal.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/* zstd_decompress_internal:\n * objects and definitions shared within lib/decompress modules */\n\n #ifndef ZSTD_DECOMPRESS_INTERNAL_H\n #define ZSTD_DECOMPRESS_INTERNAL_H\n\n\n/*-*******************************************************\n *  Dependencies\n *********************************************************/\n#include \"../common/mem.h\"             /* BYTE, U16, U32 */\n#include \"../common/zstd_internal.h\"   /* constants : MaxLL, MaxML, MaxOff, LLFSELog, etc. */\n\n\n\n/*-*******************************************************\n *  Constants\n *********************************************************/\nstatic UNUSED_ATTR const U32 LL_base[MaxLL+1] = {\n                 0,    1,    2,     3,     4,     5,     6,      7,\n                 8,    9,   10,    11,    12,    13,    14,     15,\n                16,   18,   20,    22,    24,    28,    32,     40,\n                48,   64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,\n                0x2000, 0x4000, 0x8000, 0x10000 };\n\nstatic UNUSED_ATTR const U32 OF_base[MaxOff+1] = {\n                 0,        1,       1,       5,     0xD,     0x1D,     0x3D,     0x7D,\n                 0xFD,   0x1FD,   0x3FD,   0x7FD,   0xFFD,   0x1FFD,   0x3FFD,   0x7FFD,\n                 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,\n                 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD };\n\nstatic UNUSED_ATTR const U8 OF_bits[MaxOff+1] = {\n                     0,  1,  2,  3,  4,  5,  6,  7,\n                     8,  9, 10, 11, 12, 13, 14, 15,\n                    16, 17, 18, 19, 20, 21, 22, 23,\n                    24, 25, 26, 27, 28, 29, 30, 31 };\n\nstatic UNUSED_ATTR const U32 ML_base[MaxML+1] = {\n                     3,  4,  5,    6,     7,     8,     9,    10,\n                    11, 12, 13,   14,    15,    16,    17,    18,\n                    19, 20, 21,   22,    23,    24,    25,    26,\n                    27, 28, 29,   30,    31,    32,    33,    34,\n                    35, 37, 39,   41,    43,    47,    51,    59,\n                    67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,\n                    0x1003, 0x2003, 0x4003, 0x8003, 0x10003 };\n\n\n/*-*******************************************************\n *  Decompression types\n *********************************************************/\n typedef struct {\n     U32 fastMode;\n     U32 tableLog;\n } ZSTD_seqSymbol_header;\n\n typedef struct {\n     U16  nextState;\n     BYTE nbAdditionalBits;\n     BYTE nbBits;\n     U32  baseValue;\n } ZSTD_seqSymbol;\n\n #define SEQSYMBOL_TABLE_SIZE(log)   (1 + (1 << (log)))\n\n#define ZSTD_BUILD_FSE_TABLE_WKSP_SIZE (sizeof(S16) * (MaxSeq + 1) + (1u << MaxFSELog) + sizeof(U64))\n#define ZSTD_BUILD_FSE_TABLE_WKSP_SIZE_U32 ((ZSTD_BUILD_FSE_TABLE_WKSP_SIZE + sizeof(U32) - 1) / sizeof(U32))\n#define ZSTD_HUFFDTABLE_CAPACITY_LOG 12\n\ntypedef struct {\n    ZSTD_seqSymbol LLTable[SEQSYMBOL_TABLE_SIZE(LLFSELog)];    /* Note : Space reserved for FSE Tables */\n    ZSTD_seqSymbol OFTable[SEQSYMBOL_TABLE_SIZE(OffFSELog)];   /* is also used as temporary workspace while building hufTable during DDict creation */\n    ZSTD_seqSymbol MLTable[SEQSYMBOL_TABLE_SIZE(MLFSELog)];    /* and therefore must be at least HUF_DECOMPRESS_WORKSPACE_SIZE large */\n    HUF_DTable hufTable[HUF_DTABLE_SIZE(ZSTD_HUFFDTABLE_CAPACITY_LOG)];  /* can accommodate HUF_decompress4X */\n    U32 rep[ZSTD_REP_NUM];\n    U32 workspace[ZSTD_BUILD_FSE_TABLE_WKSP_SIZE_U32];\n} ZSTD_entropyDTables_t;\n\ntypedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,\n               ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock,\n               ZSTDds_decompressLastBlock, ZSTDds_checkChecksum,\n               ZSTDds_decodeSkippableHeader, ZSTDds_skipFrame } ZSTD_dStage;\n\ntypedef enum { zdss_init=0, zdss_loadHeader,\n               zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage;\n\ntypedef enum {\n    ZSTD_use_indefinitely = -1,  /* Use the dictionary indefinitely */\n    ZSTD_dont_use = 0,           /* Do not use the dictionary (if one exists free it) */\n    ZSTD_use_once = 1            /* Use the dictionary once and set to ZSTD_dont_use */\n} ZSTD_dictUses_e;\n\n/* Hashset for storing references to multiple ZSTD_DDict within ZSTD_DCtx */\ntypedef struct {\n    const ZSTD_DDict** ddictPtrTable;\n    size_t ddictPtrTableSize;\n    size_t ddictPtrCount;\n} ZSTD_DDictHashSet;\n\n#ifndef ZSTD_DECODER_INTERNAL_BUFFER\n#  define ZSTD_DECODER_INTERNAL_BUFFER  (1 << 16)\n#endif\n\n#define ZSTD_LBMIN 64\n#define ZSTD_LBMAX (128 << 10)\n\n/* extra buffer, compensates when dst is not large enough to store litBuffer */\n#define ZSTD_LITBUFFEREXTRASIZE  BOUNDED(ZSTD_LBMIN, ZSTD_DECODER_INTERNAL_BUFFER, ZSTD_LBMAX)\n\ntypedef enum {\n    ZSTD_not_in_dst = 0,  /* Stored entirely within litExtraBuffer */\n    ZSTD_in_dst = 1,           /* Stored entirely within dst (in memory after current output write) */\n    ZSTD_split = 2            /* Split between litExtraBuffer and dst */\n} ZSTD_litLocation_e;\n\nstruct ZSTD_DCtx_s\n{\n    const ZSTD_seqSymbol* LLTptr;\n    const ZSTD_seqSymbol* MLTptr;\n    const ZSTD_seqSymbol* OFTptr;\n    const HUF_DTable* HUFptr;\n    ZSTD_entropyDTables_t entropy;\n    U32 workspace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];   /* space needed when building huffman tables */\n    const void* previousDstEnd;   /* detect continuity */\n    const void* prefixStart;      /* start of current segment */\n    const void* virtualStart;     /* virtual start of previous segment if it was just before current one */\n    const void* dictEnd;          /* end of previous segment */\n    size_t expected;\n    ZSTD_FrameHeader fParams;\n    U64 processedCSize;\n    U64 decodedSize;\n    blockType_e bType;            /* used in ZSTD_decompressContinue(), store blockType between block header decoding and block decompression stages */\n    ZSTD_dStage stage;\n    U32 litEntropy;\n    U32 fseEntropy;\n    XXH64_state_t xxhState;\n    size_t headerSize;\n    ZSTD_format_e format;\n    ZSTD_forceIgnoreChecksum_e forceIgnoreChecksum;   /* User specified: if == 1, will ignore checksums in compressed frame. Default == 0 */\n    U32 validateChecksum;         /* if == 1, will validate checksum. Is == 1 if (fParams.checksumFlag == 1) and (forceIgnoreChecksum == 0). */\n    const BYTE* litPtr;\n    ZSTD_customMem customMem;\n    size_t litSize;\n    size_t rleSize;\n    size_t staticSize;\n    int isFrameDecompression;\n#if DYNAMIC_BMI2\n    int bmi2;                     /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */\n#endif\n\n    /* dictionary */\n    ZSTD_DDict* ddictLocal;\n    const ZSTD_DDict* ddict;     /* set by ZSTD_initDStream_usingDDict(), or ZSTD_DCtx_refDDict() */\n    U32 dictID;\n    int ddictIsCold;             /* if == 1 : dictionary is \"new\" for working context, and presumed \"cold\" (not in cpu cache) */\n    ZSTD_dictUses_e dictUses;\n    ZSTD_DDictHashSet* ddictSet;                    /* Hash set for multiple ddicts */\n    ZSTD_refMultipleDDicts_e refMultipleDDicts;     /* User specified: if == 1, will allow references to multiple DDicts. Default == 0 (disabled) */\n    int disableHufAsm;\n    int maxBlockSizeParam;\n\n    /* streaming */\n    ZSTD_dStreamStage streamStage;\n    char*  inBuff;\n    size_t inBuffSize;\n    size_t inPos;\n    size_t maxWindowSize;\n    char*  outBuff;\n    size_t outBuffSize;\n    size_t outStart;\n    size_t outEnd;\n    size_t lhSize;\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)\n    void* legacyContext;\n    U32 previousLegacyVersion;\n    U32 legacyVersion;\n#endif\n    U32 hostageByte;\n    int noForwardProgress;\n    ZSTD_bufferMode_e outBufferMode;\n    ZSTD_outBuffer expectedOutBuffer;\n\n    /* workspace */\n    BYTE* litBuffer;\n    const BYTE* litBufferEnd;\n    ZSTD_litLocation_e litBufferLocation;\n    BYTE litExtraBuffer[ZSTD_LITBUFFEREXTRASIZE + WILDCOPY_OVERLENGTH]; /* literal buffer can be split between storage within dst and within this scratch buffer */\n    BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];\n\n    size_t oversizedDuration;\n\n#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION\n    void const* dictContentBeginForFuzzing;\n    void const* dictContentEndForFuzzing;\n#endif\n\n    /* Tracing */\n#if ZSTD_TRACE\n    ZSTD_TraceCtx traceCtx;\n#endif\n};  /* typedef'd to ZSTD_DCtx within \"zstd.h\" */\n\nMEM_STATIC int ZSTD_DCtx_get_bmi2(const struct ZSTD_DCtx_s *dctx) {\n#if DYNAMIC_BMI2\n    return dctx->bmi2;\n#else\n    (void)dctx;\n    return 0;\n#endif\n}\n\n/*-*******************************************************\n *  Shared internal functions\n *********************************************************/\n\n/*! ZSTD_loadDEntropy() :\n *  dict : must point at beginning of a valid zstd dictionary.\n * @return : size of dictionary header (size of magic number + dict ID + entropy tables) */\nsize_t ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,\n                   const void* const dict, size_t const dictSize);\n\n/*! ZSTD_checkContinuity() :\n *  check if next `dst` follows previous position, where decompression ended.\n *  If yes, do nothing (continue on current segment).\n *  If not, classify previous segment as \"external dictionary\", and start a new segment.\n *  This function cannot fail. */\nvoid ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst, size_t dstSize);\n\n\n#endif /* ZSTD_DECOMPRESS_INTERNAL_H */\n"
  },
  {
    "path": "lib/deprecated/zbuff.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* ***************************************************************\n*  NOTES/WARNINGS\n******************************************************************/\n/* The streaming API defined here is deprecated.\n * Consider migrating towards ZSTD_compressStream() API in `zstd.h`\n * See 'lib/README.md'.\n *****************************************************************/\n\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n#ifndef ZSTD_BUFFERED_H_23987\n#define ZSTD_BUFFERED_H_23987\n\n/* *************************************\n*  Dependencies\n***************************************/\n#include <stddef.h>      /* size_t */\n#include \"../zstd.h\"        /* ZSTD_CStream, ZSTD_DStream, ZSTDLIB_API */\n\n\n/* ***************************************************************\n*  Compiler specifics\n*****************************************************************/\n/* Deprecation warnings */\n/* Should these warnings be a problem,\n * it is generally possible to disable them,\n * typically with -Wno-deprecated-declarations for gcc\n * or _CRT_SECURE_NO_WARNINGS in Visual.\n * Otherwise, it's also possible to define ZBUFF_DISABLE_DEPRECATE_WARNINGS\n */\n#ifdef ZBUFF_DISABLE_DEPRECATE_WARNINGS\n#  define ZBUFF_DEPRECATED(message) ZSTDLIB_API  /* disable deprecation warnings */\n#else\n#  if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */\n#    define ZBUFF_DEPRECATED(message) [[deprecated(message)]] ZSTDLIB_API\n#  elif (defined(GNUC) && (GNUC > 4 || (GNUC == 4 && GNUC_MINOR >= 5))) || defined(__clang__)\n#    define ZBUFF_DEPRECATED(message) ZSTDLIB_API __attribute__((deprecated(message)))\n#  elif defined(__GNUC__) && (__GNUC__ >= 3)\n#    define ZBUFF_DEPRECATED(message) ZSTDLIB_API __attribute__((deprecated))\n#  elif defined(_MSC_VER)\n#    define ZBUFF_DEPRECATED(message) ZSTDLIB_API __declspec(deprecated(message))\n#  else\n#    pragma message(\"WARNING: You need to implement ZBUFF_DEPRECATED for this compiler\")\n#    define ZBUFF_DEPRECATED(message) ZSTDLIB_API\n#  endif\n#endif /* ZBUFF_DISABLE_DEPRECATE_WARNINGS */\n\n\n/* *************************************\n*  Streaming functions\n***************************************/\n/* This is the easier \"buffered\" streaming API,\n*  using an internal buffer to lift all restrictions on user-provided buffers\n*  which can be any size, any place, for both input and output.\n*  ZBUFF and ZSTD are 100% interoperable,\n*  frames created by one can be decoded by the other one */\n\ntypedef ZSTD_CStream ZBUFF_CCtx;\nZBUFF_DEPRECATED(\"use ZSTD_createCStream\") ZBUFF_CCtx* ZBUFF_createCCtx(void);\nZBUFF_DEPRECATED(\"use ZSTD_freeCStream\")   size_t      ZBUFF_freeCCtx(ZBUFF_CCtx* cctx);\n\nZBUFF_DEPRECATED(\"use ZSTD_initCStream\")           size_t ZBUFF_compressInit(ZBUFF_CCtx* cctx, int compressionLevel);\nZBUFF_DEPRECATED(\"use ZSTD_initCStream_usingDict\") size_t ZBUFF_compressInitDictionary(ZBUFF_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel);\n\nZBUFF_DEPRECATED(\"use ZSTD_compressStream\") size_t ZBUFF_compressContinue(ZBUFF_CCtx* cctx, void* dst, size_t* dstCapacityPtr, const void* src, size_t* srcSizePtr);\nZBUFF_DEPRECATED(\"use ZSTD_flushStream\")    size_t ZBUFF_compressFlush(ZBUFF_CCtx* cctx, void* dst, size_t* dstCapacityPtr);\nZBUFF_DEPRECATED(\"use ZSTD_endStream\")      size_t ZBUFF_compressEnd(ZBUFF_CCtx* cctx, void* dst, size_t* dstCapacityPtr);\n\n/*-*************************************************\n*  Streaming compression - howto\n*\n*  A ZBUFF_CCtx object is required to track streaming operation.\n*  Use ZBUFF_createCCtx() and ZBUFF_freeCCtx() to create/release resources.\n*  ZBUFF_CCtx objects can be reused multiple times.\n*\n*  Start by initializing ZBUF_CCtx.\n*  Use ZBUFF_compressInit() to start a new compression operation.\n*  Use ZBUFF_compressInitDictionary() for a compression which requires a dictionary.\n*\n*  Use ZBUFF_compressContinue() repetitively to consume input stream.\n*  *srcSizePtr and *dstCapacityPtr can be any size.\n*  The function will report how many bytes were read or written within *srcSizePtr and *dstCapacityPtr.\n*  Note that it may not consume the entire input, in which case it's up to the caller to present again remaining data.\n*  The content of `dst` will be overwritten (up to *dstCapacityPtr) at each call, so save its content if it matters or change @dst .\n*  @return : a hint to preferred nb of bytes to use as input for next function call (it's just a hint, to improve latency)\n*            or an error code, which can be tested using ZBUFF_isError().\n*\n*  At any moment, it's possible to flush whatever data remains within buffer, using ZBUFF_compressFlush().\n*  The nb of bytes written into `dst` will be reported into *dstCapacityPtr.\n*  Note that the function cannot output more than *dstCapacityPtr,\n*  therefore, some content might still be left into internal buffer if *dstCapacityPtr is too small.\n*  @return : nb of bytes still present into internal buffer (0 if it's empty)\n*            or an error code, which can be tested using ZBUFF_isError().\n*\n*  ZBUFF_compressEnd() instructs to finish a frame.\n*  It will perform a flush and write frame epilogue.\n*  The epilogue is required for decoders to consider a frame completed.\n*  Similar to ZBUFF_compressFlush(), it may not be able to output the entire internal buffer content if *dstCapacityPtr is too small.\n*  In which case, call again ZBUFF_compressFlush() to complete the flush.\n*  @return : nb of bytes still present into internal buffer (0 if it's empty)\n*            or an error code, which can be tested using ZBUFF_isError().\n*\n*  Hint : _recommended buffer_ sizes (not compulsory) : ZBUFF_recommendedCInSize() / ZBUFF_recommendedCOutSize()\n*  input : ZBUFF_recommendedCInSize==128 KB block size is the internal unit, use this value to reduce intermediate stages (better latency)\n*  output : ZBUFF_recommendedCOutSize==ZSTD_compressBound(128 KB) + 3 + 3 : ensures it's always possible to write/flush/end a full block. Skip some buffering.\n*  By using both, it ensures that input will be entirely consumed, and output will always contain the result, reducing intermediate buffering.\n* **************************************************/\n\n\ntypedef ZSTD_DStream ZBUFF_DCtx;\nZBUFF_DEPRECATED(\"use ZSTD_createDStream\") ZBUFF_DCtx* ZBUFF_createDCtx(void);\nZBUFF_DEPRECATED(\"use ZSTD_freeDStream\")   size_t      ZBUFF_freeDCtx(ZBUFF_DCtx* dctx);\n\nZBUFF_DEPRECATED(\"use ZSTD_initDStream\")           size_t ZBUFF_decompressInit(ZBUFF_DCtx* dctx);\nZBUFF_DEPRECATED(\"use ZSTD_initDStream_usingDict\") size_t ZBUFF_decompressInitDictionary(ZBUFF_DCtx* dctx, const void* dict, size_t dictSize);\n\nZBUFF_DEPRECATED(\"use ZSTD_decompressStream\") size_t ZBUFF_decompressContinue(ZBUFF_DCtx* dctx,\n                                            void* dst, size_t* dstCapacityPtr,\n                                      const void* src, size_t* srcSizePtr);\n\n/*-***************************************************************************\n*  Streaming decompression howto\n*\n*  A ZBUFF_DCtx object is required to track streaming operations.\n*  Use ZBUFF_createDCtx() and ZBUFF_freeDCtx() to create/release resources.\n*  Use ZBUFF_decompressInit() to start a new decompression operation,\n*   or ZBUFF_decompressInitDictionary() if decompression requires a dictionary.\n*  Note that ZBUFF_DCtx objects can be re-init multiple times.\n*\n*  Use ZBUFF_decompressContinue() repetitively to consume your input.\n*  *srcSizePtr and *dstCapacityPtr can be any size.\n*  The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr.\n*  Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again.\n*  The content of `dst` will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters, or change `dst`.\n*  @return : 0 when a frame is completely decoded and fully flushed,\n*            1 when there is still some data left within internal buffer to flush,\n*            >1 when more data is expected, with value being a suggested next input size (it's just a hint, which helps latency),\n*            or an error code, which can be tested using ZBUFF_isError().\n*\n*  Hint : recommended buffer sizes (not compulsory) : ZBUFF_recommendedDInSize() and ZBUFF_recommendedDOutSize()\n*  output : ZBUFF_recommendedDOutSize== 128 KB block size is the internal unit, it ensures it's always possible to write a full block when decoded.\n*  input  : ZBUFF_recommendedDInSize == 128KB + 3;\n*           just follow indications from ZBUFF_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .\n* *******************************************************************************/\n\n\n/* *************************************\n*  Tool functions\n***************************************/\nZBUFF_DEPRECATED(\"use ZSTD_isError\")      unsigned ZBUFF_isError(size_t errorCode);\nZBUFF_DEPRECATED(\"use ZSTD_getErrorName\") const char* ZBUFF_getErrorName(size_t errorCode);\n\n/** Functions below provide recommended buffer sizes for Compression or Decompression operations.\n*   These sizes are just hints, they tend to offer better latency */\nZBUFF_DEPRECATED(\"use ZSTD_CStreamInSize\")  size_t ZBUFF_recommendedCInSize(void);\nZBUFF_DEPRECATED(\"use ZSTD_CStreamOutSize\") size_t ZBUFF_recommendedCOutSize(void);\nZBUFF_DEPRECATED(\"use ZSTD_DStreamInSize\")  size_t ZBUFF_recommendedDInSize(void);\nZBUFF_DEPRECATED(\"use ZSTD_DStreamOutSize\") size_t ZBUFF_recommendedDOutSize(void);\n\n#endif  /* ZSTD_BUFFERED_H_23987 */\n\n\n#ifdef ZBUFF_STATIC_LINKING_ONLY\n#ifndef ZBUFF_STATIC_H_30298098432\n#define ZBUFF_STATIC_H_30298098432\n\n/* ====================================================================================\n * The definitions in this section are considered experimental.\n * They should never be used in association with a dynamic library, as they may change in the future.\n * They are provided for advanced usages.\n * Use them only in association with static linking.\n * ==================================================================================== */\n\n/*--- Dependency ---*/\n#define ZSTD_STATIC_LINKING_ONLY   /* ZSTD_parameters, ZSTD_customMem */\n#include \"../zstd.h\"\n\n\n/*--- Custom memory allocator ---*/\n/*! ZBUFF_createCCtx_advanced() :\n *  Create a ZBUFF compression context using external alloc and free functions */\nZBUFF_DEPRECATED(\"use ZSTD_createCStream_advanced\") ZBUFF_CCtx* ZBUFF_createCCtx_advanced(ZSTD_customMem customMem);\n\n/*! ZBUFF_createDCtx_advanced() :\n *  Create a ZBUFF decompression context using external alloc and free functions */\nZBUFF_DEPRECATED(\"use ZSTD_createDStream_advanced\") ZBUFF_DCtx* ZBUFF_createDCtx_advanced(ZSTD_customMem customMem);\n\n\n/*--- Advanced Streaming Initialization ---*/\nZBUFF_DEPRECATED(\"use ZSTD_initDStream_usingDict\") size_t ZBUFF_compressInit_advanced(ZBUFF_CCtx* zbc,\n                                               const void* dict, size_t dictSize,\n                                               ZSTD_parameters params, unsigned long long pledgedSrcSize);\n\n\n#endif    /* ZBUFF_STATIC_H_30298098432 */\n#endif    /* ZBUFF_STATIC_LINKING_ONLY */\n\n\n#if defined (__cplusplus)\n}\n#endif\n"
  },
  {
    "path": "lib/deprecated/zbuff_common.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/*-*************************************\n*  Dependencies\n***************************************/\n#include \"../common/error_private.h\"\n#include \"zbuff.h\"\n\n/*-****************************************\n*  ZBUFF Error Management  (deprecated)\n******************************************/\n\n/*! ZBUFF_isError() :\n*   tells if a return value is an error code */\nunsigned ZBUFF_isError(size_t errorCode) { return ERR_isError(errorCode); }\n/*! ZBUFF_getErrorName() :\n*   provides error code string from function result (useful for debugging) */\nconst char* ZBUFF_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }\n"
  },
  {
    "path": "lib/deprecated/zbuff_compress.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n\n/* *************************************\n*  Dependencies\n***************************************/\n#define ZBUFF_STATIC_LINKING_ONLY\n#include \"zbuff.h\"\n#include \"../common/error_private.h\"\n\n\n/*-***********************************************************\n*  Streaming compression\n*\n*  A ZBUFF_CCtx object is required to track streaming operation.\n*  Use ZBUFF_createCCtx() and ZBUFF_freeCCtx() to create/release resources.\n*  Use ZBUFF_compressInit() to start a new compression operation.\n*  ZBUFF_CCtx objects can be reused multiple times.\n*\n*  Use ZBUFF_compressContinue() repetitively to consume your input.\n*  *srcSizePtr and *dstCapacityPtr can be any size.\n*  The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr.\n*  Note that it may not consume the entire input, in which case it's up to the caller to call again the function with remaining input.\n*  The content of dst will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters or change dst .\n*  @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to improve latency)\n*            or an error code, which can be tested using ZBUFF_isError().\n*\n*  ZBUFF_compressFlush() can be used to instruct ZBUFF to compress and output whatever remains within its buffer.\n*  Note that it will not output more than *dstCapacityPtr.\n*  Therefore, some content might still be left into its internal buffer if dst buffer is too small.\n*  @return : nb of bytes still present into internal buffer (0 if it's empty)\n*            or an error code, which can be tested using ZBUFF_isError().\n*\n*  ZBUFF_compressEnd() instructs to finish a frame.\n*  It will perform a flush and write frame epilogue.\n*  Similar to ZBUFF_compressFlush(), it may not be able to output the entire internal buffer content if *dstCapacityPtr is too small.\n*  @return : nb of bytes still present into internal buffer (0 if it's empty)\n*            or an error code, which can be tested using ZBUFF_isError().\n*\n*  Hint : recommended buffer sizes (not compulsory)\n*  input : ZSTD_BLOCKSIZE_MAX (128 KB), internal unit size, it improves latency to use this value.\n*  output : ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + ZBUFF_endFrameSize : ensures it's always possible to write/flush/end a full block at best speed.\n* ***********************************************************/\n\nZBUFF_CCtx* ZBUFF_createCCtx(void)\n{\n    return ZSTD_createCStream();\n}\n\nZBUFF_CCtx* ZBUFF_createCCtx_advanced(ZSTD_customMem customMem)\n{\n    return ZSTD_createCStream_advanced(customMem);\n}\n\nsize_t ZBUFF_freeCCtx(ZBUFF_CCtx* zbc)\n{\n    return ZSTD_freeCStream(zbc);\n}\n\n\n/* ======   Initialization   ====== */\n\nsize_t ZBUFF_compressInit_advanced(ZBUFF_CCtx* zbc,\n                                   const void* dict, size_t dictSize,\n                                   ZSTD_parameters params, unsigned long long pledgedSrcSize)\n{\n    if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;  /* preserve \"0 == unknown\" behavior */\n    FORWARD_IF_ERROR(ZSTD_CCtx_reset(zbc, ZSTD_reset_session_only), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setPledgedSrcSize(zbc, pledgedSrcSize), \"\");\n\n    FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_windowLog, params.cParams.windowLog), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_hashLog, params.cParams.hashLog), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_chainLog, params.cParams.chainLog), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_searchLog, params.cParams.searchLog), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_minMatch, params.cParams.minMatch), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_targetLength, params.cParams.targetLength), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_strategy, params.cParams.strategy), \"\");\n\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_contentSizeFlag, params.fParams.contentSizeFlag), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_checksumFlag, params.fParams.checksumFlag), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_dictIDFlag, params.fParams.noDictIDFlag), \"\");\n\n    FORWARD_IF_ERROR(ZSTD_CCtx_loadDictionary(zbc, dict, dictSize), \"\");\n    return 0;\n}\n\nsize_t ZBUFF_compressInitDictionary(ZBUFF_CCtx* zbc, const void* dict, size_t dictSize, int compressionLevel)\n{\n    FORWARD_IF_ERROR(ZSTD_CCtx_reset(zbc, ZSTD_reset_session_only), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_compressionLevel, compressionLevel), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_loadDictionary(zbc, dict, dictSize), \"\");\n    return 0;\n}\n\nsize_t ZBUFF_compressInit(ZBUFF_CCtx* zbc, int compressionLevel)\n{\n    return ZSTD_initCStream(zbc, compressionLevel);\n}\n\n/* ======   Compression   ====== */\n\n\nsize_t ZBUFF_compressContinue(ZBUFF_CCtx* zbc,\n                              void* dst, size_t* dstCapacityPtr,\n                        const void* src, size_t* srcSizePtr)\n{\n    size_t result;\n    ZSTD_outBuffer outBuff;\n    ZSTD_inBuffer inBuff;\n    outBuff.dst = dst;\n    outBuff.pos = 0;\n    outBuff.size = *dstCapacityPtr;\n    inBuff.src = src;\n    inBuff.pos = 0;\n    inBuff.size = *srcSizePtr;\n    result = ZSTD_compressStream(zbc, &outBuff, &inBuff);\n    *dstCapacityPtr = outBuff.pos;\n    *srcSizePtr = inBuff.pos;\n    return result;\n}\n\n\n\n/* ======   Finalize   ====== */\n\nsize_t ZBUFF_compressFlush(ZBUFF_CCtx* zbc, void* dst, size_t* dstCapacityPtr)\n{\n    size_t result;\n    ZSTD_outBuffer outBuff;\n    outBuff.dst = dst;\n    outBuff.pos = 0;\n    outBuff.size = *dstCapacityPtr;\n    result = ZSTD_flushStream(zbc, &outBuff);\n    *dstCapacityPtr = outBuff.pos;\n    return result;\n}\n\n\nsize_t ZBUFF_compressEnd(ZBUFF_CCtx* zbc, void* dst, size_t* dstCapacityPtr)\n{\n    size_t result;\n    ZSTD_outBuffer outBuff;\n    outBuff.dst = dst;\n    outBuff.pos = 0;\n    outBuff.size = *dstCapacityPtr;\n    result = ZSTD_endStream(zbc, &outBuff);\n    *dstCapacityPtr = outBuff.pos;\n    return result;\n}\n\n\n\n/* *************************************\n*  Tool functions\n***************************************/\nsize_t ZBUFF_recommendedCInSize(void)  { return ZSTD_CStreamInSize(); }\nsize_t ZBUFF_recommendedCOutSize(void) { return ZSTD_CStreamOutSize(); }\n"
  },
  {
    "path": "lib/deprecated/zbuff_decompress.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n\n/* *************************************\n*  Dependencies\n***************************************/\n#define ZSTD_DISABLE_DEPRECATE_WARNINGS  /* suppress warning on ZSTD_initDStream_usingDict */\n#include \"../zstd.h\"        /* ZSTD_CStream, ZSTD_DStream, ZSTDLIB_API */\n#define ZBUFF_STATIC_LINKING_ONLY\n#include \"zbuff.h\"\n\n\nZBUFF_DCtx* ZBUFF_createDCtx(void)\n{\n    return ZSTD_createDStream();\n}\n\nZBUFF_DCtx* ZBUFF_createDCtx_advanced(ZSTD_customMem customMem)\n{\n    return ZSTD_createDStream_advanced(customMem);\n}\n\nsize_t ZBUFF_freeDCtx(ZBUFF_DCtx* zbd)\n{\n    return ZSTD_freeDStream(zbd);\n}\n\n\n/* *** Initialization *** */\n\nsize_t ZBUFF_decompressInitDictionary(ZBUFF_DCtx* zbd, const void* dict, size_t dictSize)\n{\n    return ZSTD_initDStream_usingDict(zbd, dict, dictSize);\n}\n\nsize_t ZBUFF_decompressInit(ZBUFF_DCtx* zbd)\n{\n    return ZSTD_initDStream(zbd);\n}\n\n\n/* *** Decompression *** */\n\nsize_t ZBUFF_decompressContinue(ZBUFF_DCtx* zbd,\n                                void* dst, size_t* dstCapacityPtr,\n                          const void* src, size_t* srcSizePtr)\n{\n    ZSTD_outBuffer outBuff;\n    ZSTD_inBuffer inBuff;\n    size_t result;\n    outBuff.dst  = dst;\n    outBuff.pos  = 0;\n    outBuff.size = *dstCapacityPtr;\n    inBuff.src  = src;\n    inBuff.pos  = 0;\n    inBuff.size = *srcSizePtr;\n    result = ZSTD_decompressStream(zbd, &outBuff, &inBuff);\n    *dstCapacityPtr = outBuff.pos;\n    *srcSizePtr = inBuff.pos;\n    return result;\n}\n\n\n/* *************************************\n*  Tool functions\n***************************************/\nsize_t ZBUFF_recommendedDInSize(void)  { return ZSTD_DStreamInSize(); }\nsize_t ZBUFF_recommendedDOutSize(void) { return ZSTD_DStreamOutSize(); }\n"
  },
  {
    "path": "lib/dictBuilder/cover.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* *****************************************************************************\n * Constructs a dictionary using a heuristic based on the following paper:\n *\n * Liao, Petri, Moffat, Wirth\n * Effective Construction of Relative Lempel-Ziv Dictionaries\n * Published in WWW 2016.\n *\n * Adapted from code originally written by @ot (Giuseppe Ottaviano).\n ******************************************************************************/\n\n/*-*************************************\n*  Dependencies\n***************************************/\n/* qsort_r is an extension.\n *\n * Android NDK does not ship qsort_r().\n */\n#if (defined(__linux__) && !defined(__ANDROID__)) || defined(__CYGWIN__) || defined(__MSYS__)\n# ifndef _GNU_SOURCE\n#   define _GNU_SOURCE\n# endif\n#endif\n\n#define __STDC_WANT_LIB_EXT1__ 1 /* request C11 Annex K, which includes qsort_s() */\n\n#include <stdio.h>  /* fprintf */\n#include <stdlib.h> /* malloc, free, qsort_r */\n\n#include <string.h> /* memset */\n#include <time.h>   /* clock */\n\n#ifndef ZDICT_STATIC_LINKING_ONLY\n#  define ZDICT_STATIC_LINKING_ONLY\n#endif\n\n#include \"../common/debug.h\" /* DEBUG_STATIC_ASSERT */\n#include \"../common/mem.h\" /* read */\n#include \"../common/pool.h\" /* POOL_ctx */\n#include \"../common/threading.h\" /* ZSTD_pthread_mutex_t */\n#include \"../common/zstd_internal.h\" /* includes zstd.h */\n#include \"../common/bits.h\" /* ZSTD_highbit32 */\n#include \"../zdict.h\"\n#include \"cover.h\"\n\n/*-*************************************\n*  Constants\n***************************************/\n/**\n* There are 32bit indexes used to ref samples, so limit samples size to 4GB\n* on 64bit builds.\n* For 32bit builds we choose 1 GB.\n* Most 32bit platforms have 2GB user-mode addressable space and we allocate a large\n* contiguous buffer, so 1GB is already a high limit.\n*/\n#define COVER_MAX_SAMPLES_SIZE (sizeof(size_t) == 8 ? ((unsigned)-1) : ((unsigned)1 GB))\n#define COVER_DEFAULT_SPLITPOINT 1.0\n\n/**\n * Select the qsort() variant used by cover\n */\n#define ZDICT_QSORT_MIN 0\n#define ZDICT_QSORT_C90 ZDICT_QSORT_MIN\n#define ZDICT_QSORT_GNU 1\n#define ZDICT_QSORT_APPLE 2\n#define ZDICT_QSORT_MSVC 3\n#define ZDICT_QSORT_C11 ZDICT_QSORT_MAX\n#define ZDICT_QSORT_MAX 4\n\n#ifndef ZDICT_QSORT\n# if defined(__APPLE__)\n#   define ZDICT_QSORT ZDICT_QSORT_APPLE /* uses qsort_r() with a different order for parameters */\n# elif (defined(__linux__) && !defined(__ANDROID__)) || defined(__CYGWIN__) || defined(__MSYS__)\n#   define ZDICT_QSORT ZDICT_QSORT_GNU /* uses qsort_r() */\n# elif defined(_WIN32) && defined(_MSC_VER)\n#   define ZDICT_QSORT ZDICT_QSORT_MSVC /* uses qsort_s() with a different order for parameters */\n# elif defined(STDC_LIB_EXT1) && (STDC_LIB_EXT1 > 0) /* C11 Annex K */\n#   define ZDICT_QSORT ZDICT_QSORT_C11 /* uses qsort_s() */\n# else\n#   define ZDICT_QSORT ZDICT_QSORT_C90 /* uses standard qsort() which is not re-entrant (requires global variable) */\n# endif\n#endif\n\n\n/*-*************************************\n*  Console display\n*\n* Captures the `displayLevel` variable in the local scope.\n***************************************/\n#undef  DISPLAY\n#define DISPLAY(...)                                                           \\\n  {                                                                            \\\n    fprintf(stderr, __VA_ARGS__);                                              \\\n    fflush(stderr);                                                            \\\n  }\n#undef  DISPLAYLEVEL\n#define DISPLAYLEVEL(l, ...)                                                   \\\n  if (displayLevel >= l) {                                                     \\\n    DISPLAY(__VA_ARGS__);                                                      \\\n  } /* 0 : no display;   1: errors;   2: default;  3: details;  4: debug */\n\n#undef  DISPLAYUPDATE\n#define DISPLAYUPDATE(lastUpdateTime, l, ...)                                  \\\n  if (displayLevel >= l) {                                                     \\\n    const clock_t refreshRate = CLOCKS_PER_SEC * 15 / 100;                     \\\n    if ((clock() - lastUpdateTime > refreshRate) || (displayLevel >= 4)) {     \\\n      lastUpdateTime = clock();                                                \\\n      DISPLAY(__VA_ARGS__);                                                    \\\n    }                                                                          \\\n  }\n\n/*-*************************************\n* Hash table\n***************************************\n* A small specialized hash map for storing activeDmers.\n* The map does not resize, so if it becomes full it will loop forever.\n* Thus, the map must be large enough to store every value.\n* The map implements linear probing and keeps its load less than 0.5.\n*/\n\n#define MAP_EMPTY_VALUE ((U32)-1)\ntypedef struct COVER_map_pair_t_s {\n  U32 key;\n  U32 value;\n} COVER_map_pair_t;\n\ntypedef struct COVER_map_s {\n  COVER_map_pair_t *data;\n  U32 sizeLog;\n  U32 size;\n  U32 sizeMask;\n} COVER_map_t;\n\n/**\n * Clear the map.\n */\nstatic void COVER_map_clear(COVER_map_t *map) {\n  memset(map->data, MAP_EMPTY_VALUE, map->size * sizeof(COVER_map_pair_t));\n}\n\n/**\n * Initializes a map of the given size.\n * Returns 1 on success and 0 on failure.\n * The map must be destroyed with COVER_map_destroy().\n * The map is only guaranteed to be large enough to hold size elements.\n */\nstatic int COVER_map_init(COVER_map_t *map, U32 size) {\n  map->sizeLog = ZSTD_highbit32(size) + 2;\n  map->size = (U32)1 << map->sizeLog;\n  map->sizeMask = map->size - 1;\n  map->data = (COVER_map_pair_t *)malloc(map->size * sizeof(COVER_map_pair_t));\n  if (!map->data) {\n    map->sizeLog = 0;\n    map->size = 0;\n    return 0;\n  }\n  COVER_map_clear(map);\n  return 1;\n}\n\n/**\n * Internal hash function\n */\nstatic const U32 COVER_prime4bytes = 2654435761U;\nstatic U32 COVER_map_hash(COVER_map_t *map, U32 key) {\n  return (key * COVER_prime4bytes) >> (32 - map->sizeLog);\n}\n\n/**\n * Helper function that returns the index that a key should be placed into.\n */\nstatic U32 COVER_map_index(COVER_map_t *map, U32 key) {\n  const U32 hash = COVER_map_hash(map, key);\n  U32 i;\n  for (i = hash;; i = (i + 1) & map->sizeMask) {\n    COVER_map_pair_t *pos = &map->data[i];\n    if (pos->value == MAP_EMPTY_VALUE) {\n      return i;\n    }\n    if (pos->key == key) {\n      return i;\n    }\n  }\n}\n\n/**\n * Returns the pointer to the value for key.\n * If key is not in the map, it is inserted and the value is set to 0.\n * The map must not be full.\n */\nstatic U32 *COVER_map_at(COVER_map_t *map, U32 key) {\n  COVER_map_pair_t *pos = &map->data[COVER_map_index(map, key)];\n  if (pos->value == MAP_EMPTY_VALUE) {\n    pos->key = key;\n    pos->value = 0;\n  }\n  return &pos->value;\n}\n\n/**\n * Deletes key from the map if present.\n */\nstatic void COVER_map_remove(COVER_map_t *map, U32 key) {\n  U32 i = COVER_map_index(map, key);\n  COVER_map_pair_t* del = &map->data[i];\n  U32 shift = 1;\n  if (del->value == MAP_EMPTY_VALUE) {\n    return;\n  }\n  for (i = (i + 1) & map->sizeMask;; i = (i + 1) & map->sizeMask) {\n    COVER_map_pair_t *const pos = &map->data[i];\n    /* If the position is empty we are done */\n    if (pos->value == MAP_EMPTY_VALUE) {\n      del->value = MAP_EMPTY_VALUE;\n      return;\n    }\n    /* If pos can be moved to del do so */\n    if (((i - COVER_map_hash(map, pos->key)) & map->sizeMask) >= shift) {\n      del->key = pos->key;\n      del->value = pos->value;\n      del = pos;\n      shift = 1;\n    } else {\n      ++shift;\n    }\n  }\n}\n\n/**\n * Destroys a map that is inited with COVER_map_init().\n */\nstatic void COVER_map_destroy(COVER_map_t *map) {\n  if (map->data) {\n    free(map->data);\n  }\n  map->data = NULL;\n  map->size = 0;\n}\n\n/*-*************************************\n* Context\n***************************************/\n\ntypedef struct {\n  const BYTE *samples;\n  size_t *offsets;\n  const size_t *samplesSizes;\n  size_t nbSamples;\n  size_t nbTrainSamples;\n  size_t nbTestSamples;\n  U32 *suffix;\n  size_t suffixSize;\n  U32 *freqs;\n  U32 *dmerAt;\n  unsigned d;\n  int displayLevel;\n} COVER_ctx_t;\n\n#if ZDICT_QSORT == ZDICT_QSORT_C90\n/* Use global context for non-reentrant sort functions */\nstatic COVER_ctx_t *g_coverCtx = NULL;\n#endif\n\n/*-*************************************\n*  Helper functions\n***************************************/\n\n/**\n * Returns the sum of the sample sizes.\n */\nsize_t COVER_sum(const size_t *samplesSizes, unsigned nbSamples) {\n  size_t sum = 0;\n  unsigned i;\n  for (i = 0; i < nbSamples; ++i) {\n    sum += samplesSizes[i];\n  }\n  return sum;\n}\n\n/**\n * Returns -1 if the dmer at lp is less than the dmer at rp.\n * Return 0 if the dmers at lp and rp are equal.\n * Returns 1 if the dmer at lp is greater than the dmer at rp.\n */\nstatic int COVER_cmp(COVER_ctx_t *ctx, const void *lp, const void *rp) {\n  U32 const lhs = *(U32 const *)lp;\n  U32 const rhs = *(U32 const *)rp;\n  return memcmp(ctx->samples + lhs, ctx->samples + rhs, ctx->d);\n}\n/**\n * Faster version for d <= 8.\n */\nstatic int COVER_cmp8(COVER_ctx_t *ctx, const void *lp, const void *rp) {\n  U64 const mask = (ctx->d == 8) ? (U64)-1 : (((U64)1 << (8 * ctx->d)) - 1);\n  U64 const lhs = MEM_readLE64(ctx->samples + *(U32 const *)lp) & mask;\n  U64 const rhs = MEM_readLE64(ctx->samples + *(U32 const *)rp) & mask;\n  if (lhs < rhs) {\n    return -1;\n  }\n  return (lhs > rhs);\n}\n\n/**\n * Same as COVER_cmp() except ties are broken by pointer value\n */\n#if (ZDICT_QSORT == ZDICT_QSORT_MSVC) || (ZDICT_QSORT == ZDICT_QSORT_APPLE)\nstatic int WIN_CDECL COVER_strict_cmp(void* g_coverCtx, const void* lp, const void* rp) {\n#elif (ZDICT_QSORT == ZDICT_QSORT_GNU) || (ZDICT_QSORT == ZDICT_QSORT_C11)\nstatic int COVER_strict_cmp(const void *lp, const void *rp, void *g_coverCtx) {\n#else /* C90 fallback.*/\nstatic int COVER_strict_cmp(const void *lp, const void *rp) {\n#endif\n  int result = COVER_cmp((COVER_ctx_t*)g_coverCtx, lp, rp);\n  if (result == 0) {\n    result = lp < rp ? -1 : 1;\n  }\n  return result;\n}\n/**\n * Faster version for d <= 8.\n */\n#if (ZDICT_QSORT == ZDICT_QSORT_MSVC) || (ZDICT_QSORT == ZDICT_QSORT_APPLE)\nstatic int WIN_CDECL COVER_strict_cmp8(void* g_coverCtx, const void* lp, const void* rp) {\n#elif (ZDICT_QSORT == ZDICT_QSORT_GNU) || (ZDICT_QSORT == ZDICT_QSORT_C11)\nstatic int COVER_strict_cmp8(const void *lp, const void *rp, void *g_coverCtx) {\n#else /* C90 fallback.*/\nstatic int COVER_strict_cmp8(const void *lp, const void *rp) {\n#endif\n  int result = COVER_cmp8((COVER_ctx_t*)g_coverCtx, lp, rp);\n  if (result == 0) {\n    result = lp < rp ? -1 : 1;\n  }\n  return result;\n}\n\n/**\n * Abstract away divergence of qsort_r() parameters.\n * Hopefully when C11 become the norm, we will be able\n * to clean it up.\n */\nstatic void stableSort(COVER_ctx_t *ctx)\n{\n    DEBUG_STATIC_ASSERT(ZDICT_QSORT_MIN <= ZDICT_QSORT && ZDICT_QSORT <= ZDICT_QSORT_MAX);\n#if (ZDICT_QSORT == ZDICT_QSORT_APPLE)\n    qsort_r(ctx->suffix, ctx->suffixSize, sizeof(U32),\n            ctx,\n            (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp));\n#elif (ZDICT_QSORT == ZDICT_QSORT_GNU)\n    qsort_r(ctx->suffix, ctx->suffixSize, sizeof(U32),\n            (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp),\n            ctx);\n#elif (ZDICT_QSORT == ZDICT_QSORT_MSVC)\n    qsort_s(ctx->suffix, ctx->suffixSize, sizeof(U32),\n            (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp),\n            ctx);\n#elif (ZDICT_QSORT == ZDICT_QSORT_C11)\n    qsort_s(ctx->suffix, ctx->suffixSize, sizeof(U32),\n            (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp),\n            ctx);\n#else /* C90 fallback.*/\n    g_coverCtx = ctx;\n    /* TODO(cavalcanti): implement a reentrant qsort() when _r is not available. */\n    qsort(ctx->suffix, ctx->suffixSize, sizeof(U32),\n          (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp));\n#endif\n}\n\n/**\n * Returns the first pointer in [first, last) whose element does not compare\n * less than value.  If no such element exists it returns last.\n */\nstatic const size_t *COVER_lower_bound(const size_t* first, const size_t* last,\n                                       size_t value) {\n  size_t count = (size_t)(last - first);\n  assert(last >= first);\n  while (count != 0) {\n    size_t step = count / 2;\n    const size_t *ptr = first;\n    ptr += step;\n    if (*ptr < value) {\n      first = ++ptr;\n      count -= step + 1;\n    } else {\n      count = step;\n    }\n  }\n  return first;\n}\n\n/**\n * Generic groupBy function.\n * Groups an array sorted by cmp into groups with equivalent values.\n * Calls grp for each group.\n */\nstatic void\nCOVER_groupBy(const void *data, size_t count, size_t size, COVER_ctx_t *ctx,\n              int (*cmp)(COVER_ctx_t *, const void *, const void *),\n              void (*grp)(COVER_ctx_t *, const void *, const void *)) {\n  const BYTE *ptr = (const BYTE *)data;\n  size_t num = 0;\n  while (num < count) {\n    const BYTE *grpEnd = ptr + size;\n    ++num;\n    while (num < count && cmp(ctx, ptr, grpEnd) == 0) {\n      grpEnd += size;\n      ++num;\n    }\n    grp(ctx, ptr, grpEnd);\n    ptr = grpEnd;\n  }\n}\n\n/*-*************************************\n*  Cover functions\n***************************************/\n\n/**\n * Called on each group of positions with the same dmer.\n * Counts the frequency of each dmer and saves it in the suffix array.\n * Fills `ctx->dmerAt`.\n */\nstatic void COVER_group(COVER_ctx_t *ctx, const void *group,\n                        const void *groupEnd) {\n  /* The group consists of all the positions with the same first d bytes. */\n  const U32 *grpPtr = (const U32 *)group;\n  const U32 *grpEnd = (const U32 *)groupEnd;\n  /* The dmerId is how we will reference this dmer.\n   * This allows us to map the whole dmer space to a much smaller space, the\n   * size of the suffix array.\n   */\n  const U32 dmerId = (U32)(grpPtr - ctx->suffix);\n  /* Count the number of samples this dmer shows up in */\n  U32 freq = 0;\n  /* Details */\n  const size_t *curOffsetPtr = ctx->offsets;\n  const size_t *offsetsEnd = ctx->offsets + ctx->nbSamples;\n  /* Once *grpPtr >= curSampleEnd this occurrence of the dmer is in a\n   * different sample than the last.\n   */\n  size_t curSampleEnd = ctx->offsets[0];\n  for (; grpPtr != grpEnd; ++grpPtr) {\n    /* Save the dmerId for this position so we can get back to it. */\n    ctx->dmerAt[*grpPtr] = dmerId;\n    /* Dictionaries only help for the first reference to the dmer.\n     * After that zstd can reference the match from the previous reference.\n     * So only count each dmer once for each sample it is in.\n     */\n    if (*grpPtr < curSampleEnd) {\n      continue;\n    }\n    freq += 1;\n    /* Binary search to find the end of the sample *grpPtr is in.\n     * In the common case that grpPtr + 1 == grpEnd we can skip the binary\n     * search because the loop is over.\n     */\n    if (grpPtr + 1 != grpEnd) {\n      const size_t *sampleEndPtr =\n          COVER_lower_bound(curOffsetPtr, offsetsEnd, *grpPtr);\n      curSampleEnd = *sampleEndPtr;\n      curOffsetPtr = sampleEndPtr + 1;\n    }\n  }\n  /* At this point we are never going to look at this segment of the suffix\n   * array again.  We take advantage of this fact to save memory.\n   * We store the frequency of the dmer in the first position of the group,\n   * which is dmerId.\n   */\n  ctx->suffix[dmerId] = freq;\n}\n\n\n/**\n * Selects the best segment in an epoch.\n * Segments of are scored according to the function:\n *\n * Let F(d) be the frequency of dmer d.\n * Let S_i be the dmer at position i of segment S which has length k.\n *\n *     Score(S) = F(S_1) + F(S_2) + ... + F(S_{k-d+1})\n *\n * Once the dmer d is in the dictionary we set F(d) = 0.\n */\nstatic COVER_segment_t COVER_selectSegment(const COVER_ctx_t *ctx, U32 *freqs,\n                                           COVER_map_t *activeDmers, U32 begin,\n                                           U32 end,\n                                           ZDICT_cover_params_t parameters) {\n  /* Constants */\n  const U32 k = parameters.k;\n  const U32 d = parameters.d;\n  const U32 dmersInK = k - d + 1;\n  /* Try each segment (activeSegment) and save the best (bestSegment) */\n  COVER_segment_t bestSegment = {0, 0, 0};\n  COVER_segment_t activeSegment;\n  /* Reset the activeDmers in the segment */\n  COVER_map_clear(activeDmers);\n  /* The activeSegment starts at the beginning of the epoch. */\n  activeSegment.begin = begin;\n  activeSegment.end = begin;\n  activeSegment.score = 0;\n  /* Slide the activeSegment through the whole epoch.\n   * Save the best segment in bestSegment.\n   */\n  while (activeSegment.end < end) {\n    /* The dmerId for the dmer at the next position */\n    U32 newDmer = ctx->dmerAt[activeSegment.end];\n    /* The entry in activeDmers for this dmerId */\n    U32 *newDmerOcc = COVER_map_at(activeDmers, newDmer);\n    /* If the dmer isn't already present in the segment add its score. */\n    if (*newDmerOcc == 0) {\n      /* The paper suggest using the L-0.5 norm, but experiments show that it\n       * doesn't help.\n       */\n      activeSegment.score += freqs[newDmer];\n    }\n    /* Add the dmer to the segment */\n    activeSegment.end += 1;\n    *newDmerOcc += 1;\n\n    /* If the window is now too large, drop the first position */\n    if (activeSegment.end - activeSegment.begin == dmersInK + 1) {\n      U32 delDmer = ctx->dmerAt[activeSegment.begin];\n      U32 *delDmerOcc = COVER_map_at(activeDmers, delDmer);\n      activeSegment.begin += 1;\n      *delDmerOcc -= 1;\n      /* If this is the last occurrence of the dmer, subtract its score */\n      if (*delDmerOcc == 0) {\n        COVER_map_remove(activeDmers, delDmer);\n        activeSegment.score -= freqs[delDmer];\n      }\n    }\n\n    /* If this segment is the best so far save it */\n    if (activeSegment.score > bestSegment.score) {\n      bestSegment = activeSegment;\n    }\n  }\n  {\n    /* Trim off the zero frequency head and tail from the segment. */\n    U32 newBegin = bestSegment.end;\n    U32 newEnd = bestSegment.begin;\n    U32 pos;\n    for (pos = bestSegment.begin; pos != bestSegment.end; ++pos) {\n      U32 freq = freqs[ctx->dmerAt[pos]];\n      if (freq != 0) {\n        newBegin = MIN(newBegin, pos);\n        newEnd = pos + 1;\n      }\n    }\n    bestSegment.begin = newBegin;\n    bestSegment.end = newEnd;\n  }\n  {\n    /* Zero out the frequency of each dmer covered by the chosen segment. */\n    U32 pos;\n    for (pos = bestSegment.begin; pos != bestSegment.end; ++pos) {\n      freqs[ctx->dmerAt[pos]] = 0;\n    }\n  }\n  return bestSegment;\n}\n\n/**\n * Check the validity of the parameters.\n * Returns non-zero if the parameters are valid and 0 otherwise.\n */\nstatic int COVER_checkParameters(ZDICT_cover_params_t parameters,\n                                 size_t maxDictSize) {\n  /* k and d are required parameters */\n  if (parameters.d == 0 || parameters.k == 0) {\n    return 0;\n  }\n  /* k <= maxDictSize */\n  if (parameters.k > maxDictSize) {\n    return 0;\n  }\n  /* d <= k */\n  if (parameters.d > parameters.k) {\n    return 0;\n  }\n  /* 0 < splitPoint <= 1 */\n  if (parameters.splitPoint <= 0 || parameters.splitPoint > 1){\n    return 0;\n  }\n  return 1;\n}\n\n/**\n * Clean up a context initialized with `COVER_ctx_init()`.\n */\nstatic void COVER_ctx_destroy(COVER_ctx_t *ctx) {\n  if (!ctx) {\n    return;\n  }\n  if (ctx->suffix) {\n    free(ctx->suffix);\n    ctx->suffix = NULL;\n  }\n  if (ctx->freqs) {\n    free(ctx->freqs);\n    ctx->freqs = NULL;\n  }\n  if (ctx->dmerAt) {\n    free(ctx->dmerAt);\n    ctx->dmerAt = NULL;\n  }\n  if (ctx->offsets) {\n    free(ctx->offsets);\n    ctx->offsets = NULL;\n  }\n}\n\n/**\n * Prepare a context for dictionary building.\n * The context is only dependent on the parameter `d` and can be used multiple\n * times.\n * Returns 0 on success or error code on error.\n * The context must be destroyed with `COVER_ctx_destroy()`.\n */\nstatic size_t COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer,\n                          const size_t *samplesSizes, unsigned nbSamples,\n                          unsigned d, double splitPoint, int displayLevel)\n{\n  const BYTE *const samples = (const BYTE *)samplesBuffer;\n  const size_t totalSamplesSize = COVER_sum(samplesSizes, nbSamples);\n  /* Split samples into testing and training sets */\n  const unsigned nbTrainSamples = splitPoint < 1.0 ? (unsigned)((double)nbSamples * splitPoint) : nbSamples;\n  const unsigned nbTestSamples = splitPoint < 1.0 ? nbSamples - nbTrainSamples : nbSamples;\n  const size_t trainingSamplesSize = splitPoint < 1.0 ? COVER_sum(samplesSizes, nbTrainSamples) : totalSamplesSize;\n  const size_t testSamplesSize = splitPoint < 1.0 ? COVER_sum(samplesSizes + nbTrainSamples, nbTestSamples) : totalSamplesSize;\n  ctx->displayLevel = displayLevel;\n  /* Checks */\n  if (totalSamplesSize < MAX(d, sizeof(U64)) ||\n      totalSamplesSize >= (size_t)COVER_MAX_SAMPLES_SIZE) {\n    DISPLAYLEVEL(1, \"Total samples size is too large (%u MB), maximum size is %u MB\\n\",\n                 (unsigned)(totalSamplesSize>>20), (COVER_MAX_SAMPLES_SIZE >> 20));\n    return ERROR(srcSize_wrong);\n  }\n  /* Check if there are at least 5 training samples */\n  if (nbTrainSamples < 5) {\n    DISPLAYLEVEL(1, \"Total number of training samples is %u and is invalid.\", nbTrainSamples);\n    return ERROR(srcSize_wrong);\n  }\n  /* Check if there's testing sample */\n  if (nbTestSamples < 1) {\n    DISPLAYLEVEL(1, \"Total number of testing samples is %u and is invalid.\", nbTestSamples);\n    return ERROR(srcSize_wrong);\n  }\n  /* Zero the context */\n  memset(ctx, 0, sizeof(*ctx));\n  DISPLAYLEVEL(2, \"Training on %u samples of total size %u\\n\", nbTrainSamples,\n               (unsigned)trainingSamplesSize);\n  DISPLAYLEVEL(2, \"Testing on %u samples of total size %u\\n\", nbTestSamples,\n               (unsigned)testSamplesSize);\n  ctx->samples = samples;\n  ctx->samplesSizes = samplesSizes;\n  ctx->nbSamples = nbSamples;\n  ctx->nbTrainSamples = nbTrainSamples;\n  ctx->nbTestSamples = nbTestSamples;\n  /* Partial suffix array */\n  ctx->suffixSize = trainingSamplesSize - MAX(d, sizeof(U64)) + 1;\n  ctx->suffix = (U32 *)malloc(ctx->suffixSize * sizeof(U32));\n  /* Maps index to the dmerID */\n  ctx->dmerAt = (U32 *)malloc(ctx->suffixSize * sizeof(U32));\n  /* The offsets of each file */\n  ctx->offsets = (size_t *)malloc((nbSamples + 1) * sizeof(size_t));\n  if (!ctx->suffix || !ctx->dmerAt || !ctx->offsets) {\n    DISPLAYLEVEL(1, \"Failed to allocate scratch buffers\\n\");\n    COVER_ctx_destroy(ctx);\n    return ERROR(memory_allocation);\n  }\n  ctx->freqs = NULL;\n  ctx->d = d;\n\n  /* Fill offsets from the samplesSizes */\n  {\n    U32 i;\n    ctx->offsets[0] = 0;\n    for (i = 1; i <= nbSamples; ++i) {\n      ctx->offsets[i] = ctx->offsets[i - 1] + samplesSizes[i - 1];\n    }\n  }\n  DISPLAYLEVEL(2, \"Constructing partial suffix array\\n\");\n  {\n    /* suffix is a partial suffix array.\n     * It only sorts suffixes by their first parameters.d bytes.\n     * The sort is stable, so each dmer group is sorted by position in input.\n     */\n    U32 i;\n    for (i = 0; i < ctx->suffixSize; ++i) {\n      ctx->suffix[i] = i;\n    }\n    stableSort(ctx);\n  }\n  DISPLAYLEVEL(2, \"Computing frequencies\\n\");\n  /* For each dmer group (group of positions with the same first d bytes):\n   * 1. For each position we set dmerAt[position] = dmerID.  The dmerID is\n   *    (groupBeginPtr - suffix).  This allows us to go from position to\n   *    dmerID so we can look up values in freq.\n   * 2. We calculate how many samples the dmer occurs in and save it in\n   *    freqs[dmerId].\n   */\n  COVER_groupBy(ctx->suffix, ctx->suffixSize, sizeof(U32), ctx,\n                (ctx->d <= 8 ? &COVER_cmp8 : &COVER_cmp), &COVER_group);\n  ctx->freqs = ctx->suffix;\n  ctx->suffix = NULL;\n  return 0;\n}\n\nvoid COVER_warnOnSmallCorpus(size_t maxDictSize, size_t nbDmers, int displayLevel)\n{\n  const double ratio = (double)nbDmers / (double)maxDictSize;\n  if (ratio >= 10) {\n      return;\n  }\n  DISPLAYLEVEL(1,\n               \"WARNING: The maximum dictionary size %u is too large \"\n               \"compared to the source size %u! \"\n               \"size(source)/size(dictionary) = %f, but it should be >= \"\n               \"10! This may lead to a subpar dictionary! We recommend \"\n               \"training on sources at least 10x, and preferably 100x \"\n               \"the size of the dictionary! \\n\", (U32)maxDictSize,\n               (U32)nbDmers, ratio);\n}\n\nCOVER_epoch_info_t COVER_computeEpochs(U32 maxDictSize,\n                                       U32 nbDmers, U32 k, U32 passes)\n{\n  const U32 minEpochSize = k * 10;\n  COVER_epoch_info_t epochs;\n  epochs.num = MAX(1, maxDictSize / k / passes);\n  epochs.size = nbDmers / epochs.num;\n  if (epochs.size >= minEpochSize) {\n      assert(epochs.size * epochs.num <= nbDmers);\n      return epochs;\n  }\n  epochs.size = MIN(minEpochSize, nbDmers);\n  epochs.num = nbDmers / epochs.size;\n  assert(epochs.size * epochs.num <= nbDmers);\n  return epochs;\n}\n\n/**\n * Given the prepared context build the dictionary.\n */\nstatic size_t COVER_buildDictionary(const COVER_ctx_t *ctx, U32 *freqs,\n                                    COVER_map_t *activeDmers, void *dictBuffer,\n                                    size_t dictBufferCapacity,\n                                    ZDICT_cover_params_t parameters) {\n  BYTE *const dict = (BYTE *)dictBuffer;\n  size_t tail = dictBufferCapacity;\n  /* Divide the data into epochs. We will select one segment from each epoch. */\n  const COVER_epoch_info_t epochs = COVER_computeEpochs(\n      (U32)dictBufferCapacity, (U32)ctx->suffixSize, parameters.k, 4);\n  const size_t maxZeroScoreRun = MAX(10, MIN(100, epochs.num >> 3));\n  size_t zeroScoreRun = 0;\n  size_t epoch;\n  clock_t lastUpdateTime = 0;\n  const int displayLevel = ctx->displayLevel;\n  DISPLAYLEVEL(2, \"Breaking content into %u epochs of size %u\\n\",\n                (U32)epochs.num, (U32)epochs.size);\n  /* Loop through the epochs until there are no more segments or the dictionary\n   * is full.\n   */\n  for (epoch = 0; tail > 0; epoch = (epoch + 1) % epochs.num) {\n    const U32 epochBegin = (U32)(epoch * epochs.size);\n    const U32 epochEnd = epochBegin + epochs.size;\n    size_t segmentSize;\n    /* Select a segment */\n    COVER_segment_t segment = COVER_selectSegment(\n        ctx, freqs, activeDmers, epochBegin, epochEnd, parameters);\n    /* If the segment covers no dmers, then we are out of content.\n     * There may be new content in other epochs, for continue for some time.\n     */\n    if (segment.score == 0) {\n      if (++zeroScoreRun >= maxZeroScoreRun) {\n          break;\n      }\n      continue;\n    }\n    zeroScoreRun = 0;\n    /* Trim the segment if necessary and if it is too small then we are done */\n    segmentSize = MIN(segment.end - segment.begin + parameters.d - 1, tail);\n    if (segmentSize < parameters.d) {\n      break;\n    }\n    /* We fill the dictionary from the back to allow the best segments to be\n     * referenced with the smallest offsets.\n     */\n    tail -= segmentSize;\n    memcpy(dict + tail, ctx->samples + segment.begin, segmentSize);\n    DISPLAYUPDATE(\n        lastUpdateTime,\n        2, \"\\r%u%%       \",\n        (unsigned)(((dictBufferCapacity - tail) * 100) / dictBufferCapacity));\n  }\n  DISPLAYLEVEL(2, \"\\r%79s\\r\", \"\");\n  return tail;\n}\n\nZDICTLIB_STATIC_API size_t ZDICT_trainFromBuffer_cover(\n    void *dictBuffer, size_t dictBufferCapacity,\n    const void *samplesBuffer, const size_t *samplesSizes, unsigned nbSamples,\n    ZDICT_cover_params_t parameters)\n{\n  BYTE* const dict = (BYTE*)dictBuffer;\n  COVER_ctx_t ctx;\n  COVER_map_t activeDmers;\n  const int displayLevel = (int)parameters.zParams.notificationLevel;\n  parameters.splitPoint = 1.0;\n  /* Checks */\n  if (!COVER_checkParameters(parameters, dictBufferCapacity)) {\n    DISPLAYLEVEL(1, \"Cover parameters incorrect\\n\");\n    return ERROR(parameter_outOfBound);\n  }\n  if (nbSamples == 0) {\n    DISPLAYLEVEL(1, \"Cover must have at least one input file\\n\");\n    return ERROR(srcSize_wrong);\n  }\n  if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) {\n    DISPLAYLEVEL(1, \"dictBufferCapacity must be at least %u\\n\",\n                 ZDICT_DICTSIZE_MIN);\n    return ERROR(dstSize_tooSmall);\n  }\n  /* Initialize context and activeDmers */\n  {\n    size_t const initVal = COVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples,\n                      parameters.d, parameters.splitPoint, displayLevel);\n    if (ZSTD_isError(initVal)) {\n      return initVal;\n    }\n  }\n  COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.suffixSize, displayLevel);\n  if (!COVER_map_init(&activeDmers, parameters.k - parameters.d + 1)) {\n    DISPLAYLEVEL(1, \"Failed to allocate dmer map: out of memory\\n\");\n    COVER_ctx_destroy(&ctx);\n    return ERROR(memory_allocation);\n  }\n\n  DISPLAYLEVEL(2, \"Building dictionary\\n\");\n  {\n    const size_t tail =\n        COVER_buildDictionary(&ctx, ctx.freqs, &activeDmers, dictBuffer,\n                              dictBufferCapacity, parameters);\n    const size_t dictionarySize = ZDICT_finalizeDictionary(\n        dict, dictBufferCapacity, dict + tail, dictBufferCapacity - tail,\n        samplesBuffer, samplesSizes, nbSamples, parameters.zParams);\n    if (!ZSTD_isError(dictionarySize)) {\n      DISPLAYLEVEL(2, \"Constructed dictionary of size %u\\n\",\n                   (unsigned)dictionarySize);\n    }\n    COVER_ctx_destroy(&ctx);\n    COVER_map_destroy(&activeDmers);\n    return dictionarySize;\n  }\n}\n\n\n\nsize_t COVER_checkTotalCompressedSize(const ZDICT_cover_params_t parameters,\n                                    const size_t *samplesSizes, const BYTE *samples,\n                                    size_t *offsets,\n                                    size_t nbTrainSamples, size_t nbSamples,\n                                    BYTE *const dict, size_t dictBufferCapacity) {\n  size_t totalCompressedSize = ERROR(GENERIC);\n  /* Pointers */\n  ZSTD_CCtx *cctx;\n  ZSTD_CDict *cdict;\n  void *dst;\n  /* Local variables */\n  size_t dstCapacity;\n  size_t i;\n  /* Allocate dst with enough space to compress the maximum sized sample */\n  {\n    size_t maxSampleSize = 0;\n    i = parameters.splitPoint < 1.0 ? nbTrainSamples : 0;\n    for (; i < nbSamples; ++i) {\n      maxSampleSize = MAX(samplesSizes[i], maxSampleSize);\n    }\n    dstCapacity = ZSTD_compressBound(maxSampleSize);\n    dst = malloc(dstCapacity);\n  }\n  /* Create the cctx and cdict */\n  cctx = ZSTD_createCCtx();\n  cdict = ZSTD_createCDict(dict, dictBufferCapacity,\n                           parameters.zParams.compressionLevel);\n  if (!dst || !cctx || !cdict) {\n    goto _compressCleanup;\n  }\n  /* Compress each sample and sum their sizes (or error) */\n  totalCompressedSize = dictBufferCapacity;\n  i = parameters.splitPoint < 1.0 ? nbTrainSamples : 0;\n  for (; i < nbSamples; ++i) {\n    const size_t size = ZSTD_compress_usingCDict(\n        cctx, dst, dstCapacity, samples + offsets[i],\n        samplesSizes[i], cdict);\n    if (ZSTD_isError(size)) {\n      totalCompressedSize = size;\n      goto _compressCleanup;\n    }\n    totalCompressedSize += size;\n  }\n_compressCleanup:\n  ZSTD_freeCCtx(cctx);\n  ZSTD_freeCDict(cdict);\n  if (dst) {\n    free(dst);\n  }\n  return totalCompressedSize;\n}\n\n\n/**\n * Initialize the `COVER_best_t`.\n */\nvoid COVER_best_init(COVER_best_t *best) {\n  if (best==NULL) return; /* compatible with init on NULL */\n  (void)ZSTD_pthread_mutex_init(&best->mutex, NULL);\n  (void)ZSTD_pthread_cond_init(&best->cond, NULL);\n  best->liveJobs = 0;\n  best->dict = NULL;\n  best->dictSize = 0;\n  best->compressedSize = (size_t)-1;\n  memset(&best->parameters, 0, sizeof(best->parameters));\n}\n\n/**\n * Wait until liveJobs == 0.\n */\nvoid COVER_best_wait(COVER_best_t *best) {\n  if (!best) {\n    return;\n  }\n  ZSTD_pthread_mutex_lock(&best->mutex);\n  while (best->liveJobs != 0) {\n    ZSTD_pthread_cond_wait(&best->cond, &best->mutex);\n  }\n  ZSTD_pthread_mutex_unlock(&best->mutex);\n}\n\n/**\n * Call COVER_best_wait() and then destroy the COVER_best_t.\n */\nvoid COVER_best_destroy(COVER_best_t *best) {\n  if (!best) {\n    return;\n  }\n  COVER_best_wait(best);\n  if (best->dict) {\n    free(best->dict);\n  }\n  ZSTD_pthread_mutex_destroy(&best->mutex);\n  ZSTD_pthread_cond_destroy(&best->cond);\n}\n\n/**\n * Called when a thread is about to be launched.\n * Increments liveJobs.\n */\nvoid COVER_best_start(COVER_best_t *best) {\n  if (!best) {\n    return;\n  }\n  ZSTD_pthread_mutex_lock(&best->mutex);\n  ++best->liveJobs;\n  ZSTD_pthread_mutex_unlock(&best->mutex);\n}\n\n/**\n * Called when a thread finishes executing, both on error or success.\n * Decrements liveJobs and signals any waiting threads if liveJobs == 0.\n * If this dictionary is the best so far save it and its parameters.\n */\nvoid COVER_best_finish(COVER_best_t* best,\n                      ZDICT_cover_params_t parameters,\n                      COVER_dictSelection_t selection)\n{\n  void* dict = selection.dictContent;\n  size_t compressedSize = selection.totalCompressedSize;\n  size_t dictSize = selection.dictSize;\n  if (!best) {\n    return;\n  }\n  {\n    size_t liveJobs;\n    ZSTD_pthread_mutex_lock(&best->mutex);\n    --best->liveJobs;\n    liveJobs = best->liveJobs;\n    /* If the new dictionary is better */\n    if (compressedSize < best->compressedSize) {\n      /* Allocate space if necessary */\n      if (!best->dict || best->dictSize < dictSize) {\n        if (best->dict) {\n          free(best->dict);\n        }\n        best->dict = malloc(dictSize);\n        if (!best->dict) {\n          best->compressedSize = ERROR(GENERIC);\n          best->dictSize = 0;\n          ZSTD_pthread_cond_signal(&best->cond);\n          ZSTD_pthread_mutex_unlock(&best->mutex);\n          return;\n        }\n      }\n      /* Save the dictionary, parameters, and size */\n      if (dict) {\n        memcpy(best->dict, dict, dictSize);\n        best->dictSize = dictSize;\n        best->parameters = parameters;\n        best->compressedSize = compressedSize;\n      }\n    }\n    if (liveJobs == 0) {\n      ZSTD_pthread_cond_broadcast(&best->cond);\n    }\n    ZSTD_pthread_mutex_unlock(&best->mutex);\n  }\n}\n\nstatic COVER_dictSelection_t setDictSelection(BYTE* buf, size_t s, size_t csz)\n{\n    COVER_dictSelection_t ds;\n    ds.dictContent = buf;\n    ds.dictSize = s;\n    ds.totalCompressedSize = csz;\n    return ds;\n}\n\nCOVER_dictSelection_t COVER_dictSelectionError(size_t error) {\n    return setDictSelection(NULL, 0, error);\n}\n\nunsigned COVER_dictSelectionIsError(COVER_dictSelection_t selection) {\n  return (ZSTD_isError(selection.totalCompressedSize) || !selection.dictContent);\n}\n\nvoid COVER_dictSelectionFree(COVER_dictSelection_t selection){\n  free(selection.dictContent);\n}\n\nCOVER_dictSelection_t COVER_selectDict(BYTE* customDictContent, size_t dictBufferCapacity,\n        size_t dictContentSize, const BYTE* samplesBuffer, const size_t* samplesSizes, unsigned nbFinalizeSamples,\n        size_t nbCheckSamples, size_t nbSamples, ZDICT_cover_params_t params, size_t* offsets, size_t totalCompressedSize) {\n\n  size_t largestDict = 0;\n  size_t largestCompressed = 0;\n  BYTE* customDictContentEnd = customDictContent + dictContentSize;\n\n  BYTE* largestDictbuffer = (BYTE*)malloc(dictBufferCapacity);\n  BYTE* candidateDictBuffer = (BYTE*)malloc(dictBufferCapacity);\n  double regressionTolerance = ((double)params.shrinkDictMaxRegression / 100.0) + 1.00;\n\n  if (!largestDictbuffer || !candidateDictBuffer) {\n    free(largestDictbuffer);\n    free(candidateDictBuffer);\n    return COVER_dictSelectionError(dictContentSize);\n  }\n\n  /* Initial dictionary size and compressed size */\n  memcpy(largestDictbuffer, customDictContent, dictContentSize);\n  dictContentSize = ZDICT_finalizeDictionary(\n    largestDictbuffer, dictBufferCapacity, customDictContent, dictContentSize,\n    samplesBuffer, samplesSizes, nbFinalizeSamples, params.zParams);\n\n  if (ZDICT_isError(dictContentSize)) {\n    free(largestDictbuffer);\n    free(candidateDictBuffer);\n    return COVER_dictSelectionError(dictContentSize);\n  }\n\n  totalCompressedSize = COVER_checkTotalCompressedSize(params, samplesSizes,\n                                                       samplesBuffer, offsets,\n                                                       nbCheckSamples, nbSamples,\n                                                       largestDictbuffer, dictContentSize);\n\n  if (ZSTD_isError(totalCompressedSize)) {\n    free(largestDictbuffer);\n    free(candidateDictBuffer);\n    return COVER_dictSelectionError(totalCompressedSize);\n  }\n\n  if (params.shrinkDict == 0) {\n    free(candidateDictBuffer);\n    return setDictSelection(largestDictbuffer, dictContentSize, totalCompressedSize);\n  }\n\n  largestDict = dictContentSize;\n  largestCompressed = totalCompressedSize;\n  dictContentSize = ZDICT_DICTSIZE_MIN;\n\n  /* Largest dict is initially at least ZDICT_DICTSIZE_MIN */\n  while (dictContentSize < largestDict) {\n    memcpy(candidateDictBuffer, largestDictbuffer, largestDict);\n    dictContentSize = ZDICT_finalizeDictionary(\n      candidateDictBuffer, dictBufferCapacity, customDictContentEnd - dictContentSize, dictContentSize,\n      samplesBuffer, samplesSizes, nbFinalizeSamples, params.zParams);\n\n    if (ZDICT_isError(dictContentSize)) {\n      free(largestDictbuffer);\n      free(candidateDictBuffer);\n      return COVER_dictSelectionError(dictContentSize);\n\n    }\n\n    totalCompressedSize = COVER_checkTotalCompressedSize(params, samplesSizes,\n                                                         samplesBuffer, offsets,\n                                                         nbCheckSamples, nbSamples,\n                                                         candidateDictBuffer, dictContentSize);\n\n    if (ZSTD_isError(totalCompressedSize)) {\n      free(largestDictbuffer);\n      free(candidateDictBuffer);\n      return COVER_dictSelectionError(totalCompressedSize);\n    }\n\n    if ((double)totalCompressedSize <= (double)largestCompressed * regressionTolerance) {\n      free(largestDictbuffer);\n      return setDictSelection( candidateDictBuffer, dictContentSize, totalCompressedSize );\n    }\n    dictContentSize *= 2;\n  }\n  dictContentSize = largestDict;\n  totalCompressedSize = largestCompressed;\n  free(candidateDictBuffer);\n  return setDictSelection( largestDictbuffer, dictContentSize, totalCompressedSize );\n}\n\n/**\n * Parameters for COVER_tryParameters().\n */\ntypedef struct COVER_tryParameters_data_s {\n  const COVER_ctx_t *ctx;\n  COVER_best_t *best;\n  size_t dictBufferCapacity;\n  ZDICT_cover_params_t parameters;\n} COVER_tryParameters_data_t;\n\n/**\n * Tries a set of parameters and updates the COVER_best_t with the results.\n * This function is thread safe if zstd is compiled with multithreaded support.\n * It takes its parameters as an *OWNING* opaque pointer to support threading.\n */\nstatic void COVER_tryParameters(void *opaque)\n{\n  /* Save parameters as local variables */\n  COVER_tryParameters_data_t *const data = (COVER_tryParameters_data_t*)opaque;\n  const COVER_ctx_t *const ctx = data->ctx;\n  const ZDICT_cover_params_t parameters = data->parameters;\n  size_t dictBufferCapacity = data->dictBufferCapacity;\n  size_t totalCompressedSize = ERROR(GENERIC);\n  /* Allocate space for hash table, dict, and freqs */\n  COVER_map_t activeDmers;\n  BYTE* const dict = (BYTE*)malloc(dictBufferCapacity);\n  COVER_dictSelection_t selection = COVER_dictSelectionError(ERROR(GENERIC));\n  U32* const freqs = (U32*)malloc(ctx->suffixSize * sizeof(U32));\n  const int displayLevel = ctx->displayLevel;\n  if (!COVER_map_init(&activeDmers, parameters.k - parameters.d + 1)) {\n    DISPLAYLEVEL(1, \"Failed to allocate dmer map: out of memory\\n\");\n    goto _cleanup;\n  }\n  if (!dict || !freqs) {\n    DISPLAYLEVEL(1, \"Failed to allocate buffers: out of memory\\n\");\n    goto _cleanup;\n  }\n  /* Copy the frequencies because we need to modify them */\n  memcpy(freqs, ctx->freqs, ctx->suffixSize * sizeof(U32));\n  /* Build the dictionary */\n  {\n    const size_t tail = COVER_buildDictionary(ctx, freqs, &activeDmers, dict,\n                                              dictBufferCapacity, parameters);\n    selection = COVER_selectDict(dict + tail, dictBufferCapacity, dictBufferCapacity - tail,\n        ctx->samples, ctx->samplesSizes, (unsigned)ctx->nbTrainSamples, ctx->nbTrainSamples, ctx->nbSamples, parameters, ctx->offsets,\n        totalCompressedSize);\n\n    if (COVER_dictSelectionIsError(selection)) {\n      DISPLAYLEVEL(1, \"Failed to select dictionary\\n\");\n      goto _cleanup;\n    }\n  }\n_cleanup:\n  free(dict);\n  COVER_best_finish(data->best, parameters, selection);\n  free(data);\n  COVER_map_destroy(&activeDmers);\n  COVER_dictSelectionFree(selection);\n  free(freqs);\n}\n\nZDICTLIB_STATIC_API size_t ZDICT_optimizeTrainFromBuffer_cover(\n    void* dictBuffer, size_t dictBufferCapacity, const void* samplesBuffer,\n    const size_t* samplesSizes, unsigned nbSamples,\n    ZDICT_cover_params_t* parameters)\n{\n  /* constants */\n  const unsigned nbThreads = parameters->nbThreads;\n  const double splitPoint =\n      parameters->splitPoint <= 0.0 ? COVER_DEFAULT_SPLITPOINT : parameters->splitPoint;\n  const unsigned kMinD = parameters->d == 0 ? 6 : parameters->d;\n  const unsigned kMaxD = parameters->d == 0 ? 8 : parameters->d;\n  const unsigned kMinK = parameters->k == 0 ? 50 : parameters->k;\n  const unsigned kMaxK = parameters->k == 0 ? 2000 : parameters->k;\n  const unsigned kSteps = parameters->steps == 0 ? 40 : parameters->steps;\n  const unsigned kStepSize = MAX((kMaxK - kMinK) / kSteps, 1);\n  const unsigned kIterations =\n      (1 + (kMaxD - kMinD) / 2) * (1 + (kMaxK - kMinK) / kStepSize);\n  const unsigned shrinkDict = 0;\n  /* Local variables */\n  int displayLevel = (int)parameters->zParams.notificationLevel;\n  unsigned iteration = 1;\n  unsigned d;\n  unsigned k;\n  COVER_best_t best;\n  POOL_ctx *pool = NULL;\n  int warned = 0;\n  clock_t lastUpdateTime = 0;\n\n  /* Checks */\n  if (splitPoint <= 0 || splitPoint > 1) {\n    DISPLAYLEVEL(1, \"Incorrect parameters\\n\");\n    return ERROR(parameter_outOfBound);\n  }\n  if (kMinK < kMaxD || kMaxK < kMinK) {\n    DISPLAYLEVEL(1, \"Incorrect parameters\\n\");\n    return ERROR(parameter_outOfBound);\n  }\n  if (nbSamples == 0) {\n    DISPLAYLEVEL(1, \"Cover must have at least one input file\\n\");\n    return ERROR(srcSize_wrong);\n  }\n  if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) {\n    DISPLAYLEVEL(1, \"dictBufferCapacity must be at least %u\\n\",\n                 ZDICT_DICTSIZE_MIN);\n    return ERROR(dstSize_tooSmall);\n  }\n  if (nbThreads > 1) {\n    pool = POOL_create(nbThreads, 1);\n    if (!pool) {\n      return ERROR(memory_allocation);\n    }\n  }\n  /* Initialization */\n  COVER_best_init(&best);\n  /* Loop through d first because each new value needs a new context */\n  DISPLAYLEVEL(2, \"Trying %u different sets of parameters\\n\",\n                    kIterations);\n  for (d = kMinD; d <= kMaxD; d += 2) {\n    /* Initialize the context for this value of d */\n    COVER_ctx_t ctx;\n    DISPLAYLEVEL(3, \"d=%u\\n\", d);\n    {\n      /* Turn down global display level to clean up display at level 2 and below */\n      const int childDisplayLevel = (displayLevel == 0) ? 0 : displayLevel - 1;\n      const size_t initVal = COVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples, d, splitPoint, childDisplayLevel);\n      if (ZSTD_isError(initVal)) {\n        DISPLAYLEVEL(1, \"Failed to initialize context\\n\");\n        COVER_best_destroy(&best);\n        POOL_free(pool);\n        return initVal;\n      }\n    }\n    if (!warned) {\n      COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.suffixSize, displayLevel);\n      warned = 1;\n    }\n    /* Loop through k reusing the same context */\n    for (k = kMinK; k <= kMaxK; k += kStepSize) {\n      /* Prepare the arguments */\n      COVER_tryParameters_data_t *data = (COVER_tryParameters_data_t *)malloc(\n          sizeof(COVER_tryParameters_data_t));\n      DISPLAYLEVEL(3, \"k=%u\\n\", k);\n      if (!data) {\n        DISPLAYLEVEL(1, \"Failed to allocate parameters\\n\");\n        COVER_best_destroy(&best);\n        COVER_ctx_destroy(&ctx);\n        POOL_free(pool);\n        return ERROR(memory_allocation);\n      }\n      data->ctx = &ctx;\n      data->best = &best;\n      data->dictBufferCapacity = dictBufferCapacity;\n      data->parameters = *parameters;\n      data->parameters.k = k;\n      data->parameters.d = d;\n      data->parameters.splitPoint = splitPoint;\n      data->parameters.steps = kSteps;\n      data->parameters.shrinkDict = shrinkDict;\n      data->parameters.zParams.notificationLevel = (unsigned)ctx.displayLevel;\n      /* Check the parameters */\n      if (!COVER_checkParameters(data->parameters, dictBufferCapacity)) {\n        DISPLAYLEVEL(1, \"Cover parameters incorrect\\n\");\n        free(data);\n        continue;\n      }\n      /* Call the function and pass ownership of data to it */\n      COVER_best_start(&best);\n      if (pool) {\n        POOL_add(pool, &COVER_tryParameters, data);\n      } else {\n        COVER_tryParameters(data);\n      }\n      /* Print status */\n      DISPLAYUPDATE(lastUpdateTime, 2, \"\\r%u%%       \",\n                    (unsigned)((iteration * 100) / kIterations));\n      ++iteration;\n    }\n    COVER_best_wait(&best);\n    COVER_ctx_destroy(&ctx);\n  }\n  DISPLAYLEVEL(2, \"\\r%79s\\r\", \"\");\n  /* Fill the output buffer and parameters with output of the best parameters */\n  {\n    const size_t dictSize = best.dictSize;\n    if (ZSTD_isError(best.compressedSize)) {\n      const size_t compressedSize = best.compressedSize;\n      COVER_best_destroy(&best);\n      POOL_free(pool);\n      return compressedSize;\n    }\n    *parameters = best.parameters;\n    memcpy(dictBuffer, best.dict, dictSize);\n    COVER_best_destroy(&best);\n    POOL_free(pool);\n    return dictSize;\n  }\n}\n"
  },
  {
    "path": "lib/dictBuilder/cover.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZDICT_STATIC_LINKING_ONLY\n#  define ZDICT_STATIC_LINKING_ONLY\n#endif\n\n#include \"../common/threading.h\" /* ZSTD_pthread_mutex_t */\n#include \"../common/mem.h\"   /* U32, BYTE */\n#include \"../zdict.h\"\n\n/**\n * COVER_best_t is used for two purposes:\n * 1. Synchronizing threads.\n * 2. Saving the best parameters and dictionary.\n *\n * All of the methods except COVER_best_init() are thread safe if zstd is\n * compiled with multithreaded support.\n */\ntypedef struct COVER_best_s {\n  ZSTD_pthread_mutex_t mutex;\n  ZSTD_pthread_cond_t cond;\n  size_t liveJobs;\n  void *dict;\n  size_t dictSize;\n  ZDICT_cover_params_t parameters;\n  size_t compressedSize;\n} COVER_best_t;\n\n/**\n * A segment is a range in the source as well as the score of the segment.\n */\ntypedef struct {\n  U32 begin;\n  U32 end;\n  U32 score;\n} COVER_segment_t;\n\n/**\n *Number of epochs and size of each epoch.\n */\ntypedef struct {\n  U32 num;\n  U32 size;\n} COVER_epoch_info_t;\n\n/**\n * Struct used for the dictionary selection function.\n */\ntypedef struct COVER_dictSelection {\n  BYTE* dictContent;\n  size_t dictSize;\n  size_t totalCompressedSize;\n} COVER_dictSelection_t;\n\n/**\n * Computes the number of epochs and the size of each epoch.\n * We will make sure that each epoch gets at least 10 * k bytes.\n *\n * The COVER algorithms divide the data up into epochs of equal size and\n * select one segment from each epoch.\n *\n * @param maxDictSize The maximum allowed dictionary size.\n * @param nbDmers     The number of dmers we are training on.\n * @param k           The parameter k (segment size).\n * @param passes      The target number of passes over the dmer corpus.\n *                    More passes means a better dictionary.\n */\nCOVER_epoch_info_t COVER_computeEpochs(U32 maxDictSize, U32 nbDmers,\n                                       U32 k, U32 passes);\n\n/**\n * Warns the user when their corpus is too small.\n */\nvoid COVER_warnOnSmallCorpus(size_t maxDictSize, size_t nbDmers, int displayLevel);\n\n/**\n *  Checks total compressed size of a dictionary\n */\nsize_t COVER_checkTotalCompressedSize(const ZDICT_cover_params_t parameters,\n                                      const size_t *samplesSizes, const BYTE *samples,\n                                      size_t *offsets,\n                                      size_t nbTrainSamples, size_t nbSamples,\n                                      BYTE *const dict, size_t dictBufferCapacity);\n\n/**\n * Returns the sum of the sample sizes.\n */\nsize_t COVER_sum(const size_t *samplesSizes, unsigned nbSamples) ;\n\n/**\n * Initialize the `COVER_best_t`.\n */\nvoid COVER_best_init(COVER_best_t *best);\n\n/**\n * Wait until liveJobs == 0.\n */\nvoid COVER_best_wait(COVER_best_t *best);\n\n/**\n * Call COVER_best_wait() and then destroy the COVER_best_t.\n */\nvoid COVER_best_destroy(COVER_best_t *best);\n\n/**\n * Called when a thread is about to be launched.\n * Increments liveJobs.\n */\nvoid COVER_best_start(COVER_best_t *best);\n\n/**\n * Called when a thread finishes executing, both on error or success.\n * Decrements liveJobs and signals any waiting threads if liveJobs == 0.\n * If this dictionary is the best so far save it and its parameters.\n */\nvoid COVER_best_finish(COVER_best_t *best, ZDICT_cover_params_t parameters,\n                       COVER_dictSelection_t selection);\n/**\n * Error function for COVER_selectDict function. Checks if the return\n * value is an error.\n */\nunsigned COVER_dictSelectionIsError(COVER_dictSelection_t selection);\n\n /**\n  * Error function for COVER_selectDict function. Returns a struct where\n  * return.totalCompressedSize is a ZSTD error.\n  */\nCOVER_dictSelection_t COVER_dictSelectionError(size_t error);\n\n/**\n * Always call after selectDict is called to free up used memory from\n * newly created dictionary.\n */\nvoid COVER_dictSelectionFree(COVER_dictSelection_t selection);\n\n/**\n * Called to finalize the dictionary and select one based on whether or not\n * the shrink-dict flag was enabled. If enabled the dictionary used is the\n * smallest dictionary within a specified regression of the compressed size\n * from the largest dictionary.\n */\n COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent, size_t dictBufferCapacity,\n                       size_t dictContentSize, const BYTE* samplesBuffer, const size_t* samplesSizes, unsigned nbFinalizeSamples,\n                       size_t nbCheckSamples, size_t nbSamples, ZDICT_cover_params_t params, size_t* offsets, size_t totalCompressedSize);\n"
  },
  {
    "path": "lib/dictBuilder/divsufsort.c",
    "content": "/*\n * divsufsort.c for libdivsufsort-lite\n * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.\n *\n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation\n * files (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use,\n * copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following\n * conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n/*- Compiler specifics -*/\n#if defined(_MSC_VER)\n#  pragma warning(disable : 4127)    /* C4127 : Condition expression is constant */\n#endif\n\n\n/*- Dependencies -*/\n#include <assert.h>\n#include <limits.h>\n#include <stddef.h>\n#include <stdio.h>\n#include <stdlib.h>\n\n#include \"divsufsort.h\"\n\n#define PTRDIFF_TO_INT(x) (assert((x) <= INT_MAX && (x) >= INT_MIN), (int)(x))\n\n/*- Constants -*/\n#if defined(INLINE)\n# undef INLINE\n#endif\n#if !defined(INLINE)\n# define INLINE __inline\n#endif\n#if defined(ALPHABET_SIZE) && (ALPHABET_SIZE < 1)\n# undef ALPHABET_SIZE\n#endif\n#if !defined(ALPHABET_SIZE)\n# define ALPHABET_SIZE (256)\n#endif\n#define BUCKET_A_SIZE (ALPHABET_SIZE)\n#define BUCKET_B_SIZE (ALPHABET_SIZE * ALPHABET_SIZE)\n#if defined(SS_INSERTIONSORT_THRESHOLD)\n# if SS_INSERTIONSORT_THRESHOLD < 1\n#  undef SS_INSERTIONSORT_THRESHOLD\n#  define SS_INSERTIONSORT_THRESHOLD (1)\n# endif\n#else\n# define SS_INSERTIONSORT_THRESHOLD (8)\n#endif\n#if defined(SS_BLOCKSIZE)\n# if SS_BLOCKSIZE < 0\n#  undef SS_BLOCKSIZE\n#  define SS_BLOCKSIZE (0)\n# elif 32768 <= SS_BLOCKSIZE\n#  undef SS_BLOCKSIZE\n#  define SS_BLOCKSIZE (32767)\n# endif\n#else\n# define SS_BLOCKSIZE (1024)\n#endif\n/* minstacksize = log(SS_BLOCKSIZE) / log(3) * 2 */\n#if SS_BLOCKSIZE == 0\n# define SS_MISORT_STACKSIZE (96)\n#elif SS_BLOCKSIZE <= 4096\n# define SS_MISORT_STACKSIZE (16)\n#else\n# define SS_MISORT_STACKSIZE (24)\n#endif\n#define SS_SMERGE_STACKSIZE (32)\n#define TR_INSERTIONSORT_THRESHOLD (8)\n#define TR_STACKSIZE (64)\n\n\n/*- Macros -*/\n#ifndef SWAP\n# define SWAP(_a, _b) do { t = (_a); (_a) = (_b); (_b) = t; } while(0)\n#endif /* SWAP */\n#ifndef MIN\n# define MIN(_a, _b) (((_a) < (_b)) ? (_a) : (_b))\n#endif /* MIN */\n#ifndef MAX\n# define MAX(_a, _b) (((_a) > (_b)) ? (_a) : (_b))\n#endif /* MAX */\n#define STACK_PUSH(_a, _b, _c, _d)\\\n  do {\\\n    assert(ssize < STACK_SIZE);\\\n    stack[ssize].a = (_a), stack[ssize].b = (_b),\\\n    stack[ssize].c = (_c), stack[ssize++].d = (_d);\\\n  } while(0)\n#define STACK_PUSH5(_a, _b, _c, _d, _e)\\\n  do {\\\n    assert(ssize < STACK_SIZE);\\\n    stack[ssize].a = (_a), stack[ssize].b = (_b),\\\n    stack[ssize].c = (_c), stack[ssize].d = (_d), stack[ssize++].e = (_e);\\\n  } while(0)\n#define STACK_POP(_a, _b, _c, _d)\\\n  do {\\\n    assert(0 <= ssize);\\\n    if(ssize == 0) { return; }\\\n    (_a) = stack[--ssize].a, (_b) = stack[ssize].b,\\\n    (_c) = stack[ssize].c, (_d) = stack[ssize].d;\\\n  } while(0)\n#define STACK_POP5(_a, _b, _c, _d, _e)\\\n  do {\\\n    assert(0 <= ssize);\\\n    if(ssize == 0) { return; }\\\n    (_a) = stack[--ssize].a, (_b) = stack[ssize].b,\\\n    (_c) = stack[ssize].c, (_d) = stack[ssize].d, (_e) = stack[ssize].e;\\\n  } while(0)\n#define BUCKET_A(_c0) bucket_A[(_c0)]\n#if ALPHABET_SIZE == 256\n#define BUCKET_B(_c0, _c1) (bucket_B[((_c1) << 8) | (_c0)])\n#define BUCKET_BSTAR(_c0, _c1) (bucket_B[((_c0) << 8) | (_c1)])\n#else\n#define BUCKET_B(_c0, _c1) (bucket_B[(_c1) * ALPHABET_SIZE + (_c0)])\n#define BUCKET_BSTAR(_c0, _c1) (bucket_B[(_c0) * ALPHABET_SIZE + (_c1)])\n#endif\n\n\n/*- Private Functions -*/\n\nstatic const int lg_table[256]= {\n -1,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,\n  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,\n  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7\n};\n\n#if (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE)\n\nstatic INLINE\nint\nss_ilg(int n) {\n#if SS_BLOCKSIZE == 0\n  return (n & 0xffff0000) ?\n          ((n & 0xff000000) ?\n            24 + lg_table[(n >> 24) & 0xff] :\n            16 + lg_table[(n >> 16) & 0xff]) :\n          ((n & 0x0000ff00) ?\n             8 + lg_table[(n >>  8) & 0xff] :\n             0 + lg_table[(n >>  0) & 0xff]);\n#elif SS_BLOCKSIZE < 256\n  return lg_table[n];\n#else\n  return (n & 0xff00) ?\n          8 + lg_table[(n >> 8) & 0xff] :\n          0 + lg_table[(n >> 0) & 0xff];\n#endif\n}\n\n#endif /* (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) */\n\n#if SS_BLOCKSIZE != 0\n\nstatic const int sqq_table[256] = {\n  0,  16,  22,  27,  32,  35,  39,  42,  45,  48,  50,  53,  55,  57,  59,  61,\n 64,  65,  67,  69,  71,  73,  75,  76,  78,  80,  81,  83,  84,  86,  87,  89,\n 90,  91,  93,  94,  96,  97,  98,  99, 101, 102, 103, 104, 106, 107, 108, 109,\n110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,\n128, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,\n143, 144, 144, 145, 146, 147, 148, 149, 150, 150, 151, 152, 153, 154, 155, 155,\n156, 157, 158, 159, 160, 160, 161, 162, 163, 163, 164, 165, 166, 167, 167, 168,\n169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 178, 179, 180,\n181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191,\n192, 192, 193, 193, 194, 195, 195, 196, 197, 197, 198, 199, 199, 200, 201, 201,\n202, 203, 203, 204, 204, 205, 206, 206, 207, 208, 208, 209, 209, 210, 211, 211,\n212, 212, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 221,\n221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 227, 228, 229, 229, 230,\n230, 231, 231, 232, 232, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238,\n239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 247,\n247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255\n};\n\nstatic INLINE\nint\nss_isqrt(int x) {\n  int y, e;\n\n  if(x >= (SS_BLOCKSIZE * SS_BLOCKSIZE)) { return SS_BLOCKSIZE; }\n  e = ((unsigned)x & 0xffff0000) ?\n        (((unsigned)x & 0xff000000) ?\n          24 + lg_table[(x >> 24) & 0xff] :\n          16 + lg_table[(x >> 16) & 0xff]) :\n        ((x & 0x0000ff00) ?\n           8 + lg_table[(x >>  8) & 0xff] :\n           0 + lg_table[(x >>  0) & 0xff]);\n\n  if(e >= 16) {\n    y = sqq_table[x >> ((e - 6) - (e & 1))] << ((e >> 1) - 7);\n    if(e >= 24) { y = (y + 1 + x / y) >> 1; }\n    y = (y + 1 + x / y) >> 1;\n  } else if(e >= 8) {\n    y = (sqq_table[x >> ((e - 6) - (e & 1))] >> (7 - (e >> 1))) + 1;\n  } else {\n    return sqq_table[x] >> 4;\n  }\n\n  return (x < (y * y)) ? y - 1 : y;\n}\n\n#endif /* SS_BLOCKSIZE != 0 */\n\n\n/*---------------------------------------------------------------------------*/\n\n/* Compares two suffixes. */\nstatic INLINE\nint\nss_compare(const unsigned char *T,\n           const int *p1, const int *p2,\n           int depth) {\n  const unsigned char *U1, *U2, *U1n, *U2n;\n\n  for(U1 = T + depth + *p1,\n      U2 = T + depth + *p2,\n      U1n = T + *(p1 + 1) + 2,\n      U2n = T + *(p2 + 1) + 2;\n      (U1 < U1n) && (U2 < U2n) && (*U1 == *U2);\n      ++U1, ++U2) {\n  }\n\n  return U1 < U1n ?\n        (U2 < U2n ? *U1 - *U2 : 1) :\n        (U2 < U2n ? -1 : 0);\n}\n\n\n/*---------------------------------------------------------------------------*/\n\n#if (SS_BLOCKSIZE != 1) && (SS_INSERTIONSORT_THRESHOLD != 1)\n\n/* Insertionsort for small size groups */\nstatic\nvoid\nss_insertionsort(const unsigned char *T, const int *PA,\n                 int *first, int *last, int depth) {\n  int *i, *j;\n  int t;\n  int r;\n\n  for(i = last - 2; first <= i; --i) {\n    for(t = *i, j = i + 1; 0 < (r = ss_compare(T, PA + t, PA + *j, depth));) {\n      do { *(j - 1) = *j; } while((++j < last) && (*j < 0));\n      if(last <= j) { break; }\n    }\n    if(r == 0) { *j = ~*j; }\n    *(j - 1) = t;\n  }\n}\n\n#endif /* (SS_BLOCKSIZE != 1) && (SS_INSERTIONSORT_THRESHOLD != 1) */\n\n\n/*---------------------------------------------------------------------------*/\n\n#if (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE)\n\nstatic INLINE\nvoid\nss_fixdown(const unsigned char *Td, const int *PA,\n           int *SA, int i, int size) {\n  int j, k;\n  int v;\n  int c, d, e;\n\n  for(v = SA[i], c = Td[PA[v]]; (j = 2 * i + 1) < size; SA[i] = SA[k], i = k) {\n    d = Td[PA[SA[k = j++]]];\n    if(d < (e = Td[PA[SA[j]]])) { k = j; d = e; }\n    if(d <= c) { break; }\n  }\n  SA[i] = v;\n}\n\n/* Simple top-down heapsort. */\nstatic\nvoid\nss_heapsort(const unsigned char *Td, const int *PA, int *SA, int size) {\n  int i, m;\n  int t;\n\n  m = size;\n  if((size % 2) == 0) {\n    m--;\n    if(Td[PA[SA[m / 2]]] < Td[PA[SA[m]]]) { SWAP(SA[m], SA[m / 2]); }\n  }\n\n  for(i = m / 2 - 1; 0 <= i; --i) { ss_fixdown(Td, PA, SA, i, m); }\n  if((size % 2) == 0) { SWAP(SA[0], SA[m]); ss_fixdown(Td, PA, SA, 0, m); }\n  for(i = m - 1; 0 < i; --i) {\n    t = SA[0], SA[0] = SA[i];\n    ss_fixdown(Td, PA, SA, 0, i);\n    SA[i] = t;\n  }\n}\n\n\n/*---------------------------------------------------------------------------*/\n\n/* Returns the median of three elements. */\nstatic INLINE\nint *\nss_median3(const unsigned char *Td, const int *PA,\n           int *v1, int *v2, int *v3) {\n  int *t;\n  if(Td[PA[*v1]] > Td[PA[*v2]]) { SWAP(v1, v2); }\n  if(Td[PA[*v2]] > Td[PA[*v3]]) {\n    if(Td[PA[*v1]] > Td[PA[*v3]]) { return v1; }\n    else { return v3; }\n  }\n  return v2;\n}\n\n/* Returns the median of five elements. */\nstatic INLINE\nint *\nss_median5(const unsigned char *Td, const int *PA,\n           int *v1, int *v2, int *v3, int *v4, int *v5) {\n  int *t;\n  if(Td[PA[*v2]] > Td[PA[*v3]]) { SWAP(v2, v3); }\n  if(Td[PA[*v4]] > Td[PA[*v5]]) { SWAP(v4, v5); }\n  if(Td[PA[*v2]] > Td[PA[*v4]]) { SWAP(v2, v4); SWAP(v3, v5); }\n  if(Td[PA[*v1]] > Td[PA[*v3]]) { SWAP(v1, v3); }\n  if(Td[PA[*v1]] > Td[PA[*v4]]) { SWAP(v1, v4); SWAP(v3, v5); }\n  if(Td[PA[*v3]] > Td[PA[*v4]]) { return v4; }\n  return v3;\n}\n\n/* Returns the pivot element. */\nstatic INLINE\nint *\nss_pivot(const unsigned char *Td, const int *PA, int *first, int *last) {\n  int *middle;\n  int t;\n\n  t = PTRDIFF_TO_INT(last - first);\n  middle = first + t / 2;\n\n  if(t <= 512) {\n    if(t <= 32) {\n      return ss_median3(Td, PA, first, middle, last - 1);\n    } else {\n      t >>= 2;\n      return ss_median5(Td, PA, first, first + t, middle, last - 1 - t, last - 1);\n    }\n  }\n  t >>= 3;\n  first  = ss_median3(Td, PA, first, first + t, first + (t << 1));\n  middle = ss_median3(Td, PA, middle - t, middle, middle + t);\n  last   = ss_median3(Td, PA, last - 1 - (t << 1), last - 1 - t, last - 1);\n  return ss_median3(Td, PA, first, middle, last);\n}\n\n\n/*---------------------------------------------------------------------------*/\n\n/* Binary partition for substrings. */\nstatic INLINE\nint *\nss_partition(const int *PA,\n                    int *first, int *last, int depth) {\n  int *a, *b;\n  int t;\n  for(a = first - 1, b = last;;) {\n    for(; (++a < b) && ((PA[*a] + depth) >= (PA[*a + 1] + 1));) { *a = ~*a; }\n    for(; (a < --b) && ((PA[*b] + depth) <  (PA[*b + 1] + 1));) { }\n    if(b <= a) { break; }\n    t = ~*b;\n    *b = *a;\n    *a = t;\n  }\n  if(first < a) { *first = ~*first; }\n  return a;\n}\n\n/* Multikey introsort for medium size groups. */\nstatic\nvoid\nss_mintrosort(const unsigned char *T, const int *PA,\n              int *first, int *last,\n              int depth) {\n#define STACK_SIZE SS_MISORT_STACKSIZE\n  struct { int *a, *b, c; int d; } stack[STACK_SIZE];\n  const unsigned char *Td;\n  int *a, *b, *c, *d, *e, *f;\n  int s, t;\n  int ssize;\n  int limit;\n  int v, x = 0;\n\n  for(ssize = 0, limit = ss_ilg(PTRDIFF_TO_INT(last - first));;) {\n\n    if((last - first) <= SS_INSERTIONSORT_THRESHOLD) {\n#if 1 < SS_INSERTIONSORT_THRESHOLD\n      if(1 < (last - first)) { ss_insertionsort(T, PA, first, last, depth); }\n#endif\n      STACK_POP(first, last, depth, limit);\n      continue;\n    }\n\n    Td = T + depth;\n    if(limit-- == 0) { ss_heapsort(Td, PA, first, PTRDIFF_TO_INT(last - first)); }\n    if(limit < 0) {\n      for(a = first + 1, v = Td[PA[*first]]; a < last; ++a) {\n        if((x = Td[PA[*a]]) != v) {\n          if(1 < (a - first)) { break; }\n          v = x;\n          first = a;\n        }\n      }\n      if(Td[PA[*first] - 1] < v) {\n        first = ss_partition(PA, first, a, depth);\n      }\n      if((a - first) <= (last - a)) {\n        if(1 < (a - first)) {\n          STACK_PUSH(a, last, depth, -1);\n          last = a, depth += 1, limit = ss_ilg(PTRDIFF_TO_INT(a - first));\n        } else {\n          first = a, limit = -1;\n        }\n      } else {\n        if(1 < (last - a)) {\n          STACK_PUSH(first, a, depth + 1, ss_ilg(PTRDIFF_TO_INT(a - first)));\n          first = a, limit = -1;\n        } else {\n          last = a, depth += 1, limit = ss_ilg(PTRDIFF_TO_INT(a - first));\n        }\n      }\n      continue;\n    }\n\n    /* choose pivot */\n    a = ss_pivot(Td, PA, first, last);\n    v = Td[PA[*a]];\n    SWAP(*first, *a);\n\n    /* partition */\n    for(b = first; (++b < last) && ((x = Td[PA[*b]]) == v);) { }\n    if(((a = b) < last) && (x < v)) {\n      for(; (++b < last) && ((x = Td[PA[*b]]) <= v);) {\n        if(x == v) { SWAP(*b, *a); ++a; }\n      }\n    }\n    for(c = last; (b < --c) && ((x = Td[PA[*c]]) == v);) { }\n    if((b < (d = c)) && (x > v)) {\n      for(; (b < --c) && ((x = Td[PA[*c]]) >= v);) {\n        if(x == v) { SWAP(*c, *d); --d; }\n      }\n    }\n    for(; b < c;) {\n      SWAP(*b, *c);\n      for(; (++b < c) && ((x = Td[PA[*b]]) <= v);) {\n        if(x == v) { SWAP(*b, *a); ++a; }\n      }\n      for(; (b < --c) && ((x = Td[PA[*c]]) >= v);) {\n        if(x == v) { SWAP(*c, *d); --d; }\n      }\n    }\n\n    if(a <= d) {\n      c = b - 1;\n\n      if((s = PTRDIFF_TO_INT(a - first)) > (t = PTRDIFF_TO_INT(b - a))) { s = t; }\n      for(e = first, f = b - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }\n      if((s = PTRDIFF_TO_INT(d - c)) > (t = PTRDIFF_TO_INT(last - d - 1))) { s = t; }\n      for(e = b, f = last - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }\n\n      a = first + (b - a), c = last - (d - c);\n      b = (v <= Td[PA[*a] - 1]) ? a : ss_partition(PA, a, c, depth);\n\n      if((a - first) <= (last - c)) {\n        if((last - c) <= (c - b)) {\n          STACK_PUSH(b, c, depth + 1, ss_ilg(PTRDIFF_TO_INT(c - b)));\n          STACK_PUSH(c, last, depth, limit);\n          last = a;\n        } else if((a - first) <= (c - b)) {\n          STACK_PUSH(c, last, depth, limit);\n          STACK_PUSH(b, c, depth + 1, ss_ilg(PTRDIFF_TO_INT(c - b)));\n          last = a;\n        } else {\n          STACK_PUSH(c, last, depth, limit);\n          STACK_PUSH(first, a, depth, limit);\n          first = b, last = c, depth += 1, limit = ss_ilg(PTRDIFF_TO_INT(c - b));\n        }\n      } else {\n        if((a - first) <= (c - b)) {\n          STACK_PUSH(b, c, depth + 1, ss_ilg(PTRDIFF_TO_INT(c - b)));\n          STACK_PUSH(first, a, depth, limit);\n          first = c;\n        } else if((last - c) <= (c - b)) {\n          STACK_PUSH(first, a, depth, limit);\n          STACK_PUSH(b, c, depth + 1, ss_ilg(PTRDIFF_TO_INT(c - b)));\n          first = c;\n        } else {\n          STACK_PUSH(first, a, depth, limit);\n          STACK_PUSH(c, last, depth, limit);\n          first = b, last = c, depth += 1, limit = ss_ilg(PTRDIFF_TO_INT(c - b));\n        }\n      }\n    } else {\n      limit += 1;\n      if(Td[PA[*first] - 1] < v) {\n        first = ss_partition(PA, first, last, depth);\n        limit = ss_ilg(PTRDIFF_TO_INT(last - first));\n      }\n      depth += 1;\n    }\n  }\n#undef STACK_SIZE\n}\n\n#endif /* (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) */\n\n\n/*---------------------------------------------------------------------------*/\n\n#if SS_BLOCKSIZE != 0\n\nstatic INLINE\nvoid\nss_blockswap(int *a, int *b, int n) {\n  int t;\n  for(; 0 < n; --n, ++a, ++b) {\n    t = *a, *a = *b, *b = t;\n  }\n}\n\nstatic INLINE\nvoid\nss_rotate(int *first, int *middle, int *last) {\n  int *a, *b, t;\n  int l, r;\n  l = PTRDIFF_TO_INT(middle - first);\n  r = PTRDIFF_TO_INT(last - middle);\n  for(; (0 < l) && (0 < r);) {\n    if(l == r) { ss_blockswap(first, middle, l); break; }\n    if(l < r) {\n      a = last - 1, b = middle - 1;\n      t = *a;\n      do {\n        *a-- = *b, *b-- = *a;\n        if(b < first) {\n          *a = t;\n          last = a;\n          if((r -= l + 1) <= l) { break; }\n          a -= 1, b = middle - 1;\n          t = *a;\n        }\n      } while(1);\n    } else {\n      a = first, b = middle;\n      t = *a;\n      do {\n        *a++ = *b, *b++ = *a;\n        if(last <= b) {\n          *a = t;\n          first = a + 1;\n          if((l -= r + 1) <= r) { break; }\n          a += 1, b = middle;\n          t = *a;\n        }\n      } while(1);\n    }\n  }\n}\n\n\n/*---------------------------------------------------------------------------*/\n\nstatic\nvoid\nss_inplacemerge(const unsigned char *T, const int *PA,\n                int *first, int *middle, int *last,\n                int depth) {\n  const int *p;\n  int *a, *b;\n  int len, half;\n  int q, r;\n  int x;\n\n  for(;;) {\n    if(*(last - 1) < 0) { x = 1; p = PA + ~*(last - 1); }\n    else                { x = 0; p = PA +  *(last - 1); }\n    for(a = first, len = PTRDIFF_TO_INT(middle - first), half = len >> 1, r = -1;\n        0 < len;\n        len = half, half >>= 1) {\n      b = a + half;\n      q = ss_compare(T, PA + ((0 <= *b) ? *b : ~*b), p, depth);\n      if(q < 0) {\n        a = b + 1;\n        half -= (len & 1) ^ 1;\n      } else {\n        r = q;\n      }\n    }\n    if(a < middle) {\n      if(r == 0) { *a = ~*a; }\n      ss_rotate(a, middle, last);\n      last -= middle - a;\n      middle = a;\n      if(first == middle) { break; }\n    }\n    --last;\n    if(x != 0) { while(*--last < 0) { } }\n    if(middle == last) { break; }\n  }\n}\n\n\n/*---------------------------------------------------------------------------*/\n\n/* Merge-forward with internal buffer. */\nstatic\nvoid\nss_mergeforward(const unsigned char *T, const int *PA,\n                int *first, int *middle, int *last,\n                int *buf, int depth) {\n  int *a, *b, *c, *bufend;\n  int t;\n  int r;\n\n  bufend = buf + (middle - first) - 1;\n  ss_blockswap(buf, first, PTRDIFF_TO_INT(middle - first));\n\n  for(t = *(a = first), b = buf, c = middle;;) {\n    r = ss_compare(T, PA + *b, PA + *c, depth);\n    if(r < 0) {\n      do {\n        *a++ = *b;\n        if(bufend <= b) { *bufend = t; return; }\n        *b++ = *a;\n      } while(*b < 0);\n    } else if(r > 0) {\n      do {\n        *a++ = *c, *c++ = *a;\n        if(last <= c) {\n          while(b < bufend) { *a++ = *b, *b++ = *a; }\n          *a = *b, *b = t;\n          return;\n        }\n      } while(*c < 0);\n    } else {\n      *c = ~*c;\n      do {\n        *a++ = *b;\n        if(bufend <= b) { *bufend = t; return; }\n        *b++ = *a;\n      } while(*b < 0);\n\n      do {\n        *a++ = *c, *c++ = *a;\n        if(last <= c) {\n          while(b < bufend) { *a++ = *b, *b++ = *a; }\n          *a = *b, *b = t;\n          return;\n        }\n      } while(*c < 0);\n    }\n  }\n}\n\n/* Merge-backward with internal buffer. */\nstatic\nvoid\nss_mergebackward(const unsigned char *T, const int *PA,\n                 int *first, int *middle, int *last,\n                 int *buf, int depth) {\n  const int *p1, *p2;\n  int *a, *b, *c, *bufend;\n  int t;\n  int r;\n  int x;\n\n  bufend = buf + (last - middle) - 1;\n  ss_blockswap(buf, middle, PTRDIFF_TO_INT(last - middle));\n\n  x = 0;\n  if(*bufend < 0)       { p1 = PA + ~*bufend; x |= 1; }\n  else                  { p1 = PA +  *bufend; }\n  if(*(middle - 1) < 0) { p2 = PA + ~*(middle - 1); x |= 2; }\n  else                  { p2 = PA +  *(middle - 1); }\n  for(t = *(a = last - 1), b = bufend, c = middle - 1;;) {\n    r = ss_compare(T, p1, p2, depth);\n    if(0 < r) {\n      if(x & 1) { do { *a-- = *b, *b-- = *a; } while(*b < 0); x ^= 1; }\n      *a-- = *b;\n      if(b <= buf) { *buf = t; break; }\n      *b-- = *a;\n      if(*b < 0) { p1 = PA + ~*b; x |= 1; }\n      else       { p1 = PA +  *b; }\n    } else if(r < 0) {\n      if(x & 2) { do { *a-- = *c, *c-- = *a; } while(*c < 0); x ^= 2; }\n      *a-- = *c, *c-- = *a;\n      if(c < first) {\n        while(buf < b) { *a-- = *b, *b-- = *a; }\n        *a = *b, *b = t;\n        break;\n      }\n      if(*c < 0) { p2 = PA + ~*c; x |= 2; }\n      else       { p2 = PA +  *c; }\n    } else {\n      if(x & 1) { do { *a-- = *b, *b-- = *a; } while(*b < 0); x ^= 1; }\n      *a-- = ~*b;\n      if(b <= buf) { *buf = t; break; }\n      *b-- = *a;\n      if(x & 2) { do { *a-- = *c, *c-- = *a; } while(*c < 0); x ^= 2; }\n      *a-- = *c, *c-- = *a;\n      if(c < first) {\n        while(buf < b) { *a-- = *b, *b-- = *a; }\n        *a = *b, *b = t;\n        break;\n      }\n      if(*b < 0) { p1 = PA + ~*b; x |= 1; }\n      else       { p1 = PA +  *b; }\n      if(*c < 0) { p2 = PA + ~*c; x |= 2; }\n      else       { p2 = PA +  *c; }\n    }\n  }\n}\n\n/* D&C based merge. */\nstatic\nvoid\nss_swapmerge(const unsigned char *T, const int *PA,\n             int *first, int *middle, int *last,\n             int *buf, int bufsize, int depth) {\n#define STACK_SIZE SS_SMERGE_STACKSIZE\n#define GETIDX(a) ((0 <= (a)) ? (a) : (~(a)))\n#define MERGE_CHECK(a, b, c)\\\n  do {\\\n    if(((c) & 1) ||\\\n       (((c) & 2) && (ss_compare(T, PA + GETIDX(*((a) - 1)), PA + *(a), depth) == 0))) {\\\n      *(a) = ~*(a);\\\n    }\\\n    if(((c) & 4) && ((ss_compare(T, PA + GETIDX(*((b) - 1)), PA + *(b), depth) == 0))) {\\\n      *(b) = ~*(b);\\\n    }\\\n  } while(0)\n  struct { int *a, *b, *c; int d; } stack[STACK_SIZE];\n  int *l, *r, *lm, *rm;\n  int m, len, half;\n  int ssize;\n  int check, next;\n\n  for(check = 0, ssize = 0;;) {\n    if((last - middle) <= bufsize) {\n      if((first < middle) && (middle < last)) {\n        ss_mergebackward(T, PA, first, middle, last, buf, depth);\n      }\n      MERGE_CHECK(first, last, check);\n      STACK_POP(first, middle, last, check);\n      continue;\n    }\n\n    if((middle - first) <= bufsize) {\n      if(first < middle) {\n        ss_mergeforward(T, PA, first, middle, last, buf, depth);\n      }\n      MERGE_CHECK(first, last, check);\n      STACK_POP(first, middle, last, check);\n      continue;\n    }\n\n    for(m = 0, len = PTRDIFF_TO_INT(MIN(middle - first, last - middle)), half = len >> 1;\n        0 < len;\n        len = half, half >>= 1) {\n      if(ss_compare(T, PA + GETIDX(*(middle + m + half)),\n                       PA + GETIDX(*(middle - m - half - 1)), depth) < 0) {\n        m += half + 1;\n        half -= (len & 1) ^ 1;\n      }\n    }\n\n    if(0 < m) {\n      lm = middle - m, rm = middle + m;\n      ss_blockswap(lm, middle, m);\n      l = r = middle, next = 0;\n      if(rm < last) {\n        if(*rm < 0) {\n          *rm = ~*rm;\n          if(first < lm) { for(; *--l < 0;) { } next |= 4; }\n          next |= 1;\n        } else if(first < lm) {\n          for(; *r < 0; ++r) { }\n          next |= 2;\n        }\n      }\n\n      if((l - first) <= (last - r)) {\n        STACK_PUSH(r, rm, last, (next & 3) | (check & 4));\n        middle = lm, last = l, check = (check & 3) | (next & 4);\n      } else {\n        if((next & 2) && (r == middle)) { next ^= 6; }\n        STACK_PUSH(first, lm, l, (check & 3) | (next & 4));\n        first = r, middle = rm, check = (next & 3) | (check & 4);\n      }\n    } else {\n      if(ss_compare(T, PA + GETIDX(*(middle - 1)), PA + *middle, depth) == 0) {\n        *middle = ~*middle;\n      }\n      MERGE_CHECK(first, last, check);\n      STACK_POP(first, middle, last, check);\n    }\n  }\n#undef STACK_SIZE\n}\n\n#endif /* SS_BLOCKSIZE != 0 */\n\n\n/*---------------------------------------------------------------------------*/\n\n/* Substring sort */\nstatic\nvoid\nsssort(const unsigned char *T, const int *PA,\n       int *first, int *last,\n       int *buf, int bufsize,\n       int depth, int n, int lastsuffix) {\n  int *a;\n#if SS_BLOCKSIZE != 0\n  int *b, *middle, *curbuf;\n  int j, k, curbufsize, limit;\n#endif\n  int i;\n\n  if(lastsuffix != 0) { ++first; }\n\n#if SS_BLOCKSIZE == 0\n  ss_mintrosort(T, PA, first, last, depth);\n#else\n  if((bufsize < SS_BLOCKSIZE) &&\n      (bufsize < PTRDIFF_TO_INT(last - first)) &&\n      (bufsize < (limit = ss_isqrt(PTRDIFF_TO_INT(last - first))))) {\n    if(SS_BLOCKSIZE < limit) { limit = SS_BLOCKSIZE; }\n    buf = middle = last - limit, bufsize = limit;\n  } else {\n    middle = last, limit = 0;\n  }\n  for(a = first, i = 0; SS_BLOCKSIZE < (middle - a); a += SS_BLOCKSIZE, ++i) {\n#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE\n    ss_mintrosort(T, PA, a, a + SS_BLOCKSIZE, depth);\n#elif 1 < SS_BLOCKSIZE\n    ss_insertionsort(T, PA, a, a + SS_BLOCKSIZE, depth);\n#endif\n    curbufsize = PTRDIFF_TO_INT(last - (a + SS_BLOCKSIZE));\n    curbuf = a + SS_BLOCKSIZE;\n    if(curbufsize <= bufsize) { curbufsize = bufsize, curbuf = buf; }\n    for(b = a, k = SS_BLOCKSIZE, j = i; j & 1; b -= k, k <<= 1, j >>= 1) {\n      ss_swapmerge(T, PA, b - k, b, b + k, curbuf, curbufsize, depth);\n    }\n  }\n#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE\n  ss_mintrosort(T, PA, a, middle, depth);\n#elif 1 < SS_BLOCKSIZE\n  ss_insertionsort(T, PA, a, middle, depth);\n#endif\n  for(k = SS_BLOCKSIZE; i != 0; k <<= 1, i >>= 1) {\n    if(i & 1) {\n      ss_swapmerge(T, PA, a - k, a, middle, buf, bufsize, depth);\n      a -= k;\n    }\n  }\n  if(limit != 0) {\n#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE\n    ss_mintrosort(T, PA, middle, last, depth);\n#elif 1 < SS_BLOCKSIZE\n    ss_insertionsort(T, PA, middle, last, depth);\n#endif\n    ss_inplacemerge(T, PA, first, middle, last, depth);\n  }\n#endif\n\n  if(lastsuffix != 0) {\n    /* Insert last type B* suffix. */\n    int PAi[2]; PAi[0] = PA[*(first - 1)], PAi[1] = n - 2;\n    for(a = first, i = *(first - 1);\n        (a < last) && ((*a < 0) || (0 < ss_compare(T, &(PAi[0]), PA + *a, depth)));\n        ++a) {\n      *(a - 1) = *a;\n    }\n    *(a - 1) = i;\n  }\n}\n\n\n/*---------------------------------------------------------------------------*/\n\nstatic INLINE\nint\ntr_ilg(int n) {\n  return (n & 0xffff0000) ?\n          ((n & 0xff000000) ?\n            24 + lg_table[(n >> 24) & 0xff] :\n            16 + lg_table[(n >> 16) & 0xff]) :\n          ((n & 0x0000ff00) ?\n             8 + lg_table[(n >>  8) & 0xff] :\n             0 + lg_table[(n >>  0) & 0xff]);\n}\n\n\n/*---------------------------------------------------------------------------*/\n\n/* Simple insertionsort for small size groups. */\nstatic\nvoid\ntr_insertionsort(const int *ISAd, int *first, int *last) {\n  int *a, *b;\n  int t, r;\n\n  for(a = first + 1; a < last; ++a) {\n    for(t = *a, b = a - 1; 0 > (r = ISAd[t] - ISAd[*b]);) {\n      do { *(b + 1) = *b; } while((first <= --b) && (*b < 0));\n      if(b < first) { break; }\n    }\n    if(r == 0) { *b = ~*b; }\n    *(b + 1) = t;\n  }\n}\n\n\n/*---------------------------------------------------------------------------*/\n\nstatic INLINE\nvoid\ntr_fixdown(const int *ISAd, int *SA, int i, int size) {\n  int j, k;\n  int v;\n  int c, d, e;\n\n  for(v = SA[i], c = ISAd[v]; (j = 2 * i + 1) < size; SA[i] = SA[k], i = k) {\n    d = ISAd[SA[k = j++]];\n    if(d < (e = ISAd[SA[j]])) { k = j; d = e; }\n    if(d <= c) { break; }\n  }\n  SA[i] = v;\n}\n\n/* Simple top-down heapsort. */\nstatic\nvoid\ntr_heapsort(const int *ISAd, int *SA, int size) {\n  int i, m;\n  int t;\n\n  m = size;\n  if((size % 2) == 0) {\n    m--;\n    if(ISAd[SA[m / 2]] < ISAd[SA[m]]) { SWAP(SA[m], SA[m / 2]); }\n  }\n\n  for(i = m / 2 - 1; 0 <= i; --i) { tr_fixdown(ISAd, SA, i, m); }\n  if((size % 2) == 0) { SWAP(SA[0], SA[m]); tr_fixdown(ISAd, SA, 0, m); }\n  for(i = m - 1; 0 < i; --i) {\n    t = SA[0], SA[0] = SA[i];\n    tr_fixdown(ISAd, SA, 0, i);\n    SA[i] = t;\n  }\n}\n\n\n/*---------------------------------------------------------------------------*/\n\n/* Returns the median of three elements. */\nstatic INLINE\nint *\ntr_median3(const int *ISAd, int *v1, int *v2, int *v3) {\n  int *t;\n  if(ISAd[*v1] > ISAd[*v2]) { SWAP(v1, v2); }\n  if(ISAd[*v2] > ISAd[*v3]) {\n    if(ISAd[*v1] > ISAd[*v3]) { return v1; }\n    else { return v3; }\n  }\n  return v2;\n}\n\n/* Returns the median of five elements. */\nstatic INLINE\nint *\ntr_median5(const int *ISAd,\n           int *v1, int *v2, int *v3, int *v4, int *v5) {\n  int *t;\n  if(ISAd[*v2] > ISAd[*v3]) { SWAP(v2, v3); }\n  if(ISAd[*v4] > ISAd[*v5]) { SWAP(v4, v5); }\n  if(ISAd[*v2] > ISAd[*v4]) { SWAP(v2, v4); SWAP(v3, v5); }\n  if(ISAd[*v1] > ISAd[*v3]) { SWAP(v1, v3); }\n  if(ISAd[*v1] > ISAd[*v4]) { SWAP(v1, v4); SWAP(v3, v5); }\n  if(ISAd[*v3] > ISAd[*v4]) { return v4; }\n  return v3;\n}\n\n/* Returns the pivot element. */\nstatic INLINE\nint *\ntr_pivot(const int *ISAd, int *first, int *last) {\n  int *middle;\n  int t;\n\n  t = PTRDIFF_TO_INT(last - first);\n  middle = first + t / 2;\n\n  if(t <= 512) {\n    if(t <= 32) {\n      return tr_median3(ISAd, first, middle, last - 1);\n    } else {\n      t >>= 2;\n      return tr_median5(ISAd, first, first + t, middle, last - 1 - t, last - 1);\n    }\n  }\n  t >>= 3;\n  first  = tr_median3(ISAd, first, first + t, first + (t << 1));\n  middle = tr_median3(ISAd, middle - t, middle, middle + t);\n  last   = tr_median3(ISAd, last - 1 - (t << 1), last - 1 - t, last - 1);\n  return tr_median3(ISAd, first, middle, last);\n}\n\n\n/*---------------------------------------------------------------------------*/\n\ntypedef struct _trbudget_t trbudget_t;\nstruct _trbudget_t {\n  int chance;\n  int remain;\n  int incval;\n  int count;\n};\n\nstatic INLINE\nvoid\ntrbudget_init(trbudget_t *budget, int chance, int incval) {\n  budget->chance = chance;\n  budget->remain = budget->incval = incval;\n}\n\nstatic INLINE\nint\ntrbudget_check(trbudget_t *budget, int size) {\n  if(size <= budget->remain) { budget->remain -= size; return 1; }\n  if(budget->chance == 0) { budget->count += size; return 0; }\n  budget->remain += budget->incval - size;\n  budget->chance -= 1;\n  return 1;\n}\n\n\n/*---------------------------------------------------------------------------*/\n\nstatic INLINE\nvoid\ntr_partition(const int *ISAd,\n             int *first, int *middle, int *last,\n             int **pa, int **pb, int v) {\n  int *a, *b, *c, *d, *e, *f;\n  int t, s;\n  int x = 0;\n\n  for(b = middle - 1; (++b < last) && ((x = ISAd[*b]) == v);) { }\n  if(((a = b) < last) && (x < v)) {\n    for(; (++b < last) && ((x = ISAd[*b]) <= v);) {\n      if(x == v) { SWAP(*b, *a); ++a; }\n    }\n  }\n  for(c = last; (b < --c) && ((x = ISAd[*c]) == v);) { }\n  if((b < (d = c)) && (x > v)) {\n    for(; (b < --c) && ((x = ISAd[*c]) >= v);) {\n      if(x == v) { SWAP(*c, *d); --d; }\n    }\n  }\n  for(; b < c;) {\n    SWAP(*b, *c);\n    for(; (++b < c) && ((x = ISAd[*b]) <= v);) {\n      if(x == v) { SWAP(*b, *a); ++a; }\n    }\n    for(; (b < --c) && ((x = ISAd[*c]) >= v);) {\n      if(x == v) { SWAP(*c, *d); --d; }\n    }\n  }\n\n  if(a <= d) {\n    c = b - 1;\n    if((s = PTRDIFF_TO_INT(a - first)) > (t = PTRDIFF_TO_INT(b - a))) { s = t; }\n    for(e = first, f = b - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }\n    if((s = PTRDIFF_TO_INT(d - c)) > (t = PTRDIFF_TO_INT(last - d - 1))) { s = t; }\n    for(e = b, f = last - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }\n    first += (b - a), last -= (d - c);\n  }\n  *pa = first, *pb = last;\n}\n\nstatic\nvoid\ntr_copy(int *ISA, const int *SA,\n        int *first, int *a, int *b, int *last,\n        int depth) {\n  /* sort suffixes of middle partition\n     by using sorted order of suffixes of left and right partition. */\n  int *c, *d, *e;\n  int s, v;\n\n  v = PTRDIFF_TO_INT(b - SA - 1);\n  for(c = first, d = a - 1; c <= d; ++c) {\n    if((0 <= (s = *c - depth)) && (ISA[s] == v)) {\n      *++d = s;\n      ISA[s] = PTRDIFF_TO_INT(d - SA);\n    }\n  }\n  for(c = last - 1, e = d + 1, d = b; e < d; --c) {\n    if((0 <= (s = *c - depth)) && (ISA[s] == v)) {\n      *--d = s;\n      ISA[s] = PTRDIFF_TO_INT(d - SA);\n    }\n  }\n}\n\nstatic\nvoid\ntr_partialcopy(int *ISA, const int *SA,\n               int *first, int *a, int *b, int *last,\n               int depth) {\n  int *c, *d, *e;\n  int s, v;\n  int rank, lastrank, newrank = -1;\n\n  v = PTRDIFF_TO_INT(b - SA - 1);\n  lastrank = -1;\n  for(c = first, d = a - 1; c <= d; ++c) {\n    if((0 <= (s = *c - depth)) && (ISA[s] == v)) {\n      *++d = s;\n      rank = ISA[s + depth];\n      if(lastrank != rank) { lastrank = rank; newrank = PTRDIFF_TO_INT(d - SA); }\n      ISA[s] = newrank;\n    }\n  }\n\n  lastrank = -1;\n  for(e = d; first <= e; --e) {\n    rank = ISA[*e];\n    if(lastrank != rank) { lastrank = rank; newrank = PTRDIFF_TO_INT(e - SA); }\n    if(newrank != rank) { ISA[*e] = newrank; }\n  }\n\n  lastrank = -1;\n  for(c = last - 1, e = d + 1, d = b; e < d; --c) {\n    if((0 <= (s = *c - depth)) && (ISA[s] == v)) {\n      *--d = s;\n      rank = ISA[s + depth];\n      if(lastrank != rank) { lastrank = rank; newrank = PTRDIFF_TO_INT(d - SA); }\n      ISA[s] = newrank;\n    }\n  }\n}\n\nstatic\nvoid\ntr_introsort(int *ISA, const int *ISAd,\n             int *SA, int *first, int *last,\n             trbudget_t *budget) {\n#define STACK_SIZE TR_STACKSIZE\n  struct { const int *a; int *b, *c; int d, e; }stack[STACK_SIZE];\n  int *a, *b, *c;\n  int t;\n  int v, x = 0;\n  int incr = PTRDIFF_TO_INT(ISAd - ISA);\n  int limit, next;\n  int ssize, trlink = -1;\n\n  for(ssize = 0, limit = tr_ilg(PTRDIFF_TO_INT(last - first));;) {\n\n    if(limit < 0) {\n      if(limit == -1) {\n        /* tandem repeat partition */\n        tr_partition(ISAd - incr, first, first, last, &a, &b, PTRDIFF_TO_INT(last - SA - 1));\n\n        /* update ranks */\n        if(a < last) {\n          for(c = first, v = PTRDIFF_TO_INT(a - SA - 1); c < a; ++c) { ISA[*c] = v; }\n        }\n        if(b < last) {\n          for(c = a, v = PTRDIFF_TO_INT(b - SA - 1); c < b; ++c) { ISA[*c] = v; }\n        }\n\n        /* push */\n        if(1 < (b - a)) {\n          STACK_PUSH5(NULL, a, b, 0, 0);\n          STACK_PUSH5(ISAd - incr, first, last, -2, trlink);\n          trlink = ssize - 2;\n        }\n        if((a - first) <= (last - b)) {\n          if(1 < (a - first)) {\n            STACK_PUSH5(ISAd, b, last, tr_ilg(PTRDIFF_TO_INT(last - b)), trlink);\n            last = a, limit = tr_ilg(PTRDIFF_TO_INT(a - first));\n          } else if(1 < (last - b)) {\n            first = b, limit = tr_ilg(PTRDIFF_TO_INT(last - b));\n          } else {\n            STACK_POP5(ISAd, first, last, limit, trlink);\n          }\n        } else {\n          if(1 < (last - b)) {\n            STACK_PUSH5(ISAd, first, a, tr_ilg(PTRDIFF_TO_INT(a - first)), trlink);\n            first = b, limit = tr_ilg(PTRDIFF_TO_INT(last - b));\n          } else if(1 < (a - first)) {\n            last = a, limit = tr_ilg(PTRDIFF_TO_INT(a - first));\n          } else {\n            STACK_POP5(ISAd, first, last, limit, trlink);\n          }\n        }\n      } else if(limit == -2) {\n        /* tandem repeat copy */\n        a = stack[--ssize].b, b = stack[ssize].c;\n        if(stack[ssize].d == 0) {\n          tr_copy(ISA, SA, first, a, b, last, PTRDIFF_TO_INT(ISAd - ISA));\n        } else {\n          if(0 <= trlink) { stack[trlink].d = -1; }\n          tr_partialcopy(ISA, SA, first, a, b, last, PTRDIFF_TO_INT(ISAd - ISA));\n        }\n        STACK_POP5(ISAd, first, last, limit, trlink);\n      } else {\n        /* sorted partition */\n        if(0 <= *first) {\n          a = first;\n          do { ISA[*a] = PTRDIFF_TO_INT(a - SA); } while((++a < last) && (0 <= *a));\n          first = a;\n        }\n        if(first < last) {\n          a = first; do { *a = ~*a; } while(*++a < 0);\n          next = (ISA[*a] != ISAd[*a]) ? tr_ilg(PTRDIFF_TO_INT(a - first + 1)) : -1;\n          if(++a < last) { for(b = first, v = PTRDIFF_TO_INT(a - SA - 1); b < a; ++b) { ISA[*b] = v; } }\n\n          /* push */\n          if(trbudget_check(budget, PTRDIFF_TO_INT(a - first))) {\n            if((a - first) <= (last - a)) {\n              STACK_PUSH5(ISAd, a, last, -3, trlink);\n              ISAd += incr, last = a, limit = next;\n            } else {\n              if(1 < (last - a)) {\n                STACK_PUSH5(ISAd + incr, first, a, next, trlink);\n                first = a, limit = -3;\n              } else {\n                ISAd += incr, last = a, limit = next;\n              }\n            }\n          } else {\n            if(0 <= trlink) { stack[trlink].d = -1; }\n            if(1 < (last - a)) {\n              first = a, limit = -3;\n            } else {\n              STACK_POP5(ISAd, first, last, limit, trlink);\n            }\n          }\n        } else {\n          STACK_POP5(ISAd, first, last, limit, trlink);\n        }\n      }\n      continue;\n    }\n\n    if((last - first) <= TR_INSERTIONSORT_THRESHOLD) {\n      tr_insertionsort(ISAd, first, last);\n      limit = -3;\n      continue;\n    }\n\n    if(limit-- == 0) {\n      tr_heapsort(ISAd, first, PTRDIFF_TO_INT(last - first));\n      for(a = last - 1; first < a; a = b) {\n        for(x = ISAd[*a], b = a - 1; (first <= b) && (ISAd[*b] == x); --b) { *b = ~*b; }\n      }\n      limit = -3;\n      continue;\n    }\n\n    /* choose pivot */\n    a = tr_pivot(ISAd, first, last);\n    SWAP(*first, *a);\n    v = ISAd[*first];\n\n    /* partition */\n    tr_partition(ISAd, first, first + 1, last, &a, &b, v);\n    if((last - first) != (b - a)) {\n      next = (ISA[*a] != v) ? tr_ilg(PTRDIFF_TO_INT(b - a)) : -1;\n\n      /* update ranks */\n      for(c = first, v = PTRDIFF_TO_INT(a - SA - 1); c < a; ++c) { ISA[*c] = v; }\n      if(b < last) { for(c = a, v = PTRDIFF_TO_INT(b - SA - 1); c < b; ++c) { ISA[*c] = v; } }\n\n      /* push */\n      if((1 < (b - a)) && (trbudget_check(budget, PTRDIFF_TO_INT(b - a)))) {\n        if((a - first) <= (last - b)) {\n          if((last - b) <= (b - a)) {\n            if(1 < (a - first)) {\n              STACK_PUSH5(ISAd + incr, a, b, next, trlink);\n              STACK_PUSH5(ISAd, b, last, limit, trlink);\n              last = a;\n            } else if(1 < (last - b)) {\n              STACK_PUSH5(ISAd + incr, a, b, next, trlink);\n              first = b;\n            } else {\n              ISAd += incr, first = a, last = b, limit = next;\n            }\n          } else if((a - first) <= (b - a)) {\n            if(1 < (a - first)) {\n              STACK_PUSH5(ISAd, b, last, limit, trlink);\n              STACK_PUSH5(ISAd + incr, a, b, next, trlink);\n              last = a;\n            } else {\n              STACK_PUSH5(ISAd, b, last, limit, trlink);\n              ISAd += incr, first = a, last = b, limit = next;\n            }\n          } else {\n            STACK_PUSH5(ISAd, b, last, limit, trlink);\n            STACK_PUSH5(ISAd, first, a, limit, trlink);\n            ISAd += incr, first = a, last = b, limit = next;\n          }\n        } else {\n          if((a - first) <= (b - a)) {\n            if(1 < (last - b)) {\n              STACK_PUSH5(ISAd + incr, a, b, next, trlink);\n              STACK_PUSH5(ISAd, first, a, limit, trlink);\n              first = b;\n            } else if(1 < (a - first)) {\n              STACK_PUSH5(ISAd + incr, a, b, next, trlink);\n              last = a;\n            } else {\n              ISAd += incr, first = a, last = b, limit = next;\n            }\n          } else if((last - b) <= (b - a)) {\n            if(1 < (last - b)) {\n              STACK_PUSH5(ISAd, first, a, limit, trlink);\n              STACK_PUSH5(ISAd + incr, a, b, next, trlink);\n              first = b;\n            } else {\n              STACK_PUSH5(ISAd, first, a, limit, trlink);\n              ISAd += incr, first = a, last = b, limit = next;\n            }\n          } else {\n            STACK_PUSH5(ISAd, first, a, limit, trlink);\n            STACK_PUSH5(ISAd, b, last, limit, trlink);\n            ISAd += incr, first = a, last = b, limit = next;\n          }\n        }\n      } else {\n        if((1 < (b - a)) && (0 <= trlink)) { stack[trlink].d = -1; }\n        if((a - first) <= (last - b)) {\n          if(1 < (a - first)) {\n            STACK_PUSH5(ISAd, b, last, limit, trlink);\n            last = a;\n          } else if(1 < (last - b)) {\n            first = b;\n          } else {\n            STACK_POP5(ISAd, first, last, limit, trlink);\n          }\n        } else {\n          if(1 < (last - b)) {\n            STACK_PUSH5(ISAd, first, a, limit, trlink);\n            first = b;\n          } else if(1 < (a - first)) {\n            last = a;\n          } else {\n            STACK_POP5(ISAd, first, last, limit, trlink);\n          }\n        }\n      }\n    } else {\n      if(trbudget_check(budget, PTRDIFF_TO_INT(last - first))) {\n        limit = tr_ilg(PTRDIFF_TO_INT(last - first)), ISAd += incr;\n      } else {\n        if(0 <= trlink) { stack[trlink].d = -1; }\n        STACK_POP5(ISAd, first, last, limit, trlink);\n      }\n    }\n  }\n#undef STACK_SIZE\n}\n\n\n\n/*---------------------------------------------------------------------------*/\n\n/* Tandem repeat sort */\nstatic\nvoid\ntrsort(int *ISA, int *SA, int n, int depth) {\n  int *ISAd;\n  int *first, *last;\n  trbudget_t budget;\n  int t, skip, unsorted;\n\n  trbudget_init(&budget, tr_ilg(n) * 2 / 3, n);\n/*  trbudget_init(&budget, tr_ilg(n) * 3 / 4, n); */\n  for(ISAd = ISA + depth; -n < *SA; ISAd += ISAd - ISA) {\n    first = SA;\n    skip = 0;\n    unsorted = 0;\n    do {\n      if((t = *first) < 0) { first -= t; skip += t; }\n      else {\n        if(skip != 0) { *(first + skip) = skip; skip = 0; }\n        last = SA + ISA[t] + 1;\n        if(1 < (last - first)) {\n          budget.count = 0;\n          tr_introsort(ISA, ISAd, SA, first, last, &budget);\n          if(budget.count != 0) { unsorted += budget.count; }\n          else { skip = PTRDIFF_TO_INT(first - last); }\n        } else if((last - first) == 1) {\n          skip = -1;\n        }\n        first = last;\n      }\n    } while(first < (SA + n));\n    if(skip != 0) { *(first + skip) = skip; }\n    if(unsorted == 0) { break; }\n  }\n}\n\n\n/*---------------------------------------------------------------------------*/\n\n/* Sorts suffixes of type B*. */\nstatic\nint\nsort_typeBstar(const unsigned char *T, int *SA,\n               int *bucket_A, int *bucket_B,\n               int n, int openMP) {\n  int *PAb, *ISAb, *buf;\n#ifdef LIBBSC_OPENMP\n  int *curbuf;\n  int l;\n#endif\n  int i, j, k, t, m, bufsize;\n  int c0, c1;\n#ifdef LIBBSC_OPENMP\n  int d0, d1;\n#endif\n  (void)openMP;\n\n  /* Initialize bucket arrays. */\n  for(i = 0; i < BUCKET_A_SIZE; ++i) { bucket_A[i] = 0; }\n  for(i = 0; i < BUCKET_B_SIZE; ++i) { bucket_B[i] = 0; }\n\n  /* Count the number of occurrences of the first one or two characters of each\n     type A, B and B* suffix. Moreover, store the beginning position of all\n     type B* suffixes into the array SA. */\n  for(i = n - 1, m = n, c0 = T[n - 1]; 0 <= i;) {\n    /* type A suffix. */\n    do { ++BUCKET_A(c1 = c0); } while((0 <= --i) && ((c0 = T[i]) >= c1));\n    if(0 <= i) {\n      /* type B* suffix. */\n      ++BUCKET_BSTAR(c0, c1);\n      SA[--m] = i;\n      /* type B suffix. */\n      for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) {\n        ++BUCKET_B(c0, c1);\n      }\n    }\n  }\n  m = n - m;\n/*\nnote:\n  A type B* suffix is lexicographically smaller than a type B suffix that\n  begins with the same first two characters.\n*/\n\n  /* Calculate the index of start/end point of each bucket. */\n  for(c0 = 0, i = 0, j = 0; c0 < ALPHABET_SIZE; ++c0) {\n    t = i + BUCKET_A(c0);\n    BUCKET_A(c0) = i + j; /* start point */\n    i = t + BUCKET_B(c0, c0);\n    for(c1 = c0 + 1; c1 < ALPHABET_SIZE; ++c1) {\n      j += BUCKET_BSTAR(c0, c1);\n      BUCKET_BSTAR(c0, c1) = j; /* end point */\n      i += BUCKET_B(c0, c1);\n    }\n  }\n\n  if(0 < m) {\n    /* Sort the type B* suffixes by their first two characters. */\n    PAb = SA + n - m; ISAb = SA + m;\n    for(i = m - 2; 0 <= i; --i) {\n      t = PAb[i], c0 = T[t], c1 = T[t + 1];\n      SA[--BUCKET_BSTAR(c0, c1)] = i;\n    }\n    t = PAb[m - 1], c0 = T[t], c1 = T[t + 1];\n    SA[--BUCKET_BSTAR(c0, c1)] = m - 1;\n\n    /* Sort the type B* substrings using sssort. */\n#ifdef LIBBSC_OPENMP\n    if (openMP)\n    {\n        buf = SA + m;\n        c0 = ALPHABET_SIZE - 2, c1 = ALPHABET_SIZE - 1, j = m;\n#pragma omp parallel default(shared) private(bufsize, curbuf, k, l, d0, d1)\n        {\n          bufsize = (n - (2 * m)) / omp_get_num_threads();\n          curbuf = buf + omp_get_thread_num() * bufsize;\n          k = 0;\n          for(;;) {\n            #pragma omp critical(sssort_lock)\n            {\n              if(0 < (l = j)) {\n                d0 = c0, d1 = c1;\n                do {\n                  k = BUCKET_BSTAR(d0, d1);\n                  if(--d1 <= d0) {\n                    d1 = ALPHABET_SIZE - 1;\n                    if(--d0 < 0) { break; }\n                  }\n                } while(((l - k) <= 1) && (0 < (l = k)));\n                c0 = d0, c1 = d1, j = k;\n              }\n            }\n            if(l == 0) { break; }\n            sssort(T, PAb, SA + k, SA + l,\n                   curbuf, bufsize, 2, n, *(SA + k) == (m - 1));\n          }\n        }\n    }\n    else\n    {\n        buf = SA + m, bufsize = n - (2 * m);\n        for(c0 = ALPHABET_SIZE - 2, j = m; 0 < j; --c0) {\n          for(c1 = ALPHABET_SIZE - 1; c0 < c1; j = i, --c1) {\n            i = BUCKET_BSTAR(c0, c1);\n            if(1 < (j - i)) {\n              sssort(T, PAb, SA + i, SA + j,\n                     buf, bufsize, 2, n, *(SA + i) == (m - 1));\n            }\n          }\n        }\n    }\n#else\n    buf = SA + m, bufsize = n - (2 * m);\n    for(c0 = ALPHABET_SIZE - 2, j = m; 0 < j; --c0) {\n      for(c1 = ALPHABET_SIZE - 1; c0 < c1; j = i, --c1) {\n        i = BUCKET_BSTAR(c0, c1);\n        if(1 < (j - i)) {\n          sssort(T, PAb, SA + i, SA + j,\n                 buf, bufsize, 2, n, *(SA + i) == (m - 1));\n        }\n      }\n    }\n#endif\n\n    /* Compute ranks of type B* substrings. */\n    for(i = m - 1; 0 <= i; --i) {\n      if(0 <= SA[i]) {\n        j = i;\n        do { ISAb[SA[i]] = i; } while((0 <= --i) && (0 <= SA[i]));\n        SA[i + 1] = i - j;\n        if(i <= 0) { break; }\n      }\n      j = i;\n      do { ISAb[SA[i] = ~SA[i]] = j; } while(SA[--i] < 0);\n      ISAb[SA[i]] = j;\n    }\n\n    /* Construct the inverse suffix array of type B* suffixes using trsort. */\n    trsort(ISAb, SA, m, 1);\n\n    /* Set the sorted order of type B* suffixes. */\n    for(i = n - 1, j = m, c0 = T[n - 1]; 0 <= i;) {\n      for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) >= c1); --i, c1 = c0) { }\n      if(0 <= i) {\n        t = i;\n        for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) { }\n        SA[ISAb[--j]] = ((t == 0) || (1 < (t - i))) ? t : ~t;\n      }\n    }\n\n    /* Calculate the index of start/end point of each bucket. */\n    BUCKET_B(ALPHABET_SIZE - 1, ALPHABET_SIZE - 1) = n; /* end point */\n    for(c0 = ALPHABET_SIZE - 2, k = m - 1; 0 <= c0; --c0) {\n      i = BUCKET_A(c0 + 1) - 1;\n      for(c1 = ALPHABET_SIZE - 1; c0 < c1; --c1) {\n        t = i - BUCKET_B(c0, c1);\n        BUCKET_B(c0, c1) = i; /* end point */\n\n        /* Move all type B* suffixes to the correct position. */\n        for(i = t, j = BUCKET_BSTAR(c0, c1);\n            j <= k;\n            --i, --k) { SA[i] = SA[k]; }\n      }\n      BUCKET_BSTAR(c0, c0 + 1) = i - BUCKET_B(c0, c0) + 1; /* start point */\n      BUCKET_B(c0, c0) = i; /* end point */\n    }\n  }\n\n  return m;\n}\n\n/* Constructs the suffix array by using the sorted order of type B* suffixes. */\nstatic\nvoid\nconstruct_SA(const unsigned char *T, int *SA,\n             int *bucket_A, int *bucket_B,\n             int n, int m) {\n  int *i, *j, *k;\n  int s;\n  int c0, c1, c2;\n\n  if(0 < m) {\n    /* Construct the sorted order of type B suffixes by using\n       the sorted order of type B* suffixes. */\n    for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) {\n      /* Scan the suffix array from right to left. */\n      for(i = SA + BUCKET_BSTAR(c1, c1 + 1),\n          j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1;\n          i <= j;\n          --j) {\n        if(0 < (s = *j)) {\n          assert(T[s] == c1);\n          assert(((s + 1) < n) && (T[s] <= T[s + 1]));\n          assert(T[s - 1] <= T[s]);\n          *j = ~s;\n          c0 = T[--s];\n          if((0 < s) && (T[s - 1] > c0)) { s = ~s; }\n          if(c0 != c2) {\n            if(0 <= c2) { BUCKET_B(c2, c1) = PTRDIFF_TO_INT(k - SA); }\n            k = SA + BUCKET_B(c2 = c0, c1);\n          }\n          assert(k < j); assert(k != NULL);\n          *k-- = s;\n        } else {\n          assert(((s == 0) && (T[s] == c1)) || (s < 0));\n          *j = ~s;\n        }\n      }\n    }\n  }\n\n  /* Construct the suffix array by using\n     the sorted order of type B suffixes. */\n  k = SA + BUCKET_A(c2 = T[n - 1]);\n  *k++ = (T[n - 2] < c2) ? ~(n - 1) : (n - 1);\n  /* Scan the suffix array from left to right. */\n  for(i = SA, j = SA + n; i < j; ++i) {\n    if(0 < (s = *i)) {\n      assert(T[s - 1] >= T[s]);\n      c0 = T[--s];\n      if((s == 0) || (T[s - 1] < c0)) { s = ~s; }\n      if(c0 != c2) {\n        BUCKET_A(c2) = PTRDIFF_TO_INT(k - SA);\n        k = SA + BUCKET_A(c2 = c0);\n      }\n      assert(i < k);\n      *k++ = s;\n    } else {\n      assert(s < 0);\n      *i = ~s;\n    }\n  }\n}\n\n/* Constructs the burrows-wheeler transformed string directly\n   by using the sorted order of type B* suffixes. */\nstatic\nint\nconstruct_BWT(const unsigned char *T, int *SA,\n              int *bucket_A, int *bucket_B,\n              int n, int m) {\n  int *i, *j, *k, *orig;\n  int s;\n  int c0, c1, c2;\n\n  if(0 < m) {\n    /* Construct the sorted order of type B suffixes by using\n       the sorted order of type B* suffixes. */\n    for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) {\n      /* Scan the suffix array from right to left. */\n      for(i = SA + BUCKET_BSTAR(c1, c1 + 1),\n          j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1;\n          i <= j;\n          --j) {\n        if(0 < (s = *j)) {\n          assert(T[s] == c1);\n          assert(((s + 1) < n) && (T[s] <= T[s + 1]));\n          assert(T[s - 1] <= T[s]);\n          c0 = T[--s];\n          *j = ~((int)c0);\n          if((0 < s) && (T[s - 1] > c0)) { s = ~s; }\n          if(c0 != c2) {\n            if(0 <= c2) { BUCKET_B(c2, c1) = PTRDIFF_TO_INT(k - SA); }\n            k = SA + BUCKET_B(c2 = c0, c1);\n          }\n          assert(k < j); assert(k != NULL);\n          *k-- = s;\n        } else if(s != 0) {\n          *j = ~s;\n#ifndef NDEBUG\n        } else {\n          assert(T[s] == c1);\n#endif\n        }\n      }\n    }\n  }\n\n  /* Construct the BWTed string by using\n     the sorted order of type B suffixes. */\n  k = SA + BUCKET_A(c2 = T[n - 1]);\n  *k++ = (T[n - 2] < c2) ? ~((int)T[n - 2]) : (n - 1);\n  /* Scan the suffix array from left to right. */\n  for(i = SA, j = SA + n, orig = SA; i < j; ++i) {\n    if(0 < (s = *i)) {\n      assert(T[s - 1] >= T[s]);\n      c0 = T[--s];\n      *i = c0;\n      if((0 < s) && (T[s - 1] < c0)) { s = ~((int)T[s - 1]); }\n      if(c0 != c2) {\n        BUCKET_A(c2) = PTRDIFF_TO_INT(k - SA);\n        k = SA + BUCKET_A(c2 = c0);\n      }\n      assert(i < k);\n      *k++ = s;\n    } else if(s != 0) {\n      *i = ~s;\n    } else {\n      orig = i;\n    }\n  }\n\n  return PTRDIFF_TO_INT(orig - SA);\n}\n\n/* Constructs the burrows-wheeler transformed string directly\n   by using the sorted order of type B* suffixes. */\nstatic\nint\nconstruct_BWT_indexes(const unsigned char *T, int *SA,\n                      int *bucket_A, int *bucket_B,\n                      int n, int m,\n                      unsigned char * num_indexes, int * indexes) {\n  int *i, *j, *k, *orig;\n  int s;\n  int c0, c1, c2;\n\n  int mod = n / 8;\n  {\n      mod |= mod >> 1;  mod |= mod >> 2;\n      mod |= mod >> 4;  mod |= mod >> 8;\n      mod |= mod >> 16; mod >>= 1;\n\n      *num_indexes = (unsigned char)((n - 1) / (mod + 1));\n  }\n\n  if(0 < m) {\n    /* Construct the sorted order of type B suffixes by using\n       the sorted order of type B* suffixes. */\n    for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) {\n      /* Scan the suffix array from right to left. */\n      for(i = SA + BUCKET_BSTAR(c1, c1 + 1),\n          j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1;\n          i <= j;\n          --j) {\n        if(0 < (s = *j)) {\n          assert(T[s] == c1);\n          assert(((s + 1) < n) && (T[s] <= T[s + 1]));\n          assert(T[s - 1] <= T[s]);\n\n          if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = PTRDIFF_TO_INT(j - SA);\n\n          c0 = T[--s];\n          *j = ~((int)c0);\n          if((0 < s) && (T[s - 1] > c0)) { s = ~s; }\n          if(c0 != c2) {\n            if(0 <= c2) { BUCKET_B(c2, c1) = PTRDIFF_TO_INT(k - SA); }\n            k = SA + BUCKET_B(c2 = c0, c1);\n          }\n          assert(k < j); assert(k != NULL);\n          *k-- = s;\n        } else if(s != 0) {\n          *j = ~s;\n#ifndef NDEBUG\n        } else {\n          assert(T[s] == c1);\n#endif\n        }\n      }\n    }\n  }\n\n  /* Construct the BWTed string by using\n     the sorted order of type B suffixes. */\n  k = SA + BUCKET_A(c2 = T[n - 1]);\n  if (T[n - 2] < c2) {\n    if (((n - 1) & mod) == 0) indexes[(n - 1) / (mod + 1) - 1] = PTRDIFF_TO_INT(k - SA);\n    *k++ = ~((int)T[n - 2]);\n  }\n  else {\n    *k++ = n - 1;\n  }\n\n  /* Scan the suffix array from left to right. */\n  for(i = SA, j = SA + n, orig = SA; i < j; ++i) {\n    if(0 < (s = *i)) {\n      assert(T[s - 1] >= T[s]);\n\n      if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = PTRDIFF_TO_INT(i - SA);\n\n      c0 = T[--s];\n      *i = c0;\n      if(c0 != c2) {\n        BUCKET_A(c2) = PTRDIFF_TO_INT(k - SA);\n        k = SA + BUCKET_A(c2 = c0);\n      }\n      assert(i < k);\n      if((0 < s) && (T[s - 1] < c0)) {\n          if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = PTRDIFF_TO_INT(k - SA);\n          *k++ = ~((int)T[s - 1]);\n      } else\n        *k++ = s;\n    } else if(s != 0) {\n      *i = ~s;\n    } else {\n      orig = i;\n    }\n  }\n\n  return PTRDIFF_TO_INT(orig - SA);\n}\n\n\n/*---------------------------------------------------------------------------*/\n\n/*- Function -*/\n\nint\ndivsufsort(const unsigned char *T, int *SA, int n, int openMP) {\n  int *bucket_A, *bucket_B;\n  int m;\n  int err = 0;\n\n  /* Check arguments. */\n  if((T == NULL) || (SA == NULL) || (n < 0)) { return -1; }\n  else if(n == 0) { return 0; }\n  else if(n == 1) { SA[0] = 0; return 0; }\n  else if(n == 2) { m = (T[0] < T[1]); SA[m ^ 1] = 0, SA[m] = 1; return 0; }\n\n  bucket_A = (int *)malloc(BUCKET_A_SIZE * sizeof(int));\n  bucket_B = (int *)malloc(BUCKET_B_SIZE * sizeof(int));\n\n  /* Suffixsort. */\n  if((bucket_A != NULL) && (bucket_B != NULL)) {\n    m = sort_typeBstar(T, SA, bucket_A, bucket_B, n, openMP);\n    construct_SA(T, SA, bucket_A, bucket_B, n, m);\n  } else {\n    err = -2;\n  }\n\n  free(bucket_B);\n  free(bucket_A);\n\n  return err;\n}\n\nint\ndivbwt(const unsigned char *T, unsigned char *U, int *A, int n, unsigned char * num_indexes, int * indexes, int openMP) {\n  int *B;\n  int *bucket_A, *bucket_B;\n  int m, pidx, i;\n\n  /* Check arguments. */\n  if((T == NULL) || (U == NULL) || (n < 0)) { return -1; }\n  else if(n <= 1) { if(n == 1) { U[0] = T[0]; } return n; }\n\n  if((B = A) == NULL) { B = (int *)malloc((size_t)(n + 1) * sizeof(int)); }\n  bucket_A = (int *)malloc(BUCKET_A_SIZE * sizeof(int));\n  bucket_B = (int *)malloc(BUCKET_B_SIZE * sizeof(int));\n\n  /* Burrows-Wheeler Transform. */\n  if((B != NULL) && (bucket_A != NULL) && (bucket_B != NULL)) {\n    m = sort_typeBstar(T, B, bucket_A, bucket_B, n, openMP);\n\n    if (num_indexes == NULL || indexes == NULL) {\n        pidx = construct_BWT(T, B, bucket_A, bucket_B, n, m);\n    } else {\n        pidx = construct_BWT_indexes(T, B, bucket_A, bucket_B, n, m, num_indexes, indexes);\n    }\n\n    /* Copy to output string. */\n    U[0] = T[n - 1];\n    for(i = 0; i < pidx; ++i) { U[i + 1] = (unsigned char)B[i]; }\n    for(i += 1; i < n; ++i) { U[i] = (unsigned char)B[i]; }\n    pidx += 1;\n  } else {\n    pidx = -2;\n  }\n\n  free(bucket_B);\n  free(bucket_A);\n  if(A == NULL) { free(B); }\n\n  return pidx;\n}\n"
  },
  {
    "path": "lib/dictBuilder/divsufsort.h",
    "content": "/*\n * divsufsort.h for libdivsufsort-lite\n * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.\n *\n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation\n * files (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use,\n * copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following\n * conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#ifndef _DIVSUFSORT_H\n#define _DIVSUFSORT_H 1\n\n/*- Prototypes -*/\n\n/**\n * Constructs the suffix array of a given string.\n * @param T [0..n-1] The input string.\n * @param SA [0..n-1] The output array of suffixes.\n * @param n The length of the given string.\n * @param openMP enables OpenMP optimization.\n * @return 0 if no error occurred, -1 or -2 otherwise.\n */\nint\ndivsufsort(const unsigned char *T, int *SA, int n, int openMP);\n\n/**\n * Constructs the burrows-wheeler transformed string of a given string.\n * @param T [0..n-1] The input string.\n * @param U [0..n-1] The output string. (can be T)\n * @param A [0..n-1] The temporary array. (can be NULL)\n * @param n The length of the given string.\n * @param num_indexes The length of secondary indexes array. (can be NULL)\n * @param indexes The secondary indexes array. (can be NULL)\n * @param openMP enables OpenMP optimization.\n * @return The primary index if no error occurred, -1 or -2 otherwise.\n */\nint\ndivbwt(const unsigned char *T, unsigned char *U, int *A, int n, unsigned char * num_indexes, int * indexes, int openMP);\n\n#endif /* _DIVSUFSORT_H */\n"
  },
  {
    "path": "lib/dictBuilder/fastcover.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/*-*************************************\n*  Dependencies\n***************************************/\n#include <stdio.h>  /* fprintf */\n#include <stdlib.h> /* malloc, free, qsort */\n#include <string.h> /* memset */\n#include <time.h>   /* clock */\n\n#ifndef ZDICT_STATIC_LINKING_ONLY\n#  define ZDICT_STATIC_LINKING_ONLY\n#endif\n\n#include \"../common/mem.h\" /* read */\n#include \"../common/pool.h\"\n#include \"../common/threading.h\"\n#include \"../common/zstd_internal.h\" /* includes zstd.h */\n#include \"../compress/zstd_compress_internal.h\" /* ZSTD_hash*() */\n#include \"../zdict.h\"\n#include \"cover.h\"\n\n\n/*-*************************************\n*  Constants\n***************************************/\n/**\n* There are 32bit indexes used to ref samples, so limit samples size to 4GB\n* on 64bit builds.\n* For 32bit builds we choose 1 GB.\n* Most 32bit platforms have 2GB user-mode addressable space and we allocate a large\n* contiguous buffer, so 1GB is already a high limit.\n*/\n#define FASTCOVER_MAX_SAMPLES_SIZE (sizeof(size_t) == 8 ? ((unsigned)-1) : ((unsigned)1 GB))\n#define FASTCOVER_MAX_F 31\n#define FASTCOVER_MAX_ACCEL 10\n#define FASTCOVER_DEFAULT_SPLITPOINT 0.75\n#define DEFAULT_F 20\n#define DEFAULT_ACCEL 1\n\n\n/*-*************************************\n*  Console display\n*\n* Captures the `displayLevel` variable in the local scope.\n***************************************/\n#undef  DISPLAY\n#define DISPLAY(...)                                                           \\\n  {                                                                            \\\n    fprintf(stderr, __VA_ARGS__);                                              \\\n    fflush(stderr);                                                            \\\n  }\n#undef  DISPLAYLEVEL\n#define DISPLAYLEVEL(l, ...)                                                   \\\n  if (displayLevel >= l) {                                                     \\\n    DISPLAY(__VA_ARGS__);                                                      \\\n  } /* 0 : no display;   1: errors;   2: default;  3: details;  4: debug */\n\n#undef  DISPLAYUPDATE\n#define DISPLAYUPDATE(lastUpdateTime, l, ...)                                  \\\n  if (displayLevel >= l) {                                                     \\\n    const clock_t refreshRate = CLOCKS_PER_SEC * 15 / 100;                     \\\n    if ((clock() - lastUpdateTime > refreshRate) || (displayLevel >= 4)) {     \\\n      lastUpdateTime = clock();                                                \\\n      DISPLAY(__VA_ARGS__);                                                    \\\n    }                                                                          \\\n  }\n\n\n/*-*************************************\n* Hash Functions\n***************************************/\n/**\n * Hash the d-byte value pointed to by p and mod 2^f into the frequency vector\n */\nstatic size_t FASTCOVER_hashPtrToIndex(const void* p, U32 f, unsigned d) {\n  if (d == 6) {\n    return ZSTD_hash6Ptr(p, f);\n  }\n  return ZSTD_hash8Ptr(p, f);\n}\n\n\n/*-*************************************\n* Acceleration\n***************************************/\ntypedef struct {\n  unsigned finalize;    /* Percentage of training samples used for ZDICT_finalizeDictionary */\n  unsigned skip;        /* Number of dmer skipped between each dmer counted in computeFrequency */\n} FASTCOVER_accel_t;\n\n\nstatic const FASTCOVER_accel_t FASTCOVER_defaultAccelParameters[FASTCOVER_MAX_ACCEL+1] = {\n  { 100, 0 },   /* accel = 0, should not happen because accel = 0 defaults to accel = 1 */\n  { 100, 0 },   /* accel = 1 */\n  { 50, 1 },   /* accel = 2 */\n  { 34, 2 },   /* accel = 3 */\n  { 25, 3 },   /* accel = 4 */\n  { 20, 4 },   /* accel = 5 */\n  { 17, 5 },   /* accel = 6 */\n  { 14, 6 },   /* accel = 7 */\n  { 13, 7 },   /* accel = 8 */\n  { 11, 8 },   /* accel = 9 */\n  { 10, 9 },   /* accel = 10 */\n};\n\n\n/*-*************************************\n* Context\n***************************************/\ntypedef struct {\n  const BYTE *samples;\n  size_t *offsets;\n  const size_t *samplesSizes;\n  size_t nbSamples;\n  size_t nbTrainSamples;\n  size_t nbTestSamples;\n  size_t nbDmers;\n  U32 *freqs;\n  unsigned d;\n  unsigned f;\n  FASTCOVER_accel_t accelParams;\n  int displayLevel;\n} FASTCOVER_ctx_t;\n\n\n/*-*************************************\n*  Helper functions\n***************************************/\n/**\n * Selects the best segment in an epoch.\n * Segments of are scored according to the function:\n *\n * Let F(d) be the frequency of all dmers with hash value d.\n * Let S_i be hash value of the dmer at position i of segment S which has length k.\n *\n *     Score(S) = F(S_1) + F(S_2) + ... + F(S_{k-d+1})\n *\n * Once the dmer with hash value d is in the dictionary we set F(d) = 0.\n */\nstatic COVER_segment_t FASTCOVER_selectSegment(const FASTCOVER_ctx_t *ctx,\n                                              U32 *freqs, U32 begin, U32 end,\n                                              ZDICT_cover_params_t parameters,\n                                              U16* segmentFreqs) {\n  /* Constants */\n  const U32 k = parameters.k;\n  const U32 d = parameters.d;\n  const U32 f = ctx->f;\n  const U32 dmersInK = k - d + 1;\n\n  /* Try each segment (activeSegment) and save the best (bestSegment) */\n  COVER_segment_t bestSegment = {0, 0, 0};\n  COVER_segment_t activeSegment;\n\n  /* Reset the activeDmers in the segment */\n  /* The activeSegment starts at the beginning of the epoch. */\n  activeSegment.begin = begin;\n  activeSegment.end = begin;\n  activeSegment.score = 0;\n\n  /* Slide the activeSegment through the whole epoch.\n   * Save the best segment in bestSegment.\n   */\n  while (activeSegment.end < end) {\n    /* Get hash value of current dmer */\n    const size_t idx = FASTCOVER_hashPtrToIndex(ctx->samples + activeSegment.end, f, d);\n\n    /* Add frequency of this index to score if this is the first occurrence of index in active segment */\n    if (segmentFreqs[idx] == 0) {\n      activeSegment.score += freqs[idx];\n    }\n    /* Increment end of segment and segmentFreqs*/\n    activeSegment.end += 1;\n    segmentFreqs[idx] += 1;\n    /* If the window is now too large, drop the first position */\n    if (activeSegment.end - activeSegment.begin == dmersInK + 1) {\n      /* Get hash value of the dmer to be eliminated from active segment */\n      const size_t delIndex = FASTCOVER_hashPtrToIndex(ctx->samples + activeSegment.begin, f, d);\n      segmentFreqs[delIndex] -= 1;\n      /* Subtract frequency of this index from score if this is the last occurrence of this index in active segment */\n      if (segmentFreqs[delIndex] == 0) {\n        activeSegment.score -= freqs[delIndex];\n      }\n      /* Increment start of segment */\n      activeSegment.begin += 1;\n    }\n\n    /* If this segment is the best so far save it */\n    if (activeSegment.score > bestSegment.score) {\n      bestSegment = activeSegment;\n    }\n  }\n\n  /* Zero out rest of segmentFreqs array */\n  while (activeSegment.begin < end) {\n    const size_t delIndex = FASTCOVER_hashPtrToIndex(ctx->samples + activeSegment.begin, f, d);\n    segmentFreqs[delIndex] -= 1;\n    activeSegment.begin += 1;\n  }\n\n  {\n    /*  Zero the frequency of hash value of each dmer covered by the chosen segment. */\n    U32 pos;\n    for (pos = bestSegment.begin; pos != bestSegment.end; ++pos) {\n      const size_t i = FASTCOVER_hashPtrToIndex(ctx->samples + pos, f, d);\n      freqs[i] = 0;\n    }\n  }\n\n  return bestSegment;\n}\n\n\nstatic int FASTCOVER_checkParameters(ZDICT_cover_params_t parameters,\n                                     size_t maxDictSize, unsigned f,\n                                     unsigned accel) {\n  /* k, d, and f are required parameters */\n  if (parameters.d == 0 || parameters.k == 0) {\n    return 0;\n  }\n  /* d has to be 6 or 8 */\n  if (parameters.d != 6 && parameters.d != 8) {\n    return 0;\n  }\n  /* k <= maxDictSize */\n  if (parameters.k > maxDictSize) {\n    return 0;\n  }\n  /* d <= k */\n  if (parameters.d > parameters.k) {\n    return 0;\n  }\n  /* 0 < f <= FASTCOVER_MAX_F*/\n  if (f > FASTCOVER_MAX_F || f == 0) {\n    return 0;\n  }\n  /* 0 < splitPoint <= 1 */\n  if (parameters.splitPoint <= 0 || parameters.splitPoint > 1) {\n    return 0;\n  }\n  /* 0 < accel <= 10 */\n  if (accel > 10 || accel == 0) {\n    return 0;\n  }\n  return 1;\n}\n\n\n/**\n * Clean up a context initialized with `FASTCOVER_ctx_init()`.\n */\nstatic void\nFASTCOVER_ctx_destroy(FASTCOVER_ctx_t* ctx)\n{\n    if (!ctx) return;\n\n    free(ctx->freqs);\n    ctx->freqs = NULL;\n\n    free(ctx->offsets);\n    ctx->offsets = NULL;\n}\n\n\n/**\n * Calculate for frequency of hash value of each dmer in ctx->samples\n */\nstatic void\nFASTCOVER_computeFrequency(U32* freqs, const FASTCOVER_ctx_t* ctx)\n{\n    const unsigned f = ctx->f;\n    const unsigned d = ctx->d;\n    const unsigned skip = ctx->accelParams.skip;\n    const unsigned readLength = MAX(d, 8);\n    size_t i;\n    assert(ctx->nbTrainSamples >= 5);\n    assert(ctx->nbTrainSamples <= ctx->nbSamples);\n    for (i = 0; i < ctx->nbTrainSamples; i++) {\n        size_t start = ctx->offsets[i];  /* start of current dmer */\n        size_t const currSampleEnd = ctx->offsets[i+1];\n        while (start + readLength <= currSampleEnd) {\n            const size_t dmerIndex = FASTCOVER_hashPtrToIndex(ctx->samples + start, f, d);\n            freqs[dmerIndex]++;\n            start = start + skip + 1;\n        }\n    }\n}\n\n\n/**\n * Prepare a context for dictionary building.\n * The context is only dependent on the parameter `d` and can be used multiple\n * times.\n * Returns 0 on success or error code on error.\n * The context must be destroyed with `FASTCOVER_ctx_destroy()`.\n */\nstatic size_t\nFASTCOVER_ctx_init(FASTCOVER_ctx_t* ctx,\n                   const void* samplesBuffer,\n                   const size_t* samplesSizes, unsigned nbSamples,\n                   unsigned d, double splitPoint, unsigned f,\n                   FASTCOVER_accel_t accelParams,\n                   int displayLevel)\n{\n    const BYTE* const samples = (const BYTE*)samplesBuffer;\n    const size_t totalSamplesSize = COVER_sum(samplesSizes, nbSamples);\n    /* Split samples into testing and training sets */\n    const unsigned nbTrainSamples = splitPoint < 1.0 ? (unsigned)((double)nbSamples * splitPoint) : nbSamples;\n    const unsigned nbTestSamples = splitPoint < 1.0 ? nbSamples - nbTrainSamples : nbSamples;\n    const size_t trainingSamplesSize = splitPoint < 1.0 ? COVER_sum(samplesSizes, nbTrainSamples) : totalSamplesSize;\n    const size_t testSamplesSize = splitPoint < 1.0 ? COVER_sum(samplesSizes + nbTrainSamples, nbTestSamples) : totalSamplesSize;\n    ctx->displayLevel = displayLevel;\n\n    /* Checks */\n    if (totalSamplesSize < MAX(d, sizeof(U64)) ||\n        totalSamplesSize >= (size_t)FASTCOVER_MAX_SAMPLES_SIZE) {\n        DISPLAYLEVEL(1, \"Total samples size is too large (%u MB), maximum size is %u MB\\n\",\n                    (unsigned)(totalSamplesSize >> 20), (FASTCOVER_MAX_SAMPLES_SIZE >> 20));\n        return ERROR(srcSize_wrong);\n    }\n\n    /* Check if there are at least 5 training samples */\n    if (nbTrainSamples < 5) {\n        DISPLAYLEVEL(1, \"Total number of training samples is %u and is invalid\\n\", nbTrainSamples);\n        return ERROR(srcSize_wrong);\n    }\n\n    /* Check if there's testing sample */\n    if (nbTestSamples < 1) {\n        DISPLAYLEVEL(1, \"Total number of testing samples is %u and is invalid.\\n\", nbTestSamples);\n        return ERROR(srcSize_wrong);\n    }\n\n    /* Zero the context */\n    memset(ctx, 0, sizeof(*ctx));\n    DISPLAYLEVEL(2, \"Training on %u samples of total size %u\\n\", nbTrainSamples,\n                    (unsigned)trainingSamplesSize);\n    DISPLAYLEVEL(2, \"Testing on %u samples of total size %u\\n\", nbTestSamples,\n                    (unsigned)testSamplesSize);\n\n    ctx->samples = samples;\n    ctx->samplesSizes = samplesSizes;\n    ctx->nbSamples = nbSamples;\n    ctx->nbTrainSamples = nbTrainSamples;\n    ctx->nbTestSamples = nbTestSamples;\n    ctx->nbDmers = trainingSamplesSize - MAX(d, sizeof(U64)) + 1;\n    ctx->d = d;\n    ctx->f = f;\n    ctx->accelParams = accelParams;\n\n    /* The offsets of each file */\n    ctx->offsets = (size_t*)calloc((nbSamples + 1), sizeof(size_t));\n    if (ctx->offsets == NULL) {\n        DISPLAYLEVEL(1, \"Failed to allocate scratch buffers \\n\");\n        FASTCOVER_ctx_destroy(ctx);\n        return ERROR(memory_allocation);\n    }\n\n    /* Fill offsets from the samplesSizes */\n    {   U32 i;\n        ctx->offsets[0] = 0;\n        assert(nbSamples >= 5);\n        for (i = 1; i <= nbSamples; ++i) {\n            ctx->offsets[i] = ctx->offsets[i - 1] + samplesSizes[i - 1];\n        }\n    }\n\n    /* Initialize frequency array of size 2^f */\n    ctx->freqs = (U32*)calloc(((U64)1 << f), sizeof(U32));\n    if (ctx->freqs == NULL) {\n        DISPLAYLEVEL(1, \"Failed to allocate frequency table \\n\");\n        FASTCOVER_ctx_destroy(ctx);\n        return ERROR(memory_allocation);\n    }\n\n    DISPLAYLEVEL(2, \"Computing frequencies\\n\");\n    FASTCOVER_computeFrequency(ctx->freqs, ctx);\n\n    return 0;\n}\n\n\n/**\n * Given the prepared context build the dictionary.\n */\nstatic size_t\nFASTCOVER_buildDictionary(const FASTCOVER_ctx_t* ctx,\n                          U32* freqs,\n                          void* dictBuffer, size_t dictBufferCapacity,\n                          ZDICT_cover_params_t parameters,\n                          U16* segmentFreqs)\n{\n  BYTE *const dict = (BYTE *)dictBuffer;\n  size_t tail = dictBufferCapacity;\n  /* Divide the data into epochs. We will select one segment from each epoch. */\n  const COVER_epoch_info_t epochs = COVER_computeEpochs(\n      (U32)dictBufferCapacity, (U32)ctx->nbDmers, parameters.k, 1);\n  const size_t maxZeroScoreRun = 10;\n  const int displayLevel = ctx->displayLevel;\n  size_t zeroScoreRun = 0;\n  clock_t lastUpdateTime = 0;\n  size_t epoch;\n  DISPLAYLEVEL(2, \"Breaking content into %u epochs of size %u\\n\",\n                (U32)epochs.num, (U32)epochs.size);\n  /* Loop through the epochs until there are no more segments or the dictionary\n   * is full.\n   */\n  for (epoch = 0; tail > 0; epoch = (epoch + 1) % epochs.num) {\n    const U32 epochBegin = (U32)(epoch * epochs.size);\n    const U32 epochEnd = epochBegin + epochs.size;\n    size_t segmentSize;\n    /* Select a segment */\n    COVER_segment_t segment = FASTCOVER_selectSegment(\n        ctx, freqs, epochBegin, epochEnd, parameters, segmentFreqs);\n\n    /* If the segment covers no dmers, then we are out of content.\n     * There may be new content in other epochs, for continue for some time.\n     */\n    if (segment.score == 0) {\n      if (++zeroScoreRun >= maxZeroScoreRun) {\n          break;\n      }\n      continue;\n    }\n    zeroScoreRun = 0;\n\n    /* Trim the segment if necessary and if it is too small then we are done */\n    segmentSize = MIN(segment.end - segment.begin + parameters.d - 1, tail);\n    if (segmentSize < parameters.d) {\n      break;\n    }\n\n    /* We fill the dictionary from the back to allow the best segments to be\n     * referenced with the smallest offsets.\n     */\n    tail -= segmentSize;\n    memcpy(dict + tail, ctx->samples + segment.begin, segmentSize);\n    DISPLAYUPDATE(\n        lastUpdateTime,\n        2, \"\\r%u%%       \",\n        (unsigned)(((dictBufferCapacity - tail) * 100) / dictBufferCapacity));\n  }\n  DISPLAYLEVEL(2, \"\\r%79s\\r\", \"\");\n  return tail;\n}\n\n/**\n * Parameters for FASTCOVER_tryParameters().\n */\ntypedef struct FASTCOVER_tryParameters_data_s {\n    const FASTCOVER_ctx_t* ctx;\n    COVER_best_t* best;\n    size_t dictBufferCapacity;\n    ZDICT_cover_params_t parameters;\n} FASTCOVER_tryParameters_data_t;\n\n\n/**\n * Tries a set of parameters and updates the COVER_best_t with the results.\n * This function is thread safe if zstd is compiled with multithreaded support.\n * It takes its parameters as an *OWNING* opaque pointer to support threading.\n */\nstatic void FASTCOVER_tryParameters(void* opaque)\n{\n  /* Save parameters as local variables */\n  FASTCOVER_tryParameters_data_t *const data = (FASTCOVER_tryParameters_data_t*)opaque;\n  const FASTCOVER_ctx_t *const ctx = data->ctx;\n  const ZDICT_cover_params_t parameters = data->parameters;\n  size_t dictBufferCapacity = data->dictBufferCapacity;\n  size_t totalCompressedSize = ERROR(GENERIC);\n  /* Initialize array to keep track of frequency of dmer within activeSegment */\n  U16* segmentFreqs = (U16*)calloc(((U64)1 << ctx->f), sizeof(U16));\n  /* Allocate space for hash table, dict, and freqs */\n  BYTE *const dict = (BYTE*)malloc(dictBufferCapacity);\n  COVER_dictSelection_t selection = COVER_dictSelectionError(ERROR(GENERIC));\n  U32* freqs = (U32*) malloc(((U64)1 << ctx->f) * sizeof(U32));\n  const int displayLevel = ctx->displayLevel;\n  if (!segmentFreqs || !dict || !freqs) {\n    DISPLAYLEVEL(1, \"Failed to allocate buffers: out of memory\\n\");\n    goto _cleanup;\n  }\n  /* Copy the frequencies because we need to modify them */\n  memcpy(freqs, ctx->freqs, ((U64)1 << ctx->f) * sizeof(U32));\n  /* Build the dictionary */\n  { const size_t tail = FASTCOVER_buildDictionary(ctx, freqs, dict, dictBufferCapacity,\n                                                    parameters, segmentFreqs);\n\n    const unsigned nbFinalizeSamples = (unsigned)(ctx->nbTrainSamples * ctx->accelParams.finalize / 100);\n    selection = COVER_selectDict(dict + tail, dictBufferCapacity, dictBufferCapacity - tail,\n         ctx->samples, ctx->samplesSizes, nbFinalizeSamples, ctx->nbTrainSamples, ctx->nbSamples, parameters, ctx->offsets,\n         totalCompressedSize);\n\n    if (COVER_dictSelectionIsError(selection)) {\n      DISPLAYLEVEL(1, \"Failed to select dictionary\\n\");\n      goto _cleanup;\n    }\n  }\n_cleanup:\n  free(dict);\n  COVER_best_finish(data->best, parameters, selection);\n  free(data);\n  free(segmentFreqs);\n  COVER_dictSelectionFree(selection);\n  free(freqs);\n}\n\n\nstatic void\nFASTCOVER_convertToCoverParams(ZDICT_fastCover_params_t fastCoverParams,\n                               ZDICT_cover_params_t* coverParams)\n{\n    coverParams->k = fastCoverParams.k;\n    coverParams->d = fastCoverParams.d;\n    coverParams->steps = fastCoverParams.steps;\n    coverParams->nbThreads = fastCoverParams.nbThreads;\n    coverParams->splitPoint = fastCoverParams.splitPoint;\n    coverParams->zParams = fastCoverParams.zParams;\n    coverParams->shrinkDict = fastCoverParams.shrinkDict;\n}\n\n\nstatic void\nFASTCOVER_convertToFastCoverParams(ZDICT_cover_params_t coverParams,\n                                   ZDICT_fastCover_params_t* fastCoverParams,\n                                   unsigned f, unsigned accel)\n{\n    fastCoverParams->k = coverParams.k;\n    fastCoverParams->d = coverParams.d;\n    fastCoverParams->steps = coverParams.steps;\n    fastCoverParams->nbThreads = coverParams.nbThreads;\n    fastCoverParams->splitPoint = coverParams.splitPoint;\n    fastCoverParams->f = f;\n    fastCoverParams->accel = accel;\n    fastCoverParams->zParams = coverParams.zParams;\n    fastCoverParams->shrinkDict = coverParams.shrinkDict;\n}\n\n\nZDICTLIB_STATIC_API size_t\nZDICT_trainFromBuffer_fastCover(void* dictBuffer, size_t dictBufferCapacity,\n                                const void* samplesBuffer,\n                                const size_t* samplesSizes, unsigned nbSamples,\n                                ZDICT_fastCover_params_t parameters)\n{\n    BYTE* const dict = (BYTE*)dictBuffer;\n    FASTCOVER_ctx_t ctx;\n    ZDICT_cover_params_t coverParams;\n    FASTCOVER_accel_t accelParams;\n    const int displayLevel = (int)parameters.zParams.notificationLevel;\n    /* Assign splitPoint and f if not provided */\n    parameters.splitPoint = 1.0;\n    parameters.f = parameters.f == 0 ? DEFAULT_F : parameters.f;\n    parameters.accel = parameters.accel == 0 ? DEFAULT_ACCEL : parameters.accel;\n    /* Convert to cover parameter */\n    memset(&coverParams, 0 , sizeof(coverParams));\n    FASTCOVER_convertToCoverParams(parameters, &coverParams);\n    /* Checks */\n    if (!FASTCOVER_checkParameters(coverParams, dictBufferCapacity, parameters.f,\n                                   parameters.accel)) {\n      DISPLAYLEVEL(1, \"FASTCOVER parameters incorrect\\n\");\n      return ERROR(parameter_outOfBound);\n    }\n    if (nbSamples == 0) {\n      DISPLAYLEVEL(1, \"FASTCOVER must have at least one input file\\n\");\n      return ERROR(srcSize_wrong);\n    }\n    if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) {\n      DISPLAYLEVEL(1, \"dictBufferCapacity must be at least %u\\n\",\n                   ZDICT_DICTSIZE_MIN);\n      return ERROR(dstSize_tooSmall);\n    }\n    /* Assign corresponding FASTCOVER_accel_t to accelParams*/\n    accelParams = FASTCOVER_defaultAccelParameters[parameters.accel];\n    /* Initialize context */\n    {\n      size_t const initVal = FASTCOVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples,\n                            coverParams.d, parameters.splitPoint, parameters.f,\n                            accelParams, displayLevel);\n      if (ZSTD_isError(initVal)) {\n        DISPLAYLEVEL(1, \"Failed to initialize context\\n\");\n        return initVal;\n      }\n    }\n    COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.nbDmers, displayLevel);\n    /* Build the dictionary */\n    DISPLAYLEVEL(2, \"Building dictionary\\n\");\n    {\n      /* Initialize array to keep track of frequency of dmer within activeSegment */\n      U16* segmentFreqs = (U16 *)calloc(((U64)1 << parameters.f), sizeof(U16));\n      const size_t tail = FASTCOVER_buildDictionary(&ctx, ctx.freqs, dictBuffer,\n                                                dictBufferCapacity, coverParams, segmentFreqs);\n      const unsigned nbFinalizeSamples = (unsigned)(ctx.nbTrainSamples * ctx.accelParams.finalize / 100);\n      const size_t dictionarySize = ZDICT_finalizeDictionary(\n          dict, dictBufferCapacity, dict + tail, dictBufferCapacity - tail,\n          samplesBuffer, samplesSizes, nbFinalizeSamples, coverParams.zParams);\n      if (!ZSTD_isError(dictionarySize)) {\n          DISPLAYLEVEL(2, \"Constructed dictionary of size %u\\n\",\n                      (unsigned)dictionarySize);\n      }\n      FASTCOVER_ctx_destroy(&ctx);\n      free(segmentFreqs);\n      return dictionarySize;\n    }\n}\n\n\nZDICTLIB_STATIC_API size_t\nZDICT_optimizeTrainFromBuffer_fastCover(\n                    void* dictBuffer, size_t dictBufferCapacity,\n                    const void* samplesBuffer,\n                    const size_t* samplesSizes, unsigned nbSamples,\n                    ZDICT_fastCover_params_t* parameters)\n{\n    ZDICT_cover_params_t coverParams;\n    FASTCOVER_accel_t accelParams;\n    /* constants */\n    const unsigned nbThreads = parameters->nbThreads;\n    const double splitPoint =\n        parameters->splitPoint <= 0.0 ? FASTCOVER_DEFAULT_SPLITPOINT : parameters->splitPoint;\n    const unsigned kMinD = parameters->d == 0 ? 6 : parameters->d;\n    const unsigned kMaxD = parameters->d == 0 ? 8 : parameters->d;\n    const unsigned kMinK = parameters->k == 0 ? 50 : parameters->k;\n    const unsigned kMaxK = parameters->k == 0 ? 2000 : parameters->k;\n    const unsigned kSteps = parameters->steps == 0 ? 40 : parameters->steps;\n    const unsigned kStepSize = MAX((kMaxK - kMinK) / kSteps, 1);\n    const unsigned kIterations =\n        (1 + (kMaxD - kMinD) / 2) * (1 + (kMaxK - kMinK) / kStepSize);\n    const unsigned f = parameters->f == 0 ? DEFAULT_F : parameters->f;\n    const unsigned accel = parameters->accel == 0 ? DEFAULT_ACCEL : parameters->accel;\n    const unsigned shrinkDict = 0;\n    /* Local variables */\n    const int displayLevel = (int)parameters->zParams.notificationLevel;\n    unsigned iteration = 1;\n    unsigned d;\n    unsigned k;\n    COVER_best_t best;\n    POOL_ctx *pool = NULL;\n    int warned = 0;\n    clock_t lastUpdateTime = 0;\n    /* Checks */\n    if (splitPoint <= 0 || splitPoint > 1) {\n      DISPLAYLEVEL(1, \"Incorrect splitPoint\\n\");\n      return ERROR(parameter_outOfBound);\n    }\n    if (accel == 0 || accel > FASTCOVER_MAX_ACCEL) {\n      DISPLAYLEVEL(1, \"Incorrect accel\\n\");\n      return ERROR(parameter_outOfBound);\n    }\n    if (kMinK < kMaxD || kMaxK < kMinK) {\n      DISPLAYLEVEL(1, \"Incorrect k\\n\");\n      return ERROR(parameter_outOfBound);\n    }\n    if (nbSamples == 0) {\n      DISPLAYLEVEL(1, \"FASTCOVER must have at least one input file\\n\");\n      return ERROR(srcSize_wrong);\n    }\n    if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) {\n      DISPLAYLEVEL(1, \"dictBufferCapacity must be at least %u\\n\",\n                   ZDICT_DICTSIZE_MIN);\n      return ERROR(dstSize_tooSmall);\n    }\n    if (nbThreads > 1) {\n      pool = POOL_create(nbThreads, 1);\n      if (!pool) {\n        return ERROR(memory_allocation);\n      }\n    }\n    /* Initialization */\n    COVER_best_init(&best);\n    memset(&coverParams, 0 , sizeof(coverParams));\n    FASTCOVER_convertToCoverParams(*parameters, &coverParams);\n    accelParams = FASTCOVER_defaultAccelParameters[accel];\n    /* Loop through d first because each new value needs a new context */\n    DISPLAYLEVEL(2, \"Trying %u different sets of parameters\\n\", kIterations);\n    for (d = kMinD; d <= kMaxD; d += 2) {\n      /* Initialize the context for this value of d */\n      FASTCOVER_ctx_t ctx;\n      DISPLAYLEVEL(3, \"d=%u\\n\", d);\n      {\n        /* Turn down global display level to clean up display at level 2 and below */\n        const int childDisplayLevel = displayLevel == 0 ? 0 : displayLevel - 1;\n        size_t const initVal = FASTCOVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples, d, splitPoint, f, accelParams, childDisplayLevel);\n        if (ZSTD_isError(initVal)) {\n          DISPLAYLEVEL(1, \"Failed to initialize context\\n\");\n          COVER_best_destroy(&best);\n          POOL_free(pool);\n          return initVal;\n        }\n      }\n      if (!warned) {\n        COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.nbDmers, displayLevel);\n        warned = 1;\n      }\n      /* Loop through k reusing the same context */\n      for (k = kMinK; k <= kMaxK; k += kStepSize) {\n        /* Prepare the arguments */\n        FASTCOVER_tryParameters_data_t *data = (FASTCOVER_tryParameters_data_t *)malloc(\n            sizeof(FASTCOVER_tryParameters_data_t));\n        DISPLAYLEVEL(3, \"k=%u\\n\", k);\n        if (!data) {\n          DISPLAYLEVEL(1, \"Failed to allocate parameters\\n\");\n          COVER_best_destroy(&best);\n          FASTCOVER_ctx_destroy(&ctx);\n          POOL_free(pool);\n          return ERROR(memory_allocation);\n        }\n        data->ctx = &ctx;\n        data->best = &best;\n        data->dictBufferCapacity = dictBufferCapacity;\n        data->parameters = coverParams;\n        data->parameters.k = k;\n        data->parameters.d = d;\n        data->parameters.splitPoint = splitPoint;\n        data->parameters.steps = kSteps;\n        data->parameters.shrinkDict = shrinkDict;\n        data->parameters.zParams.notificationLevel = (unsigned)ctx.displayLevel;\n        /* Check the parameters */\n        if (!FASTCOVER_checkParameters(data->parameters, dictBufferCapacity,\n                                       data->ctx->f, accel)) {\n          DISPLAYLEVEL(1, \"FASTCOVER parameters incorrect\\n\");\n          free(data);\n          continue;\n        }\n        /* Call the function and pass ownership of data to it */\n        COVER_best_start(&best);\n        if (pool) {\n          POOL_add(pool, &FASTCOVER_tryParameters, data);\n        } else {\n          FASTCOVER_tryParameters(data);\n        }\n        /* Print status */\n        DISPLAYUPDATE(lastUpdateTime,\n                      2, \"\\r%u%%       \",\n                      (unsigned)((iteration * 100) / kIterations));\n        ++iteration;\n      }\n      COVER_best_wait(&best);\n      FASTCOVER_ctx_destroy(&ctx);\n    }\n    DISPLAYLEVEL(2, \"\\r%79s\\r\", \"\");\n    /* Fill the output buffer and parameters with output of the best parameters */\n    {\n      const size_t dictSize = best.dictSize;\n      if (ZSTD_isError(best.compressedSize)) {\n        const size_t compressedSize = best.compressedSize;\n        COVER_best_destroy(&best);\n        POOL_free(pool);\n        return compressedSize;\n      }\n      FASTCOVER_convertToFastCoverParams(best.parameters, parameters, f, accel);\n      memcpy(dictBuffer, best.dict, dictSize);\n      COVER_best_destroy(&best);\n      POOL_free(pool);\n      return dictSize;\n    }\n\n}\n"
  },
  {
    "path": "lib/dictBuilder/zdict.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/*-**************************************\n*  Tuning parameters\n****************************************/\n#define MINRATIO 4   /* minimum nb of apparition to be selected in dictionary */\n#define ZDICT_MAX_SAMPLES_SIZE (2000U << 20)\n#define ZDICT_MIN_SAMPLES_SIZE (ZDICT_CONTENTSIZE_MIN * MINRATIO)\n\n\n/*-**************************************\n*  Compiler Options\n****************************************/\n/* Unix Large Files support (>4GB) */\n#define _FILE_OFFSET_BITS 64\n#if (defined(__sun__) && (!defined(__LP64__)))   /* Sun Solaris 32-bits requires specific definitions */\n#  ifndef _LARGEFILE_SOURCE\n#  define _LARGEFILE_SOURCE\n#  endif\n#elif ! defined(__LP64__)                        /* No point defining Large file for 64 bit */\n#  ifndef _LARGEFILE64_SOURCE\n#  define _LARGEFILE64_SOURCE\n#  endif\n#endif\n\n\n/*-*************************************\n*  Dependencies\n***************************************/\n#include <stdlib.h>        /* malloc, free */\n#include <string.h>        /* memset */\n#include <stdio.h>         /* fprintf, fopen, ftello64 */\n#include <time.h>          /* clock */\n\n#ifndef ZDICT_STATIC_LINKING_ONLY\n#  define ZDICT_STATIC_LINKING_ONLY\n#endif\n\n#include \"../common/mem.h\"           /* read */\n#include \"../common/fse.h\"           /* FSE_normalizeCount, FSE_writeNCount */\n#include \"../common/huf.h\"           /* HUF_buildCTable, HUF_writeCTable */\n#include \"../common/zstd_internal.h\" /* includes zstd.h */\n#include \"../common/xxhash.h\"        /* XXH64 */\n#include \"../compress/zstd_compress_internal.h\" /* ZSTD_loadCEntropy() */\n#include \"../zdict.h\"\n#include \"divsufsort.h\"\n#include \"../common/bits.h\"          /* ZSTD_NbCommonBytes */\n\n\n/*-*************************************\n*  Constants\n***************************************/\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\n#define DICTLISTSIZE_DEFAULT 10000\n\n#define NOISELENGTH 32\n\nstatic const U32 g_selectivity_default = 9;\n\n\n/*-*************************************\n*  Console display\n***************************************/\n#undef  DISPLAY\n#define DISPLAY(...)         do { fprintf(stderr, __VA_ARGS__); fflush( stderr ); } while (0)\n#undef  DISPLAYLEVEL\n#define DISPLAYLEVEL(l, ...) do { if (notificationLevel>=l) { DISPLAY(__VA_ARGS__); } } while (0)    /* 0 : no display;   1: errors;   2: default;  3: details;  4: debug */\n\nstatic clock_t ZDICT_clockSpan(clock_t nPrevious) { return clock() - nPrevious; }\n\nstatic void ZDICT_printHex(const void* ptr, size_t length)\n{\n    const BYTE* const b = (const BYTE*)ptr;\n    size_t u;\n    for (u=0; u<length; u++) {\n        BYTE c = b[u];\n        if (c<32 || c>126) c = '.';   /* non-printable char */\n        DISPLAY(\"%c\", c);\n    }\n}\n\n\n/*-********************************************************\n*  Helper functions\n**********************************************************/\nunsigned ZDICT_isError(size_t errorCode) { return ERR_isError(errorCode); }\n\nconst char* ZDICT_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }\n\nunsigned ZDICT_getDictID(const void* dictBuffer, size_t dictSize)\n{\n    if (dictSize < 8) return 0;\n    if (MEM_readLE32(dictBuffer) != ZSTD_MAGIC_DICTIONARY) return 0;\n    return MEM_readLE32((const char*)dictBuffer + 4);\n}\n\nsize_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize)\n{\n    size_t headerSize;\n    if (dictSize <= 8 || MEM_readLE32(dictBuffer) != ZSTD_MAGIC_DICTIONARY) return ERROR(dictionary_corrupted);\n\n    {   ZSTD_compressedBlockState_t* bs = (ZSTD_compressedBlockState_t*)malloc(sizeof(ZSTD_compressedBlockState_t));\n        U32* wksp = (U32*)malloc(HUF_WORKSPACE_SIZE);\n        if (!bs || !wksp) {\n            headerSize = ERROR(memory_allocation);\n        } else {\n            ZSTD_reset_compressedBlockState(bs);\n            headerSize = ZSTD_loadCEntropy(bs, wksp, dictBuffer, dictSize);\n        }\n\n        free(bs);\n        free(wksp);\n    }\n\n    return headerSize;\n}\n\n/*-********************************************************\n*  Dictionary training functions\n**********************************************************/\n/*! ZDICT_count() :\n    Count the nb of common bytes between 2 pointers.\n    Note : this function presumes end of buffer followed by noisy guard band.\n*/\nstatic size_t ZDICT_count(const void* pIn, const void* pMatch)\n{\n    const char* const pStart = (const char*)pIn;\n    for (;;) {\n        size_t const diff = MEM_readST(pMatch) ^ MEM_readST(pIn);\n        if (!diff) {\n            pIn = (const char*)pIn+sizeof(size_t);\n            pMatch = (const char*)pMatch+sizeof(size_t);\n            continue;\n        }\n        pIn = (const char*)pIn+ZSTD_NbCommonBytes(diff);\n        return (size_t)((const char*)pIn - pStart);\n    }\n}\n\n\ntypedef struct {\n    U32 pos;\n    U32 length;\n    U32 savings;\n} dictItem;\n\nstatic void ZDICT_initDictItem(dictItem* d)\n{\n    d->pos = 1;\n    d->length = 0;\n    d->savings = (U32)(-1);\n}\n\n\n#define LLIMIT 64          /* heuristic determined experimentally */\n#define MINMATCHLENGTH 7   /* heuristic determined experimentally */\nstatic dictItem ZDICT_analyzePos(\n                       BYTE* doneMarks,\n                       const unsigned* suffix, U32 start,\n                       const void* buffer, U32 minRatio, U32 notificationLevel)\n{\n    U32 lengthList[LLIMIT] = {0};\n    U32 cumulLength[LLIMIT] = {0};\n    U32 savings[LLIMIT] = {0};\n    const BYTE* b = (const BYTE*)buffer;\n    size_t maxLength = LLIMIT;\n    size_t pos = (size_t)suffix[start];\n    U32 end = start;\n    dictItem solution;\n\n    /* init */\n    memset(&solution, 0, sizeof(solution));\n    doneMarks[pos] = 1;\n\n    /* trivial repetition cases */\n    if ( (MEM_read16(b+pos+0) == MEM_read16(b+pos+2))\n       ||(MEM_read16(b+pos+1) == MEM_read16(b+pos+3))\n       ||(MEM_read16(b+pos+2) == MEM_read16(b+pos+4)) ) {\n        /* skip and mark segment */\n        U16 const pattern16 = MEM_read16(b+pos+4);\n        U32 u, patternEnd = 6;\n        while (MEM_read16(b+pos+patternEnd) == pattern16) patternEnd+=2 ;\n        if (b[pos+patternEnd] == b[pos+patternEnd-1]) patternEnd++;\n        for (u=1; u<patternEnd; u++)\n            doneMarks[pos+u] = 1;\n        return solution;\n    }\n\n    /* look forward */\n    {   size_t length;\n        do {\n            end++;\n            length = ZDICT_count(b + pos, b + suffix[end]);\n        } while (length >= MINMATCHLENGTH);\n    }\n\n    /* look backward */\n    {   size_t length;\n        do {\n            length = ZDICT_count(b + pos, b + *(suffix+start-1));\n            if (length >=MINMATCHLENGTH) start--;\n        } while(length >= MINMATCHLENGTH);\n    }\n\n    /* exit if not found a minimum nb of repetitions */\n    if (end-start < minRatio) {\n        U32 idx;\n        for(idx=start; idx<end; idx++)\n            doneMarks[suffix[idx]] = 1;\n        return solution;\n    }\n\n    {   int i;\n        U32 mml;\n        U32 refinedStart = start;\n        U32 refinedEnd = end;\n\n        DISPLAYLEVEL(4, \"\\n\");\n        DISPLAYLEVEL(4, \"found %3u matches of length >= %i at pos %7u  \", (unsigned)(end-start), MINMATCHLENGTH, (unsigned)pos);\n        DISPLAYLEVEL(4, \"\\n\");\n\n        for (mml = MINMATCHLENGTH ; ; mml++) {\n            BYTE currentChar = 0;\n            U32 currentCount = 0;\n            U32 currentID = refinedStart;\n            U32 id;\n            U32 selectedCount = 0;\n            U32 selectedID = currentID;\n            for (id =refinedStart; id < refinedEnd; id++) {\n                if (b[suffix[id] + mml] != currentChar) {\n                    if (currentCount > selectedCount) {\n                        selectedCount = currentCount;\n                        selectedID = currentID;\n                    }\n                    currentID = id;\n                    currentChar = b[ suffix[id] + mml];\n                    currentCount = 0;\n                }\n                currentCount ++;\n            }\n            if (currentCount > selectedCount) {  /* for last */\n                selectedCount = currentCount;\n                selectedID = currentID;\n            }\n\n            if (selectedCount < minRatio)\n                break;\n            refinedStart = selectedID;\n            refinedEnd = refinedStart + selectedCount;\n        }\n\n        /* evaluate gain based on new dict */\n        start = refinedStart;\n        pos = suffix[refinedStart];\n        end = start;\n        memset(lengthList, 0, sizeof(lengthList));\n\n        /* look forward */\n        {   size_t length;\n            do {\n                end++;\n                length = ZDICT_count(b + pos, b + suffix[end]);\n                if (length >= LLIMIT) length = LLIMIT-1;\n                lengthList[length]++;\n            } while (length >=MINMATCHLENGTH);\n        }\n\n        /* look backward */\n        {   size_t length = MINMATCHLENGTH;\n            while ((length >= MINMATCHLENGTH) & (start > 0)) {\n                length = ZDICT_count(b + pos, b + suffix[start - 1]);\n                if (length >= LLIMIT) length = LLIMIT - 1;\n                lengthList[length]++;\n                if (length >= MINMATCHLENGTH) start--;\n            }\n        }\n\n        /* largest useful length */\n        memset(cumulLength, 0, sizeof(cumulLength));\n        cumulLength[maxLength-1] = lengthList[maxLength-1];\n        for (i=(int)(maxLength-2); i>=0; i--)\n            cumulLength[i] = cumulLength[i+1] + lengthList[i];\n\n        {   unsigned u;\n            for (u=LLIMIT-1; u>=MINMATCHLENGTH; u--) if (cumulLength[u]>=minRatio) break;\n            maxLength = u;\n        }\n\n        /* reduce maxLength in case of final into repetitive data */\n        {   U32 l = (U32)maxLength;\n            BYTE const c = b[pos + maxLength-1];\n            while (b[pos+l-2]==c) l--;\n            maxLength = l;\n        }\n        if (maxLength < MINMATCHLENGTH) return solution;   /* skip : no long-enough solution */\n\n        /* calculate savings */\n        savings[5] = 0;\n        {   unsigned u;\n            for (u=MINMATCHLENGTH; u<=maxLength; u++)\n                savings[u] = savings[u-1] + (lengthList[u] * (u-3));\n        }\n\n        DISPLAYLEVEL(4, \"Selected dict at position %u, of length %u : saves %u (ratio: %.2f)  \\n\",\n                     (unsigned)pos, (unsigned)maxLength, (unsigned)savings[maxLength], (double)savings[maxLength] / (double)maxLength);\n\n        solution.pos = (U32)pos;\n        solution.length = (U32)maxLength;\n        solution.savings = savings[maxLength];\n\n        /* mark positions done */\n        {   U32 id;\n            for (id=start; id<end; id++) {\n                U32 p, pEnd, length;\n                U32 const testedPos = (U32)suffix[id];\n                if (testedPos == pos)\n                    length = solution.length;\n                else {\n                    length = (U32)ZDICT_count(b+pos, b+testedPos);\n                    if (length > solution.length) length = solution.length;\n                }\n                pEnd = (U32)(testedPos + length);\n                for (p=testedPos; p<pEnd; p++)\n                    doneMarks[p] = 1;\n    }   }   }\n\n    return solution;\n}\n\n\nstatic int isIncluded(const void* in, const void* container, size_t length)\n{\n    const char* const ip = (const char*) in;\n    const char* const into = (const char*) container;\n    size_t u;\n\n    for (u=0; u<length; u++) {  /* works because end of buffer is a noisy guard band */\n        if (ip[u] != into[u]) break;\n    }\n\n    return u==length;\n}\n\n/*! ZDICT_tryMerge() :\n    check if dictItem can be merged, do it if possible\n    @return : id of destination elt, 0 if not merged\n*/\nstatic U32 ZDICT_tryMerge(dictItem* table, dictItem elt, U32 eltNbToSkip, const void* buffer)\n{\n    const U32 tableSize = table->pos;\n    const U32 eltEnd = elt.pos + elt.length;\n    const char* const buf = (const char*) buffer;\n\n    /* tail overlap */\n    U32 u; for (u=1; u<tableSize; u++) {\n        if (u==eltNbToSkip) continue;\n        if ((table[u].pos > elt.pos) && (table[u].pos <= eltEnd)) {  /* overlap, existing > new */\n            /* append */\n            U32 const addedLength = table[u].pos - elt.pos;\n            table[u].length += addedLength;\n            table[u].pos = elt.pos;\n            table[u].savings += elt.savings * addedLength / elt.length;   /* rough approx */\n            table[u].savings += elt.length / 8;    /* rough approx bonus */\n            elt = table[u];\n            /* sort : improve rank */\n            while ((u>1) && (table[u-1].savings < elt.savings))\n                table[u] = table[u-1], u--;\n            table[u] = elt;\n            return u;\n    }   }\n\n    /* front overlap */\n    for (u=1; u<tableSize; u++) {\n        if (u==eltNbToSkip) continue;\n\n        if ((table[u].pos + table[u].length >= elt.pos) && (table[u].pos < elt.pos)) {  /* overlap, existing < new */\n            /* append */\n            int const addedLength = (int)eltEnd - (int)(table[u].pos + table[u].length); /* note: can be negative */\n            table[u].savings += elt.length / 8;    /* rough approx bonus */\n            if (addedLength > 0) {   /* otherwise, elt fully included into existing */\n                table[u].length += (unsigned)addedLength;\n                table[u].savings += elt.savings * (unsigned)addedLength / elt.length;   /* rough approx */\n            }\n            /* sort : improve rank */\n            elt = table[u];\n            while ((u>1) && (table[u-1].savings < elt.savings))\n                table[u] = table[u-1], u--;\n            table[u] = elt;\n            return u;\n        }\n\n        if (MEM_read64(buf + table[u].pos) == MEM_read64(buf + elt.pos + 1)) {\n            if (isIncluded(buf + table[u].pos, buf + elt.pos + 1, table[u].length)) {\n                size_t const addedLength = MAX( elt.length - table[u].length , 1 );\n                table[u].pos = elt.pos;\n                table[u].savings += (U32)(elt.savings * addedLength / elt.length);\n                table[u].length = MIN(elt.length, table[u].length + 1);\n                return u;\n            }\n        }\n    }\n\n    return 0;\n}\n\n\nstatic void ZDICT_removeDictItem(dictItem* table, U32 id)\n{\n    /* convention : table[0].pos stores nb of elts */\n    U32 const max = table[0].pos;\n    U32 u;\n    if (!id) return;   /* protection, should never happen */\n    for (u=id; u<max-1; u++)\n        table[u] = table[u+1];\n    table->pos--;\n}\n\n\nstatic void ZDICT_insertDictItem(dictItem* table, U32 maxSize, dictItem elt, const void* buffer)\n{\n    /* merge if possible */\n    U32 mergeId = ZDICT_tryMerge(table, elt, 0, buffer);\n    if (mergeId) {\n        U32 newMerge = 1;\n        while (newMerge) {\n            newMerge = ZDICT_tryMerge(table, table[mergeId], mergeId, buffer);\n            if (newMerge) ZDICT_removeDictItem(table, mergeId);\n            mergeId = newMerge;\n        }\n        return;\n    }\n\n    /* insert */\n    {   U32 current;\n        U32 nextElt = table->pos;\n        if (nextElt >= maxSize) nextElt = maxSize-1;\n        current = nextElt-1;\n        while (table[current].savings < elt.savings) {\n            table[current+1] = table[current];\n            current--;\n        }\n        table[current+1] = elt;\n        table->pos = nextElt+1;\n    }\n}\n\n\nstatic U32 ZDICT_dictSize(const dictItem* dictList)\n{\n    U32 u, dictSize = 0;\n    for (u=1; u<dictList[0].pos; u++)\n        dictSize += dictList[u].length;\n    return dictSize;\n}\n\n\nstatic size_t ZDICT_trainBuffer_legacy(dictItem* dictList, U32 dictListSize,\n                            const void* const buffer, size_t bufferSize,   /* buffer must end with noisy guard band */\n                            const size_t* fileSizes, unsigned nbFiles,\n                            unsigned minRatio, U32 notificationLevel)\n{\n    unsigned* const suffix0 = (unsigned*)malloc((bufferSize+2)*sizeof(*suffix0));\n    unsigned* const suffix = suffix0+1;\n    U32* reverseSuffix = (U32*)malloc((bufferSize)*sizeof(*reverseSuffix));\n    BYTE* doneMarks = (BYTE*)malloc((bufferSize+16)*sizeof(*doneMarks));   /* +16 for overflow security */\n    U32* filePos = (U32*)malloc(nbFiles * sizeof(*filePos));\n    size_t result = 0;\n    clock_t displayClock = 0;\n    clock_t const refreshRate = CLOCKS_PER_SEC * 3 / 10;\n\n#   undef  DISPLAYUPDATE\n#   define DISPLAYUPDATE(l, ...)                                   \\\n        do {                                                       \\\n            if (notificationLevel>=l) {                            \\\n                if (ZDICT_clockSpan(displayClock) > refreshRate) { \\\n                    displayClock = clock();                        \\\n                    DISPLAY(__VA_ARGS__);                          \\\n                }                                                  \\\n                if (notificationLevel>=4) fflush(stderr);          \\\n            }                                                      \\\n        } while (0)\n\n    /* init */\n    DISPLAYLEVEL(2, \"\\r%70s\\r\", \"\");   /* clean display line */\n    if (!suffix0 || !reverseSuffix || !doneMarks || !filePos) {\n        result = ERROR(memory_allocation);\n        goto _cleanup;\n    }\n    if (minRatio < MINRATIO) minRatio = MINRATIO;\n    memset(doneMarks, 0, bufferSize+16);\n\n    /* limit sample set size (divsufsort limitation)*/\n    if (bufferSize > ZDICT_MAX_SAMPLES_SIZE) DISPLAYLEVEL(3, \"sample set too large : reduced to %u MB ...\\n\", (unsigned)(ZDICT_MAX_SAMPLES_SIZE>>20));\n    while (bufferSize > ZDICT_MAX_SAMPLES_SIZE) bufferSize -= fileSizes[--nbFiles];\n\n    /* sort */\n    DISPLAYLEVEL(2, \"sorting %u files of total size %u MB ...\\n\", nbFiles, (unsigned)(bufferSize>>20));\n    {   int const divSuftSortResult = divsufsort((const unsigned char*)buffer, (int*)suffix, (int)bufferSize, 0);\n        if (divSuftSortResult != 0) { result = ERROR(GENERIC); goto _cleanup; }\n    }\n    suffix[bufferSize] = (unsigned)bufferSize;   /* leads into noise */\n    suffix0[0] = (unsigned)bufferSize;           /* leads into noise */\n    /* build reverse suffix sort */\n    {   size_t pos;\n        for (pos=0; pos < bufferSize; pos++)\n            reverseSuffix[suffix[pos]] = (U32)pos;\n        /* note filePos tracks borders between samples.\n           It's not used at this stage, but planned to become useful in a later update */\n        filePos[0] = 0;\n        for (pos=1; pos<nbFiles; pos++)\n            filePos[pos] = (U32)(filePos[pos-1] + fileSizes[pos-1]);\n    }\n\n    DISPLAYLEVEL(2, \"finding patterns ... \\n\");\n    DISPLAYLEVEL(3, \"minimum ratio : %u \\n\", minRatio);\n\n    {   U32 cursor; for (cursor=0; cursor < bufferSize; ) {\n            dictItem solution;\n            if (doneMarks[cursor]) { cursor++; continue; }\n            solution = ZDICT_analyzePos(doneMarks, suffix, reverseSuffix[cursor], buffer, minRatio, notificationLevel);\n            if (solution.length==0) { cursor++; continue; }\n            ZDICT_insertDictItem(dictList, dictListSize, solution, buffer);\n            cursor += solution.length;\n            DISPLAYUPDATE(2, \"\\r%4.2f %% \\r\", (double)cursor / (double)bufferSize * 100.0);\n    }   }\n\n_cleanup:\n    free(suffix0);\n    free(reverseSuffix);\n    free(doneMarks);\n    free(filePos);\n    return result;\n}\n\n\nstatic void ZDICT_fillNoise(void* buffer, size_t length)\n{\n    unsigned const prime1 = 2654435761U;\n    unsigned const prime2 = 2246822519U;\n    unsigned acc = prime1;\n    size_t p=0;\n    for (p=0; p<length; p++) {\n        acc *= prime2;\n        ((unsigned char*)buffer)[p] = (unsigned char)(acc >> 21);\n    }\n}\n\n\ntypedef struct\n{\n    ZSTD_CDict* dict;    /* dictionary */\n    ZSTD_CCtx* zc;     /* working context */\n    void* workPlace;   /* must be ZSTD_BLOCKSIZE_MAX allocated */\n} EStats_ress_t;\n\n#define MAXREPOFFSET 1024\n\nstatic void ZDICT_countEStats(EStats_ress_t esr, const ZSTD_parameters* params,\n                              unsigned* countLit, unsigned* offsetcodeCount, unsigned* matchlengthCount, unsigned* litlengthCount, U32* repOffsets,\n                              const void* src, size_t srcSize,\n                              U32 notificationLevel)\n{\n    size_t const blockSizeMax = MIN (ZSTD_BLOCKSIZE_MAX, 1 << params->cParams.windowLog);\n    size_t cSize;\n\n    if (srcSize > blockSizeMax) srcSize = blockSizeMax;   /* protection vs large samples */\n    {   size_t const errorCode = ZSTD_compressBegin_usingCDict_deprecated(esr.zc, esr.dict);\n        if (ZSTD_isError(errorCode)) { DISPLAYLEVEL(1, \"warning : ZSTD_compressBegin_usingCDict failed \\n\"); return; }\n\n    }\n    cSize = ZSTD_compressBlock_deprecated(esr.zc, esr.workPlace, ZSTD_BLOCKSIZE_MAX, src, srcSize);\n    if (ZSTD_isError(cSize)) { DISPLAYLEVEL(3, \"warning : could not compress sample size %u \\n\", (unsigned)srcSize); return; }\n\n    if (cSize) {  /* if == 0; block is not compressible */\n        const SeqStore_t* const seqStorePtr = ZSTD_getSeqStore(esr.zc);\n\n        /* literals stats */\n        {   const BYTE* bytePtr;\n            for(bytePtr = seqStorePtr->litStart; bytePtr < seqStorePtr->lit; bytePtr++)\n                countLit[*bytePtr]++;\n        }\n\n        /* seqStats */\n        {   U32 const nbSeq = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);\n            ZSTD_seqToCodes(seqStorePtr);\n\n            {   const BYTE* codePtr = seqStorePtr->ofCode;\n                U32 u;\n                for (u=0; u<nbSeq; u++) offsetcodeCount[codePtr[u]]++;\n            }\n\n            {   const BYTE* codePtr = seqStorePtr->mlCode;\n                U32 u;\n                for (u=0; u<nbSeq; u++) matchlengthCount[codePtr[u]]++;\n            }\n\n            {   const BYTE* codePtr = seqStorePtr->llCode;\n                U32 u;\n                for (u=0; u<nbSeq; u++) litlengthCount[codePtr[u]]++;\n            }\n\n            if (nbSeq >= 2) { /* rep offsets */\n                const SeqDef* const seq = seqStorePtr->sequencesStart;\n                U32 offset1 = seq[0].offBase - ZSTD_REP_NUM;\n                U32 offset2 = seq[1].offBase - ZSTD_REP_NUM;\n                if (offset1 >= MAXREPOFFSET) offset1 = 0;\n                if (offset2 >= MAXREPOFFSET) offset2 = 0;\n                repOffsets[offset1] += 3;\n                repOffsets[offset2] += 1;\n    }   }   }\n}\n\nstatic size_t ZDICT_totalSampleSize(const size_t* fileSizes, unsigned nbFiles)\n{\n    size_t total=0;\n    unsigned u;\n    for (u=0; u<nbFiles; u++) total += fileSizes[u];\n    return total;\n}\n\ntypedef struct { U32 offset; U32 count; } offsetCount_t;\n\nstatic void ZDICT_insertSortCount(offsetCount_t table[ZSTD_REP_NUM+1], U32 val, U32 count)\n{\n    U32 u;\n    table[ZSTD_REP_NUM].offset = val;\n    table[ZSTD_REP_NUM].count = count;\n    for (u=ZSTD_REP_NUM; u>0; u--) {\n        offsetCount_t tmp;\n        if (table[u-1].count >= table[u].count) break;\n        tmp = table[u-1];\n        table[u-1] = table[u];\n        table[u] = tmp;\n    }\n}\n\n/* ZDICT_flatLit() :\n * rewrite `countLit` to contain a mostly flat but still compressible distribution of literals.\n * necessary to avoid generating a non-compressible distribution that HUF_writeCTable() cannot encode.\n */\nstatic void ZDICT_flatLit(unsigned* countLit)\n{\n    int u;\n    for (u=1; u<256; u++) countLit[u] = 2;\n    countLit[0]   = 4;\n    countLit[253] = 1;\n    countLit[254] = 1;\n}\n\n#define OFFCODE_MAX 30  /* only applicable to first block */\nstatic size_t ZDICT_analyzeEntropy(void*  dstBuffer, size_t maxDstSize,\n                                   int compressionLevel,\n                             const void*  srcBuffer, const size_t* fileSizes, unsigned nbFiles,\n                             const void* dictBuffer, size_t  dictBufferSize,\n                                   unsigned notificationLevel)\n{\n    unsigned countLit[256];\n    HUF_CREATE_STATIC_CTABLE(hufTable, 255);\n    unsigned offcodeCount[OFFCODE_MAX+1];\n    short offcodeNCount[OFFCODE_MAX+1];\n    U32 offcodeMax = ZSTD_highbit32((U32)(dictBufferSize + 128 KB));\n    unsigned matchLengthCount[MaxML+1];\n    short matchLengthNCount[MaxML+1];\n    unsigned litLengthCount[MaxLL+1];\n    short litLengthNCount[MaxLL+1];\n    U32 repOffset[MAXREPOFFSET];\n    offsetCount_t bestRepOffset[ZSTD_REP_NUM+1];\n    EStats_ress_t esr = { NULL, NULL, NULL };\n    ZSTD_parameters params;\n    U32 u, huffLog = 11, Offlog = OffFSELog, mlLog = MLFSELog, llLog = LLFSELog, total;\n    size_t pos = 0, errorCode;\n    size_t eSize = 0;\n    size_t const totalSrcSize = ZDICT_totalSampleSize(fileSizes, nbFiles);\n    size_t const averageSampleSize = totalSrcSize / (nbFiles + !nbFiles);\n    BYTE* dstPtr = (BYTE*)dstBuffer;\n    U32 wksp[HUF_CTABLE_WORKSPACE_SIZE_U32];\n\n    /* init */\n    DEBUGLOG(4, \"ZDICT_analyzeEntropy\");\n    if (offcodeMax>OFFCODE_MAX) { eSize = ERROR(dictionaryCreation_failed); goto _cleanup; }   /* too large dictionary */\n    for (u=0; u<256; u++) countLit[u] = 1;   /* any character must be described */\n    for (u=0; u<=offcodeMax; u++) offcodeCount[u] = 1;\n    for (u=0; u<=MaxML; u++) matchLengthCount[u] = 1;\n    for (u=0; u<=MaxLL; u++) litLengthCount[u] = 1;\n    memset(repOffset, 0, sizeof(repOffset));\n    repOffset[1] = repOffset[4] = repOffset[8] = 1;\n    memset(bestRepOffset, 0, sizeof(bestRepOffset));\n    if (compressionLevel==0) compressionLevel = ZSTD_CLEVEL_DEFAULT;\n    params = ZSTD_getParams(compressionLevel, averageSampleSize, dictBufferSize);\n\n    esr.dict = ZSTD_createCDict_advanced(dictBuffer, dictBufferSize, ZSTD_dlm_byRef, ZSTD_dct_rawContent, params.cParams, ZSTD_defaultCMem);\n    esr.zc = ZSTD_createCCtx();\n    esr.workPlace = malloc(ZSTD_BLOCKSIZE_MAX);\n    if (!esr.dict || !esr.zc || !esr.workPlace) {\n        eSize = ERROR(memory_allocation);\n        DISPLAYLEVEL(1, \"Not enough memory \\n\");\n        goto _cleanup;\n    }\n\n    /* collect stats on all samples */\n    for (u=0; u<nbFiles; u++) {\n        ZDICT_countEStats(esr, &params,\n                          countLit, offcodeCount, matchLengthCount, litLengthCount, repOffset,\n                         (const char*)srcBuffer + pos, fileSizes[u],\n                          notificationLevel);\n        pos += fileSizes[u];\n    }\n\n    if (notificationLevel >= 4) {\n        /* writeStats */\n        DISPLAYLEVEL(4, \"Offset Code Frequencies : \\n\");\n        for (u=0; u<=offcodeMax; u++) {\n            DISPLAYLEVEL(4, \"%2u :%7u \\n\", u, offcodeCount[u]);\n    }   }\n\n    /* analyze, build stats, starting with literals */\n    {   size_t maxNbBits = HUF_buildCTable_wksp(hufTable, countLit, 255, huffLog, wksp, sizeof(wksp));\n        if (HUF_isError(maxNbBits)) {\n            eSize = maxNbBits;\n            DISPLAYLEVEL(1, \" HUF_buildCTable error \\n\");\n            goto _cleanup;\n        }\n        if (maxNbBits==8) {  /* not compressible : will fail on HUF_writeCTable() */\n            DISPLAYLEVEL(2, \"warning : pathological dataset : literals are not compressible : samples are noisy or too regular \\n\");\n            ZDICT_flatLit(countLit);  /* replace distribution by a fake \"mostly flat but still compressible\" distribution, that HUF_writeCTable() can encode */\n            maxNbBits = HUF_buildCTable_wksp(hufTable, countLit, 255, huffLog, wksp, sizeof(wksp));\n            assert(maxNbBits==9);\n        }\n        huffLog = (U32)maxNbBits;\n    }\n\n    /* looking for most common first offsets */\n    {   U32 offset;\n        for (offset=1; offset<MAXREPOFFSET; offset++)\n            ZDICT_insertSortCount(bestRepOffset, offset, repOffset[offset]);\n    }\n    /* note : the result of this phase should be used to better appreciate the impact on statistics */\n\n    total=0; for (u=0; u<=offcodeMax; u++) total+=offcodeCount[u];\n    errorCode = FSE_normalizeCount(offcodeNCount, Offlog, offcodeCount, total, offcodeMax, /* useLowProbCount */ 1);\n    if (FSE_isError(errorCode)) {\n        eSize = errorCode;\n        DISPLAYLEVEL(1, \"FSE_normalizeCount error with offcodeCount \\n\");\n        goto _cleanup;\n    }\n    Offlog = (U32)errorCode;\n\n    total=0; for (u=0; u<=MaxML; u++) total+=matchLengthCount[u];\n    errorCode = FSE_normalizeCount(matchLengthNCount, mlLog, matchLengthCount, total, MaxML, /* useLowProbCount */ 1);\n    if (FSE_isError(errorCode)) {\n        eSize = errorCode;\n        DISPLAYLEVEL(1, \"FSE_normalizeCount error with matchLengthCount \\n\");\n        goto _cleanup;\n    }\n    mlLog = (U32)errorCode;\n\n    total=0; for (u=0; u<=MaxLL; u++) total+=litLengthCount[u];\n    errorCode = FSE_normalizeCount(litLengthNCount, llLog, litLengthCount, total, MaxLL, /* useLowProbCount */ 1);\n    if (FSE_isError(errorCode)) {\n        eSize = errorCode;\n        DISPLAYLEVEL(1, \"FSE_normalizeCount error with litLengthCount \\n\");\n        goto _cleanup;\n    }\n    llLog = (U32)errorCode;\n\n    /* write result to buffer */\n    {   size_t const hhSize = HUF_writeCTable_wksp(dstPtr, maxDstSize, hufTable, 255, huffLog, wksp, sizeof(wksp));\n        if (HUF_isError(hhSize)) {\n            eSize = hhSize;\n            DISPLAYLEVEL(1, \"HUF_writeCTable error \\n\");\n            goto _cleanup;\n        }\n        dstPtr += hhSize;\n        maxDstSize -= hhSize;\n        eSize += hhSize;\n    }\n\n    {   size_t const ohSize = FSE_writeNCount(dstPtr, maxDstSize, offcodeNCount, OFFCODE_MAX, Offlog);\n        if (FSE_isError(ohSize)) {\n            eSize = ohSize;\n            DISPLAYLEVEL(1, \"FSE_writeNCount error with offcodeNCount \\n\");\n            goto _cleanup;\n        }\n        dstPtr += ohSize;\n        maxDstSize -= ohSize;\n        eSize += ohSize;\n    }\n\n    {   size_t const mhSize = FSE_writeNCount(dstPtr, maxDstSize, matchLengthNCount, MaxML, mlLog);\n        if (FSE_isError(mhSize)) {\n            eSize = mhSize;\n            DISPLAYLEVEL(1, \"FSE_writeNCount error with matchLengthNCount \\n\");\n            goto _cleanup;\n        }\n        dstPtr += mhSize;\n        maxDstSize -= mhSize;\n        eSize += mhSize;\n    }\n\n    {   size_t const lhSize = FSE_writeNCount(dstPtr, maxDstSize, litLengthNCount, MaxLL, llLog);\n        if (FSE_isError(lhSize)) {\n            eSize = lhSize;\n            DISPLAYLEVEL(1, \"FSE_writeNCount error with litlengthNCount \\n\");\n            goto _cleanup;\n        }\n        dstPtr += lhSize;\n        maxDstSize -= lhSize;\n        eSize += lhSize;\n    }\n\n    if (maxDstSize<12) {\n        eSize = ERROR(dstSize_tooSmall);\n        DISPLAYLEVEL(1, \"not enough space to write RepOffsets \\n\");\n        goto _cleanup;\n    }\n# if 0\n    MEM_writeLE32(dstPtr+0, bestRepOffset[0].offset);\n    MEM_writeLE32(dstPtr+4, bestRepOffset[1].offset);\n    MEM_writeLE32(dstPtr+8, bestRepOffset[2].offset);\n#else\n    /* at this stage, we don't use the result of \"most common first offset\",\n     * as the impact of statistics is not properly evaluated */\n    MEM_writeLE32(dstPtr+0, repStartValue[0]);\n    MEM_writeLE32(dstPtr+4, repStartValue[1]);\n    MEM_writeLE32(dstPtr+8, repStartValue[2]);\n#endif\n    eSize += 12;\n\n_cleanup:\n    ZSTD_freeCDict(esr.dict);\n    ZSTD_freeCCtx(esr.zc);\n    free(esr.workPlace);\n\n    return eSize;\n}\n\n\n/**\n * @returns the maximum repcode value\n */\nstatic U32 ZDICT_maxRep(U32 const reps[ZSTD_REP_NUM])\n{\n    U32 maxRep = reps[0];\n    int r;\n    for (r = 1; r < ZSTD_REP_NUM; ++r)\n        maxRep = MAX(maxRep, reps[r]);\n    return maxRep;\n}\n\nsize_t ZDICT_finalizeDictionary(void* dictBuffer, size_t dictBufferCapacity,\n                          const void* customDictContent, size_t dictContentSize,\n                          const void* samplesBuffer, const size_t* samplesSizes,\n                          unsigned nbSamples, ZDICT_params_t params)\n{\n    size_t hSize;\n#define HBUFFSIZE 256   /* should prove large enough for all entropy headers */\n    BYTE header[HBUFFSIZE];\n    int const compressionLevel = (params.compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : params.compressionLevel;\n    U32 const notificationLevel = params.notificationLevel;\n    /* The final dictionary content must be at least as large as the largest repcode */\n    size_t const minContentSize = (size_t)ZDICT_maxRep(repStartValue);\n    size_t paddingSize;\n\n    /* check conditions */\n    DEBUGLOG(4, \"ZDICT_finalizeDictionary\");\n    if (dictBufferCapacity < dictContentSize) return ERROR(dstSize_tooSmall);\n    if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) return ERROR(dstSize_tooSmall);\n\n    /* dictionary header */\n    MEM_writeLE32(header, ZSTD_MAGIC_DICTIONARY);\n    {   U64 const randomID = XXH64(customDictContent, dictContentSize, 0);\n        U32 const compliantID = (randomID % ((1U<<31)-32768)) + 32768;\n        U32 const dictID = params.dictID ? params.dictID : compliantID;\n        MEM_writeLE32(header+4, dictID);\n    }\n    hSize = 8;\n\n    /* entropy tables */\n    DISPLAYLEVEL(2, \"\\r%70s\\r\", \"\");   /* clean display line */\n    DISPLAYLEVEL(2, \"statistics ... \\n\");\n    {   size_t const eSize = ZDICT_analyzeEntropy(header+hSize, HBUFFSIZE-hSize,\n                                  compressionLevel,\n                                  samplesBuffer, samplesSizes, nbSamples,\n                                  customDictContent, dictContentSize,\n                                  notificationLevel);\n        if (ZDICT_isError(eSize)) return eSize;\n        hSize += eSize;\n    }\n\n    /* Shrink the content size if it doesn't fit in the buffer */\n    if (hSize + dictContentSize > dictBufferCapacity) {\n        dictContentSize = dictBufferCapacity - hSize;\n    }\n\n    /* Pad the dictionary content with zeros if it is too small */\n    if (dictContentSize < minContentSize) {\n        RETURN_ERROR_IF(hSize + minContentSize > dictBufferCapacity, dstSize_tooSmall,\n                        \"dictBufferCapacity too small to fit max repcode\");\n        paddingSize = minContentSize - dictContentSize;\n    } else {\n        paddingSize = 0;\n    }\n\n    {\n        size_t const dictSize = hSize + paddingSize + dictContentSize;\n\n        /* The dictionary consists of the header, optional padding, and the content.\n         * The padding comes before the content because the \"best\" position in the\n         * dictionary is the last byte.\n         */\n        BYTE* const outDictHeader = (BYTE*)dictBuffer;\n        BYTE* const outDictPadding = outDictHeader + hSize;\n        BYTE* const outDictContent = outDictPadding + paddingSize;\n\n        assert(dictSize <= dictBufferCapacity);\n        assert(outDictContent + dictContentSize == (BYTE*)dictBuffer + dictSize);\n\n        /* First copy the customDictContent into its final location.\n         * `customDictContent` and `dictBuffer` may overlap, so we must\n         * do this before any other writes into the output buffer.\n         * Then copy the header & padding into the output buffer.\n         */\n        memmove(outDictContent, customDictContent, dictContentSize);\n        memcpy(outDictHeader, header, hSize);\n        memset(outDictPadding, 0, paddingSize);\n\n        return dictSize;\n    }\n}\n\n\nstatic size_t ZDICT_addEntropyTablesFromBuffer_advanced(\n        void* dictBuffer, size_t dictContentSize, size_t dictBufferCapacity,\n        const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,\n        ZDICT_params_t params)\n{\n    int const compressionLevel = (params.compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : params.compressionLevel;\n    U32 const notificationLevel = params.notificationLevel;\n    size_t hSize = 8;\n\n    /* calculate entropy tables */\n    DISPLAYLEVEL(2, \"\\r%70s\\r\", \"\");   /* clean display line */\n    DISPLAYLEVEL(2, \"statistics ... \\n\");\n    {   size_t const eSize = ZDICT_analyzeEntropy((char*)dictBuffer+hSize, dictBufferCapacity-hSize,\n                                  compressionLevel,\n                                  samplesBuffer, samplesSizes, nbSamples,\n                                  (char*)dictBuffer + dictBufferCapacity - dictContentSize, dictContentSize,\n                                  notificationLevel);\n        if (ZDICT_isError(eSize)) return eSize;\n        hSize += eSize;\n    }\n\n    /* add dictionary header (after entropy tables) */\n    MEM_writeLE32(dictBuffer, ZSTD_MAGIC_DICTIONARY);\n    {   U64 const randomID = XXH64((char*)dictBuffer + dictBufferCapacity - dictContentSize, dictContentSize, 0);\n        U32 const compliantID = (randomID % ((1U<<31)-32768)) + 32768;\n        U32 const dictID = params.dictID ? params.dictID : compliantID;\n        MEM_writeLE32((char*)dictBuffer+4, dictID);\n    }\n\n    if (hSize + dictContentSize < dictBufferCapacity)\n        memmove((char*)dictBuffer + hSize, (char*)dictBuffer + dictBufferCapacity - dictContentSize, dictContentSize);\n    return MIN(dictBufferCapacity, hSize+dictContentSize);\n}\n\n/*! ZDICT_trainFromBuffer_unsafe_legacy() :\n*   Warning : `samplesBuffer` must be followed by noisy guard band !!!\n*   @return : size of dictionary, or an error code which can be tested with ZDICT_isError()\n*/\nstatic size_t ZDICT_trainFromBuffer_unsafe_legacy(\n                            void* dictBuffer, size_t maxDictSize,\n                            const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,\n                            ZDICT_legacy_params_t params)\n{\n    U32 const dictListSize = MAX(MAX(DICTLISTSIZE_DEFAULT, nbSamples), (U32)(maxDictSize/16));\n    dictItem* const dictList = (dictItem*)malloc(dictListSize * sizeof(*dictList));\n    unsigned const selectivity = params.selectivityLevel == 0 ? g_selectivity_default : params.selectivityLevel;\n    unsigned const minRep = (selectivity > 30) ? MINRATIO : nbSamples >> selectivity;\n    size_t const targetDictSize = maxDictSize;\n    size_t const samplesBuffSize = ZDICT_totalSampleSize(samplesSizes, nbSamples);\n    size_t dictSize = 0;\n    U32 const notificationLevel = params.zParams.notificationLevel;\n\n    /* checks */\n    if (!dictList) return ERROR(memory_allocation);\n    if (maxDictSize < ZDICT_DICTSIZE_MIN) { free(dictList); return ERROR(dstSize_tooSmall); }   /* requested dictionary size is too small */\n    if (samplesBuffSize < ZDICT_MIN_SAMPLES_SIZE) { free(dictList); return ERROR(dictionaryCreation_failed); }   /* not enough source to create dictionary */\n\n    /* init */\n    ZDICT_initDictItem(dictList);\n\n    /* build dictionary */\n    ZDICT_trainBuffer_legacy(dictList, dictListSize,\n                       samplesBuffer, samplesBuffSize,\n                       samplesSizes, nbSamples,\n                       minRep, notificationLevel);\n\n    /* display best matches */\n    if (params.zParams.notificationLevel>= 3) {\n        unsigned const nb = MIN(25, dictList[0].pos);\n        unsigned const dictContentSize = ZDICT_dictSize(dictList);\n        unsigned u;\n        DISPLAYLEVEL(3, \"\\n %u segments found, of total size %u \\n\", (unsigned)dictList[0].pos-1, dictContentSize);\n        DISPLAYLEVEL(3, \"list %u best segments \\n\", nb-1);\n        for (u=1; u<nb; u++) {\n            unsigned const pos = dictList[u].pos;\n            unsigned const length = dictList[u].length;\n            U32 const printedLength = MIN(40, length);\n            if ((pos > samplesBuffSize) || ((pos + length) > samplesBuffSize)) {\n                free(dictList);\n                return ERROR(GENERIC);   /* should never happen */\n            }\n            DISPLAYLEVEL(3, \"%3u:%3u bytes at pos %8u, savings %7u bytes |\",\n                         u, length, pos, (unsigned)dictList[u].savings);\n            ZDICT_printHex((const char*)samplesBuffer+pos, printedLength);\n            DISPLAYLEVEL(3, \"| \\n\");\n    }   }\n\n\n    /* create dictionary */\n    {   unsigned dictContentSize = ZDICT_dictSize(dictList);\n        if (dictContentSize < ZDICT_CONTENTSIZE_MIN) { free(dictList); return ERROR(dictionaryCreation_failed); }   /* dictionary content too small */\n        if (dictContentSize < targetDictSize/4) {\n            DISPLAYLEVEL(2, \"!  warning : selected content significantly smaller than requested (%u < %u) \\n\", dictContentSize, (unsigned)maxDictSize);\n            if (samplesBuffSize < 10 * targetDictSize)\n                DISPLAYLEVEL(2, \"!  consider increasing the number of samples (total size : %u MB)\\n\", (unsigned)(samplesBuffSize>>20));\n            if (minRep > MINRATIO) {\n                DISPLAYLEVEL(2, \"!  consider increasing selectivity to produce larger dictionary (-s%u) \\n\", selectivity+1);\n                DISPLAYLEVEL(2, \"!  note : larger dictionaries are not necessarily better, test its efficiency on samples \\n\");\n            }\n        }\n\n        if ((dictContentSize > targetDictSize*3) && (nbSamples > 2*MINRATIO) && (selectivity>1)) {\n            unsigned proposedSelectivity = selectivity-1;\n            while ((nbSamples >> proposedSelectivity) <= MINRATIO) { proposedSelectivity--; }\n            DISPLAYLEVEL(2, \"!  note : calculated dictionary significantly larger than requested (%u > %u) \\n\", dictContentSize, (unsigned)maxDictSize);\n            DISPLAYLEVEL(2, \"!  consider increasing dictionary size, or produce denser dictionary (-s%u) \\n\", proposedSelectivity);\n            DISPLAYLEVEL(2, \"!  always test dictionary efficiency on real samples \\n\");\n        }\n\n        /* limit dictionary size */\n        {   U32 const max = dictList->pos;   /* convention : nb of useful elts within dictList */\n            U32 currentSize = 0;\n            U32 n; for (n=1; n<max; n++) {\n                currentSize += dictList[n].length;\n                if (currentSize > targetDictSize) { currentSize -= dictList[n].length; break; }\n            }\n            dictList->pos = n;\n            dictContentSize = currentSize;\n        }\n\n        /* build dict content */\n        {   U32 u;\n            BYTE* ptr = (BYTE*)dictBuffer + maxDictSize;\n            for (u=1; u<dictList->pos; u++) {\n                U32 l = dictList[u].length;\n                ptr -= l;\n                if (ptr<(BYTE*)dictBuffer) { free(dictList); return ERROR(GENERIC); }   /* should not happen */\n                memcpy(ptr, (const char*)samplesBuffer+dictList[u].pos, l);\n        }   }\n\n        dictSize = ZDICT_addEntropyTablesFromBuffer_advanced(dictBuffer, dictContentSize, maxDictSize,\n                                                             samplesBuffer, samplesSizes, nbSamples,\n                                                             params.zParams);\n    }\n\n    /* clean up */\n    free(dictList);\n    return dictSize;\n}\n\n\n/* ZDICT_trainFromBuffer_legacy() :\n * issue : samplesBuffer need to be followed by a noisy guard band.\n * work around : duplicate the buffer, and add the noise */\nsize_t ZDICT_trainFromBuffer_legacy(void* dictBuffer, size_t dictBufferCapacity,\n                              const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,\n                              ZDICT_legacy_params_t params)\n{\n    size_t result;\n    void* newBuff;\n    size_t const sBuffSize = ZDICT_totalSampleSize(samplesSizes, nbSamples);\n    if (sBuffSize < ZDICT_MIN_SAMPLES_SIZE) return 0;   /* not enough content => no dictionary */\n\n    newBuff = malloc(sBuffSize + NOISELENGTH);\n    if (!newBuff) return ERROR(memory_allocation);\n\n    memcpy(newBuff, samplesBuffer, sBuffSize);\n    ZDICT_fillNoise((char*)newBuff + sBuffSize, NOISELENGTH);   /* guard band, for end of buffer condition */\n\n    result =\n        ZDICT_trainFromBuffer_unsafe_legacy(dictBuffer, dictBufferCapacity, newBuff,\n                                            samplesSizes, nbSamples, params);\n    free(newBuff);\n    return result;\n}\n\n\nsize_t ZDICT_trainFromBuffer(void* dictBuffer, size_t dictBufferCapacity,\n                             const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples)\n{\n    ZDICT_fastCover_params_t params;\n    DEBUGLOG(3, \"ZDICT_trainFromBuffer\");\n    memset(&params, 0, sizeof(params));\n    params.d = 8;\n    params.steps = 4;\n    /* Use default level since no compression level information is available */\n    params.zParams.compressionLevel = ZSTD_CLEVEL_DEFAULT;\n#if defined(DEBUGLEVEL) && (DEBUGLEVEL>=1)\n    params.zParams.notificationLevel = DEBUGLEVEL;\n#endif\n    return ZDICT_optimizeTrainFromBuffer_fastCover(dictBuffer, dictBufferCapacity,\n                                               samplesBuffer, samplesSizes, nbSamples,\n                                               &params);\n}\n\nsize_t ZDICT_addEntropyTablesFromBuffer(void* dictBuffer, size_t dictContentSize, size_t dictBufferCapacity,\n                                  const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples)\n{\n    ZDICT_params_t params;\n    memset(&params, 0, sizeof(params));\n    return ZDICT_addEntropyTablesFromBuffer_advanced(dictBuffer, dictContentSize, dictBufferCapacity,\n                                                     samplesBuffer, samplesSizes, nbSamples,\n                                                     params);\n}\n"
  },
  {
    "path": "lib/dll/example/Makefile",
    "content": "# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ################################################################\n\nVOID    := /dev/null\nZSTDDIR  := ../include\nLIBDIR  := ../static\nDLLDIR  := ../dll\n\nCFLAGS  ?= -O3   # can select custom flags. For example : CFLAGS=\"-O2 -g\" make\nCFLAGS  += -Wall -Wextra -Wundef -Wcast-qual -Wcast-align -Wshadow -Wswitch-enum \\\n           -Wdeclaration-after-statement -Wstrict-prototypes \\\n           -Wpointer-arith -Wstrict-aliasing=1\nCFLAGS  += $(MOREFLAGS)\nCPPFLAGS:= -I$(ZSTDDIR) -DXXH_NAMESPACE=ZSTD_\nFLAGS   := $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)\n\n\n# Define *.exe as extension for Windows systems\nifneq (,$(filter Windows%,$(OS)))\nEXT =.exe\nelse\nEXT =\nendif\n\n.PHONY: default fullbench-dll fullbench-lib\n\n\ndefault: all\n\nall: fullbench-dll fullbench-lib\n\n\nfullbench-lib: fullbench.c datagen.c\n\t$(CC) $(FLAGS) $^ -o $@$(EXT) $(LIBDIR)/libzstd_static.lib\n\nfullbench-dll: fullbench.c datagen.c\n\t$(CC) $(FLAGS) $^ -o $@$(EXT) -DZSTD_DLL_IMPORT=1 $(DLLDIR)/libzstd.dll\n\nclean:\n\t@$(RM) fullbench-dll$(EXT) fullbench-lib$(EXT) \\\n\t@echo Cleaning completed\n"
  },
  {
    "path": "lib/dll/example/README.md",
    "content": "# ZSTD Windows binary package\n\n## The package contents\n\n- `zstd.exe` : Command Line Utility, supporting gzip-like arguments\n- `dll\\libzstd.dll` : The ZSTD dynamic library (DLL)\n- `dll\\libzstd.lib` : The import library of the ZSTD dynamic library (DLL) for Visual C++\n- `example\\` : The example of usage of the ZSTD library\n- `include\\` : Header files required by the ZSTD library\n- `static\\libzstd_static.lib` : The static ZSTD library (LIB)\n\n## Usage of Command Line Interface\n\nCommand Line Interface (CLI) supports gzip-like arguments.\nBy default CLI takes an input file and compresses it to an output file:\n\n    Usage: zstd [arg] [input] [output]\n\nThe full list of commands for CLI can be obtained with `-h` or `-H`. The ratio can\nbe improved with commands from `-3` to `-16` but higher levels also have slower\ncompression. CLI includes in-memory compression benchmark module with compression\nlevels starting from `-b` and ending with `-e` with iteration time of `-i` seconds.\nCLI supports aggregation of parameters i.e. `-b1`, `-e18`, and `-i1` can be joined\ninto `-b1e18i1`.\n\n## The example of usage of static and dynamic ZSTD libraries with gcc/MinGW\n\nUse `cd example` and `make` to build `fullbench-dll` and `fullbench-lib`.\n`fullbench-dll` uses a dynamic ZSTD library from the `dll` directory.\n`fullbench-lib` uses a static ZSTD library from the `lib` directory.\n\n## Using ZSTD DLL with gcc/MinGW\n\nThe header files from `include\\` and the dynamic library `dll\\libzstd.dll`\nare required to compile a project using gcc/MinGW.\nThe dynamic library has to be added to linking options.\nIt means that if a project that uses ZSTD consists of a single `test-dll.c`\nfile it should be linked with `dll\\libzstd.dll`. For example:\n\n    gcc $(CFLAGS) -Iinclude\\ test-dll.c -o test-dll dll\\libzstd.dll\n\nThe compiled executable will require ZSTD DLL which is available at `dll\\libzstd.dll`.\n\n## The example of usage of static and dynamic ZSTD libraries with Visual C++\n\nOpen `example\\fullbench-dll.sln` to compile `fullbench-dll` that uses a\ndynamic ZSTD library from the `dll` directory. The solution works with Visual C++\n2010 or newer. When one will open the solution with Visual C++ newer than 2010\nthen the solution will be upgraded to the current version.\n\n## Using ZSTD DLL with Visual C++\n\nThe header files from `include\\` and the import library `dll\\libzstd.lib`\nare required to compile a project using Visual C++.\n\n1. The path to header files should be added to `Additional Include Directories` that can\n   be found in project properties `C/C++` then `General`.\n2. The import library has to be added to `Additional Dependencies` that can\n   be found in project properties `Linker` then `Input`.\n   If one will provide only the name `libzstd.lib` without a full path to the library\n   the directory has to be added to `Linker\\General\\Additional Library Directories`.\n\nThe compiled executable will require ZSTD DLL which is available at `dll\\libzstd.dll`.\n"
  },
  {
    "path": "lib/dll/example/build_package.bat",
    "content": "@echo off\r\nsetlocal\r\n\r\nrem Detect build type based on available files\r\nset BUILD_TYPE=make\r\nif exist \"build\\cmake\\build\\lib\\Release\\zstd_static.lib\" set BUILD_TYPE=cmake\r\n\r\necho Detected build type: %BUILD_TYPE%\r\n\r\nrem Create required directories\r\nmkdir bin\\dll bin\\static bin\\example bin\\include\r\n\r\nrem Copy common files using a subroutine. Exits immediately on failure.\r\ncall :copyFile \"tests\\fullbench.c\" \"bin\\example\\\"\r\ncall :copyFile \"programs\\datagen.c\" \"bin\\example\\\"\r\ncall :copyFile \"programs\\datagen.h\" \"bin\\example\\\"\r\ncall :copyFile \"programs\\util.h\" \"bin\\example\\\"\r\ncall :copyFile \"programs\\platform.h\" \"bin\\example\\\"\r\ncall :copyFile \"lib\\common\\mem.h\" \"bin\\example\\\"\r\ncall :copyFile \"lib\\common\\zstd_internal.h\" \"bin\\example\\\"\r\ncall :copyFile \"lib\\common\\error_private.h\" \"bin\\example\\\"\r\ncall :copyFile \"lib\\common\\xxhash.h\" \"bin\\example\\\"\r\ncall :copyFile \"lib\\dll\\example\\Makefile\" \"bin\\example\\\"\r\ncall :copyFile \"lib\\dll\\example\\fullbench-dll.*\" \"bin\\example\\\"\r\ncall :copyFile \"lib\\zstd.h\" \"bin\\include\\\"\r\ncall :copyFile \"lib\\zstd_errors.h\" \"bin\\include\\\"\r\ncall :copyFile \"lib\\zdict.h\" \"bin\\include\\\"\r\n\r\nrem Copy build-specific files\r\nif \"%BUILD_TYPE%\"==\"cmake\" (\r\n    echo Copying CMake build artifacts...\r\n    call :copyFile \"build\\cmake\\build\\lib\\Release\\zstd_static.lib\" \"bin\\static\\libzstd_static.lib\"\r\n    call :copyFile \"build\\cmake\\build\\lib\\Release\\zstd.dll\" \"bin\\dll\\libzstd.dll\"\r\n    call :copyFile \"build\\cmake\\build\\lib\\Release\\zstd.lib\" \"bin\\dll\\zstd.lib\"\r\n    call :copyFile \"build\\cmake\\build\\programs\\Release\\zstd.exe\" \"bin\\zstd.exe\"\r\n    call :copyFile \"lib\\dll\\example\\README.md\" \"bin\\README.md\"\r\n) else (\r\n    echo Copying Make build artifacts...\r\n    call :copyFile \"lib\\libzstd.a\" \"bin\\static\\libzstd_static.lib\"\r\n    call :copyFile \"lib\\dll\\libzstd.*\" \"bin\\dll\\\"\r\n    call :copyFile \"programs\\zstd.exe\" \"bin\\zstd.exe\"\r\n    call :copyFile \"lib\\dll\\example\\README.md\" \"bin\\\"\r\n)\r\n\r\necho Build package created successfully for %BUILD_TYPE% build!\r\nendlocal\r\nexit /b 0\r\n\r\n:copyFile\r\ncopy \"%~1\" \"%~2\"\r\nif errorlevel 1 (\r\n    echo Failed to copy \"%~1\"\r\n    exit 1\r\n)\r\nexit /b"
  },
  {
    "path": "lib/dll/example/fullbench-dll.sln",
    "content": "Microsoft Visual Studio Solution File, Format Version 12.00\r\n# Visual Studio Express 2012 for Windows Desktop\r\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"fullbench-dll\", \"fullbench-dll.vcxproj\", \"{13992FD2-077E-4954-B065-A428198201A9}\"\r\nEndProject\r\nGlobal\r\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n\t\tDebug|Win32 = Debug|Win32\r\n\t\tDebug|x64 = Debug|x64\r\n\t\tRelease|Win32 = Release|Win32\r\n\t\tRelease|x64 = Release|x64\r\n\tEndGlobalSection\r\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n\t\t{13992FD2-077E-4954-B065-A428198201A9}.Debug|Win32.ActiveCfg = Debug|Win32\r\n\t\t{13992FD2-077E-4954-B065-A428198201A9}.Debug|Win32.Build.0 = Debug|Win32\r\n\t\t{13992FD2-077E-4954-B065-A428198201A9}.Debug|x64.ActiveCfg = Debug|x64\r\n\t\t{13992FD2-077E-4954-B065-A428198201A9}.Debug|x64.Build.0 = Debug|x64\r\n\t\t{13992FD2-077E-4954-B065-A428198201A9}.Release|Win32.ActiveCfg = Release|Win32\r\n\t\t{13992FD2-077E-4954-B065-A428198201A9}.Release|Win32.Build.0 = Release|Win32\r\n\t\t{13992FD2-077E-4954-B065-A428198201A9}.Release|x64.ActiveCfg = Release|x64\r\n\t\t{13992FD2-077E-4954-B065-A428198201A9}.Release|x64.Build.0 = Release|x64\r\n\tEndGlobalSection\r\n\tGlobalSection(SolutionProperties) = preSolution\r\n\t\tHideSolutionNode = FALSE\r\n\tEndGlobalSection\r\nEndGlobal\r\n"
  },
  {
    "path": "lib/dll/example/fullbench-dll.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup Label=\"ProjectConfigurations\">\r\n    <ProjectConfiguration Include=\"Debug|Win32\">\r\n      <Configuration>Debug</Configuration>\r\n      <Platform>Win32</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Debug|x64\">\r\n      <Configuration>Debug</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release|Win32\">\r\n      <Configuration>Release</Configuration>\r\n      <Platform>Win32</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release|x64\">\r\n      <Configuration>Release</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n  </ItemGroup>\r\n  <PropertyGroup Label=\"Globals\">\r\n    <ProjectGuid>{00000000-1CC8-4FD7-9281-6B8DBB9D3DF8}</ProjectGuid>\r\n    <Keyword>Win32Proj</Keyword>\r\n    <RootNamespace>fullbench-dll</RootNamespace>\r\n    <OutDir>$(SolutionDir)bin\\$(Platform)_$(Configuration)\\</OutDir>\r\n    <IntDir>$(SolutionDir)bin\\obj\\$(RootNamespace)_$(Platform)_$(Configuration)\\</IntDir>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>true</UseDebugLibraries>\r\n    <CharacterSet>MultiByte</CharacterSet>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>true</UseDebugLibraries>\r\n    <CharacterSet>MultiByte</CharacterSet>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>false</UseDebugLibraries>\r\n    <WholeProgramOptimization>true</WholeProgramOptimization>\r\n    <CharacterSet>MultiByte</CharacterSet>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>false</UseDebugLibraries>\r\n    <WholeProgramOptimization>true</WholeProgramOptimization>\r\n    <CharacterSet>MultiByte</CharacterSet>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\r\n  <ImportGroup Label=\"ExtensionSettings\">\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <PropertyGroup Label=\"UserMacros\" />\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\r\n    <LinkIncremental>true</LinkIncremental>\r\n    <IncludePath>$(IncludePath);$(SolutionDir)..\\..\\lib;$(SolutionDir)..\\..\\programs;$(SolutionDir)..\\..\\lib\\legacy;$(SolutionDir)..\\..\\lib\\common;$(UniversalCRT_IncludePath);</IncludePath>\r\n    <RunCodeAnalysis>false</RunCodeAnalysis>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\r\n    <LinkIncremental>true</LinkIncremental>\r\n    <IncludePath>$(IncludePath);$(SolutionDir)..\\..\\lib;$(SolutionDir)..\\..\\programs;$(SolutionDir)..\\..\\lib\\legacy;$(SolutionDir)..\\..\\lib\\common;$(UniversalCRT_IncludePath);</IncludePath>\r\n    <RunCodeAnalysis>false</RunCodeAnalysis>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\r\n    <LinkIncremental>false</LinkIncremental>\r\n    <IncludePath>$(IncludePath);$(SolutionDir)..\\..\\lib;$(SolutionDir)..\\..\\programs;$(SolutionDir)..\\..\\lib\\legacy;$(SolutionDir)..\\..\\lib\\common;$(UniversalCRT_IncludePath);</IncludePath>\r\n    <RunCodeAnalysis>false</RunCodeAnalysis>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\r\n    <LinkIncremental>false</LinkIncremental>\r\n    <IncludePath>$(IncludePath);$(SolutionDir)..\\..\\lib;$(SolutionDir)..\\..\\programs;$(SolutionDir)..\\..\\lib\\legacy;$(SolutionDir)..\\..\\lib\\common;$(UniversalCRT_IncludePath);</IncludePath>\r\n    <RunCodeAnalysis>false</RunCodeAnalysis>\r\n  </PropertyGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\r\n    <ClCompile>\r\n      <PrecompiledHeader>\r\n      </PrecompiledHeader>\r\n      <WarningLevel>Level4</WarningLevel>\r\n      <Optimization>Disabled</Optimization>\r\n      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;ZSTD_DLL_IMPORT=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <TreatWarningAsError>true</TreatWarningAsError>\r\n      <EnablePREfast>false</EnablePREfast>\r\n      <AdditionalIncludeDirectories>..\\include</AdditionalIncludeDirectories>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Console</SubSystem>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n      <AdditionalLibraryDirectories>$(SolutionDir)..\\dll;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r\n      <AdditionalDependencies>libzstd.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n      <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\r\n    <ClCompile>\r\n      <PrecompiledHeader>\r\n      </PrecompiledHeader>\r\n      <WarningLevel>Level4</WarningLevel>\r\n      <Optimization>Disabled</Optimization>\r\n      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;ZSTD_DLL_IMPORT=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <TreatWarningAsError>true</TreatWarningAsError>\r\n      <EnablePREfast>false</EnablePREfast>\r\n      <AdditionalIncludeDirectories>..\\include</AdditionalIncludeDirectories>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Console</SubSystem>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n      <AdditionalLibraryDirectories>$(SolutionDir)..\\dll;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r\n      <AdditionalDependencies>libzstd.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\r\n    <ClCompile>\r\n      <WarningLevel>Level4</WarningLevel>\r\n      <PrecompiledHeader>\r\n      </PrecompiledHeader>\r\n      <Optimization>MaxSpeed</Optimization>\r\n      <FunctionLevelLinking>true</FunctionLevelLinking>\r\n      <IntrinsicFunctions>true</IntrinsicFunctions>\r\n      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;ZSTD_DLL_IMPORT=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <EnablePREfast>false</EnablePREfast>\r\n      <AdditionalIncludeDirectories>..\\include</AdditionalIncludeDirectories>\r\n      <TreatWarningAsError>false</TreatWarningAsError>\r\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Console</SubSystem>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r\n      <OptimizeReferences>true</OptimizeReferences>\r\n      <AdditionalLibraryDirectories>$(SolutionDir)..\\dll;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r\n      <AdditionalDependencies>libzstd.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n      <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\r\n    <ClCompile>\r\n      <WarningLevel>Level4</WarningLevel>\r\n      <PrecompiledHeader>\r\n      </PrecompiledHeader>\r\n      <Optimization>MaxSpeed</Optimization>\r\n      <FunctionLevelLinking>true</FunctionLevelLinking>\r\n      <IntrinsicFunctions>true</IntrinsicFunctions>\r\n      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;ZSTD_DLL_IMPORT=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <TreatWarningAsError>false</TreatWarningAsError>\r\n      <EnablePREfast>false</EnablePREfast>\r\n      <AdditionalIncludeDirectories>..\\include</AdditionalIncludeDirectories>\r\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Console</SubSystem>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r\n      <OptimizeReferences>true</OptimizeReferences>\r\n      <AdditionalLibraryDirectories>$(SolutionDir)..\\dll;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r\n      <AdditionalDependencies>libzstd.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"datagen.c\" />\r\n    <ClCompile Include=\"fullbench.c\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"..\\include\\zstd.h\" />\r\n  </ItemGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\r\n  <ImportGroup Label=\"ExtensionTargets\">\r\n  </ImportGroup>\r\n</Project>"
  },
  {
    "path": "lib/install_oses.mk",
    "content": "# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ################################################################\n\n# This included Makefile provides the following variables :\n# UNAME, INSTALL_OS_LIST\n\nUNAME := $(shell sh -c 'MSYSTEM=\"MSYS\" uname')\n\n# List of OSes for which target install is supported\nINSTALL_OS_LIST ?= Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS Haiku AIX MSYS_NT% CYGWIN_NT%\n"
  },
  {
    "path": "lib/legacy/zstd_legacy.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_LEGACY_H\n#define ZSTD_LEGACY_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* *************************************\n*  Includes\n***************************************/\n#include \"../common/mem.h\"            /* MEM_STATIC */\n#include \"../common/error_private.h\"  /* ERROR */\n#include \"../common/zstd_internal.h\"  /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTD_frameSizeInfo */\n\n#if !defined (ZSTD_LEGACY_SUPPORT) || (ZSTD_LEGACY_SUPPORT == 0)\n#  undef ZSTD_LEGACY_SUPPORT\n#  define ZSTD_LEGACY_SUPPORT 8\n#endif\n\n#if (ZSTD_LEGACY_SUPPORT <= 1)\n#  include \"zstd_v01.h\"\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 2)\n#  include \"zstd_v02.h\"\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 3)\n#  include \"zstd_v03.h\"\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 4)\n#  include \"zstd_v04.h\"\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 5)\n#  include \"zstd_v05.h\"\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 6)\n#  include \"zstd_v06.h\"\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 7)\n#  include \"zstd_v07.h\"\n#endif\n\n/** ZSTD_isLegacy() :\n    @return : > 0 if supported by legacy decoder. 0 otherwise.\n              return value is the version.\n*/\nMEM_STATIC unsigned ZSTD_isLegacy(const void* src, size_t srcSize)\n{\n    U32 magicNumberLE;\n    if (srcSize<4) return 0;\n    magicNumberLE = MEM_readLE32(src);\n    switch(magicNumberLE)\n    {\n#if (ZSTD_LEGACY_SUPPORT <= 1)\n        case ZSTDv01_magicNumberLE:return 1;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 2)\n        case ZSTDv02_magicNumber : return 2;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 3)\n        case ZSTDv03_magicNumber : return 3;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 4)\n        case ZSTDv04_magicNumber : return 4;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 5)\n        case ZSTDv05_MAGICNUMBER : return 5;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 6)\n        case ZSTDv06_MAGICNUMBER : return 6;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 7)\n        case ZSTDv07_MAGICNUMBER : return 7;\n#endif\n        default : return 0;\n    }\n}\n\n\nMEM_STATIC unsigned long long ZSTD_getDecompressedSize_legacy(const void* src, size_t srcSize)\n{\n    U32 const version = ZSTD_isLegacy(src, srcSize);\n    if (version < 5) return 0;  /* no decompressed size in frame header, or not a legacy format */\n#if (ZSTD_LEGACY_SUPPORT <= 5)\n    if (version==5) {\n        ZSTDv05_parameters fParams;\n        size_t const frResult = ZSTDv05_getFrameParams(&fParams, src, srcSize);\n        if (frResult != 0) return 0;\n        return fParams.srcSize;\n    }\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 6)\n    if (version==6) {\n        ZSTDv06_frameParams fParams;\n        size_t const frResult = ZSTDv06_getFrameParams(&fParams, src, srcSize);\n        if (frResult != 0) return 0;\n        return fParams.frameContentSize;\n    }\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 7)\n    if (version==7) {\n        ZSTDv07_frameParams fParams;\n        size_t const frResult = ZSTDv07_getFrameParams(&fParams, src, srcSize);\n        if (frResult != 0) return 0;\n        return fParams.frameContentSize;\n    }\n#endif\n    return 0;   /* should not be possible */\n}\n\n\nMEM_STATIC size_t ZSTD_decompressLegacy(\n                     void* dst, size_t dstCapacity,\n               const void* src, size_t compressedSize,\n               const void* dict,size_t dictSize)\n{\n    U32 const version = ZSTD_isLegacy(src, compressedSize);\n    char x;\n    /* Avoid passing NULL to legacy decoding. */\n    if (dst == NULL) {\n        assert(dstCapacity == 0);\n        dst = &x;\n    }\n    if (src == NULL) {\n        assert(compressedSize == 0);\n        src = &x;\n    }\n    if (dict == NULL) {\n        assert(dictSize == 0);\n        dict = &x;\n    }\n    (void)dst; (void)dstCapacity; (void)dict; (void)dictSize;  /* unused when ZSTD_LEGACY_SUPPORT >= 8 */\n    switch(version)\n    {\n#if (ZSTD_LEGACY_SUPPORT <= 1)\n        case 1 :\n            return ZSTDv01_decompress(dst, dstCapacity, src, compressedSize);\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 2)\n        case 2 :\n            return ZSTDv02_decompress(dst, dstCapacity, src, compressedSize);\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 3)\n        case 3 :\n            return ZSTDv03_decompress(dst, dstCapacity, src, compressedSize);\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 4)\n        case 4 :\n            return ZSTDv04_decompress(dst, dstCapacity, src, compressedSize);\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 5)\n        case 5 :\n            {   size_t result;\n                ZSTDv05_DCtx* const zd = ZSTDv05_createDCtx();\n                if (zd==NULL) return ERROR(memory_allocation);\n                result = ZSTDv05_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize);\n                ZSTDv05_freeDCtx(zd);\n                return result;\n            }\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 6)\n        case 6 :\n            {   size_t result;\n                ZSTDv06_DCtx* const zd = ZSTDv06_createDCtx();\n                if (zd==NULL) return ERROR(memory_allocation);\n                result = ZSTDv06_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize);\n                ZSTDv06_freeDCtx(zd);\n                return result;\n            }\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 7)\n        case 7 :\n            {   size_t result;\n                ZSTDv07_DCtx* const zd = ZSTDv07_createDCtx();\n                if (zd==NULL) return ERROR(memory_allocation);\n                result = ZSTDv07_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize);\n                ZSTDv07_freeDCtx(zd);\n                return result;\n            }\n#endif\n        default :\n            return ERROR(prefix_unknown);\n    }\n}\n\nMEM_STATIC ZSTD_frameSizeInfo ZSTD_findFrameSizeInfoLegacy(const void *src, size_t srcSize)\n{\n    ZSTD_frameSizeInfo frameSizeInfo;\n    U32 const version = ZSTD_isLegacy(src, srcSize);\n    switch(version)\n    {\n#if (ZSTD_LEGACY_SUPPORT <= 1)\n        case 1 :\n            ZSTDv01_findFrameSizeInfoLegacy(src, srcSize,\n                &frameSizeInfo.compressedSize,\n                &frameSizeInfo.decompressedBound);\n            break;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 2)\n        case 2 :\n            ZSTDv02_findFrameSizeInfoLegacy(src, srcSize,\n                &frameSizeInfo.compressedSize,\n                &frameSizeInfo.decompressedBound);\n            break;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 3)\n        case 3 :\n            ZSTDv03_findFrameSizeInfoLegacy(src, srcSize,\n                &frameSizeInfo.compressedSize,\n                &frameSizeInfo.decompressedBound);\n            break;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 4)\n        case 4 :\n            ZSTDv04_findFrameSizeInfoLegacy(src, srcSize,\n                &frameSizeInfo.compressedSize,\n                &frameSizeInfo.decompressedBound);\n            break;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 5)\n        case 5 :\n            ZSTDv05_findFrameSizeInfoLegacy(src, srcSize,\n                &frameSizeInfo.compressedSize,\n                &frameSizeInfo.decompressedBound);\n            break;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 6)\n        case 6 :\n            ZSTDv06_findFrameSizeInfoLegacy(src, srcSize,\n                &frameSizeInfo.compressedSize,\n                &frameSizeInfo.decompressedBound);\n            break;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 7)\n        case 7 :\n            ZSTDv07_findFrameSizeInfoLegacy(src, srcSize,\n                &frameSizeInfo.compressedSize,\n                &frameSizeInfo.decompressedBound);\n            break;\n#endif\n        default :\n            frameSizeInfo.compressedSize = ERROR(prefix_unknown);\n            frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;\n            break;\n    }\n    if (!ZSTD_isError(frameSizeInfo.compressedSize) && frameSizeInfo.compressedSize > srcSize) {\n        frameSizeInfo.compressedSize = ERROR(srcSize_wrong);\n        frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;\n    }\n    /* In all cases, decompressedBound == nbBlocks * ZSTD_BLOCKSIZE_MAX.\n     * So we can compute nbBlocks without having to change every function.\n     */\n    if (frameSizeInfo.decompressedBound != ZSTD_CONTENTSIZE_ERROR) {\n        assert((frameSizeInfo.decompressedBound & (ZSTD_BLOCKSIZE_MAX - 1)) == 0);\n        frameSizeInfo.nbBlocks = (size_t)(frameSizeInfo.decompressedBound / ZSTD_BLOCKSIZE_MAX);\n    }\n    return frameSizeInfo;\n}\n\nMEM_STATIC size_t ZSTD_findFrameCompressedSizeLegacy(const void *src, size_t srcSize)\n{\n    ZSTD_frameSizeInfo frameSizeInfo = ZSTD_findFrameSizeInfoLegacy(src, srcSize);\n    return frameSizeInfo.compressedSize;\n}\n\nMEM_STATIC size_t ZSTD_freeLegacyStreamContext(void* legacyContext, U32 version)\n{\n    switch(version)\n    {\n        default :\n        case 1 :\n        case 2 :\n        case 3 :\n            (void)legacyContext;\n            return ERROR(version_unsupported);\n#if (ZSTD_LEGACY_SUPPORT <= 4)\n        case 4 : return ZBUFFv04_freeDCtx((ZBUFFv04_DCtx*)legacyContext);\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 5)\n        case 5 : return ZBUFFv05_freeDCtx((ZBUFFv05_DCtx*)legacyContext);\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 6)\n        case 6 : return ZBUFFv06_freeDCtx((ZBUFFv06_DCtx*)legacyContext);\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 7)\n        case 7 : return ZBUFFv07_freeDCtx((ZBUFFv07_DCtx*)legacyContext);\n#endif\n    }\n}\n\n\nMEM_STATIC size_t ZSTD_initLegacyStream(void** legacyContext, U32 prevVersion, U32 newVersion,\n                                        const void* dict, size_t dictSize)\n{\n    char x;\n    /* Avoid passing NULL to legacy decoding. */\n    if (dict == NULL) {\n        assert(dictSize == 0);\n        dict = &x;\n    }\n    DEBUGLOG(5, \"ZSTD_initLegacyStream for v0.%u\", newVersion);\n    if (prevVersion != newVersion) ZSTD_freeLegacyStreamContext(*legacyContext, prevVersion);\n    switch(newVersion)\n    {\n        default :\n        case 1 :\n        case 2 :\n        case 3 :\n            (void)dict; (void)dictSize;\n            return 0;\n#if (ZSTD_LEGACY_SUPPORT <= 4)\n        case 4 :\n        {\n            ZBUFFv04_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv04_createDCtx() : (ZBUFFv04_DCtx*)*legacyContext;\n            if (dctx==NULL) return ERROR(memory_allocation);\n            ZBUFFv04_decompressInit(dctx);\n            ZBUFFv04_decompressWithDictionary(dctx, dict, dictSize);\n            *legacyContext = dctx;\n            return 0;\n        }\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 5)\n        case 5 :\n        {\n            ZBUFFv05_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv05_createDCtx() : (ZBUFFv05_DCtx*)*legacyContext;\n            if (dctx==NULL) return ERROR(memory_allocation);\n            ZBUFFv05_decompressInitDictionary(dctx, dict, dictSize);\n            *legacyContext = dctx;\n            return 0;\n        }\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 6)\n        case 6 :\n        {\n            ZBUFFv06_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv06_createDCtx() : (ZBUFFv06_DCtx*)*legacyContext;\n            if (dctx==NULL) return ERROR(memory_allocation);\n            ZBUFFv06_decompressInitDictionary(dctx, dict, dictSize);\n            *legacyContext = dctx;\n            return 0;\n        }\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 7)\n        case 7 :\n        {\n            ZBUFFv07_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv07_createDCtx() : (ZBUFFv07_DCtx*)*legacyContext;\n            if (dctx==NULL) return ERROR(memory_allocation);\n            ZBUFFv07_decompressInitDictionary(dctx, dict, dictSize);\n            *legacyContext = dctx;\n            return 0;\n        }\n#endif\n    }\n}\n\n\n\nMEM_STATIC size_t ZSTD_decompressLegacyStream(void* legacyContext, U32 version,\n                                              ZSTD_outBuffer* output, ZSTD_inBuffer* input)\n{\n    static char x;\n    /* Avoid passing NULL to legacy decoding. */\n    if (output->dst == NULL) {\n        assert(output->size == 0);\n        output->dst = &x;\n    }\n    if (input->src == NULL) {\n        assert(input->size == 0);\n        input->src = &x;\n    }\n    DEBUGLOG(5, \"ZSTD_decompressLegacyStream for v0.%u\", version);\n    switch(version)\n    {\n        default :\n        case 1 :\n        case 2 :\n        case 3 :\n            (void)legacyContext; (void)output; (void)input;\n            return ERROR(version_unsupported);\n#if (ZSTD_LEGACY_SUPPORT <= 4)\n        case 4 :\n            {\n                ZBUFFv04_DCtx* dctx = (ZBUFFv04_DCtx*) legacyContext;\n                const void* src = (const char*)input->src + input->pos;\n                size_t readSize = input->size - input->pos;\n                void* dst = (char*)output->dst + output->pos;\n                size_t decodedSize = output->size - output->pos;\n                size_t const hintSize = ZBUFFv04_decompressContinue(dctx, dst, &decodedSize, src, &readSize);\n                output->pos += decodedSize;\n                input->pos += readSize;\n                return hintSize;\n            }\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 5)\n        case 5 :\n            {\n                ZBUFFv05_DCtx* dctx = (ZBUFFv05_DCtx*) legacyContext;\n                const void* src = (const char*)input->src + input->pos;\n                size_t readSize = input->size - input->pos;\n                void* dst = (char*)output->dst + output->pos;\n                size_t decodedSize = output->size - output->pos;\n                size_t const hintSize = ZBUFFv05_decompressContinue(dctx, dst, &decodedSize, src, &readSize);\n                output->pos += decodedSize;\n                input->pos += readSize;\n                return hintSize;\n            }\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 6)\n        case 6 :\n            {\n                ZBUFFv06_DCtx* dctx = (ZBUFFv06_DCtx*) legacyContext;\n                const void* src = (const char*)input->src + input->pos;\n                size_t readSize = input->size - input->pos;\n                void* dst = (char*)output->dst + output->pos;\n                size_t decodedSize = output->size - output->pos;\n                size_t const hintSize = ZBUFFv06_decompressContinue(dctx, dst, &decodedSize, src, &readSize);\n                output->pos += decodedSize;\n                input->pos += readSize;\n                return hintSize;\n            }\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 7)\n        case 7 :\n            {\n                ZBUFFv07_DCtx* dctx = (ZBUFFv07_DCtx*) legacyContext;\n                const void* src = (const char*)input->src + input->pos;\n                size_t readSize = input->size - input->pos;\n                void* dst = (char*)output->dst + output->pos;\n                size_t decodedSize = output->size - output->pos;\n                size_t const hintSize = ZBUFFv07_decompressContinue(dctx, dst, &decodedSize, src, &readSize);\n                output->pos += decodedSize;\n                input->pos += readSize;\n                return hintSize;\n            }\n#endif\n    }\n}\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif   /* ZSTD_LEGACY_H */\n"
  },
  {
    "path": "lib/legacy/zstd_v01.c",
    "content": "/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/******************************************\n*  Includes\n******************************************/\n#include <stddef.h>    /* size_t, ptrdiff_t */\n#include \"zstd_v01.h\"\n#include \"../common/compiler.h\"\n#include \"../common/error_private.h\"\n\n\n/******************************************\n*  Static allocation\n******************************************/\n/* You can statically allocate FSE CTable/DTable as a table of unsigned using below macro */\n#define FSE_DTABLE_SIZE_U32(maxTableLog)                   (1 + (1<<maxTableLog))\n\n/* You can statically allocate Huff0 DTable as a table of unsigned short using below macro */\n#define HUF_DTABLE_SIZE_U16(maxTableLog)   (1 + (1<<maxTableLog))\n#define HUF_CREATE_STATIC_DTABLE(DTable, maxTableLog) \\\n        unsigned short DTable[HUF_DTABLE_SIZE_U16(maxTableLog)] = { maxTableLog }\n\n\n/******************************************\n*  Error Management\n******************************************/\n#define FSE_LIST_ERRORS(ITEM) \\\n        ITEM(FSE_OK_NoError) ITEM(FSE_ERROR_GENERIC) \\\n        ITEM(FSE_ERROR_tableLog_tooLarge) ITEM(FSE_ERROR_maxSymbolValue_tooLarge) ITEM(FSE_ERROR_maxSymbolValue_tooSmall) \\\n        ITEM(FSE_ERROR_dstSize_tooSmall) ITEM(FSE_ERROR_srcSize_wrong)\\\n        ITEM(FSE_ERROR_corruptionDetected) \\\n        ITEM(FSE_ERROR_maxCode)\n\n#define FSE_GENERATE_ENUM(ENUM) ENUM,\ntypedef enum { FSE_LIST_ERRORS(FSE_GENERATE_ENUM) } FSE_errorCodes;  /* enum is exposed, to detect & handle specific errors; compare function result to -enum value */\n\n\n/******************************************\n*  FSE symbol compression API\n******************************************/\n/*\n   This API consists of small unitary functions, which highly benefit from being inlined.\n   You will want to enable link-time-optimization to ensure these functions are properly inlined in your binary.\n   Visual seems to do it automatically.\n   For gcc or clang, you'll need to add -flto flag at compilation and linking stages.\n   If none of these solutions is applicable, include \"fse.c\" directly.\n*/\n\ntypedef unsigned FSE_CTable;   /* don't allocate that. It's just a way to be more restrictive than void* */\ntypedef unsigned FSE_DTable;   /* don't allocate that. It's just a way to be more restrictive than void* */\n\ntypedef struct\n{\n    size_t bitContainer;\n    int    bitPos;\n    char*  startPtr;\n    char*  ptr;\n    char*  endPtr;\n} FSE_CStream_t;\n\ntypedef struct\n{\n    ptrdiff_t   value;\n    const void* stateTable;\n    const void* symbolTT;\n    unsigned    stateLog;\n} FSE_CState_t;\n\ntypedef struct\n{\n    size_t   bitContainer;\n    unsigned bitsConsumed;\n    const char* ptr;\n    const char* start;\n} FSE_DStream_t;\n\ntypedef struct\n{\n    size_t      state;\n    const void* table;   /* precise table may vary, depending on U16 */\n} FSE_DState_t;\n\ntypedef enum { FSE_DStream_unfinished = 0,\n               FSE_DStream_endOfBuffer = 1,\n               FSE_DStream_completed = 2,\n               FSE_DStream_tooFar = 3 } FSE_DStream_status;  /* result of FSE_reloadDStream() */\n               /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... ?! */\n\n\n/****************************************************************\n*  Tuning parameters\n****************************************************************/\n/* MEMORY_USAGE :\n*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n*  Increasing memory usage improves compression ratio\n*  Reduced memory usage can improve speed, due to cache effect\n*  Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */\n#define FSE_MAX_MEMORY_USAGE 14\n#define FSE_DEFAULT_MEMORY_USAGE 13\n\n/* FSE_MAX_SYMBOL_VALUE :\n*  Maximum symbol value authorized.\n*  Required for proper stack allocation */\n#define FSE_MAX_SYMBOL_VALUE 255\n\n\n/****************************************************************\n*  template functions type & suffix\n****************************************************************/\n#define FSE_FUNCTION_TYPE BYTE\n#define FSE_FUNCTION_EXTENSION\n\n\n/****************************************************************\n*  Byte symbol type\n****************************************************************/\ntypedef struct\n{\n    unsigned short newState;\n    unsigned char  symbol;\n    unsigned char  nbBits;\n} FSE_decode_t;   /* size == U32 */\n\n\n\n/****************************************************************\n*  Compiler specifics\n****************************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  define FORCE_INLINE static __forceinline\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4214)        /* disable: C4214: non-int bitfields */\n#else\n#  define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)\n#  if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */\n#    ifdef __GNUC__\n#      define FORCE_INLINE static inline __attribute__((always_inline))\n#    else\n#      define FORCE_INLINE static inline\n#    endif\n#  else\n#    define FORCE_INLINE static\n#  endif /* __STDC_VERSION__ */\n#endif\n\n\n/****************************************************************\n*  Includes\n****************************************************************/\n#include <stdlib.h>     /* malloc, free, qsort */\n#include <string.h>     /* memcpy, memset */\n#include <stdio.h>      /* printf (debug) */\n\n\n#ifndef MEM_ACCESS_MODULE\n#define MEM_ACCESS_MODULE\n/****************************************************************\n*  Basic Types\n*****************************************************************/\n#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */\n# include <stdint.h>\ntypedef  uint8_t BYTE;\ntypedef uint16_t U16;\ntypedef  int16_t S16;\ntypedef uint32_t U32;\ntypedef  int32_t S32;\ntypedef uint64_t U64;\ntypedef  int64_t S64;\n#else\ntypedef unsigned char       BYTE;\ntypedef unsigned short      U16;\ntypedef   signed short      S16;\ntypedef unsigned int        U32;\ntypedef   signed int        S32;\ntypedef unsigned long long  U64;\ntypedef   signed long long  S64;\n#endif\n\n#endif   /* MEM_ACCESS_MODULE */\n\n/****************************************************************\n*  Memory I/O\n*****************************************************************/\n\nstatic unsigned FSE_32bits(void)\n{\n    return sizeof(void*)==4;\n}\n\nstatic unsigned FSE_isLittleEndian(void)\n{\n    const union { U32 i; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */\n    return one.c[0];\n}\n\nstatic U16 FSE_read16(const void* memPtr)\n{\n    U16 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nstatic U32 FSE_read32(const void* memPtr)\n{\n    U32 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nstatic U64 FSE_read64(const void* memPtr)\n{\n    U64 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nstatic U16 FSE_readLE16(const void* memPtr)\n{\n    if (FSE_isLittleEndian())\n        return FSE_read16(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U16)(p[0] + (p[1]<<8));\n    }\n}\n\nstatic U32 FSE_readLE32(const void* memPtr)\n{\n    if (FSE_isLittleEndian())\n        return FSE_read32(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U32)((U32)p[0] + ((U32)p[1]<<8) + ((U32)p[2]<<16) + ((U32)p[3]<<24));\n    }\n}\n\n\nstatic U64 FSE_readLE64(const void* memPtr)\n{\n    if (FSE_isLittleEndian())\n        return FSE_read64(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U64)((U64)p[0] + ((U64)p[1]<<8) + ((U64)p[2]<<16) + ((U64)p[3]<<24)\n                     + ((U64)p[4]<<32) + ((U64)p[5]<<40) + ((U64)p[6]<<48) + ((U64)p[7]<<56));\n    }\n}\n\nstatic size_t FSE_readLEST(const void* memPtr)\n{\n    if (FSE_32bits())\n        return (size_t)FSE_readLE32(memPtr);\n    else\n        return (size_t)FSE_readLE64(memPtr);\n}\n\n\n\n/****************************************************************\n*  Constants\n*****************************************************************/\n#define FSE_MAX_TABLELOG  (FSE_MAX_MEMORY_USAGE-2)\n#define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG)\n#define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1)\n#define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2)\n#define FSE_MIN_TABLELOG 5\n\n#define FSE_TABLELOG_ABSOLUTE_MAX 15\n#if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX\n#error \"FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported\"\n#endif\n\n\n/****************************************************************\n*  Error Management\n****************************************************************/\n#define FSE_STATIC_ASSERT(c) { enum { FSE_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n/****************************************************************\n*  Complex types\n****************************************************************/\ntypedef struct\n{\n    int deltaFindState;\n    U32 deltaNbBits;\n} FSE_symbolCompressionTransform; /* total 8 bytes */\n\ntypedef U32 DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)];\n\n/****************************************************************\n*  Internal functions\n****************************************************************/\nFORCE_INLINE unsigned FSE_highbit32 (U32 val)\n{\n#   if defined(_MSC_VER)   /* Visual */\n    unsigned long r;\n    return _BitScanReverse(&r, val) ? (unsigned)r : 0;\n#   elif defined(__GNUC__) && (GCC_VERSION >= 304)   /* GCC Intrinsic */\n    return __builtin_clz (val) ^ 31;\n#   else   /* Software version */\n    static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };\n    U32 v = val;\n    unsigned r;\n    v |= v >> 1;\n    v |= v >> 2;\n    v |= v >> 4;\n    v |= v >> 8;\n    v |= v >> 16;\n    r = DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];\n    return r;\n#   endif\n}\n\n\n/****************************************************************\n*  Templates\n****************************************************************/\n/*\n  designed to be included\n  for type-specific functions (template emulation in C)\n  Objective is to write these functions only once, for improved maintenance\n*/\n\n/* safety checks */\n#ifndef FSE_FUNCTION_EXTENSION\n#  error \"FSE_FUNCTION_EXTENSION must be defined\"\n#endif\n#ifndef FSE_FUNCTION_TYPE\n#  error \"FSE_FUNCTION_TYPE must be defined\"\n#endif\n\n/* Function names */\n#define FSE_CAT(X,Y) X##Y\n#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y)\n#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y)\n\n\n\nstatic U32 FSE_tableStep(U32 tableSize) { return (tableSize>>1) + (tableSize>>3) + 3; }\n\n#define FSE_DECODE_TYPE FSE_decode_t\n\n\ntypedef struct {\n    U16 tableLog;\n    U16 fastMode;\n} FSE_DTableHeader;   /* sizeof U32 */\n\nstatic size_t FSE_buildDTable\n(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)\n{\n    void* ptr = dt;\n    FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;\n    FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*)(ptr) + 1;   /* because dt is unsigned, 32-bits aligned on 32-bits */\n    const U32 tableSize = 1 << tableLog;\n    const U32 tableMask = tableSize-1;\n    const U32 step = FSE_tableStep(tableSize);\n    U16 symbolNext[FSE_MAX_SYMBOL_VALUE+1];\n    U32 position = 0;\n    U32 highThreshold = tableSize-1;\n    const S16 largeLimit= (S16)(1 << (tableLog-1));\n    U32 noLarge = 1;\n    U32 s;\n\n    /* Sanity Checks */\n    if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return (size_t)-FSE_ERROR_maxSymbolValue_tooLarge;\n    if (tableLog > FSE_MAX_TABLELOG) return (size_t)-FSE_ERROR_tableLog_tooLarge;\n\n    /* Init, lay down lowprob symbols */\n    DTableH[0].tableLog = (U16)tableLog;\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        if (normalizedCounter[s]==-1)\n        {\n            tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s;\n            symbolNext[s] = 1;\n        }\n        else\n        {\n            if (normalizedCounter[s] >= largeLimit) noLarge=0;\n            symbolNext[s] = normalizedCounter[s];\n        }\n    }\n\n    /* Spread symbols */\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        int i;\n        for (i=0; i<normalizedCounter[s]; i++)\n        {\n            tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;\n            position = (position + step) & tableMask;\n            while (position > highThreshold) position = (position + step) & tableMask;   /* lowprob area */\n        }\n    }\n\n    if (position!=0) return (size_t)-FSE_ERROR_GENERIC;   /* position must reach all cells once, otherwise normalizedCounter is incorrect */\n\n    /* Build Decoding table */\n    {\n        U32 i;\n        for (i=0; i<tableSize; i++)\n        {\n            FSE_FUNCTION_TYPE symbol = (FSE_FUNCTION_TYPE)(tableDecode[i].symbol);\n            U16 nextState = symbolNext[symbol]++;\n            tableDecode[i].nbBits = (BYTE) (tableLog - FSE_highbit32 ((U32)nextState) );\n            tableDecode[i].newState = (U16) ( (nextState << tableDecode[i].nbBits) - tableSize);\n        }\n    }\n\n    DTableH->fastMode = (U16)noLarge;\n    return 0;\n}\n\n\n/******************************************\n*  FSE byte symbol\n******************************************/\n#ifndef FSE_COMMONDEFS_ONLY\n\nstatic unsigned FSE_isError(size_t code) { return (code > (size_t)(-FSE_ERROR_maxCode)); }\n\nstatic short FSE_abs(short a)\n{\n    return a<0? (short)-a : a;\n}\n\n\n/****************************************************************\n*  Header bitstream management\n****************************************************************/\nstatic size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n                 const void* headerBuffer, size_t hbSize)\n{\n    const BYTE* const istart = (const BYTE*) headerBuffer;\n    const BYTE* const iend = istart + hbSize;\n    const BYTE* ip = istart;\n    int nbBits;\n    int remaining;\n    int threshold;\n    U32 bitStream;\n    int bitCount;\n    unsigned charnum = 0;\n    int previous0 = 0;\n\n    if (hbSize < 4) return (size_t)-FSE_ERROR_srcSize_wrong;\n    bitStream = FSE_readLE32(ip);\n    nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG;   /* extract tableLog */\n    if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return (size_t)-FSE_ERROR_tableLog_tooLarge;\n    bitStream >>= 4;\n    bitCount = 4;\n    *tableLogPtr = nbBits;\n    remaining = (1<<nbBits)+1;\n    threshold = 1<<nbBits;\n    nbBits++;\n\n    while ((remaining>1) && (charnum<=*maxSVPtr))\n    {\n        if (previous0)\n        {\n            unsigned n0 = charnum;\n            while ((bitStream & 0xFFFF) == 0xFFFF)\n            {\n                n0+=24;\n                if (ip < iend-5)\n                {\n                    ip+=2;\n                    bitStream = FSE_readLE32(ip) >> bitCount;\n                }\n                else\n                {\n                    bitStream >>= 16;\n                    bitCount+=16;\n                }\n            }\n            while ((bitStream & 3) == 3)\n            {\n                n0+=3;\n                bitStream>>=2;\n                bitCount+=2;\n            }\n            n0 += bitStream & 3;\n            bitCount += 2;\n            if (n0 > *maxSVPtr) return (size_t)-FSE_ERROR_maxSymbolValue_tooSmall;\n            while (charnum < n0) normalizedCounter[charnum++] = 0;\n            if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4))\n            {\n                ip += bitCount>>3;\n                bitCount &= 7;\n                bitStream = FSE_readLE32(ip) >> bitCount;\n            }\n            else\n                bitStream >>= 2;\n        }\n        {\n            const short max = (short)((2*threshold-1)-remaining);\n            short count;\n\n            if ((bitStream & (threshold-1)) < (U32)max)\n            {\n                count = (short)(bitStream & (threshold-1));\n                bitCount   += nbBits-1;\n            }\n            else\n            {\n                count = (short)(bitStream & (2*threshold-1));\n                if (count >= threshold) count -= max;\n                bitCount   += nbBits;\n            }\n\n            count--;   /* extra accuracy */\n            remaining -= FSE_abs(count);\n            normalizedCounter[charnum++] = count;\n            previous0 = !count;\n            while (remaining < threshold)\n            {\n                nbBits--;\n                threshold >>= 1;\n            }\n\n            {\n                if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4))\n                {\n                    ip += bitCount>>3;\n                    bitCount &= 7;\n                }\n                else\n                {\n                    bitCount -= (int)(8 * (iend - 4 - ip));\n                    ip = iend - 4;\n                }\n                bitStream = FSE_readLE32(ip) >> (bitCount & 31);\n            }\n        }\n    }\n    if (remaining != 1) return (size_t)-FSE_ERROR_GENERIC;\n    *maxSVPtr = charnum-1;\n\n    ip += (bitCount+7)>>3;\n    if ((size_t)(ip-istart) > hbSize) return (size_t)-FSE_ERROR_srcSize_wrong;\n    return ip-istart;\n}\n\n\n/*********************************************************\n*  Decompression (Byte symbols)\n*********************************************************/\nstatic size_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue)\n{\n    void* ptr = dt;\n    FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;\n    FSE_decode_t* const cell = (FSE_decode_t*)(ptr) + 1;   /* because dt is unsigned */\n\n    DTableH->tableLog = 0;\n    DTableH->fastMode = 0;\n\n    cell->newState = 0;\n    cell->symbol = symbolValue;\n    cell->nbBits = 0;\n\n    return 0;\n}\n\n\nstatic size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits)\n{\n    void* ptr = dt;\n    FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;\n    FSE_decode_t* const dinfo = (FSE_decode_t*)(ptr) + 1;   /* because dt is unsigned */\n    const unsigned tableSize = 1 << nbBits;\n    const unsigned tableMask = tableSize - 1;\n    const unsigned maxSymbolValue = tableMask;\n    unsigned s;\n\n    /* Sanity checks */\n    if (nbBits < 1) return (size_t)-FSE_ERROR_GENERIC;             /* min size */\n\n    /* Build Decoding Table */\n    DTableH->tableLog = (U16)nbBits;\n    DTableH->fastMode = 1;\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        dinfo[s].newState = 0;\n        dinfo[s].symbol = (BYTE)s;\n        dinfo[s].nbBits = (BYTE)nbBits;\n    }\n\n    return 0;\n}\n\n\n/* FSE_initDStream\n * Initialize a FSE_DStream_t.\n * srcBuffer must point at the beginning of an FSE block.\n * The function result is the size of the FSE_block (== srcSize).\n * If srcSize is too small, the function will return an errorCode;\n */\nstatic size_t FSE_initDStream(FSE_DStream_t* bitD, const void* srcBuffer, size_t srcSize)\n{\n    if (srcSize < 1) return (size_t)-FSE_ERROR_srcSize_wrong;\n\n    if (srcSize >=  sizeof(size_t))\n    {\n        U32 contain32;\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = (const char*)srcBuffer + srcSize - sizeof(size_t);\n        bitD->bitContainer = FSE_readLEST(bitD->ptr);\n        contain32 = ((const BYTE*)srcBuffer)[srcSize-1];\n        if (contain32 == 0) return (size_t)-FSE_ERROR_GENERIC;   /* stop bit not present */\n        bitD->bitsConsumed = 8 - FSE_highbit32(contain32);\n    }\n    else\n    {\n        U32 contain32;\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = bitD->start;\n        bitD->bitContainer = *(const BYTE*)(bitD->start);\n        switch(srcSize)\n        {\n            case 7: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[6]) << (sizeof(size_t)*8 - 16);\n                    /* fallthrough */\n            case 6: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[5]) << (sizeof(size_t)*8 - 24);\n                    /* fallthrough */\n            case 5: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[4]) << (sizeof(size_t)*8 - 32);\n                    /* fallthrough */\n            case 4: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[3]) << 24;\n                    /* fallthrough */\n            case 3: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[2]) << 16;\n                    /* fallthrough */\n            case 2: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[1]) <<  8;\n                    /* fallthrough */\n            default:;\n        }\n        contain32 = ((const BYTE*)srcBuffer)[srcSize-1];\n        if (contain32 == 0) return (size_t)-FSE_ERROR_GENERIC;   /* stop bit not present */\n        bitD->bitsConsumed = 8 - FSE_highbit32(contain32);\n        bitD->bitsConsumed += (U32)(sizeof(size_t) - srcSize)*8;\n    }\n\n    return srcSize;\n}\n\n\n/*!FSE_lookBits\n * Provides next n bits from the bitContainer.\n * bitContainer is not modified (bits are still present for next read/look)\n * On 32-bits, maxNbBits==25\n * On 64-bits, maxNbBits==57\n * return : value extracted.\n */\nstatic size_t FSE_lookBits(FSE_DStream_t* bitD, U32 nbBits)\n{\n    const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);\n}\n\nstatic size_t FSE_lookBitsFast(FSE_DStream_t* bitD, U32 nbBits)   /* only if nbBits >= 1 !! */\n{\n    const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);\n}\n\nstatic void FSE_skipBits(FSE_DStream_t* bitD, U32 nbBits)\n{\n    bitD->bitsConsumed += nbBits;\n}\n\n\n/*!FSE_readBits\n * Read next n bits from the bitContainer.\n * On 32-bits, don't read more than maxNbBits==25\n * On 64-bits, don't read more than maxNbBits==57\n * Use the fast variant *only* if n >= 1.\n * return : value extracted.\n */\nstatic size_t FSE_readBits(FSE_DStream_t* bitD, U32 nbBits)\n{\n    size_t value = FSE_lookBits(bitD, nbBits);\n    FSE_skipBits(bitD, nbBits);\n    return value;\n}\n\nstatic size_t FSE_readBitsFast(FSE_DStream_t* bitD, U32 nbBits)   /* only if nbBits >= 1 !! */\n{\n    size_t value = FSE_lookBitsFast(bitD, nbBits);\n    FSE_skipBits(bitD, nbBits);\n    return value;\n}\n\nstatic unsigned FSE_reloadDStream(FSE_DStream_t* bitD)\n{\n    if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */\n        return FSE_DStream_tooFar;\n\n    if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer))\n    {\n        bitD->ptr -= bitD->bitsConsumed >> 3;\n        bitD->bitsConsumed &= 7;\n        bitD->bitContainer = FSE_readLEST(bitD->ptr);\n        return FSE_DStream_unfinished;\n    }\n    if (bitD->ptr == bitD->start)\n    {\n        if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return FSE_DStream_endOfBuffer;\n        return FSE_DStream_completed;\n    }\n    {\n        U32 nbBytes = bitD->bitsConsumed >> 3;\n        U32 result = FSE_DStream_unfinished;\n        if (bitD->ptr - nbBytes < bitD->start)\n        {\n            nbBytes = (U32)(bitD->ptr - bitD->start);  /* ptr > start */\n            result = FSE_DStream_endOfBuffer;\n        }\n        bitD->ptr -= nbBytes;\n        bitD->bitsConsumed -= nbBytes*8;\n        bitD->bitContainer = FSE_readLEST(bitD->ptr);   /* reminder : srcSize > sizeof(bitD) */\n        return result;\n    }\n}\n\n\nstatic void FSE_initDState(FSE_DState_t* DStatePtr, FSE_DStream_t* bitD, const FSE_DTable* dt)\n{\n    const void* ptr = dt;\n    const FSE_DTableHeader* const DTableH = (const FSE_DTableHeader*)ptr;\n    DStatePtr->state = FSE_readBits(bitD, DTableH->tableLog);\n    FSE_reloadDStream(bitD);\n    DStatePtr->table = dt + 1;\n}\n\nstatic BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, FSE_DStream_t* bitD)\n{\n    const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    const U32  nbBits = DInfo.nbBits;\n    BYTE symbol = DInfo.symbol;\n    size_t lowBits = FSE_readBits(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\nstatic BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, FSE_DStream_t* bitD)\n{\n    const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    const U32 nbBits = DInfo.nbBits;\n    BYTE symbol = DInfo.symbol;\n    size_t lowBits = FSE_readBitsFast(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\n/* FSE_endOfDStream\n   Tells if bitD has reached end of bitStream or not */\n\nstatic unsigned FSE_endOfDStream(const FSE_DStream_t* bitD)\n{\n    return ((bitD->ptr == bitD->start) && (bitD->bitsConsumed == sizeof(bitD->bitContainer)*8));\n}\n\nstatic unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)\n{\n    return DStatePtr->state == 0;\n}\n\n\nFORCE_INLINE size_t FSE_decompress_usingDTable_generic(\n          void* dst, size_t maxDstSize,\n    const void* cSrc, size_t cSrcSize,\n    const FSE_DTable* dt, const unsigned fast)\n{\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* op = ostart;\n    BYTE* const omax = op + maxDstSize;\n    BYTE* const olimit = omax-3;\n\n    FSE_DStream_t bitD;\n    FSE_DState_t state1;\n    FSE_DState_t state2;\n    size_t errorCode;\n\n    /* Init */\n    errorCode = FSE_initDStream(&bitD, cSrc, cSrcSize);   /* replaced last arg by maxCompressed Size */\n    if (FSE_isError(errorCode)) return errorCode;\n\n    FSE_initDState(&state1, &bitD, dt);\n    FSE_initDState(&state2, &bitD, dt);\n\n#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD)\n\n    /* 4 symbols per loop */\n    for ( ; (FSE_reloadDStream(&bitD)==FSE_DStream_unfinished) && (op<olimit) ; op+=4)\n    {\n        op[0] = FSE_GETSYMBOL(&state1);\n\n        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            FSE_reloadDStream(&bitD);\n\n        op[1] = FSE_GETSYMBOL(&state2);\n\n        if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            { if (FSE_reloadDStream(&bitD) > FSE_DStream_unfinished) { op+=2; break; } }\n\n        op[2] = FSE_GETSYMBOL(&state1);\n\n        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            FSE_reloadDStream(&bitD);\n\n        op[3] = FSE_GETSYMBOL(&state2);\n    }\n\n    /* tail */\n    /* note : FSE_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly FSE_DStream_completed */\n    while (1)\n    {\n        if ( (FSE_reloadDStream(&bitD)>FSE_DStream_completed) || (op==omax) || (FSE_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state1))) )\n            break;\n\n        *op++ = FSE_GETSYMBOL(&state1);\n\n        if ( (FSE_reloadDStream(&bitD)>FSE_DStream_completed) || (op==omax) || (FSE_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state2))) )\n            break;\n\n        *op++ = FSE_GETSYMBOL(&state2);\n    }\n\n    /* end ? */\n    if (FSE_endOfDStream(&bitD) && FSE_endOfDState(&state1) && FSE_endOfDState(&state2))\n        return op-ostart;\n\n    if (op==omax) return (size_t)-FSE_ERROR_dstSize_tooSmall;   /* dst buffer is full, but cSrc unfinished */\n\n    return (size_t)-FSE_ERROR_corruptionDetected;\n}\n\n\nstatic size_t FSE_decompress_usingDTable(void* dst, size_t originalSize,\n                            const void* cSrc, size_t cSrcSize,\n                            const FSE_DTable* dt)\n{\n    FSE_DTableHeader DTableH;\n    memcpy(&DTableH, dt, sizeof(DTableH));   /* memcpy() into local variable, to avoid strict aliasing warning */\n\n    /* select fast mode (static) */\n    if (DTableH.fastMode) return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);\n    return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);\n}\n\n\nstatic size_t FSE_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)\n{\n    const BYTE* const istart = (const BYTE*)cSrc;\n    const BYTE* ip = istart;\n    short counting[FSE_MAX_SYMBOL_VALUE+1];\n    DTable_max_t dt;   /* Static analyzer seems unable to understand this table will be properly initialized later */\n    unsigned tableLog;\n    unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;\n    size_t errorCode;\n\n    if (cSrcSize<2) return (size_t)-FSE_ERROR_srcSize_wrong;   /* too small input size */\n\n    /* normal FSE decoding mode */\n    errorCode = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);\n    if (FSE_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return (size_t)-FSE_ERROR_srcSize_wrong;   /* too small input size */\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    errorCode = FSE_buildDTable (dt, counting, maxSymbolValue, tableLog);\n    if (FSE_isError(errorCode)) return errorCode;\n\n    /* always return, even if it is an error code */\n    return FSE_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt);\n}\n\n\n\n/* *******************************************************\n*  Huff0 : Huffman block compression\n*********************************************************/\n#define HUF_MAX_SYMBOL_VALUE 255\n#define HUF_DEFAULT_TABLELOG  12       /* used by default, when not specified */\n#define HUF_MAX_TABLELOG  12           /* max possible tableLog; for allocation purpose; can be modified */\n#define HUF_ABSOLUTEMAX_TABLELOG  16   /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */\n#if (HUF_MAX_TABLELOG > HUF_ABSOLUTEMAX_TABLELOG)\n#  error \"HUF_MAX_TABLELOG is too large !\"\n#endif\n\ntypedef struct HUF_CElt_s {\n  U16  val;\n  BYTE nbBits;\n} HUF_CElt ;\n\ntypedef struct nodeElt_s {\n    U32 count;\n    U16 parent;\n    BYTE byte;\n    BYTE nbBits;\n} nodeElt;\n\n\n/* *******************************************************\n*  Huff0 : Huffman block decompression\n*********************************************************/\ntypedef struct {\n    BYTE byte;\n    BYTE nbBits;\n} HUF_DElt;\n\nstatic size_t HUF_readDTable (U16* DTable, const void* src, size_t srcSize)\n{\n    BYTE huffWeight[HUF_MAX_SYMBOL_VALUE + 1];\n    U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];  /* large enough for values from 0 to 16 */\n    U32 weightTotal;\n    U32 maxBits;\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize;\n    size_t oSize;\n    U32 n;\n    U32 nextRankStart;\n    void* ptr = DTable+1;\n    HUF_DElt* const dt = (HUF_DElt*)ptr;\n\n    if (!srcSize) return (size_t)-FSE_ERROR_srcSize_wrong;\n    iSize = ip[0];\n\n    FSE_STATIC_ASSERT(sizeof(HUF_DElt) == sizeof(U16));   /* if compilation fails here, assertion is false */\n    //memset(huffWeight, 0, sizeof(huffWeight));   /* should not be necessary, but some analyzer complain ... */\n    if (iSize >= 128)  /* special header */\n    {\n        if (iSize >= (242))   /* RLE */\n        {\n            static int l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };\n            oSize = l[iSize-242];\n            memset(huffWeight, 1, sizeof(huffWeight));\n            iSize = 0;\n        }\n        else   /* Incompressible */\n        {\n            oSize = iSize - 127;\n            iSize = ((oSize+1)/2);\n            if (iSize+1 > srcSize) return (size_t)-FSE_ERROR_srcSize_wrong;\n            ip += 1;\n            for (n=0; n<oSize; n+=2)\n            {\n                huffWeight[n]   = ip[n/2] >> 4;\n                huffWeight[n+1] = ip[n/2] & 15;\n            }\n        }\n    }\n    else  /* header compressed with FSE (normal case) */\n    {\n        if (iSize+1 > srcSize) return (size_t)-FSE_ERROR_srcSize_wrong;\n        oSize = FSE_decompress(huffWeight, HUF_MAX_SYMBOL_VALUE, ip+1, iSize);   /* max 255 values decoded, last one is implied */\n        if (FSE_isError(oSize)) return oSize;\n    }\n\n    /* collect weight stats */\n    memset(rankVal, 0, sizeof(rankVal));\n    weightTotal = 0;\n    for (n=0; n<oSize; n++)\n    {\n        if (huffWeight[n] >= HUF_ABSOLUTEMAX_TABLELOG) return (size_t)-FSE_ERROR_corruptionDetected;\n        rankVal[huffWeight[n]]++;\n        weightTotal += (1 << huffWeight[n]) >> 1;\n    }\n    if (weightTotal == 0) return (size_t)-FSE_ERROR_corruptionDetected;\n\n    /* get last non-null symbol weight (implied, total must be 2^n) */\n    maxBits = FSE_highbit32(weightTotal) + 1;\n    if (maxBits > DTable[0]) return (size_t)-FSE_ERROR_tableLog_tooLarge;   /* DTable is too small */\n    DTable[0] = (U16)maxBits;\n    {\n        U32 total = 1 << maxBits;\n        U32 rest = total - weightTotal;\n        U32 verif = 1 << FSE_highbit32(rest);\n        U32 lastWeight = FSE_highbit32(rest) + 1;\n        if (verif != rest) return (size_t)-FSE_ERROR_corruptionDetected;    /* last value must be a clean power of 2 */\n        huffWeight[oSize] = (BYTE)lastWeight;\n        rankVal[lastWeight]++;\n    }\n\n    /* check tree construction validity */\n    if ((rankVal[1] < 2) || (rankVal[1] & 1)) return (size_t)-FSE_ERROR_corruptionDetected;   /* by construction : at least 2 elts of rank 1, must be even */\n\n    /* Prepare ranks */\n    nextRankStart = 0;\n    for (n=1; n<=maxBits; n++)\n    {\n        U32 current = nextRankStart;\n        nextRankStart += (rankVal[n] << (n-1));\n        rankVal[n] = current;\n    }\n\n    /* fill DTable */\n    for (n=0; n<=oSize; n++)\n    {\n        const U32 w = huffWeight[n];\n        const U32 length = (1 << w) >> 1;\n        U32 i;\n        HUF_DElt D;\n        D.byte = (BYTE)n; D.nbBits = (BYTE)(maxBits + 1 - w);\n        for (i = rankVal[w]; i < rankVal[w] + length; i++)\n            dt[i] = D;\n        rankVal[w] += length;\n    }\n\n    return iSize+1;\n}\n\n\nstatic BYTE HUF_decodeSymbol(FSE_DStream_t* Dstream, const HUF_DElt* dt, const U32 dtLog)\n{\n        const size_t val = FSE_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */\n        const BYTE c = dt[val].byte;\n        FSE_skipBits(Dstream, dt[val].nbBits);\n        return c;\n}\n\nstatic size_t HUF_decompress_usingDTable(   /* -3% slower when non static */\n          void* dst, size_t maxDstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U16* DTable)\n{\n    if (cSrcSize < 6) return (size_t)-FSE_ERROR_srcSize_wrong;\n    {\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* op = ostart;\n        BYTE* const omax = op + maxDstSize;\n        BYTE* const olimit = maxDstSize < 15 ? op : omax-15;\n\n        const void* ptr = DTable;\n        const HUF_DElt* const dt = (const HUF_DElt*)(ptr)+1;\n        const U32 dtLog = DTable[0];\n        size_t errorCode;\n        U32 reloadStatus;\n\n        /* Init */\n\n        const U16* jumpTable = (const U16*)cSrc;\n        const size_t length1 = FSE_readLE16(jumpTable);\n        const size_t length2 = FSE_readLE16(jumpTable+1);\n        const size_t length3 = FSE_readLE16(jumpTable+2);\n        const size_t length4 = cSrcSize - 6 - length1 - length2 - length3;   /* check coherency !! */\n        const char* const start1 = (const char*)(cSrc) + 6;\n        const char* const start2 = start1 + length1;\n        const char* const start3 = start2 + length2;\n        const char* const start4 = start3 + length3;\n        FSE_DStream_t bitD1, bitD2, bitD3, bitD4;\n\n        if (length1+length2+length3+6 >= cSrcSize) return (size_t)-FSE_ERROR_srcSize_wrong;\n\n        errorCode = FSE_initDStream(&bitD1, start1, length1);\n        if (FSE_isError(errorCode)) return errorCode;\n        errorCode = FSE_initDStream(&bitD2, start2, length2);\n        if (FSE_isError(errorCode)) return errorCode;\n        errorCode = FSE_initDStream(&bitD3, start3, length3);\n        if (FSE_isError(errorCode)) return errorCode;\n        errorCode = FSE_initDStream(&bitD4, start4, length4);\n        if (FSE_isError(errorCode)) return errorCode;\n\n        reloadStatus=FSE_reloadDStream(&bitD2);\n\n        /* 16 symbols per loop */\n        for ( ; (reloadStatus<FSE_DStream_completed) && (op<olimit);  /* D2-3-4 are supposed to be synchronized and finish together */\n            op+=16, reloadStatus = FSE_reloadDStream(&bitD2) | FSE_reloadDStream(&bitD3) | FSE_reloadDStream(&bitD4), FSE_reloadDStream(&bitD1))\n        {\n    #define HUF_DECODE_SYMBOL_0(n, Dstream) \\\n            op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog);\n\n    #define HUF_DECODE_SYMBOL_1(n, Dstream) \\\n            op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog); \\\n            if (FSE_32bits() && (HUF_MAX_TABLELOG>12)) FSE_reloadDStream(&Dstream)\n\n    #define HUF_DECODE_SYMBOL_2(n, Dstream) \\\n            op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog); \\\n            if (FSE_32bits()) FSE_reloadDStream(&Dstream)\n\n            HUF_DECODE_SYMBOL_1( 0, bitD1);\n            HUF_DECODE_SYMBOL_1( 1, bitD2);\n            HUF_DECODE_SYMBOL_1( 2, bitD3);\n            HUF_DECODE_SYMBOL_1( 3, bitD4);\n            HUF_DECODE_SYMBOL_2( 4, bitD1);\n            HUF_DECODE_SYMBOL_2( 5, bitD2);\n            HUF_DECODE_SYMBOL_2( 6, bitD3);\n            HUF_DECODE_SYMBOL_2( 7, bitD4);\n            HUF_DECODE_SYMBOL_1( 8, bitD1);\n            HUF_DECODE_SYMBOL_1( 9, bitD2);\n            HUF_DECODE_SYMBOL_1(10, bitD3);\n            HUF_DECODE_SYMBOL_1(11, bitD4);\n            HUF_DECODE_SYMBOL_0(12, bitD1);\n            HUF_DECODE_SYMBOL_0(13, bitD2);\n            HUF_DECODE_SYMBOL_0(14, bitD3);\n            HUF_DECODE_SYMBOL_0(15, bitD4);\n        }\n\n        if (reloadStatus!=FSE_DStream_completed)   /* not complete : some bitStream might be FSE_DStream_unfinished */\n            return (size_t)-FSE_ERROR_corruptionDetected;\n\n        /* tail */\n        {\n            /* bitTail = bitD1; */   /* *much* slower : -20% !??! */\n            FSE_DStream_t bitTail;\n            bitTail.ptr = bitD1.ptr;\n            bitTail.bitsConsumed = bitD1.bitsConsumed;\n            bitTail.bitContainer = bitD1.bitContainer;   /* required in case of FSE_DStream_endOfBuffer */\n            bitTail.start = start1;\n            for ( ; (FSE_reloadDStream(&bitTail) < FSE_DStream_completed) && (op<omax) ; op++)\n            {\n                HUF_DECODE_SYMBOL_0(0, bitTail);\n            }\n\n            if (FSE_endOfDStream(&bitTail))\n                return op-ostart;\n        }\n\n        if (op==omax) return (size_t)-FSE_ERROR_dstSize_tooSmall;   /* dst buffer is full, but cSrc unfinished */\n\n        return (size_t)-FSE_ERROR_corruptionDetected;\n    }\n}\n\n\nstatic size_t HUF_decompress (void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUF_CREATE_STATIC_DTABLE(DTable, HUF_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n    size_t errorCode;\n\n    errorCode = HUF_readDTable (DTable, cSrc, cSrcSize);\n    if (FSE_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return (size_t)-FSE_ERROR_srcSize_wrong;\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    return HUF_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, DTable);\n}\n\n\n#endif   /* FSE_COMMONDEFS_ONLY */\n\n/*\n    zstd - standard compression library\n    Copyright (C) 2014-2015, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n    - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n\n/****************************************************************\n*  Tuning parameters\n*****************************************************************/\n/* MEMORY_USAGE :\n*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n*  Increasing memory usage improves compression ratio\n*  Reduced memory usage can improve speed, due to cache effect */\n#define ZSTD_MEMORY_USAGE 17\n\n\n/**************************************\n   CPU Feature Detection\n**************************************/\n/*\n * Automated efficient unaligned memory access detection\n * Based on known hardware architectures\n * This list will be updated thanks to feedbacks\n */\n#if defined(CPU_HAS_EFFICIENT_UNALIGNED_MEMORY_ACCESS) \\\n    || defined(__ARM_FEATURE_UNALIGNED) \\\n    || defined(__i386__) || defined(__x86_64__) \\\n    || defined(_M_IX86) || defined(_M_X64) \\\n    || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_8__) \\\n    || (defined(_M_ARM) && (_M_ARM >= 7))\n#  define ZSTD_UNALIGNED_ACCESS 1\n#else\n#  define ZSTD_UNALIGNED_ACCESS 0\n#endif\n\n\n/********************************************************\n*  Includes\n*********************************************************/\n#include <stdlib.h>      /* calloc */\n#include <string.h>      /* memcpy, memmove */\n#include <stdio.h>       /* debug : printf */\n\n\n/********************************************************\n*  Compiler specifics\n*********************************************************/\n#ifdef __AVX2__\n#  include <immintrin.h>   /* AVX2 intrinsics */\n#endif\n\n#ifdef _MSC_VER    /* Visual Studio */\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4324)        /* disable: C4324: padded structure */\n#endif\n\n\n#ifndef MEM_ACCESS_MODULE\n#define MEM_ACCESS_MODULE\n/********************************************************\n*  Basic Types\n*********************************************************/\n#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */\n# if defined(_AIX)\n#  include <inttypes.h>\n# else\n#  include <stdint.h> /* intptr_t */\n# endif\ntypedef  uint8_t BYTE;\ntypedef uint16_t U16;\ntypedef  int16_t S16;\ntypedef uint32_t U32;\ntypedef  int32_t S32;\ntypedef uint64_t U64;\n#else\ntypedef unsigned char       BYTE;\ntypedef unsigned short      U16;\ntypedef   signed short      S16;\ntypedef unsigned int        U32;\ntypedef   signed int        S32;\ntypedef unsigned long long  U64;\n#endif\n\n#endif   /* MEM_ACCESS_MODULE */\n\n\n/********************************************************\n*  Constants\n*********************************************************/\nstatic const U32 ZSTD_magicNumber = 0xFD2FB51E;   /* 3rd version : seqNb header */\n\n#define HASH_LOG (ZSTD_MEMORY_USAGE - 2)\n#define HASH_TABLESIZE (1 << HASH_LOG)\n#define HASH_MASK (HASH_TABLESIZE - 1)\n\n#define KNUTH 2654435761\n\n#define BIT7 128\n#define BIT6  64\n#define BIT5  32\n#define BIT4  16\n\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\n#define BLOCKSIZE (128 KB)                 /* define, for static allocation */\n\n#define WORKPLACESIZE (BLOCKSIZE*3)\n#define MINMATCH 4\n#define MLbits   7\n#define LLbits   6\n#define Offbits  5\n#define MaxML  ((1<<MLbits )-1)\n#define MaxLL  ((1<<LLbits )-1)\n#define MaxOff ((1<<Offbits)-1)\n#define LitFSELog  11\n#define MLFSELog   10\n#define LLFSELog   10\n#define OffFSELog   9\n#define MAX(a,b) ((a)<(b)?(b):(a))\n#define MaxSeq MAX(MaxLL, MaxML)\n\n#define LITERAL_NOENTROPY 63\n#define COMMAND_NOENTROPY 7   /* to remove */\n\n#define ZSTD_CONTENTSIZE_ERROR   (0ULL - 2)\n\nstatic const size_t ZSTD_blockHeaderSize = 3;\nstatic const size_t ZSTD_frameHeaderSize = 4;\n\n\n/********************************************************\n*  Memory operations\n*********************************************************/\nstatic unsigned ZSTD_32bits(void) { return sizeof(void*)==4; }\n\nstatic unsigned ZSTD_isLittleEndian(void)\n{\n    const union { U32 i; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */\n    return one.c[0];\n}\n\nstatic U16    ZSTD_read16(const void* p) { U16 r; memcpy(&r, p, sizeof(r)); return r; }\n\nstatic void   ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }\n\nstatic void   ZSTD_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }\n\n#define COPY8(d,s)    { ZSTD_copy8(d,s); d+=8; s+=8; }\n\nstatic void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length)\n{\n    const BYTE* ip = (const BYTE*)src;\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + length;\n    while (op < oend) COPY8(op, ip);\n}\n\nstatic U16 ZSTD_readLE16(const void* memPtr)\n{\n    if (ZSTD_isLittleEndian()) return ZSTD_read16(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U16)((U16)p[0] + ((U16)p[1]<<8));\n    }\n}\n\nstatic U32 ZSTD_readLE24(const void* memPtr)\n{\n    return ZSTD_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16);\n}\n\nstatic U32 ZSTD_readBE32(const void* memPtr)\n{\n    const BYTE* p = (const BYTE*)memPtr;\n    return (U32)(((U32)p[0]<<24) + ((U32)p[1]<<16) + ((U32)p[2]<<8) + ((U32)p[3]<<0));\n}\n\n\n/**************************************\n*  Local structures\n***************************************/\ntypedef struct ZSTD_Cctx_s ZSTD_Cctx;\n\ntypedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;\n\ntypedef struct\n{\n    blockType_t blockType;\n    U32 origSize;\n} blockProperties_t;\n\ntypedef struct {\n    void* buffer;\n    U32*  offsetStart;\n    U32*  offset;\n    BYTE* offCodeStart;\n    BYTE* offCode;\n    BYTE* litStart;\n    BYTE* lit;\n    BYTE* litLengthStart;\n    BYTE* litLength;\n    BYTE* matchLengthStart;\n    BYTE* matchLength;\n    BYTE* dumpsStart;\n    BYTE* dumps;\n} SeqStore_t;\n\n\ntypedef struct ZSTD_Cctx_s\n{\n    const BYTE* base;\n    U32 current;\n    U32 nextUpdate;\n    SeqStore_t seqStore;\n#ifdef __AVX2__\n    __m256i hashTable[HASH_TABLESIZE>>3];\n#else\n    U32 hashTable[HASH_TABLESIZE];\n#endif\n    BYTE buffer[WORKPLACESIZE];\n} cctxi_t;\n\n\n\n\n/**************************************\n*  Error Management\n**************************************/\n/* published entry point */\nunsigned ZSTDv01_isError(size_t code) { return ERR_isError(code); }\n\n\n/**************************************\n*  Tool functions\n**************************************/\n#define ZSTD_VERSION_MAJOR    0    /* for breaking interface changes  */\n#define ZSTD_VERSION_MINOR    1    /* for new (non-breaking) interface capabilities */\n#define ZSTD_VERSION_RELEASE  3    /* for tweaks, bug-fixes, or development */\n#define ZSTD_VERSION_NUMBER  (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)\n\n/**************************************************************\n*   Decompression code\n**************************************************************/\n\nstatic size_t ZSTDv01_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)\n{\n    const BYTE* const in = (const BYTE* const)src;\n    BYTE headerFlags;\n    U32 cSize;\n\n    if (srcSize < 3) return ERROR(srcSize_wrong);\n\n    headerFlags = *in;\n    cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);\n\n    bpPtr->blockType = (blockType_t)(headerFlags >> 6);\n    bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;\n\n    if (bpPtr->blockType == bt_end) return 0;\n    if (bpPtr->blockType == bt_rle) return 1;\n    return cSize;\n}\n\n\nstatic size_t ZSTD_copyUncompressedBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall);\n    if (srcSize > 0) {\n        memcpy(dst, src, srcSize);\n    }\n    return srcSize;\n}\n\n\nstatic size_t ZSTD_decompressLiterals(void* ctx,\n                                      void* dst, size_t maxDstSize,\n                                const void* src, size_t srcSize)\n{\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + maxDstSize;\n    const BYTE* ip = (const BYTE*)src;\n    size_t errorCode;\n    size_t litSize;\n\n    /* check : minimum 2, for litSize, +1, for content */\n    if (srcSize <= 3) return ERROR(corruption_detected);\n\n    litSize = ip[1] + (ip[0]<<8);\n    litSize += ((ip[-3] >> 3) & 7) << 16;   /* mmmmh.... */\n    op = oend - litSize;\n\n    (void)ctx;\n    if (litSize > maxDstSize) return ERROR(dstSize_tooSmall);\n    errorCode = HUF_decompress(op, litSize, ip+2, srcSize-2);\n    if (FSE_isError(errorCode)) return ERROR(GENERIC);\n    return litSize;\n}\n\n\nstatic size_t ZSTDv01_decodeLiteralsBlock(void* ctx,\n                                void* dst, size_t maxDstSize,\n                          const BYTE** litStart, size_t* litSize,\n                          const void* src, size_t srcSize)\n{\n    const BYTE* const istart = (const BYTE* const)src;\n    const BYTE* ip = istart;\n    BYTE* const ostart = (BYTE* const)dst;\n    BYTE* const oend = ostart + maxDstSize;\n    blockProperties_t litbp;\n\n    size_t litcSize = ZSTDv01_getcBlockSize(src, srcSize, &litbp);\n    if (ZSTDv01_isError(litcSize)) return litcSize;\n    if (litcSize > srcSize - ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);\n    ip += ZSTD_blockHeaderSize;\n\n    switch(litbp.blockType)\n    {\n    case bt_raw:\n        *litStart = ip;\n        ip += litcSize;\n        *litSize = litcSize;\n        break;\n    case bt_rle:\n        {\n            size_t rleSize = litbp.origSize;\n            if (rleSize>maxDstSize) return ERROR(dstSize_tooSmall);\n            if (!srcSize) return ERROR(srcSize_wrong);\n            if (rleSize > 0) {\n                memset(oend - rleSize, *ip, rleSize);\n            }\n            *litStart = oend - rleSize;\n            *litSize = rleSize;\n            ip++;\n            break;\n        }\n    case bt_compressed:\n        {\n            size_t decodedLitSize = ZSTD_decompressLiterals(ctx, dst, maxDstSize, ip, litcSize);\n            if (ZSTDv01_isError(decodedLitSize)) return decodedLitSize;\n            *litStart = oend - decodedLitSize;\n            *litSize = decodedLitSize;\n            ip += litcSize;\n            break;\n        }\n    case bt_end:\n    default:\n        return ERROR(GENERIC);\n    }\n\n    return ip-istart;\n}\n\n\nstatic size_t ZSTDv01_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLengthPtr,\n                         FSE_DTable* DTableLL, FSE_DTable* DTableML, FSE_DTable* DTableOffb,\n                         const void* src, size_t srcSize)\n{\n    const BYTE* const istart = (const BYTE* const)src;\n    const BYTE* ip = istart;\n    const BYTE* const iend = istart + srcSize;\n    U32 LLtype, Offtype, MLtype;\n    U32 LLlog, Offlog, MLlog;\n    size_t dumpsLength;\n\n    /* check */\n    if (srcSize < 5) return ERROR(srcSize_wrong);\n\n    /* SeqHead */\n    *nbSeq = ZSTD_readLE16(ip); ip+=2;\n    LLtype  = *ip >> 6;\n    Offtype = (*ip >> 4) & 3;\n    MLtype  = (*ip >> 2) & 3;\n    if (*ip & 2)\n    {\n        dumpsLength  = ip[2];\n        dumpsLength += ip[1] << 8;\n        ip += 3;\n    }\n    else\n    {\n        dumpsLength  = ip[1];\n        dumpsLength += (ip[0] & 1) << 8;\n        ip += 2;\n    }\n    *dumpsPtr = ip;\n    ip += dumpsLength;\n    *dumpsLengthPtr = dumpsLength;\n\n    /* check */\n    if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are \"raw\", hence no header, but at least xxLog bits per type */\n\n    /* sequences */\n    {\n        S16 norm[MaxML+1];    /* assumption : MaxML >= MaxLL and MaxOff */\n        size_t headerSize;\n\n        /* Build DTables */\n        switch(LLtype)\n        {\n        case bt_rle :\n            LLlog = 0;\n            FSE_buildDTable_rle(DTableLL, *ip++); break;\n        case bt_raw :\n            LLlog = LLbits;\n            FSE_buildDTable_raw(DTableLL, LLbits); break;\n        default :\n            {   U32 max = MaxLL;\n                headerSize = FSE_readNCount(norm, &max, &LLlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (LLlog > LLFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableLL, norm, max, LLlog);\n        }   }\n\n        switch(Offtype)\n        {\n        case bt_rle :\n            Offlog = 0;\n            if (ip > iend-2) return ERROR(srcSize_wrong); /* min : \"raw\", hence no header, but at least xxLog bits */\n            FSE_buildDTable_rle(DTableOffb, *ip++); break;\n        case bt_raw :\n            Offlog = Offbits;\n            FSE_buildDTable_raw(DTableOffb, Offbits); break;\n        default :\n            {   U32 max = MaxOff;\n                headerSize = FSE_readNCount(norm, &max, &Offlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (Offlog > OffFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableOffb, norm, max, Offlog);\n        }   }\n\n        switch(MLtype)\n        {\n        case bt_rle :\n            MLlog = 0;\n            if (ip > iend-2) return ERROR(srcSize_wrong); /* min : \"raw\", hence no header, but at least xxLog bits */\n            FSE_buildDTable_rle(DTableML, *ip++); break;\n        case bt_raw :\n            MLlog = MLbits;\n            FSE_buildDTable_raw(DTableML, MLbits); break;\n        default :\n            {   U32 max = MaxML;\n                headerSize = FSE_readNCount(norm, &max, &MLlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (MLlog > MLFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableML, norm, max, MLlog);\n    }   }   }\n\n    return ip-istart;\n}\n\n\ntypedef struct {\n    size_t litLength;\n    size_t offset;\n    size_t matchLength;\n} seq_t;\n\ntypedef struct {\n    FSE_DStream_t DStream;\n    FSE_DState_t stateLL;\n    FSE_DState_t stateOffb;\n    FSE_DState_t stateML;\n    size_t prevOffset;\n    const BYTE* dumps;\n    const BYTE* dumpsEnd;\n} seqState_t;\n\n\nstatic void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)\n{\n    size_t litLength;\n    size_t prevOffset;\n    size_t offset;\n    size_t matchLength;\n    const BYTE* dumps = seqState->dumps;\n    const BYTE* const de = seqState->dumpsEnd;\n\n    /* Literal length */\n    litLength = FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream));\n    prevOffset = litLength ? seq->offset : seqState->prevOffset;\n    seqState->prevOffset = seq->offset;\n    if (litLength == MaxLL)\n    {\n        const U32 add = dumps<de ? *dumps++ : 0;\n        if (add < 255) litLength += add;\n        else\n        {\n            if (dumps<=(de-3))\n            {\n                litLength = ZSTD_readLE24(dumps);\n                dumps += 3;\n            }\n        }\n    }\n\n    /* Offset */\n    {\n        U32 offsetCode, nbBits;\n        offsetCode = FSE_decodeSymbol(&(seqState->stateOffb), &(seqState->DStream));\n        if (ZSTD_32bits()) FSE_reloadDStream(&(seqState->DStream));\n        nbBits = offsetCode - 1;\n        if (offsetCode==0) nbBits = 0;   /* cmove */\n        offset = ((size_t)1 << (nbBits & ((sizeof(offset)*8)-1))) + FSE_readBits(&(seqState->DStream), nbBits);\n        if (ZSTD_32bits()) FSE_reloadDStream(&(seqState->DStream));\n        if (offsetCode==0) offset = prevOffset;\n    }\n\n    /* MatchLength */\n    matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream));\n    if (matchLength == MaxML)\n    {\n        const U32 add = dumps<de ? *dumps++ : 0;\n        if (add < 255) matchLength += add;\n        else\n        {\n            if (dumps<=(de-3))\n            {\n                matchLength = ZSTD_readLE24(dumps);\n                dumps += 3;\n            }\n        }\n    }\n    matchLength += MINMATCH;\n\n    /* save result */\n    seq->litLength = litLength;\n    seq->offset = offset;\n    seq->matchLength = matchLength;\n    seqState->dumps = dumps;\n}\n\n\nstatic size_t ZSTD_execSequence(BYTE* op,\n                                seq_t sequence,\n                                const BYTE** litPtr, const BYTE* const litLimit,\n                                BYTE* const base, BYTE* const oend)\n{\n    static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4};   /* added */\n    static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11};   /* subtracted */\n    const BYTE* const ostart = op;\n    BYTE* const oLitEnd = op + sequence.litLength;\n    const size_t litLength = sequence.litLength;\n    BYTE* const endMatch = op + litLength + sequence.matchLength;    /* risk : address space overflow (32-bits) */\n    const BYTE* const litEnd = *litPtr + litLength;\n\n    /* checks */\n    size_t const seqLength = sequence.litLength + sequence.matchLength;\n\n    if (seqLength > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);\n    if (sequence.litLength > (size_t)(litLimit - *litPtr)) return ERROR(corruption_detected);\n    /* Now we know there are no overflow in literal nor match lengths, can use pointer checks */\n    if (sequence.offset > (U32)(oLitEnd - base)) return ERROR(corruption_detected);\n\n    if (endMatch > oend) return ERROR(dstSize_tooSmall);   /* overwrite beyond dst buffer */\n    if (litEnd > litLimit) return ERROR(corruption_detected);   /* overRead beyond lit buffer */\n    if (sequence.matchLength > (size_t)(*litPtr-op)) return ERROR(dstSize_tooSmall);  /* overwrite literal segment */\n\n    /* copy Literals */\n    ZSTD_memmove(op, *litPtr, sequence.litLength);   /* note : v0.1 seems to allow scenarios where output or input are close to end of buffer */\n\n    op += litLength;\n    *litPtr = litEnd;   /* update for next sequence */\n\n    /* check : last match must be at a minimum distance of 8 from end of dest buffer */\n    if (oend-op < 8) return ERROR(dstSize_tooSmall);\n\n    /* copy Match */\n    {\n        const U32 overlapRisk = (((size_t)(litEnd - endMatch)) < 12);\n        const BYTE* match = op - sequence.offset;            /* possible underflow at op - offset ? */\n        size_t qutt = 12;\n        U64 saved[2];\n\n        /* check */\n        if (match < base) return ERROR(corruption_detected);\n        if (sequence.offset > (size_t)base) return ERROR(corruption_detected);\n\n        /* save beginning of literal sequence, in case of write overlap */\n        if (overlapRisk)\n        {\n            if ((endMatch + qutt) > oend) qutt = oend-endMatch;\n            memcpy(saved, endMatch, qutt);\n        }\n\n        if (sequence.offset < 8)\n        {\n            const int dec64 = dec64table[sequence.offset];\n            op[0] = match[0];\n            op[1] = match[1];\n            op[2] = match[2];\n            op[3] = match[3];\n            match += dec32table[sequence.offset];\n            ZSTD_copy4(op+4, match);\n            match -= dec64;\n        } else { ZSTD_copy8(op, match); }\n        op += 8; match += 8;\n\n        if (endMatch > oend-(16-MINMATCH))\n        {\n            if (op < oend-8)\n            {\n                ZSTD_wildcopy(op, match, (oend-8) - op);\n                match += (oend-8) - op;\n                op = oend-8;\n            }\n            while (op<endMatch) *op++ = *match++;\n        }\n        else\n            ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8);   /* works even if matchLength < 8 */\n\n        /* restore, in case of overlap */\n        if (overlapRisk) memcpy(endMatch, saved, qutt);\n    }\n\n    return endMatch-ostart;\n}\n\ntypedef struct ZSTDv01_Dctx_s\n{\n    U32 LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];\n    U32 OffTable[FSE_DTABLE_SIZE_U32(OffFSELog)];\n    U32 MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];\n    void* previousDstEnd;\n    void* base;\n    size_t expected;\n    blockType_t bType;\n    U32 phase;\n} dctx_t;\n\n\nstatic size_t ZSTD_decompressSequences(\n                               void* ctx,\n                               void* dst, size_t maxDstSize,\n                         const void* seqStart, size_t seqSize,\n                         const BYTE* litStart, size_t litSize)\n{\n    dctx_t* dctx = (dctx_t*)ctx;\n    const BYTE* ip = (const BYTE*)seqStart;\n    const BYTE* const iend = ip + seqSize;\n    BYTE* const ostart = (BYTE* const)dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + maxDstSize;\n    size_t errorCode = 0;\n    size_t dumpsLength = 0;\n    const BYTE* litPtr = litStart;\n    const BYTE* const litEnd = litStart + litSize;\n    int nbSeq = 0;\n    const BYTE* dumps = NULL;\n    U32* DTableLL = dctx->LLTable;\n    U32* DTableML = dctx->MLTable;\n    U32* DTableOffb = dctx->OffTable;\n    BYTE* const base = (BYTE*) (dctx->base);\n\n    /* Build Decoding Tables */\n    errorCode = ZSTDv01_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,\n                                      DTableLL, DTableML, DTableOffb,\n                                      ip, iend-ip);\n    if (ZSTDv01_isError(errorCode)) return errorCode;\n    ip += errorCode;\n\n    /* Regen sequences */\n    {\n        seq_t sequence;\n        seqState_t seqState;\n\n        memset(&sequence, 0, sizeof(sequence));\n        seqState.dumps = dumps;\n        seqState.dumpsEnd = dumps + dumpsLength;\n        seqState.prevOffset = 1;\n        errorCode = FSE_initDStream(&(seqState.DStream), ip, iend-ip);\n        if (FSE_isError(errorCode)) return ERROR(corruption_detected);\n        FSE_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);\n        FSE_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);\n        FSE_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);\n\n        for ( ; (FSE_reloadDStream(&(seqState.DStream)) <= FSE_DStream_completed) && (nbSeq>0) ; )\n        {\n            size_t oneSeqSize;\n            nbSeq--;\n            ZSTD_decodeSequence(&sequence, &seqState);\n            oneSeqSize = ZSTD_execSequence(op, sequence, &litPtr, litEnd, base, oend);\n            if (ZSTDv01_isError(oneSeqSize)) return oneSeqSize;\n            op += oneSeqSize;\n        }\n\n        /* check if reached exact end */\n        if ( !FSE_endOfDStream(&(seqState.DStream)) ) return ERROR(corruption_detected);   /* requested too much : data is corrupted */\n        if (nbSeq<0) return ERROR(corruption_detected);   /* requested too many sequences : data is corrupted */\n\n        /* last literal segment */\n        {\n            size_t lastLLSize = litEnd - litPtr;\n            if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);\n            if (lastLLSize > 0) {\n                if (op != litPtr) memmove(op, litPtr, lastLLSize);\n                op += lastLLSize;\n            }\n        }\n    }\n\n    return op-ostart;\n}\n\n\nstatic size_t ZSTD_decompressBlock(\n                            void* ctx,\n                            void* dst, size_t maxDstSize,\n                      const void* src, size_t srcSize)\n{\n    /* blockType == blockCompressed, srcSize is trusted */\n    const BYTE* ip = (const BYTE*)src;\n    const BYTE* litPtr = NULL;\n    size_t litSize = 0;\n    size_t errorCode;\n\n    /* Decode literals sub-block */\n    errorCode = ZSTDv01_decodeLiteralsBlock(ctx, dst, maxDstSize, &litPtr, &litSize, src, srcSize);\n    if (ZSTDv01_isError(errorCode)) return errorCode;\n    ip += errorCode;\n    srcSize -= errorCode;\n\n    return ZSTD_decompressSequences(ctx, dst, maxDstSize, ip, srcSize, litPtr, litSize);\n}\n\n\nsize_t ZSTDv01_decompressDCtx(void* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n    const BYTE* iend = ip + srcSize;\n    BYTE* const ostart = (BYTE* const)dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + maxDstSize;\n    size_t remainingSize = srcSize;\n    U32 magicNumber;\n    size_t errorCode=0;\n    blockProperties_t blockProperties = { 0 };\n\n    /* Frame Header */\n    if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);\n    magicNumber = ZSTD_readBE32(src);\n    if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);\n    ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;\n\n    /* Loop on each block */\n    while (1)\n    {\n        size_t blockSize = ZSTDv01_getcBlockSize(ip, iend-ip, &blockProperties);\n        if (ZSTDv01_isError(blockSize)) return blockSize;\n\n        ip += ZSTD_blockHeaderSize;\n        remainingSize -= ZSTD_blockHeaderSize;\n        if (blockSize > remainingSize) return ERROR(srcSize_wrong);\n\n        switch(blockProperties.blockType)\n        {\n        case bt_compressed:\n            errorCode = ZSTD_decompressBlock(ctx, op, oend-op, ip, blockSize);\n            break;\n        case bt_raw :\n            errorCode = ZSTD_copyUncompressedBlock(op, oend-op, ip, blockSize);\n            break;\n        case bt_rle :\n            return ERROR(GENERIC);   /* not yet supported */\n            break;\n        case bt_end :\n            /* end of frame */\n            if (remainingSize) return ERROR(srcSize_wrong);\n            break;\n        default:\n            return ERROR(GENERIC);\n        }\n        if (blockSize == 0) break;   /* bt_end */\n\n        if (ZSTDv01_isError(errorCode)) return errorCode;\n        op += errorCode;\n        ip += blockSize;\n        remainingSize -= blockSize;\n    }\n\n    return op-ostart;\n}\n\nsize_t ZSTDv01_decompress(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    dctx_t ctx;\n    ctx.base = dst;\n    return ZSTDv01_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize);\n}\n\n/* ZSTD_errorFrameSizeInfoLegacy() :\n   assumes `cSize` and `dBound` are _not_ NULL */\nstatic void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)\n{\n    *cSize = ret;\n    *dBound = ZSTD_CONTENTSIZE_ERROR;\n}\n\nvoid ZSTDv01_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)\n{\n    const BYTE* ip = (const BYTE*)src;\n    size_t remainingSize = srcSize;\n    size_t nbBlocks = 0;\n    U32 magicNumber;\n    blockProperties_t blockProperties;\n\n    /* Frame Header */\n    if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) {\n        ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n        return;\n    }\n    magicNumber = ZSTD_readBE32(src);\n    if (magicNumber != ZSTD_magicNumber) {\n        ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));\n        return;\n    }\n    ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;\n\n    /* Loop on each block */\n    while (1)\n    {\n        size_t blockSize = ZSTDv01_getcBlockSize(ip, remainingSize, &blockProperties);\n        if (ZSTDv01_isError(blockSize)) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, blockSize);\n            return;\n        }\n\n        ip += ZSTD_blockHeaderSize;\n        remainingSize -= ZSTD_blockHeaderSize;\n        if (blockSize > remainingSize) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n            return;\n        }\n\n        if (blockSize == 0) break;   /* bt_end */\n\n        ip += blockSize;\n        remainingSize -= blockSize;\n        nbBlocks++;\n    }\n\n    *cSize = ip - (const BYTE*)src;\n    *dBound = nbBlocks * BLOCKSIZE;\n}\n\n/*******************************\n*  Streaming Decompression API\n*******************************/\n\nsize_t ZSTDv01_resetDCtx(ZSTDv01_Dctx* dctx)\n{\n    dctx->expected = ZSTD_frameHeaderSize;\n    dctx->phase = 0;\n    dctx->previousDstEnd = NULL;\n    dctx->base = NULL;\n    return 0;\n}\n\nZSTDv01_Dctx* ZSTDv01_createDCtx(void)\n{\n    ZSTDv01_Dctx* dctx = (ZSTDv01_Dctx*)malloc(sizeof(ZSTDv01_Dctx));\n    if (dctx==NULL) return NULL;\n    ZSTDv01_resetDCtx(dctx);\n    return dctx;\n}\n\nsize_t ZSTDv01_freeDCtx(ZSTDv01_Dctx* dctx)\n{\n    free(dctx);\n    return 0;\n}\n\nsize_t ZSTDv01_nextSrcSizeToDecompress(ZSTDv01_Dctx* dctx)\n{\n    return ((dctx_t*)dctx)->expected;\n}\n\nsize_t ZSTDv01_decompressContinue(ZSTDv01_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    dctx_t* ctx = (dctx_t*)dctx;\n\n    /* Sanity check */\n    if (srcSize != ctx->expected) return ERROR(srcSize_wrong);\n    if (dst != ctx->previousDstEnd)  /* not contiguous */\n        ctx->base = dst;\n\n    /* Decompress : frame header */\n    if (ctx->phase == 0)\n    {\n        /* Check frame magic header */\n        U32 magicNumber = ZSTD_readBE32(src);\n        if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);\n        ctx->phase = 1;\n        ctx->expected = ZSTD_blockHeaderSize;\n        return 0;\n    }\n\n    /* Decompress : block header */\n    if (ctx->phase == 1)\n    {\n        blockProperties_t bp;\n        size_t blockSize = ZSTDv01_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);\n        if (ZSTDv01_isError(blockSize)) return blockSize;\n        if (bp.blockType == bt_end)\n        {\n            ctx->expected = 0;\n            ctx->phase = 0;\n        }\n        else\n        {\n            ctx->expected = blockSize;\n            ctx->bType = bp.blockType;\n            ctx->phase = 2;\n        }\n\n        return 0;\n    }\n\n    /* Decompress : block content */\n    {\n        size_t rSize;\n        switch(ctx->bType)\n        {\n        case bt_compressed:\n            rSize = ZSTD_decompressBlock(ctx, dst, maxDstSize, src, srcSize);\n            break;\n        case bt_raw :\n            rSize = ZSTD_copyUncompressedBlock(dst, maxDstSize, src, srcSize);\n            break;\n        case bt_rle :\n            return ERROR(GENERIC);   /* not yet handled */\n            break;\n        case bt_end :   /* should never happen (filtered at phase 1) */\n            rSize = 0;\n            break;\n        default:\n            return ERROR(GENERIC);\n        }\n        ctx->phase = 1;\n        ctx->expected = ZSTD_blockHeaderSize;\n        if (ZSTDv01_isError(rSize)) return rSize;\n        ctx->previousDstEnd = (void*)( ((char*)dst) + rSize);\n        return rSize;\n    }\n\n}\n"
  },
  {
    "path": "lib/legacy/zstd_v01.h",
    "content": "/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_V01_H_28739879432\n#define ZSTD_V01_H_28739879432\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* *************************************\n*  Includes\n***************************************/\n#include <stddef.h>   /* size_t */\n\n\n/* *************************************\n*  Simple one-step function\n***************************************/\n/**\nZSTDv01_decompress() : decompress ZSTD frames compliant with v0.1.x format\n    compressedSize : is the exact source size\n    maxOriginalSize : is the size of the 'dst' buffer, which must be already allocated.\n                      It must be equal or larger than originalSize, otherwise decompression will fail.\n    return : the number of bytes decompressed into destination buffer (originalSize)\n             or an errorCode if it fails (which can be tested using ZSTDv01_isError())\n*/\nsize_t ZSTDv01_decompress( void* dst, size_t maxOriginalSize,\n                     const void* src, size_t compressedSize);\n\n /**\n ZSTDv01_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.1.x format\n     srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'\n     cSize (output parameter)  : the number of bytes that would be read to decompress this frame\n                                 or an error code if it fails (which can be tested using ZSTDv01_isError())\n     dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame\n                                 or ZSTD_CONTENTSIZE_ERROR if an error occurs\n\n     note : assumes `cSize` and `dBound` are _not_ NULL.\n */\nvoid ZSTDv01_findFrameSizeInfoLegacy(const void *src, size_t srcSize,\n                                     size_t* cSize, unsigned long long* dBound);\n\n/**\nZSTDv01_isError() : tells if the result of ZSTDv01_decompress() is an error\n*/\nunsigned ZSTDv01_isError(size_t code);\n\n\n/* *************************************\n*  Advanced functions\n***************************************/\ntypedef struct ZSTDv01_Dctx_s ZSTDv01_Dctx;\nZSTDv01_Dctx* ZSTDv01_createDCtx(void);\nsize_t ZSTDv01_freeDCtx(ZSTDv01_Dctx* dctx);\n\nsize_t ZSTDv01_decompressDCtx(void* ctx,\n                              void* dst, size_t maxOriginalSize,\n                        const void* src, size_t compressedSize);\n\n/* *************************************\n*  Streaming functions\n***************************************/\nsize_t ZSTDv01_resetDCtx(ZSTDv01_Dctx* dctx);\n\nsize_t ZSTDv01_nextSrcSizeToDecompress(ZSTDv01_Dctx* dctx);\nsize_t ZSTDv01_decompressContinue(ZSTDv01_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize);\n/**\n  Use above functions alternatively.\n  ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue().\n  ZSTD_decompressContinue() will use previous data blocks to improve compression if they are located prior to current block.\n  Result is the number of bytes regenerated within 'dst'.\n  It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header.\n*/\n\n/* *************************************\n*  Prefix - version detection\n***************************************/\n#define ZSTDv01_magicNumber   0xFD2FB51E   /* Big Endian version */\n#define ZSTDv01_magicNumberLE 0x1EB52FFD   /* Little Endian version */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* ZSTD_V01_H_28739879432 */\n"
  },
  {
    "path": "lib/legacy/zstd_v02.c",
    "content": "/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n#include <stddef.h>    /* size_t, ptrdiff_t */\n#include \"zstd_v02.h\"\n#include \"../common/compiler.h\"\n#include \"../common/error_private.h\"\n\n\n/******************************************\n*  Compiler-specific\n******************************************/\n#if defined(_MSC_VER)   /* Visual Studio */\n#   include <stdlib.h>  /* _byteswap_ulong */\n#   include <intrin.h>  /* _byteswap_* */\n#endif\n\n\n/* ******************************************************************\n   mem.h\n   low-level memory access routines\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef MEM_H_MODULE\n#define MEM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/******************************************\n*  Includes\n******************************************/\n#include <stddef.h>    /* size_t, ptrdiff_t */\n#include <string.h>    /* memcpy */\n\n\n/****************************************************************\n*  Basic Types\n*****************************************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n# if defined(_AIX)\n#  include <inttypes.h>\n# else\n#  include <stdint.h> /* intptr_t */\n# endif\n  typedef  uint8_t BYTE;\n  typedef uint16_t U16;\n  typedef  int16_t S16;\n  typedef uint32_t U32;\n  typedef  int32_t S32;\n  typedef uint64_t U64;\n  typedef  int64_t S64;\n#else\n  typedef unsigned char       BYTE;\n  typedef unsigned short      U16;\n  typedef   signed short      S16;\n  typedef unsigned int        U32;\n  typedef   signed int        S32;\n  typedef unsigned long long  U64;\n  typedef   signed long long  S64;\n#endif\n\n\n/****************************************************************\n*  Memory I/O\n*****************************************************************/\n\nMEM_STATIC unsigned MEM_32bits(void) { return sizeof(void*)==4; }\nMEM_STATIC unsigned MEM_64bits(void) { return sizeof(void*)==8; }\n\nMEM_STATIC unsigned MEM_isLittleEndian(void)\n{\n    const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */\n    return one.c[0];\n}\n\nMEM_STATIC U16 MEM_read16(const void* memPtr)\n{\n    U16 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U32 MEM_read32(const void* memPtr)\n{\n    U32 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U64 MEM_read64(const void* memPtr)\n{\n    U64 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value)\n{\n    memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC U16 MEM_readLE16(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read16(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U16)(p[0] + (p[1]<<8));\n    }\n}\n\nMEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)\n{\n    if (MEM_isLittleEndian())\n    {\n        MEM_write16(memPtr, val);\n    }\n    else\n    {\n        BYTE* p = (BYTE*)memPtr;\n        p[0] = (BYTE)val;\n        p[1] = (BYTE)(val>>8);\n    }\n}\n\nMEM_STATIC U32 MEM_readLE24(const void* memPtr)\n{\n    return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16);\n}\n\nMEM_STATIC U32 MEM_readLE32(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read32(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U32)((U32)p[0] + ((U32)p[1]<<8) + ((U32)p[2]<<16) + ((U32)p[3]<<24));\n    }\n}\n\n\nMEM_STATIC U64 MEM_readLE64(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read64(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U64)((U64)p[0] + ((U64)p[1]<<8) + ((U64)p[2]<<16) + ((U64)p[3]<<24)\n                     + ((U64)p[4]<<32) + ((U64)p[5]<<40) + ((U64)p[6]<<48) + ((U64)p[7]<<56));\n    }\n}\n\n\nMEM_STATIC size_t MEM_readLEST(const void* memPtr)\n{\n    if (MEM_32bits())\n        return (size_t)MEM_readLE32(memPtr);\n    else\n        return (size_t)MEM_readLE64(memPtr);\n}\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* MEM_H_MODULE */\n\n\n/* ******************************************************************\n   bitstream\n   Part of NewGen Entropy library\n   header file (to include)\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef BITSTREAM_H_MODULE\n#define BITSTREAM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/*\n*  This API consists of small unitary functions, which highly benefit from being inlined.\n*  Since link-time-optimization is not available for all compilers,\n*  these functions are defined into a .h to be included.\n*/\n\n\n/**********************************************\n*  bitStream decompression API (read backward)\n**********************************************/\ntypedef struct\n{\n    size_t   bitContainer;\n    unsigned bitsConsumed;\n    const char* ptr;\n    const char* start;\n} BIT_DStream_t;\n\ntypedef enum { BIT_DStream_unfinished = 0,\n               BIT_DStream_endOfBuffer = 1,\n               BIT_DStream_completed = 2,\n               BIT_DStream_overflow = 3 } BIT_DStream_status;  /* result of BIT_reloadDStream() */\n               /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */\n\nMEM_STATIC size_t   BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize);\nMEM_STATIC size_t   BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);\nMEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD);\nMEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);\n\n\n/******************************************\n*  unsafe API\n******************************************/\nMEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);\n/* faster, but works only if nbBits >= 1 */\n\n\n\n/****************************************************************\n*  Helper functions\n****************************************************************/\nMEM_STATIC unsigned BIT_highbit32 (U32 val)\n{\n#   if defined(_MSC_VER)   /* Visual */\n    unsigned long r;\n    return _BitScanReverse(&r, val) ? (unsigned)r : 0;\n#   elif defined(__GNUC__) && (__GNUC__ >= 3)   /* Use GCC Intrinsic */\n    return __builtin_clz (val) ^ 31;\n#   else   /* Software version */\n    static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };\n    U32 v = val;\n    unsigned r;\n    v |= v >> 1;\n    v |= v >> 2;\n    v |= v >> 4;\n    v |= v >> 8;\n    v |= v >> 16;\n    r = DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];\n    return r;\n#   endif\n}\n\n\n\n/**********************************************************\n* bitStream decoding\n**********************************************************/\n\n/*!BIT_initDStream\n*  Initialize a BIT_DStream_t.\n*  @bitD : a pointer to an already allocated BIT_DStream_t structure\n*  @srcBuffer must point at the beginning of a bitStream\n*  @srcSize must be the exact size of the bitStream\n*  @result : size of stream (== srcSize) or an errorCode if a problem is detected\n*/\nMEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize)\n{\n    if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }\n\n    if (srcSize >=  sizeof(size_t))   /* normal case */\n    {\n        U32 contain32;\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = (const char*)srcBuffer + srcSize - sizeof(size_t);\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        contain32 = ((const BYTE*)srcBuffer)[srcSize-1];\n        if (contain32 == 0) return ERROR(GENERIC);   /* endMark not present */\n        bitD->bitsConsumed = 8 - BIT_highbit32(contain32);\n    }\n    else\n    {\n        U32 contain32;\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = bitD->start;\n        bitD->bitContainer = *(const BYTE*)(bitD->start);\n        switch(srcSize)\n        {\n            case 7: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[6]) << (sizeof(size_t)*8 - 16);\n                    /* fallthrough */\n            case 6: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[5]) << (sizeof(size_t)*8 - 24);\n                    /* fallthrough */\n            case 5: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[4]) << (sizeof(size_t)*8 - 32);\n                    /* fallthrough */\n            case 4: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[3]) << 24;\n                    /* fallthrough */\n            case 3: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[2]) << 16;\n                    /* fallthrough */\n            case 2: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[1]) <<  8;\n                    /* fallthrough */\n            default:;\n        }\n        contain32 = ((const BYTE*)srcBuffer)[srcSize-1];\n        if (contain32 == 0) return ERROR(GENERIC);   /* endMark not present */\n        bitD->bitsConsumed = 8 - BIT_highbit32(contain32);\n        bitD->bitsConsumed += (U32)(sizeof(size_t) - srcSize)*8;\n    }\n\n    return srcSize;\n}\n\nMEM_STATIC size_t BIT_lookBits(BIT_DStream_t* bitD, U32 nbBits)\n{\n    const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);\n}\n\n/*! BIT_lookBitsFast :\n*   unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BIT_lookBitsFast(BIT_DStream_t* bitD, U32 nbBits)\n{\n    const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);\n}\n\nMEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)\n{\n    bitD->bitsConsumed += nbBits;\n}\n\nMEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits)\n{\n    size_t value = BIT_lookBits(bitD, nbBits);\n    BIT_skipBits(bitD, nbBits);\n    return value;\n}\n\n/*!BIT_readBitsFast :\n*  unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)\n{\n    size_t value = BIT_lookBitsFast(bitD, nbBits);\n    BIT_skipBits(bitD, nbBits);\n    return value;\n}\n\nMEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)\n{\n    if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */\n        return BIT_DStream_overflow;\n\n    if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer))\n    {\n        bitD->ptr -= bitD->bitsConsumed >> 3;\n        bitD->bitsConsumed &= 7;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        return BIT_DStream_unfinished;\n    }\n    if (bitD->ptr == bitD->start)\n    {\n        if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;\n        return BIT_DStream_completed;\n    }\n    {\n        U32 nbBytes = bitD->bitsConsumed >> 3;\n        BIT_DStream_status result = BIT_DStream_unfinished;\n        if (bitD->ptr - nbBytes < bitD->start)\n        {\n            nbBytes = (U32)(bitD->ptr - bitD->start);  /* ptr > start */\n            result = BIT_DStream_endOfBuffer;\n        }\n        bitD->ptr -= nbBytes;\n        bitD->bitsConsumed -= nbBytes*8;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);   /* reminder : srcSize > sizeof(bitD) */\n        return result;\n    }\n}\n\n/*! BIT_endOfDStream\n*   @return Tells if DStream has reached its exact end\n*/\nMEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)\n{\n    return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));\n}\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* BITSTREAM_H_MODULE */\n/* ******************************************************************\n   Error codes and messages\n   Copyright (C) 2013-2015, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef ERROR_H_MODULE\n#define ERROR_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/******************************************\n*  Compiler-specific\n******************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n#  define ERR_STATIC static inline\n#elif defined(_MSC_VER)\n#  define ERR_STATIC static __inline\n#elif defined(__GNUC__)\n#  define ERR_STATIC static __attribute__((unused))\n#else\n#  define ERR_STATIC static  /* this version may generate warnings for unused static functions; disable the relevant warning */\n#endif\n\n\n/******************************************\n*  Error Management\n******************************************/\n#define PREFIX(name) ZSTD_error_##name\n\n#define ERROR(name) (size_t)-PREFIX(name)\n\n#define ERROR_LIST(ITEM) \\\n        ITEM(PREFIX(No_Error)) ITEM(PREFIX(GENERIC)) \\\n        ITEM(PREFIX(dstSize_tooSmall)) ITEM(PREFIX(srcSize_wrong)) \\\n        ITEM(PREFIX(prefix_unknown)) ITEM(PREFIX(corruption_detected)) \\\n        ITEM(PREFIX(tableLog_tooLarge)) ITEM(PREFIX(maxSymbolValue_tooLarge)) ITEM(PREFIX(maxSymbolValue_tooSmall)) \\\n        ITEM(PREFIX(maxCode))\n\n#define ERROR_GENERATE_ENUM(ENUM) ENUM,\ntypedef enum { ERROR_LIST(ERROR_GENERATE_ENUM) } ERR_codes;  /* enum is exposed, to detect & handle specific errors; compare function result to -enum value */\n\n#define ERROR_CONVERTTOSTRING(STRING) #STRING,\n#define ERROR_GENERATE_STRING(EXPR) ERROR_CONVERTTOSTRING(EXPR)\nstatic const char* ERR_strings[] = { ERROR_LIST(ERROR_GENERATE_STRING) };\n\nERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }\n\nERR_STATIC const char* ERR_getErrorName(size_t code)\n{\n    static const char* codeError = \"Unspecified error code\";\n    if (ERR_isError(code)) return ERR_strings[-(int)(code)];\n    return codeError;\n}\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* ERROR_H_MODULE */\n/*\nConstructor and Destructor of type FSE_CTable\n    Note that its size depends on 'tableLog' and 'maxSymbolValue' */\ntypedef unsigned FSE_CTable;   /* don't allocate that. It's just a way to be more restrictive than void* */\ntypedef unsigned FSE_DTable;   /* don't allocate that. It's just a way to be more restrictive than void* */\n\n\n/* ******************************************************************\n   FSE : Finite State Entropy coder\n   header file for static linking (only)\n   Copyright (C) 2013-2015, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/******************************************\n*  Static allocation\n******************************************/\n/* FSE buffer bounds */\n#define FSE_NCOUNTBOUND 512\n#define FSE_BLOCKBOUND(size) (size + (size>>7))\n#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size))   /* Macro version, useful for static allocation */\n\n/* You can statically allocate FSE CTable/DTable as a table of unsigned using below macro */\n#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue)   (1 + (1<<(maxTableLog-1)) + ((maxSymbolValue+1)*2))\n#define FSE_DTABLE_SIZE_U32(maxTableLog)                   (1 + (1<<maxTableLog))\n\n\n/******************************************\n*  FSE advanced API\n******************************************/\nstatic size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits);\n/* build a fake FSE_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */\n\nstatic size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue);\n/* build a fake FSE_DTable, designed to always generate the same symbolValue */\n\n\n/******************************************\n*  FSE symbol decompression API\n******************************************/\ntypedef struct\n{\n    size_t      state;\n    const void* table;   /* precise table may vary, depending on U16 */\n} FSE_DState_t;\n\n\nstatic void     FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt);\n\nstatic unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);\n\nstatic unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr);\n\n\n/******************************************\n*  FSE unsafe API\n******************************************/\nstatic unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);\n/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */\n\n\n/******************************************\n*  Implementation of inline functions\n******************************************/\n\n/* decompression */\n\ntypedef struct {\n    U16 tableLog;\n    U16 fastMode;\n} FSE_DTableHeader;   /* sizeof U32 */\n\ntypedef struct\n{\n    unsigned short newState;\n    unsigned char  symbol;\n    unsigned char  nbBits;\n} FSE_decode_t;   /* size == U32 */\n\nMEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt)\n{\n    FSE_DTableHeader DTableH;\n    memcpy(&DTableH, dt, sizeof(DTableH));\n    DStatePtr->state = BIT_readBits(bitD, DTableH.tableLog);\n    BIT_reloadDStream(bitD);\n    DStatePtr->table = dt + 1;\n}\n\nMEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)\n{\n    const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    const U32  nbBits = DInfo.nbBits;\n    BYTE symbol = DInfo.symbol;\n    size_t lowBits = BIT_readBits(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\nMEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)\n{\n    const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    const U32 nbBits = DInfo.nbBits;\n    BYTE symbol = DInfo.symbol;\n    size_t lowBits = BIT_readBitsFast(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\nMEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)\n{\n    return DStatePtr->state == 0;\n}\n\n\n#if defined (__cplusplus)\n}\n#endif\n/* ******************************************************************\n   Huff0 : Huffman coder, part of New Generation Entropy library\n   header file for static linking (only)\n   Copyright (C) 2013-2015, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/******************************************\n*  Static allocation macros\n******************************************/\n/* Huff0 buffer bounds */\n#define HUF_CTABLEBOUND 129\n#define HUF_BLOCKBOUND(size) (size + (size>>8) + 8)   /* only true if incompressible pre-filtered with fast heuristic */\n#define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size))   /* Macro version, useful for static allocation */\n\n/* static allocation of Huff0's DTable */\n#define HUF_DTABLE_SIZE(maxTableLog)   (1 + (1<<maxTableLog))  /* nb Cells; use unsigned short for X2, unsigned int for X4 */\n#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \\\n        unsigned short DTable[HUF_DTABLE_SIZE(maxTableLog)] = { maxTableLog }\n#define HUF_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \\\n        unsigned int DTable[HUF_DTABLE_SIZE(maxTableLog)] = { maxTableLog }\n#define HUF_CREATE_STATIC_DTABLEX6(DTable, maxTableLog) \\\n        unsigned int DTable[HUF_DTABLE_SIZE(maxTableLog) * 3 / 2] = { maxTableLog }\n\n\n/******************************************\n*  Advanced functions\n******************************************/\nstatic size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */\nstatic size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbols decoder */\nstatic size_t HUF_decompress4X6 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* quad-symbols decoder */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n/*\n    zstd - standard compression library\n    Header File\n    Copyright (C) 2014-2015, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n    - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* *************************************\n*  Includes\n***************************************/\n#include <stddef.h>   /* size_t */\n\n\n/* *************************************\n*  Version\n***************************************/\n#define ZSTD_VERSION_MAJOR    0    /* for breaking interface changes  */\n#define ZSTD_VERSION_MINOR    2    /* for new (non-breaking) interface capabilities */\n#define ZSTD_VERSION_RELEASE  2    /* for tweaks, bug-fixes, or development */\n#define ZSTD_VERSION_NUMBER  (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)\n\n\n/* *************************************\n*  Advanced functions\n***************************************/\ntypedef struct ZSTD_CCtx_s ZSTD_CCtx;   /* incomplete type */\n\n#if defined (__cplusplus)\n}\n#endif\n/*\n    zstd - standard compression library\n    Header File for static linking only\n    Copyright (C) 2014-2015, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n    - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n\n/* The objects defined into this file should be considered experimental.\n * They are not labelled stable, as their prototype may change in the future.\n * You can use them for tests, provide feedback, or if you can endure risk of future changes.\n */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* *************************************\n*  Streaming functions\n***************************************/\n\ntypedef struct ZSTDv02_Dctx_s ZSTD_DCtx;\n\n/*\n  Use above functions alternatively.\n  ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue().\n  ZSTD_decompressContinue() will use previous data blocks to improve compression if they are located prior to current block.\n  Result is the number of bytes regenerated within 'dst'.\n  It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header.\n*/\n\n/* *************************************\n*  Prefix - version detection\n***************************************/\n#define ZSTD_magicNumber 0xFD2FB522   /* v0.2 (current)*/\n\n\n#if defined (__cplusplus)\n}\n#endif\n/* ******************************************************************\n   FSE : Finite State Entropy coder\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n#ifndef FSE_COMMONDEFS_ONLY\n\n/****************************************************************\n*  Tuning parameters\n****************************************************************/\n/* MEMORY_USAGE :\n*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n*  Increasing memory usage improves compression ratio\n*  Reduced memory usage can improve speed, due to cache effect\n*  Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */\n#define FSE_MAX_MEMORY_USAGE 14\n#define FSE_DEFAULT_MEMORY_USAGE 13\n\n/* FSE_MAX_SYMBOL_VALUE :\n*  Maximum symbol value authorized.\n*  Required for proper stack allocation */\n#define FSE_MAX_SYMBOL_VALUE 255\n\n\n/****************************************************************\n*  template functions type & suffix\n****************************************************************/\n#define FSE_FUNCTION_TYPE BYTE\n#define FSE_FUNCTION_EXTENSION\n\n\n/****************************************************************\n*  Byte symbol type\n****************************************************************/\n#endif   /* !FSE_COMMONDEFS_ONLY */\n\n\n/****************************************************************\n*  Compiler specifics\n****************************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  define FORCE_INLINE static __forceinline\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4214)        /* disable: C4214: non-int bitfields */\n#else\n#  if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */\n#    ifdef __GNUC__\n#      define FORCE_INLINE static inline __attribute__((always_inline))\n#    else\n#      define FORCE_INLINE static inline\n#    endif\n#  else\n#    define FORCE_INLINE static\n#  endif /* __STDC_VERSION__ */\n#endif\n\n\n/****************************************************************\n*  Includes\n****************************************************************/\n#include <stdlib.h>     /* malloc, free, qsort */\n#include <string.h>     /* memcpy, memset */\n#include <stdio.h>      /* printf (debug) */\n\n/****************************************************************\n*  Constants\n*****************************************************************/\n#define FSE_MAX_TABLELOG  (FSE_MAX_MEMORY_USAGE-2)\n#define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG)\n#define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1)\n#define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2)\n#define FSE_MIN_TABLELOG 5\n\n#define FSE_TABLELOG_ABSOLUTE_MAX 15\n#if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX\n#error \"FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported\"\n#endif\n\n\n/****************************************************************\n*  Error Management\n****************************************************************/\n#define FSE_STATIC_ASSERT(c) { enum { FSE_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n/****************************************************************\n*  Complex types\n****************************************************************/\ntypedef U32 DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)];\n\n\n/****************************************************************\n*  Templates\n****************************************************************/\n/*\n  designed to be included\n  for type-specific functions (template emulation in C)\n  Objective is to write these functions only once, for improved maintenance\n*/\n\n/* safety checks */\n#ifndef FSE_FUNCTION_EXTENSION\n#  error \"FSE_FUNCTION_EXTENSION must be defined\"\n#endif\n#ifndef FSE_FUNCTION_TYPE\n#  error \"FSE_FUNCTION_TYPE must be defined\"\n#endif\n\n/* Function names */\n#define FSE_CAT(X,Y) X##Y\n#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y)\n#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y)\n\n\n/* Function templates */\n\n#define FSE_DECODE_TYPE FSE_decode_t\n\nstatic U32 FSE_tableStep(U32 tableSize) { return (tableSize>>1) + (tableSize>>3) + 3; }\n\nstatic size_t FSE_buildDTable\n(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)\n{\n    void* ptr = dt+1;\n    FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*)ptr;\n    FSE_DTableHeader DTableH;\n    const U32 tableSize = 1 << tableLog;\n    const U32 tableMask = tableSize-1;\n    const U32 step = FSE_tableStep(tableSize);\n    U16 symbolNext[FSE_MAX_SYMBOL_VALUE+1];\n    U32 position = 0;\n    U32 highThreshold = tableSize-1;\n    const S16 largeLimit= (S16)(1 << (tableLog-1));\n    U32 noLarge = 1;\n    U32 s;\n\n    /* Sanity Checks */\n    if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);\n    if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);\n\n    /* Init, lay down lowprob symbols */\n    DTableH.tableLog = (U16)tableLog;\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        if (normalizedCounter[s]==-1)\n        {\n            tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s;\n            symbolNext[s] = 1;\n        }\n        else\n        {\n            if (normalizedCounter[s] >= largeLimit) noLarge=0;\n            symbolNext[s] = normalizedCounter[s];\n        }\n    }\n\n    /* Spread symbols */\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        int i;\n        for (i=0; i<normalizedCounter[s]; i++)\n        {\n            tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;\n            position = (position + step) & tableMask;\n            while (position > highThreshold) position = (position + step) & tableMask;   /* lowprob area */\n        }\n    }\n\n    if (position!=0) return ERROR(GENERIC);   /* position must reach all cells once, otherwise normalizedCounter is incorrect */\n\n    /* Build Decoding table */\n    {\n        U32 i;\n        for (i=0; i<tableSize; i++)\n        {\n            FSE_FUNCTION_TYPE symbol = (FSE_FUNCTION_TYPE)(tableDecode[i].symbol);\n            U16 nextState = symbolNext[symbol]++;\n            tableDecode[i].nbBits = (BYTE) (tableLog - BIT_highbit32 ((U32)nextState) );\n            tableDecode[i].newState = (U16) ( (nextState << tableDecode[i].nbBits) - tableSize);\n        }\n    }\n\n    DTableH.fastMode = (U16)noLarge;\n    memcpy(dt, &DTableH, sizeof(DTableH));   /* memcpy(), to avoid strict aliasing warnings */\n    return 0;\n}\n\n\n#ifndef FSE_COMMONDEFS_ONLY\n/******************************************\n*  FSE helper functions\n******************************************/\nstatic unsigned FSE_isError(size_t code) { return ERR_isError(code); }\n\n\n/****************************************************************\n*  FSE NCount encoding-decoding\n****************************************************************/\nstatic short FSE_abs(short a)\n{\n    return (short)(a<0 ? -a : a);\n}\n\nstatic size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n                 const void* headerBuffer, size_t hbSize)\n{\n    const BYTE* const istart = (const BYTE*) headerBuffer;\n    const BYTE* const iend = istart + hbSize;\n    const BYTE* ip = istart;\n    int nbBits;\n    int remaining;\n    int threshold;\n    U32 bitStream;\n    int bitCount;\n    unsigned charnum = 0;\n    int previous0 = 0;\n\n    if (hbSize < 4) return ERROR(srcSize_wrong);\n    bitStream = MEM_readLE32(ip);\n    nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG;   /* extract tableLog */\n    if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);\n    bitStream >>= 4;\n    bitCount = 4;\n    *tableLogPtr = nbBits;\n    remaining = (1<<nbBits)+1;\n    threshold = 1<<nbBits;\n    nbBits++;\n\n    while ((remaining>1) && (charnum<=*maxSVPtr))\n    {\n        if (previous0)\n        {\n            unsigned n0 = charnum;\n            while ((bitStream & 0xFFFF) == 0xFFFF)\n            {\n                n0+=24;\n                if (ip < iend-5)\n                {\n                    ip+=2;\n                    bitStream = MEM_readLE32(ip) >> bitCount;\n                }\n                else\n                {\n                    bitStream >>= 16;\n                    bitCount+=16;\n                }\n            }\n            while ((bitStream & 3) == 3)\n            {\n                n0+=3;\n                bitStream>>=2;\n                bitCount+=2;\n            }\n            n0 += bitStream & 3;\n            bitCount += 2;\n            if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);\n            while (charnum < n0) normalizedCounter[charnum++] = 0;\n            if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4))\n            {\n                ip += bitCount>>3;\n                bitCount &= 7;\n                bitStream = MEM_readLE32(ip) >> bitCount;\n            }\n            else\n                bitStream >>= 2;\n        }\n        {\n            const short max = (short)((2*threshold-1)-remaining);\n            short count;\n\n            if ((bitStream & (threshold-1)) < (U32)max)\n            {\n                count = (short)(bitStream & (threshold-1));\n                bitCount   += nbBits-1;\n            }\n            else\n            {\n                count = (short)(bitStream & (2*threshold-1));\n                if (count >= threshold) count -= max;\n                bitCount   += nbBits;\n            }\n\n            count--;   /* extra accuracy */\n            remaining -= FSE_abs(count);\n            normalizedCounter[charnum++] = count;\n            previous0 = !count;\n            while (remaining < threshold)\n            {\n                nbBits--;\n                threshold >>= 1;\n            }\n\n            {\n                if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4))\n                {\n                    ip += bitCount>>3;\n                    bitCount &= 7;\n                }\n                else\n                {\n                    bitCount -= (int)(8 * (iend - 4 - ip));\n                    ip = iend - 4;\n                }\n                bitStream = MEM_readLE32(ip) >> (bitCount & 31);\n            }\n        }\n    }\n    if (remaining != 1) return ERROR(GENERIC);\n    *maxSVPtr = charnum-1;\n\n    ip += (bitCount+7)>>3;\n    if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong);\n    return ip-istart;\n}\n\n\n/*********************************************************\n*  Decompression (Byte symbols)\n*********************************************************/\nstatic size_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue)\n{\n    void* ptr = dt;\n    FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;\n    FSE_decode_t* const cell = (FSE_decode_t*)(ptr) + 1;   /* because dt is unsigned */\n\n    DTableH->tableLog = 0;\n    DTableH->fastMode = 0;\n\n    cell->newState = 0;\n    cell->symbol = symbolValue;\n    cell->nbBits = 0;\n\n    return 0;\n}\n\n\nstatic size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits)\n{\n    void* ptr = dt;\n    FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;\n    FSE_decode_t* const dinfo = (FSE_decode_t*)(ptr) + 1;   /* because dt is unsigned */\n    const unsigned tableSize = 1 << nbBits;\n    const unsigned tableMask = tableSize - 1;\n    const unsigned maxSymbolValue = tableMask;\n    unsigned s;\n\n    /* Sanity checks */\n    if (nbBits < 1) return ERROR(GENERIC);         /* min size */\n\n    /* Build Decoding Table */\n    DTableH->tableLog = (U16)nbBits;\n    DTableH->fastMode = 1;\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        dinfo[s].newState = 0;\n        dinfo[s].symbol = (BYTE)s;\n        dinfo[s].nbBits = (BYTE)nbBits;\n    }\n\n    return 0;\n}\n\nFORCE_INLINE size_t FSE_decompress_usingDTable_generic(\n          void* dst, size_t maxDstSize,\n    const void* cSrc, size_t cSrcSize,\n    const FSE_DTable* dt, const unsigned fast)\n{\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* op = ostart;\n    BYTE* const omax = op + maxDstSize;\n    BYTE* const olimit = omax-3;\n\n    BIT_DStream_t bitD;\n    FSE_DState_t state1;\n    FSE_DState_t state2;\n    size_t errorCode;\n\n    /* Init */\n    errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize);   /* replaced last arg by maxCompressed Size */\n    if (FSE_isError(errorCode)) return errorCode;\n\n    FSE_initDState(&state1, &bitD, dt);\n    FSE_initDState(&state2, &bitD, dt);\n\n#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD)\n\n    /* 4 symbols per loop */\n    for ( ; (BIT_reloadDStream(&bitD)==BIT_DStream_unfinished) && (op<olimit) ; op+=4)\n    {\n        op[0] = FSE_GETSYMBOL(&state1);\n\n        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BIT_reloadDStream(&bitD);\n\n        op[1] = FSE_GETSYMBOL(&state2);\n\n        if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            { if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) { op+=2; break; } }\n\n        op[2] = FSE_GETSYMBOL(&state1);\n\n        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BIT_reloadDStream(&bitD);\n\n        op[3] = FSE_GETSYMBOL(&state2);\n    }\n\n    /* tail */\n    /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */\n    while (1)\n    {\n        if ( (BIT_reloadDStream(&bitD)>BIT_DStream_completed) || (op==omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state1))) )\n            break;\n\n        *op++ = FSE_GETSYMBOL(&state1);\n\n        if ( (BIT_reloadDStream(&bitD)>BIT_DStream_completed) || (op==omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state2))) )\n            break;\n\n        *op++ = FSE_GETSYMBOL(&state2);\n    }\n\n    /* end ? */\n    if (BIT_endOfDStream(&bitD) && FSE_endOfDState(&state1) && FSE_endOfDState(&state2))\n        return op-ostart;\n\n    if (op==omax) return ERROR(dstSize_tooSmall);   /* dst buffer is full, but cSrc unfinished */\n\n    return ERROR(corruption_detected);\n}\n\n\nstatic size_t FSE_decompress_usingDTable(void* dst, size_t originalSize,\n                            const void* cSrc, size_t cSrcSize,\n                            const FSE_DTable* dt)\n{\n    FSE_DTableHeader DTableH;\n    memcpy(&DTableH, dt, sizeof(DTableH));\n\n    /* select fast mode (static) */\n    if (DTableH.fastMode) return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);\n    return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);\n}\n\n\nstatic size_t FSE_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)\n{\n    const BYTE* const istart = (const BYTE*)cSrc;\n    const BYTE* ip = istart;\n    short counting[FSE_MAX_SYMBOL_VALUE+1];\n    DTable_max_t dt;   /* Static analyzer seems unable to understand this table will be properly initialized later */\n    unsigned tableLog;\n    unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;\n    size_t errorCode;\n\n    if (cSrcSize<2) return ERROR(srcSize_wrong);   /* too small input size */\n\n    /* normal FSE decoding mode */\n    errorCode = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);\n    if (FSE_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);   /* too small input size */\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    errorCode = FSE_buildDTable (dt, counting, maxSymbolValue, tableLog);\n    if (FSE_isError(errorCode)) return errorCode;\n\n    /* always return, even if it is an error code */\n    return FSE_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt);\n}\n\n\n\n#endif   /* FSE_COMMONDEFS_ONLY */\n/* ******************************************************************\n   Huff0 : Huffman coder, part of New Generation Entropy library\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE+Huff0 source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n/****************************************************************\n*  Compiler specifics\n****************************************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n/* inline is defined */\n#elif defined(_MSC_VER)\n#  define inline __inline\n#else\n#  define inline /* disable inline */\n#endif\n\n\n#ifdef _MSC_VER    /* Visual Studio */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#endif\n\n\n/****************************************************************\n*  Includes\n****************************************************************/\n#include <stdlib.h>     /* malloc, free, qsort */\n#include <string.h>     /* memcpy, memset */\n#include <stdio.h>      /* printf (debug) */\n\n/****************************************************************\n*  Error Management\n****************************************************************/\n#define HUF_STATIC_ASSERT(c) { enum { HUF_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n/******************************************\n*  Helper functions\n******************************************/\nstatic unsigned HUF_isError(size_t code) { return ERR_isError(code); }\n\n#define HUF_ABSOLUTEMAX_TABLELOG  16   /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */\n#define HUF_MAX_TABLELOG  12           /* max configured tableLog (for static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */\n#define HUF_DEFAULT_TABLELOG  HUF_MAX_TABLELOG   /* tableLog by default, when not specified */\n#define HUF_MAX_SYMBOL_VALUE 255\n#if (HUF_MAX_TABLELOG > HUF_ABSOLUTEMAX_TABLELOG)\n#  error \"HUF_MAX_TABLELOG is too large !\"\n#endif\n\n\n\n/*********************************************************\n*  Huff0 : Huffman block decompression\n*********************************************************/\ntypedef struct { BYTE byte; BYTE nbBits; } HUF_DEltX2;   /* single-symbol decoding */\n\ntypedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX4;  /* double-symbols decoding */\n\ntypedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;\n\n/*! HUF_readStats\n    Read compact Huffman tree, saved by HUF_writeCTable\n    @huffWeight : destination buffer\n    @return : size read from `src`\n*/\nstatic size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                            U32* nbSymbolsPtr, U32* tableLogPtr,\n                            const void* src, size_t srcSize)\n{\n    U32 weightTotal;\n    U32 tableLog;\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize;\n    size_t oSize;\n    U32 n;\n\n    if (!srcSize) return ERROR(srcSize_wrong);\n    iSize = ip[0];\n    //memset(huffWeight, 0, hwSize);   /* is not necessary, even though some analyzer complain ... */\n\n    if (iSize >= 128)  /* special header */\n    {\n        if (iSize >= (242))   /* RLE */\n        {\n            static int l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };\n            oSize = l[iSize-242];\n            memset(huffWeight, 1, hwSize);\n            iSize = 0;\n        }\n        else   /* Incompressible */\n        {\n            oSize = iSize - 127;\n            iSize = ((oSize+1)/2);\n            if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n            if (oSize >= hwSize) return ERROR(corruption_detected);\n            ip += 1;\n            for (n=0; n<oSize; n+=2)\n            {\n                huffWeight[n]   = ip[n/2] >> 4;\n                huffWeight[n+1] = ip[n/2] & 15;\n            }\n        }\n    }\n    else  /* header compressed with FSE (normal case) */\n    {\n        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n        oSize = FSE_decompress(huffWeight, hwSize-1, ip+1, iSize);   /* max (hwSize-1) values decoded, as last one is implied */\n        if (FSE_isError(oSize)) return oSize;\n    }\n\n    /* collect weight stats */\n    memset(rankStats, 0, (HUF_ABSOLUTEMAX_TABLELOG + 1) * sizeof(U32));\n    weightTotal = 0;\n    for (n=0; n<oSize; n++)\n    {\n        if (huffWeight[n] >= HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);\n        rankStats[huffWeight[n]]++;\n        weightTotal += (1 << huffWeight[n]) >> 1;\n    }\n    if (weightTotal == 0) return ERROR(corruption_detected);\n\n    /* get last non-null symbol weight (implied, total must be 2^n) */\n    tableLog = BIT_highbit32(weightTotal) + 1;\n    if (tableLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);\n    {\n        U32 total = 1 << tableLog;\n        U32 rest = total - weightTotal;\n        U32 verif = 1 << BIT_highbit32(rest);\n        U32 lastWeight = BIT_highbit32(rest) + 1;\n        if (verif != rest) return ERROR(corruption_detected);    /* last value must be a clean power of 2 */\n        huffWeight[oSize] = (BYTE)lastWeight;\n        rankStats[lastWeight]++;\n    }\n\n    /* check tree construction validity */\n    if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected);   /* by construction : at least 2 elts of rank 1, must be even */\n\n    /* results */\n    *nbSymbolsPtr = (U32)(oSize+1);\n    *tableLogPtr = tableLog;\n    return iSize+1;\n}\n\n\n/**************************/\n/* single-symbol decoding */\n/**************************/\n\nstatic size_t HUF_readDTableX2 (U16* DTable, const void* src, size_t srcSize)\n{\n    BYTE huffWeight[HUF_MAX_SYMBOL_VALUE + 1];\n    U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];   /* large enough for values from 0 to 16 */\n    U32 tableLog = 0;\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize = ip[0];\n    U32 nbSymbols = 0;\n    U32 n;\n    U32 nextRankStart;\n    void* ptr = DTable+1;\n    HUF_DEltX2* const dt = (HUF_DEltX2*)ptr;\n\n    HUF_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(U16));   /* if compilation fails here, assertion is false */\n    //memset(huffWeight, 0, sizeof(huffWeight));   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUF_readStats(huffWeight, HUF_MAX_SYMBOL_VALUE + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);\n    if (HUF_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > DTable[0]) return ERROR(tableLog_tooLarge);   /* DTable is too small */\n    DTable[0] = (U16)tableLog;   /* maybe should separate sizeof DTable, as allocated, from used size of DTable, in case of DTable re-use */\n\n    /* Prepare ranks */\n    nextRankStart = 0;\n    for (n=1; n<=tableLog; n++)\n    {\n        U32 current = nextRankStart;\n        nextRankStart += (rankVal[n] << (n-1));\n        rankVal[n] = current;\n    }\n\n    /* fill DTable */\n    for (n=0; n<nbSymbols; n++)\n    {\n        const U32 w = huffWeight[n];\n        const U32 length = (1 << w) >> 1;\n        U32 i;\n        HUF_DEltX2 D;\n        D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w);\n        for (i = rankVal[w]; i < rankVal[w] + length; i++)\n            dt[i] = D;\n        rankVal[w] += length;\n    }\n\n    return iSize;\n}\n\nstatic BYTE HUF_decodeSymbolX2(BIT_DStream_t* Dstream, const HUF_DEltX2* dt, const U32 dtLog)\n{\n        const size_t val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */\n        const BYTE c = dt[val].byte;\n        BIT_skipBits(Dstream, dt[val].nbBits);\n        return c;\n}\n\n#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \\\n    *ptr++ = HUF_decodeSymbolX2(DStreamPtr, dt, dtLog)\n\n#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \\\n        HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\n#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\nstatic inline size_t HUF_decodeStreamX2(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX2* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 4 symbols at a time */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-4))\n    {\n        HUF_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX2_1(p, bitDPtr);\n        HUF_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n    }\n\n    /* closer to the end */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd))\n        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    /* no more data to retrieve from bitstream, hence no need to reload */\n    while (p < pEnd)\n        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    return pEnd-pStart;\n}\n\n\nstatic size_t HUF_decompress4X2_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U16* DTable)\n{\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n\n    {\n        const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n\n        const void* ptr = DTable;\n        const HUF_DEltX2* const dt = ((const HUF_DEltX2*)ptr) +1;\n        const U32 dtLog = DTable[0];\n        size_t errorCode;\n\n        /* Init */\n        BIT_DStream_t bitD1;\n        BIT_DStream_t bitD2;\n        BIT_DStream_t bitD3;\n        BIT_DStream_t bitD4;\n        const size_t length1 = MEM_readLE16(istart);\n        const size_t length2 = MEM_readLE16(istart+2);\n        const size_t length3 = MEM_readLE16(istart+4);\n        size_t length4;\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n\n        length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        errorCode = BIT_initDStream(&bitD1, istart1, length1);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD2, istart2, length2);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD3, istart3, length3);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD4, istart4, length4);\n        if (HUF_isError(errorCode)) return errorCode;\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        for ( ; (endSignal==BIT_DStream_unfinished) && (op4<(oend-7)) ; )\n        {\n            HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_1(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_1(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_1(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_1(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_0(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_0(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_0(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_0(op4, &bitD4);\n\n            endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);\n        HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);\n        HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);\n        HUF_decodeStreamX2(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nstatic size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n    size_t errorCode;\n\n    errorCode = HUF_readDTableX2 (DTable, cSrc, cSrcSize);\n    if (HUF_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    return HUF_decompress4X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\n/***************************/\n/* double-symbols decoding */\n/***************************/\n\nstatic void HUF_fillDTableX4Level2(HUF_DEltX4* DTable, U32 sizeLog, const U32 consumed,\n                           const U32* rankValOrigin, const int minWeight,\n                           const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,\n                           U32 nbBitsBaseline, U16 baseSeq)\n{\n    HUF_DEltX4 DElt;\n    U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];\n    U32 s;\n\n    /* get pre-calculated rankVal */\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill skipped values */\n    if (minWeight>1)\n    {\n        U32 i, skipSize = rankVal[minWeight];\n        MEM_writeLE16(&(DElt.sequence), baseSeq);\n        DElt.nbBits   = (BYTE)(consumed);\n        DElt.length   = 1;\n        for (i = 0; i < skipSize; i++)\n            DTable[i] = DElt;\n    }\n\n    /* fill DTable */\n    for (s=0; s<sortedListSize; s++)   /* note : sortedSymbols already skipped */\n    {\n        const U32 symbol = sortedSymbols[s].symbol;\n        const U32 weight = sortedSymbols[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 length = 1 << (sizeLog-nbBits);\n        const U32 start = rankVal[weight];\n        U32 i = start;\n        const U32 end = start + length;\n\n        MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));\n        DElt.nbBits = (BYTE)(nbBits + consumed);\n        DElt.length = 2;\n        do { DTable[i++] = DElt; } while (i<end);   /* since length >= 1 */\n\n        rankVal[weight] += length;\n    }\n}\n\ntypedef U32 rankVal_t[HUF_ABSOLUTEMAX_TABLELOG][HUF_ABSOLUTEMAX_TABLELOG + 1];\n\nstatic void HUF_fillDTableX4(HUF_DEltX4* DTable, const U32 targetLog,\n                           const sortedSymbol_t* sortedList, const U32 sortedListSize,\n                           const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,\n                           const U32 nbBitsBaseline)\n{\n    U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];\n    const int scaleLog = nbBitsBaseline - targetLog;   /* note : targetLog >= srcLog, hence scaleLog <= 1 */\n    const U32 minBits  = nbBitsBaseline - maxWeight;\n    U32 s;\n\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill DTable */\n    for (s=0; s<sortedListSize; s++)\n    {\n        const U16 symbol = sortedList[s].symbol;\n        const U32 weight = sortedList[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 start = rankVal[weight];\n        const U32 length = 1 << (targetLog-nbBits);\n\n        if (targetLog-nbBits >= minBits)   /* enough room for a second symbol */\n        {\n            U32 sortedRank;\n            int minWeight = nbBits + scaleLog;\n            if (minWeight < 1) minWeight = 1;\n            sortedRank = rankStart[minWeight];\n            HUF_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits,\n                           rankValOrigin[nbBits], minWeight,\n                           sortedList+sortedRank, sortedListSize-sortedRank,\n                           nbBitsBaseline, symbol);\n        }\n        else\n        {\n            U32 i;\n            const U32 end = start + length;\n            HUF_DEltX4 DElt;\n\n            MEM_writeLE16(&(DElt.sequence), symbol);\n            DElt.nbBits   = (BYTE)(nbBits);\n            DElt.length   = 1;\n            for (i = start; i < end; i++)\n                DTable[i] = DElt;\n        }\n        rankVal[weight] += length;\n    }\n}\n\nstatic size_t HUF_readDTableX4 (U32* DTable, const void* src, size_t srcSize)\n{\n    BYTE weightList[HUF_MAX_SYMBOL_VALUE + 1];\n    sortedSymbol_t sortedSymbol[HUF_MAX_SYMBOL_VALUE + 1];\n    U32 rankStats[HUF_ABSOLUTEMAX_TABLELOG + 1] = { 0 };\n    U32 rankStart0[HUF_ABSOLUTEMAX_TABLELOG + 2] = { 0 };\n    U32* const rankStart = rankStart0+1;\n    rankVal_t rankVal;\n    U32 tableLog, maxW, sizeOfSort, nbSymbols;\n    const U32 memLog = DTable[0];\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize = ip[0];\n    void* ptr = DTable;\n    HUF_DEltX4* const dt = ((HUF_DEltX4*)ptr) + 1;\n\n    HUF_STATIC_ASSERT(sizeof(HUF_DEltX4) == sizeof(U32));   /* if compilation fails here, assertion is false */\n    if (memLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge);\n    //memset(weightList, 0, sizeof(weightList));   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUF_readStats(weightList, HUF_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);\n    if (HUF_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > memLog) return ERROR(tableLog_tooLarge);   /* DTable can't fit code depth */\n\n    /* find maxWeight */\n    for (maxW = tableLog; rankStats[maxW]==0; maxW--)\n        {if (!maxW) return ERROR(GENERIC); }  /* necessarily finds a solution before maxW==0 */\n\n    /* Get start index of each weight */\n    {\n        U32 w, nextRankStart = 0;\n        for (w=1; w<=maxW; w++)\n        {\n            U32 current = nextRankStart;\n            nextRankStart += rankStats[w];\n            rankStart[w] = current;\n        }\n        rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/\n        sizeOfSort = nextRankStart;\n    }\n\n    /* sort symbols by weight */\n    {\n        U32 s;\n        for (s=0; s<nbSymbols; s++)\n        {\n            U32 w = weightList[s];\n            U32 r = rankStart[w]++;\n            sortedSymbol[r].symbol = (BYTE)s;\n            sortedSymbol[r].weight = (BYTE)w;\n        }\n        rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */\n    }\n\n    /* Build rankVal */\n    {\n        const U32 minBits = tableLog+1 - maxW;\n        U32 nextRankVal = 0;\n        U32 w, consumed;\n        const int rescale = (memLog-tableLog) - 1;   /* tableLog <= memLog */\n        U32* rankVal0 = rankVal[0];\n        for (w=1; w<=maxW; w++)\n        {\n            U32 current = nextRankVal;\n            nextRankVal += rankStats[w] << (w+rescale);\n            rankVal0[w] = current;\n        }\n        for (consumed = minBits; consumed <= memLog - minBits; consumed++)\n        {\n            U32* rankValPtr = rankVal[consumed];\n            for (w = 1; w <= maxW; w++)\n            {\n                rankValPtr[w] = rankVal0[w] >> consumed;\n            }\n        }\n    }\n\n    HUF_fillDTableX4(dt, memLog,\n                   sortedSymbol, sizeOfSort,\n                   rankStart0, rankVal, maxW,\n                   tableLog+1);\n\n    return iSize;\n}\n\n\nstatic U32 HUF_decodeSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 2);\n    BIT_skipBits(DStream, dt[val].nbBits);\n    return dt[val].length;\n}\n\nstatic U32 HUF_decodeLastSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 1);\n    if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits);\n    else\n    {\n        if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8))\n        {\n            BIT_skipBits(DStream, dt[val].nbBits);\n            if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))\n                DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);   /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */\n        }\n    }\n    return 1;\n}\n\n\n#define HUF_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \\\n    ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUF_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \\\n        ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUF_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\nstatic inline size_t HUF_decodeStreamX4(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd, const HUF_DEltX4* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 8 symbols at a time */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd-7))\n    {\n        HUF_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX4_1(p, bitDPtr);\n        HUF_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX4_0(p, bitDPtr);\n    }\n\n    /* closer to the end */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-2))\n        HUF_DECODE_SYMBOLX4_0(p, bitDPtr);\n\n    while (p <= pEnd-2)\n        HUF_DECODE_SYMBOLX4_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */\n\n    if (p < pEnd)\n        p += HUF_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);\n\n    return p-pStart;\n}\n\n\n\nstatic size_t HUF_decompress4X4_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U32* DTable)\n{\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n\n    {\n        const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n\n        const void* ptr = DTable;\n        const HUF_DEltX4* const dt = ((const HUF_DEltX4*)ptr) +1;\n        const U32 dtLog = DTable[0];\n        size_t errorCode;\n\n        /* Init */\n        BIT_DStream_t bitD1;\n        BIT_DStream_t bitD2;\n        BIT_DStream_t bitD3;\n        BIT_DStream_t bitD4;\n        const size_t length1 = MEM_readLE16(istart);\n        const size_t length2 = MEM_readLE16(istart+2);\n        const size_t length3 = MEM_readLE16(istart+4);\n        size_t length4;\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n\n        length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        errorCode = BIT_initDStream(&bitD1, istart1, length1);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD2, istart2, length2);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD3, istart3, length3);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD4, istart4, length4);\n        if (HUF_isError(errorCode)) return errorCode;\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        for ( ; (endSignal==BIT_DStream_unfinished) && (op4<(oend-7)) ; )\n        {\n            HUF_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX4_1(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_1(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_1(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_1(op4, &bitD4);\n            HUF_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX4_0(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_0(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_0(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_0(op4, &bitD4);\n\n            endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUF_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);\n        HUF_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);\n        HUF_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);\n        HUF_decodeStreamX4(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nstatic size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUF_CREATE_STATIC_DTABLEX4(DTable, HUF_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t hSize = HUF_readDTableX4 (DTable, cSrc, cSrcSize);\n    if (HUF_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize;\n    cSrcSize -= hSize;\n\n    return HUF_decompress4X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\n/**********************************/\n/* quad-symbol decoding           */\n/**********************************/\ntypedef struct { BYTE nbBits; BYTE nbBytes; } HUF_DDescX6;\ntypedef union { BYTE byte[4]; U32 sequence; } HUF_DSeqX6;\n\n/* recursive, up to level 3; may benefit from <template>-like strategy to nest each level inline */\nstatic void HUF_fillDTableX6LevelN(HUF_DDescX6* DDescription, HUF_DSeqX6* DSequence, int sizeLog,\n                           const rankVal_t rankValOrigin, const U32 consumed, const int minWeight, const U32 maxWeight,\n                           const sortedSymbol_t* sortedSymbols, const U32 sortedListSize, const U32* rankStart,\n                           const U32 nbBitsBaseline, HUF_DSeqX6 baseSeq, HUF_DDescX6 DDesc)\n{\n    const int scaleLog = nbBitsBaseline - sizeLog;   /* note : targetLog >= (nbBitsBaseline-1), hence scaleLog <= 1 */\n    const int minBits  = nbBitsBaseline - maxWeight;\n    const U32 level = DDesc.nbBytes;\n    U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];\n    U32 symbolStartPos, s;\n\n    /* local rankVal, will be modified */\n    memcpy(rankVal, rankValOrigin[consumed], sizeof(rankVal));\n\n    /* fill skipped values */\n    if (minWeight>1)\n    {\n        U32 i;\n        const U32 skipSize = rankVal[minWeight];\n        for (i = 0; i < skipSize; i++)\n        {\n            DSequence[i] = baseSeq;\n            DDescription[i] = DDesc;\n        }\n    }\n\n    /* fill DTable */\n    DDesc.nbBytes++;\n    symbolStartPos = rankStart[minWeight];\n    for (s=symbolStartPos; s<sortedListSize; s++)\n    {\n        const BYTE symbol = sortedSymbols[s].symbol;\n        const U32  weight = sortedSymbols[s].weight;   /* >= 1 (sorted) */\n        const int  nbBits = nbBitsBaseline - weight;   /* >= 1 (by construction) */\n        const int  totalBits = consumed+nbBits;\n        const U32  start  = rankVal[weight];\n        const U32  length = 1 << (sizeLog-nbBits);\n        baseSeq.byte[level] = symbol;\n        DDesc.nbBits = (BYTE)totalBits;\n\n        if ((level<3) && (sizeLog-totalBits >= minBits))   /* enough room for another symbol */\n        {\n            int nextMinWeight = totalBits + scaleLog;\n            if (nextMinWeight < 1) nextMinWeight = 1;\n            HUF_fillDTableX6LevelN(DDescription+start, DSequence+start, sizeLog-nbBits,\n                           rankValOrigin, totalBits, nextMinWeight, maxWeight,\n                           sortedSymbols, sortedListSize, rankStart,\n                           nbBitsBaseline, baseSeq, DDesc);   /* recursive (max : level 3) */\n        }\n        else\n        {\n            U32 i;\n            const U32 end = start + length;\n            for (i = start; i < end; i++)\n            {\n                DDescription[i] = DDesc;\n                DSequence[i] = baseSeq;\n            }\n        }\n        rankVal[weight] += length;\n    }\n}\n\n\n/* note : same preparation as X4 */\nstatic size_t HUF_readDTableX6 (U32* DTable, const void* src, size_t srcSize)\n{\n    BYTE weightList[HUF_MAX_SYMBOL_VALUE + 1];\n    sortedSymbol_t sortedSymbol[HUF_MAX_SYMBOL_VALUE + 1];\n    U32 rankStats[HUF_ABSOLUTEMAX_TABLELOG + 1] = { 0 };\n    U32 rankStart0[HUF_ABSOLUTEMAX_TABLELOG + 2] = { 0 };\n    U32* const rankStart = rankStart0+1;\n    U32 tableLog, maxW, sizeOfSort, nbSymbols;\n    rankVal_t rankVal;\n    const U32 memLog = DTable[0];\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize = ip[0];\n\n    if (memLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge);\n    //memset(weightList, 0, sizeof(weightList));   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUF_readStats(weightList, HUF_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);\n    if (HUF_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > memLog) return ERROR(tableLog_tooLarge);   /* DTable is too small */\n\n    /* find maxWeight */\n    for (maxW = tableLog; rankStats[maxW]==0; maxW--)\n        { if (!maxW) return ERROR(GENERIC); }  /* necessarily finds a solution before maxW==0 */\n\n\n    /* Get start index of each weight */\n    {\n        U32 w, nextRankStart = 0;\n        for (w=1; w<=maxW; w++)\n        {\n            U32 current = nextRankStart;\n            nextRankStart += rankStats[w];\n            rankStart[w] = current;\n        }\n        rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/\n        sizeOfSort = nextRankStart;\n    }\n\n    /* sort symbols by weight */\n    {\n        U32 s;\n        for (s=0; s<nbSymbols; s++)\n        {\n            U32 w = weightList[s];\n            U32 r = rankStart[w]++;\n            sortedSymbol[r].symbol = (BYTE)s;\n            sortedSymbol[r].weight = (BYTE)w;\n        }\n        rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */\n    }\n\n    /* Build rankVal */\n    {\n        const U32 minBits = tableLog+1 - maxW;\n        U32 nextRankVal = 0;\n        U32 w, consumed;\n        const int rescale = (memLog-tableLog) - 1;   /* tableLog <= memLog */\n        U32* rankVal0 = rankVal[0];\n        for (w=1; w<=maxW; w++)\n        {\n            U32 current = nextRankVal;\n            nextRankVal += rankStats[w] << (w+rescale);\n            rankVal0[w] = current;\n        }\n        for (consumed = minBits; consumed <= memLog - minBits; consumed++)\n        {\n            U32* rankValPtr = rankVal[consumed];\n            for (w = 1; w <= maxW; w++)\n            {\n                rankValPtr[w] = rankVal0[w] >> consumed;\n            }\n        }\n    }\n\n\n    /* fill tables */\n    {\n        void* ptr = DTable+1;\n        HUF_DDescX6* DDescription = (HUF_DDescX6*)(ptr);\n        void* dSeqStart = DTable + 1 + ((size_t)1<<(memLog-1));\n        HUF_DSeqX6* DSequence = (HUF_DSeqX6*)(dSeqStart);\n        HUF_DSeqX6 DSeq;\n        HUF_DDescX6 DDesc;\n        DSeq.sequence = 0;\n        DDesc.nbBits = 0;\n        DDesc.nbBytes = 0;\n        HUF_fillDTableX6LevelN(DDescription, DSequence, memLog,\n                       (const U32 (*)[HUF_ABSOLUTEMAX_TABLELOG + 1])rankVal, 0, 1, maxW,\n                       sortedSymbol, sizeOfSort, rankStart0,\n                       tableLog+1, DSeq, DDesc);\n    }\n\n    return iSize;\n}\n\n\nstatic U32 HUF_decodeSymbolX6(void* op, BIT_DStream_t* DStream, const HUF_DDescX6* dd, const HUF_DSeqX6* ds, const U32 dtLog)\n{\n    const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, ds+val, sizeof(HUF_DSeqX6));\n    BIT_skipBits(DStream, dd[val].nbBits);\n    return dd[val].nbBytes;\n}\n\nstatic U32 HUF_decodeLastSymbolsX6(void* op, const U32 maxL, BIT_DStream_t* DStream,\n                                  const HUF_DDescX6* dd, const HUF_DSeqX6* ds, const U32 dtLog)\n{\n    const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    U32 length = dd[val].nbBytes;\n    if (length <= maxL)\n    {\n        memcpy(op, ds+val, length);\n        BIT_skipBits(DStream, dd[val].nbBits);\n        return length;\n    }\n    memcpy(op, ds+val, maxL);\n    if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8))\n    {\n        BIT_skipBits(DStream, dd[val].nbBits);\n        if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))\n            DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);   /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */\n    }\n    return maxL;\n}\n\n\n#define HUF_DECODE_SYMBOLX6_0(ptr, DStreamPtr) \\\n    ptr += HUF_decodeSymbolX6(ptr, DStreamPtr, dd, ds, dtLog)\n\n#define HUF_DECODE_SYMBOLX6_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \\\n        HUF_DECODE_SYMBOLX6_0(ptr, DStreamPtr)\n\n#define HUF_DECODE_SYMBOLX6_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        HUF_DECODE_SYMBOLX6_0(ptr, DStreamPtr)\n\nstatic inline size_t HUF_decodeStreamX6(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd, const U32* DTable, const U32 dtLog)\n{\n    const void* ddPtr = DTable+1;\n    const HUF_DDescX6* dd = (const HUF_DDescX6*)(ddPtr);\n    const void* dsPtr = DTable + 1 + ((size_t)1<<(dtLog-1));\n    const HUF_DSeqX6* ds = (const HUF_DSeqX6*)(dsPtr);\n    BYTE* const pStart = p;\n\n    /* up to 16 symbols at a time */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-16))\n    {\n        HUF_DECODE_SYMBOLX6_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX6_1(p, bitDPtr);\n        HUF_DECODE_SYMBOLX6_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX6_0(p, bitDPtr);\n    }\n\n    /* closer to the end, up to 4 symbols at a time */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-4))\n        HUF_DECODE_SYMBOLX6_0(p, bitDPtr);\n\n    while (p <= pEnd-4)\n        HUF_DECODE_SYMBOLX6_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */\n\n    while (p < pEnd)\n        p += HUF_decodeLastSymbolsX6(p, (U32)(pEnd-p), bitDPtr, dd, ds, dtLog);\n\n    return p-pStart;\n}\n\n\n\nstatic size_t HUF_decompress4X6_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U32* DTable)\n{\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n\n    {\n        const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n\n        const U32 dtLog = DTable[0];\n        const void* ddPtr = DTable+1;\n        const HUF_DDescX6* dd = (const HUF_DDescX6*)(ddPtr);\n        const void* dsPtr = DTable + 1 + ((size_t)1<<(dtLog-1));\n        const HUF_DSeqX6* ds = (const HUF_DSeqX6*)(dsPtr);\n        size_t errorCode;\n\n        /* Init */\n        BIT_DStream_t bitD1;\n        BIT_DStream_t bitD2;\n        BIT_DStream_t bitD3;\n        BIT_DStream_t bitD4;\n        const size_t length1 = MEM_readLE16(istart);\n        const size_t length2 = MEM_readLE16(istart+2);\n        const size_t length3 = MEM_readLE16(istart+4);\n        size_t length4;\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n\n        length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        errorCode = BIT_initDStream(&bitD1, istart1, length1);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD2, istart2, length2);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD3, istart3, length3);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD4, istart4, length4);\n        if (HUF_isError(errorCode)) return errorCode;\n\n        /* 16-64 symbols per loop (4-16 symbols per stream) */\n        endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        for ( ; (op3 <= opStart4) && (endSignal==BIT_DStream_unfinished) && (op4<=(oend-16)) ; )\n        {\n            HUF_DECODE_SYMBOLX6_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX6_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX6_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX6_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX6_1(op1, &bitD1);\n            HUF_DECODE_SYMBOLX6_1(op2, &bitD2);\n            HUF_DECODE_SYMBOLX6_1(op3, &bitD3);\n            HUF_DECODE_SYMBOLX6_1(op4, &bitD4);\n            HUF_DECODE_SYMBOLX6_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX6_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX6_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX6_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX6_0(op1, &bitD1);\n            HUF_DECODE_SYMBOLX6_0(op2, &bitD2);\n            HUF_DECODE_SYMBOLX6_0(op3, &bitD3);\n            HUF_DECODE_SYMBOLX6_0(op4, &bitD4);\n\n            endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUF_decodeStreamX6(op1, &bitD1, opStart2, DTable, dtLog);\n        HUF_decodeStreamX6(op2, &bitD2, opStart3, DTable, dtLog);\n        HUF_decodeStreamX6(op3, &bitD3, opStart4, DTable, dtLog);\n        HUF_decodeStreamX6(op4, &bitD4, oend,     DTable, dtLog);\n\n        /* check */\n        endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nstatic size_t HUF_decompress4X6 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUF_CREATE_STATIC_DTABLEX6(DTable, HUF_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t hSize = HUF_readDTableX6 (DTable, cSrc, cSrcSize);\n    if (HUF_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize;\n    cSrcSize -= hSize;\n\n    return HUF_decompress4X6_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\n/**********************************/\n/* Generic decompression selector */\n/**********************************/\n\ntypedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;\nstatic const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =\n{\n    /* single, double, quad */\n    {{0,0}, {1,1}, {2,2}},  /* Q==0 : impossible */\n    {{0,0}, {1,1}, {2,2}},  /* Q==1 : impossible */\n    {{  38,130}, {1313, 74}, {2151, 38}},   /* Q == 2 : 12-18% */\n    {{ 448,128}, {1353, 74}, {2238, 41}},   /* Q == 3 : 18-25% */\n    {{ 556,128}, {1353, 74}, {2238, 47}},   /* Q == 4 : 25-32% */\n    {{ 714,128}, {1418, 74}, {2436, 53}},   /* Q == 5 : 32-38% */\n    {{ 883,128}, {1437, 74}, {2464, 61}},   /* Q == 6 : 38-44% */\n    {{ 897,128}, {1515, 75}, {2622, 68}},   /* Q == 7 : 44-50% */\n    {{ 926,128}, {1613, 75}, {2730, 75}},   /* Q == 8 : 50-56% */\n    {{ 947,128}, {1729, 77}, {3359, 77}},   /* Q == 9 : 56-62% */\n    {{1107,128}, {2083, 81}, {4006, 84}},   /* Q ==10 : 62-69% */\n    {{1177,128}, {2379, 87}, {4785, 88}},   /* Q ==11 : 69-75% */\n    {{1242,128}, {2415, 93}, {5155, 84}},   /* Q ==12 : 75-81% */\n    {{1349,128}, {2644,106}, {5260,106}},   /* Q ==13 : 81-87% */\n    {{1455,128}, {2422,124}, {4174,124}},   /* Q ==14 : 87-93% */\n    {{ 722,128}, {1891,145}, {1936,146}},   /* Q ==15 : 93-99% */\n};\n\ntypedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);\n\nstatic size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    static const decompressionAlgo decompress[3] = { HUF_decompress4X2, HUF_decompress4X4, HUF_decompress4X6 };\n    /* estimate decompression time */\n    U32 Q;\n    const U32 D256 = (U32)(dstSize >> 8);\n    U32 Dtime[3];\n    U32 algoNb = 0;\n    int n;\n\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */\n    if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */\n    if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */\n\n    /* decoder timing evaluation */\n    Q = (U32)(cSrcSize * 16 / dstSize);   /* Q < 16 since dstSize > cSrcSize */\n    for (n=0; n<3; n++)\n        Dtime[n] = algoTime[Q][n].tableTime + (algoTime[Q][n].decode256Time * D256);\n\n    Dtime[1] += Dtime[1] >> 4; Dtime[2] += Dtime[2] >> 3; /* advantage to algorithms using less memory, for cache eviction */\n\n    if (Dtime[1] < Dtime[0]) algoNb = 1;\n    if (Dtime[2] < Dtime[algoNb]) algoNb = 2;\n\n    return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);\n\n    //return HUF_decompress4X2(dst, dstSize, cSrc, cSrcSize);   /* multi-streams single-symbol decoding */\n    //return HUF_decompress4X4(dst, dstSize, cSrc, cSrcSize);   /* multi-streams double-symbols decoding */\n    //return HUF_decompress4X6(dst, dstSize, cSrc, cSrcSize);   /* multi-streams quad-symbols decoding */\n}\n/*\n    zstd - standard compression library\n    Copyright (C) 2014-2015, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n    - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n\n/* ***************************************************************\n*  Tuning parameters\n*****************************************************************/\n/*!\n*  MEMORY_USAGE :\n*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n*  Increasing memory usage improves compression ratio\n*  Reduced memory usage can improve speed, due to cache effect\n*/\n#define ZSTD_MEMORY_USAGE 17\n\n/*!\n * HEAPMODE :\n * Select how default compression functions will allocate memory for their hash table,\n * in memory stack (0, fastest), or in memory heap (1, requires malloc())\n * Note that compression context is fairly large, as a consequence heap memory is recommended.\n */\n#ifndef ZSTD_HEAPMODE\n#  define ZSTD_HEAPMODE 1\n#endif /* ZSTD_HEAPMODE */\n\n/*!\n*  LEGACY_SUPPORT :\n*  decompressor can decode older formats (starting from Zstd 0.1+)\n*/\n#ifndef ZSTD_LEGACY_SUPPORT\n#  define ZSTD_LEGACY_SUPPORT 1\n#endif\n\n\n/* *******************************************************\n*  Includes\n*********************************************************/\n#include <stdlib.h>      /* calloc */\n#include <string.h>      /* memcpy, memmove */\n#include <stdio.h>       /* debug : printf */\n\n\n/* *******************************************************\n*  Compiler specifics\n*********************************************************/\n#ifdef __AVX2__\n#  include <immintrin.h>   /* AVX2 intrinsics */\n#endif\n\n#ifdef _MSC_VER    /* Visual Studio */\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4324)        /* disable: C4324: padded structure */\n#endif\n\n\n/* *******************************************************\n*  Constants\n*********************************************************/\n#define HASH_LOG (ZSTD_MEMORY_USAGE - 2)\n#define HASH_TABLESIZE (1 << HASH_LOG)\n#define HASH_MASK (HASH_TABLESIZE - 1)\n\n#define KNUTH 2654435761\n\n#define BIT7 128\n#define BIT6  64\n#define BIT5  32\n#define BIT4  16\n#define BIT1   2\n#define BIT0   1\n\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\n#define BLOCKSIZE (128 KB)                 /* define, for static allocation */\n#define MIN_SEQUENCES_SIZE (2 /*seqNb*/ + 2 /*dumps*/ + 3 /*seqTables*/ + 1 /*bitStream*/)\n#define MIN_CBLOCK_SIZE (3 /*litCSize*/ + MIN_SEQUENCES_SIZE)\n#define IS_RAW BIT0\n#define IS_RLE BIT1\n\n#define WORKPLACESIZE (BLOCKSIZE*3)\n#define MINMATCH 4\n#define MLbits   7\n#define LLbits   6\n#define Offbits  5\n#define MaxML  ((1<<MLbits )-1)\n#define MaxLL  ((1<<LLbits )-1)\n#define MaxOff   31\n#define LitFSELog  11\n#define MLFSELog   10\n#define LLFSELog   10\n#define OffFSELog   9\n#define MAX(a,b) ((a)<(b)?(b):(a))\n#define MaxSeq MAX(MaxLL, MaxML)\n\n#define LITERAL_NOENTROPY 63\n#define COMMAND_NOENTROPY 7   /* to remove */\n\n#define ZSTD_CONTENTSIZE_ERROR   (0ULL - 2)\n\nstatic const size_t ZSTD_blockHeaderSize = 3;\nstatic const size_t ZSTD_frameHeaderSize = 4;\n\n\n/* *******************************************************\n*  Memory operations\n**********************************************************/\nstatic void   ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }\n\nstatic void   ZSTD_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }\n\n#define COPY8(d,s) { ZSTD_copy8(d,s); d+=8; s+=8; }\n\n/*! ZSTD_wildcopy : custom version of memcpy(), can copy up to 7-8 bytes too many */\nstatic void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length)\n{\n    const BYTE* ip = (const BYTE*)src;\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + length;\n    do COPY8(op, ip) while (op < oend);\n}\n\n\n/* **************************************\n*  Local structures\n****************************************/\ntypedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;\n\ntypedef struct\n{\n    blockType_t blockType;\n    U32 origSize;\n} blockProperties_t;\n\ntypedef struct {\n    void* buffer;\n    U32*  offsetStart;\n    U32*  offset;\n    BYTE* offCodeStart;\n    BYTE* offCode;\n    BYTE* litStart;\n    BYTE* lit;\n    BYTE* litLengthStart;\n    BYTE* litLength;\n    BYTE* matchLengthStart;\n    BYTE* matchLength;\n    BYTE* dumpsStart;\n    BYTE* dumps;\n} SeqStore_t;\n\n\n/* *************************************\n*  Error Management\n***************************************/\n/*! ZSTD_isError\n*   tells if a return value is an error code */\nstatic unsigned ZSTD_isError(size_t code) { return ERR_isError(code); }\n\n\n\n/* *************************************************************\n*   Decompression section\n***************************************************************/\nstruct ZSTDv02_Dctx_s\n{\n    U32 LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];\n    U32 OffTable[FSE_DTABLE_SIZE_U32(OffFSELog)];\n    U32 MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];\n    void* previousDstEnd;\n    void* base;\n    size_t expected;\n    blockType_t bType;\n    U32 phase;\n    const BYTE* litPtr;\n    size_t litSize;\n    BYTE litBuffer[BLOCKSIZE + 8 /* margin for wildcopy */];\n};   /* typedef'd to ZSTD_Dctx within \"zstd_static.h\" */\n\n\nstatic size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)\n{\n    const BYTE* const in = (const BYTE* const)src;\n    BYTE headerFlags;\n    U32 cSize;\n\n    if (srcSize < 3) return ERROR(srcSize_wrong);\n\n    headerFlags = *in;\n    cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);\n\n    bpPtr->blockType = (blockType_t)(headerFlags >> 6);\n    bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;\n\n    if (bpPtr->blockType == bt_end) return 0;\n    if (bpPtr->blockType == bt_rle) return 1;\n    return cSize;\n}\n\nstatic size_t ZSTD_copyUncompressedBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall);\n    if (srcSize > 0) {\n        memcpy(dst, src, srcSize);\n    }\n    return srcSize;\n}\n\n\n/** ZSTD_decompressLiterals\n    @return : nb of bytes read from src, or an error code*/\nstatic size_t ZSTD_decompressLiterals(void* dst, size_t* maxDstSizePtr,\n                                const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n\n    const size_t litSize = (MEM_readLE32(src) & 0x1FFFFF) >> 2;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n    const size_t litCSize = (MEM_readLE32(ip+2) & 0xFFFFFF) >> 5;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n\n    if (litSize > *maxDstSizePtr) return ERROR(corruption_detected);\n    if (litCSize + 5 > srcSize) return ERROR(corruption_detected);\n\n    if (HUF_isError(HUF_decompress(dst, litSize, ip+5, litCSize))) return ERROR(corruption_detected);\n\n    *maxDstSizePtr = litSize;\n    return litCSize + 5;\n}\n\n\n/** ZSTD_decodeLiteralsBlock\n    @return : nb of bytes read from src (< srcSize )*/\nstatic size_t ZSTD_decodeLiteralsBlock(void* ctx,\n                          const void* src, size_t srcSize)\n{\n    ZSTD_DCtx* dctx = (ZSTD_DCtx*)ctx;\n    const BYTE* const istart = (const BYTE* const)src;\n\n    /* any compressed block with literals segment must be at least this size */\n    if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);\n\n    switch(*istart & 3)\n    {\n    default:\n    case 0:\n        {\n            size_t litSize = BLOCKSIZE;\n            const size_t readSize = ZSTD_decompressLiterals(dctx->litBuffer, &litSize, src, srcSize);\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            memset(dctx->litBuffer + dctx->litSize, 0, 8);\n            return readSize;   /* works if it's an error too */\n        }\n    case IS_RAW:\n        {\n            const size_t litSize = (MEM_readLE32(istart) & 0xFFFFFF) >> 2;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n            if (litSize > srcSize-11)   /* risk of reading too far with wildcopy */\n            {\n                if (litSize > BLOCKSIZE) return ERROR(corruption_detected);\n                if (litSize > srcSize-3) return ERROR(corruption_detected);\n                memcpy(dctx->litBuffer, istart, litSize);\n                dctx->litPtr = dctx->litBuffer;\n                dctx->litSize = litSize;\n                memset(dctx->litBuffer + dctx->litSize, 0, 8);\n                return litSize+3;\n            }\n            /* direct reference into compressed stream */\n            dctx->litPtr = istart+3;\n            dctx->litSize = litSize;\n            return litSize+3;\n        }\n    case IS_RLE:\n        {\n            const size_t litSize = (MEM_readLE32(istart) & 0xFFFFFF) >> 2;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n            if (litSize > BLOCKSIZE) return ERROR(corruption_detected);\n            memset(dctx->litBuffer, istart[3], litSize + 8);\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            return 4;\n        }\n    }\n}\n\n\nstatic size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLengthPtr,\n                         FSE_DTable* DTableLL, FSE_DTable* DTableML, FSE_DTable* DTableOffb,\n                         const void* src, size_t srcSize)\n{\n    const BYTE* const istart = (const BYTE* const)src;\n    const BYTE* ip = istart;\n    const BYTE* const iend = istart + srcSize;\n    U32 LLtype, Offtype, MLtype;\n    U32 LLlog, Offlog, MLlog;\n    size_t dumpsLength;\n\n    /* check */\n    if (srcSize < 5) return ERROR(srcSize_wrong);\n\n    /* SeqHead */\n    *nbSeq = MEM_readLE16(ip); ip+=2;\n    LLtype  = *ip >> 6;\n    Offtype = (*ip >> 4) & 3;\n    MLtype  = (*ip >> 2) & 3;\n    if (*ip & 2)\n    {\n        dumpsLength  = ip[2];\n        dumpsLength += ip[1] << 8;\n        ip += 3;\n    }\n    else\n    {\n        dumpsLength  = ip[1];\n        dumpsLength += (ip[0] & 1) << 8;\n        ip += 2;\n    }\n    *dumpsPtr = ip;\n    ip += dumpsLength;\n    *dumpsLengthPtr = dumpsLength;\n\n    /* check */\n    if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are \"raw\", hence no header, but at least xxLog bits per type */\n\n    /* sequences */\n    {\n        S16 norm[MaxML+1];    /* assumption : MaxML >= MaxLL and MaxOff */\n        size_t headerSize;\n\n        /* Build DTables */\n        switch(LLtype)\n        {\n        case bt_rle :\n            LLlog = 0;\n            FSE_buildDTable_rle(DTableLL, *ip++); break;\n        case bt_raw :\n            LLlog = LLbits;\n            FSE_buildDTable_raw(DTableLL, LLbits); break;\n        default :\n            {   U32 max = MaxLL;\n                headerSize = FSE_readNCount(norm, &max, &LLlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (LLlog > LLFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableLL, norm, max, LLlog);\n        }   }\n\n        switch(Offtype)\n        {\n        case bt_rle :\n            Offlog = 0;\n            if (ip > iend-2) return ERROR(srcSize_wrong);   /* min : \"raw\", hence no header, but at least xxLog bits */\n            FSE_buildDTable_rle(DTableOffb, *ip++ & MaxOff); /* if *ip > MaxOff, data is corrupted */\n            break;\n        case bt_raw :\n            Offlog = Offbits;\n            FSE_buildDTable_raw(DTableOffb, Offbits); break;\n        default :\n            {   U32 max = MaxOff;\n                headerSize = FSE_readNCount(norm, &max, &Offlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (Offlog > OffFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableOffb, norm, max, Offlog);\n        }   }\n\n        switch(MLtype)\n        {\n        case bt_rle :\n            MLlog = 0;\n            if (ip > iend-2) return ERROR(srcSize_wrong); /* min : \"raw\", hence no header, but at least xxLog bits */\n            FSE_buildDTable_rle(DTableML, *ip++); break;\n        case bt_raw :\n            MLlog = MLbits;\n            FSE_buildDTable_raw(DTableML, MLbits); break;\n        default :\n            {   U32 max = MaxML;\n                headerSize = FSE_readNCount(norm, &max, &MLlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (MLlog > MLFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableML, norm, max, MLlog);\n    }   }   }\n\n    return ip-istart;\n}\n\n\ntypedef struct {\n    size_t litLength;\n    size_t offset;\n    size_t matchLength;\n} seq_t;\n\ntypedef struct {\n    BIT_DStream_t DStream;\n    FSE_DState_t stateLL;\n    FSE_DState_t stateOffb;\n    FSE_DState_t stateML;\n    size_t prevOffset;\n    const BYTE* dumps;\n    const BYTE* dumpsEnd;\n} seqState_t;\n\n\nstatic void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)\n{\n    size_t litLength;\n    size_t prevOffset;\n    size_t offset;\n    size_t matchLength;\n    const BYTE* dumps = seqState->dumps;\n    const BYTE* const de = seqState->dumpsEnd;\n\n    /* Literal length */\n    litLength = FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream));\n    prevOffset = litLength ? seq->offset : seqState->prevOffset;\n    seqState->prevOffset = seq->offset;\n    if (litLength == MaxLL)\n    {\n        const U32 add = dumps<de ? *dumps++ : 0;\n        if (add < 255) litLength += add;\n        else if (dumps + 3 <= de)\n        {\n            litLength = MEM_readLE24(dumps);\n            dumps += 3;\n        }\n        if (dumps >= de) dumps = de-1;   /* late correction, to avoid read overflow (data is now corrupted anyway) */\n    }\n\n    /* Offset */\n    {\n        static const size_t offsetPrefix[MaxOff+1] = {  /* note : size_t faster than U32 */\n                1 /*fake*/, 1, 2, 4, 8, 16, 32, 64, 128, 256,\n                512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144,\n                524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, /*fake*/ 1, 1, 1, 1, 1 };\n        U32 offsetCode, nbBits;\n        offsetCode = FSE_decodeSymbol(&(seqState->stateOffb), &(seqState->DStream));   /* <= maxOff, by table construction */\n        if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));\n        nbBits = offsetCode - 1;\n        if (offsetCode==0) nbBits = 0;   /* cmove */\n        offset = offsetPrefix[offsetCode] + BIT_readBits(&(seqState->DStream), nbBits);\n        if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));\n        if (offsetCode==0) offset = prevOffset;   /* cmove */\n    }\n\n    /* MatchLength */\n    matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream));\n    if (matchLength == MaxML)\n    {\n        const U32 add = dumps<de ? *dumps++ : 0;\n        if (add < 255) matchLength += add;\n        else if (dumps + 3 <= de)\n        {\n            matchLength = MEM_readLE24(dumps);\n            dumps += 3;\n        }\n        if (dumps >= de) dumps = de-1;   /* late correction, to avoid read overflow (data is now corrupted anyway) */\n    }\n    matchLength += MINMATCH;\n\n    /* save result */\n    seq->litLength = litLength;\n    seq->offset = offset;\n    seq->matchLength = matchLength;\n    seqState->dumps = dumps;\n}\n\n\nstatic size_t ZSTD_execSequence(BYTE* op,\n                                seq_t sequence,\n                                const BYTE** litPtr, const BYTE* const litLimit,\n                                BYTE* const base, BYTE* const oend)\n{\n    static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4};   /* added */\n    static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11};   /* subtracted */\n    const BYTE* const ostart = op;\n    BYTE* const oLitEnd = op + sequence.litLength;\n    BYTE* const oMatchEnd = op + sequence.litLength + sequence.matchLength;   /* risk : address space overflow (32-bits) */\n    BYTE* const oend_8 = oend-8;\n    const BYTE* const litEnd = *litPtr + sequence.litLength;\n\n    /* checks */\n    size_t const seqLength = sequence.litLength + sequence.matchLength;\n\n    if (seqLength > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);\n    if (sequence.litLength > (size_t)(litLimit - *litPtr)) return ERROR(corruption_detected);\n    /* Now we know there are no overflow in literal nor match lengths, can use the pointer check */\n    if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall);\n    if (sequence.offset > (U32)(oLitEnd - base)) return ERROR(corruption_detected);\n\n    if (oMatchEnd > oend) return ERROR(dstSize_tooSmall);   /* overwrite beyond dst buffer */\n    if (litEnd > litLimit) return ERROR(corruption_detected);   /* overRead beyond lit buffer */\n\n    /* copy Literals */\n    ZSTD_wildcopy(op, *litPtr, (ptrdiff_t)sequence.litLength);   /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */\n    op = oLitEnd;\n    *litPtr = litEnd;   /* update for next sequence */\n\n    /* copy Match */\n    {\n        const BYTE* match = op - sequence.offset;\n\n        /* check */\n        if (sequence.offset > (size_t)op) return ERROR(corruption_detected);   /* address space overflow test (this test seems kept by clang optimizer) */\n        //if (match > op) return ERROR(corruption_detected);   /* address space overflow test (is clang optimizer removing this test ?) */\n        if (match < base) return ERROR(corruption_detected);\n\n        /* close range match, overlap */\n        if (sequence.offset < 8)\n        {\n            const int dec64 = dec64table[sequence.offset];\n            op[0] = match[0];\n            op[1] = match[1];\n            op[2] = match[2];\n            op[3] = match[3];\n            match += dec32table[sequence.offset];\n            ZSTD_copy4(op+4, match);\n            match -= dec64;\n        }\n        else\n        {\n            ZSTD_copy8(op, match);\n        }\n        op += 8; match += 8;\n\n        if (oMatchEnd > oend-(16-MINMATCH))\n        {\n            if (op < oend_8)\n            {\n                ZSTD_wildcopy(op, match, oend_8 - op);\n                match += oend_8 - op;\n                op = oend_8;\n            }\n            while (op < oMatchEnd) *op++ = *match++;\n        }\n        else\n        {\n            ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8);   /* works even if matchLength < 8 */\n        }\n    }\n\n    return oMatchEnd - ostart;\n}\n\nstatic size_t ZSTD_decompressSequences(\n                               void* ctx,\n                               void* dst, size_t maxDstSize,\n                         const void* seqStart, size_t seqSize)\n{\n    ZSTD_DCtx* dctx = (ZSTD_DCtx*)ctx;\n    const BYTE* ip = (const BYTE*)seqStart;\n    const BYTE* const iend = ip + seqSize;\n    BYTE* const ostart = (BYTE* const)dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + maxDstSize;\n    size_t errorCode, dumpsLength;\n    const BYTE* litPtr = dctx->litPtr;\n    const BYTE* const litEnd = litPtr + dctx->litSize;\n    int nbSeq;\n    const BYTE* dumps;\n    U32* DTableLL = dctx->LLTable;\n    U32* DTableML = dctx->MLTable;\n    U32* DTableOffb = dctx->OffTable;\n    BYTE* const base = (BYTE*) (dctx->base);\n\n    /* Build Decoding Tables */\n    errorCode = ZSTD_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,\n                                      DTableLL, DTableML, DTableOffb,\n                                      ip, iend-ip);\n    if (ZSTD_isError(errorCode)) return errorCode;\n    ip += errorCode;\n\n    /* Regen sequences */\n    {\n        seq_t sequence;\n        seqState_t seqState;\n\n        memset(&sequence, 0, sizeof(sequence));\n        seqState.dumps = dumps;\n        seqState.dumpsEnd = dumps + dumpsLength;\n        seqState.prevOffset = 1;\n        errorCode = BIT_initDStream(&(seqState.DStream), ip, iend-ip);\n        if (ERR_isError(errorCode)) return ERROR(corruption_detected);\n        FSE_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);\n        FSE_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);\n        FSE_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);\n\n        for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (nbSeq>0) ; )\n        {\n            size_t oneSeqSize;\n            nbSeq--;\n            ZSTD_decodeSequence(&sequence, &seqState);\n            oneSeqSize = ZSTD_execSequence(op, sequence, &litPtr, litEnd, base, oend);\n            if (ZSTD_isError(oneSeqSize)) return oneSeqSize;\n            op += oneSeqSize;\n        }\n\n        /* check if reached exact end */\n        if ( !BIT_endOfDStream(&(seqState.DStream)) ) return ERROR(corruption_detected);   /* requested too much : data is corrupted */\n        if (nbSeq<0) return ERROR(corruption_detected);   /* requested too many sequences : data is corrupted */\n\n        /* last literal segment */\n        {\n            size_t lastLLSize = litEnd - litPtr;\n            if (litPtr > litEnd) return ERROR(corruption_detected);\n            if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);\n            if (lastLLSize > 0) {\n                if (op != litPtr) memmove(op, litPtr, lastLLSize);\n                op += lastLLSize;\n            }\n        }\n    }\n\n    return op-ostart;\n}\n\n\nstatic size_t ZSTD_decompressBlock(\n                            void* ctx,\n                            void* dst, size_t maxDstSize,\n                      const void* src, size_t srcSize)\n{\n    /* blockType == blockCompressed */\n    const BYTE* ip = (const BYTE*)src;\n\n    /* Decode literals sub-block */\n    size_t litCSize = ZSTD_decodeLiteralsBlock(ctx, src, srcSize);\n    if (ZSTD_isError(litCSize)) return litCSize;\n    ip += litCSize;\n    srcSize -= litCSize;\n\n    return ZSTD_decompressSequences(ctx, dst, maxDstSize, ip, srcSize);\n}\n\n\nstatic size_t ZSTD_decompressDCtx(void* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n    const BYTE* iend = ip + srcSize;\n    BYTE* const ostart = (BYTE* const)dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + maxDstSize;\n    size_t remainingSize = srcSize;\n    U32 magicNumber;\n    blockProperties_t blockProperties;\n\n    /* Frame Header */\n    if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);\n    magicNumber = MEM_readLE32(src);\n    if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);\n    ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;\n\n    /* Loop on each block */\n    while (1)\n    {\n        size_t decodedSize=0;\n        size_t cBlockSize = ZSTD_getcBlockSize(ip, iend-ip, &blockProperties);\n        if (ZSTD_isError(cBlockSize)) return cBlockSize;\n\n        ip += ZSTD_blockHeaderSize;\n        remainingSize -= ZSTD_blockHeaderSize;\n        if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);\n\n        switch(blockProperties.blockType)\n        {\n        case bt_compressed:\n            decodedSize = ZSTD_decompressBlock(ctx, op, oend-op, ip, cBlockSize);\n            break;\n        case bt_raw :\n            decodedSize = ZSTD_copyUncompressedBlock(op, oend-op, ip, cBlockSize);\n            break;\n        case bt_rle :\n            return ERROR(GENERIC);   /* not yet supported */\n            break;\n        case bt_end :\n            /* end of frame */\n            if (remainingSize) return ERROR(srcSize_wrong);\n            break;\n        default:\n            return ERROR(GENERIC);   /* impossible */\n        }\n        if (cBlockSize == 0) break;   /* bt_end */\n\n        if (ZSTD_isError(decodedSize)) return decodedSize;\n        op += decodedSize;\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n    }\n\n    return op-ostart;\n}\n\nstatic size_t ZSTD_decompress(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    ZSTD_DCtx ctx;\n    ctx.base = dst;\n    return ZSTD_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize);\n}\n\n/* ZSTD_errorFrameSizeInfoLegacy() :\n   assumes `cSize` and `dBound` are _not_ NULL */\nstatic void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)\n{\n    *cSize = ret;\n    *dBound = ZSTD_CONTENTSIZE_ERROR;\n}\n\nvoid ZSTDv02_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)\n{\n    const BYTE* ip = (const BYTE*)src;\n    size_t remainingSize = srcSize;\n    size_t nbBlocks = 0;\n    U32 magicNumber;\n    blockProperties_t blockProperties;\n\n    /* Frame Header */\n    if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) {\n        ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n        return;\n    }\n    magicNumber = MEM_readLE32(src);\n    if (magicNumber != ZSTD_magicNumber) {\n        ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));\n        return;\n    }\n    ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;\n\n    /* Loop on each block */\n    while (1)\n    {\n        size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);\n        if (ZSTD_isError(cBlockSize)) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);\n            return;\n        }\n\n        ip += ZSTD_blockHeaderSize;\n        remainingSize -= ZSTD_blockHeaderSize;\n        if (cBlockSize > remainingSize) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n            return;\n        }\n\n        if (cBlockSize == 0) break;   /* bt_end */\n\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n        nbBlocks++;\n    }\n\n    *cSize = ip - (const BYTE*)src;\n    *dBound = nbBlocks * BLOCKSIZE;\n}\n\n/*******************************\n*  Streaming Decompression API\n*******************************/\n\nstatic size_t ZSTD_resetDCtx(ZSTD_DCtx* dctx)\n{\n    dctx->expected = ZSTD_frameHeaderSize;\n    dctx->phase = 0;\n    dctx->previousDstEnd = NULL;\n    dctx->base = NULL;\n    return 0;\n}\n\nstatic ZSTD_DCtx* ZSTD_createDCtx(void)\n{\n    ZSTD_DCtx* dctx = (ZSTD_DCtx*)malloc(sizeof(ZSTD_DCtx));\n    if (dctx==NULL) return NULL;\n    ZSTD_resetDCtx(dctx);\n    return dctx;\n}\n\nstatic size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)\n{\n    free(dctx);\n    return 0;\n}\n\nstatic size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx)\n{\n    return dctx->expected;\n}\n\nstatic size_t ZSTD_decompressContinue(ZSTD_DCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    /* Sanity check */\n    if (srcSize != ctx->expected) return ERROR(srcSize_wrong);\n    if (dst != ctx->previousDstEnd)  /* not contiguous */\n        ctx->base = dst;\n\n    /* Decompress : frame header */\n    if (ctx->phase == 0)\n    {\n        /* Check frame magic header */\n        U32 magicNumber = MEM_readLE32(src);\n        if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);\n        ctx->phase = 1;\n        ctx->expected = ZSTD_blockHeaderSize;\n        return 0;\n    }\n\n    /* Decompress : block header */\n    if (ctx->phase == 1)\n    {\n        blockProperties_t bp;\n        size_t blockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);\n        if (ZSTD_isError(blockSize)) return blockSize;\n        if (bp.blockType == bt_end)\n        {\n            ctx->expected = 0;\n            ctx->phase = 0;\n        }\n        else\n        {\n            ctx->expected = blockSize;\n            ctx->bType = bp.blockType;\n            ctx->phase = 2;\n        }\n\n        return 0;\n    }\n\n    /* Decompress : block content */\n    {\n        size_t rSize;\n        switch(ctx->bType)\n        {\n        case bt_compressed:\n            rSize = ZSTD_decompressBlock(ctx, dst, maxDstSize, src, srcSize);\n            break;\n        case bt_raw :\n            rSize = ZSTD_copyUncompressedBlock(dst, maxDstSize, src, srcSize);\n            break;\n        case bt_rle :\n            return ERROR(GENERIC);   /* not yet handled */\n            break;\n        case bt_end :   /* should never happen (filtered at phase 1) */\n            rSize = 0;\n            break;\n        default:\n            return ERROR(GENERIC);\n        }\n        ctx->phase = 1;\n        ctx->expected = ZSTD_blockHeaderSize;\n        if (ZSTD_isError(rSize)) return rSize;\n        ctx->previousDstEnd = (void*)( ((char*)dst) + rSize);\n        return rSize;\n    }\n\n}\n\n\n/* wrapper layer */\n\nunsigned ZSTDv02_isError(size_t code)\n{\n    return ZSTD_isError(code);\n}\n\nsize_t ZSTDv02_decompress( void* dst, size_t maxOriginalSize,\n                     const void* src, size_t compressedSize)\n{\n    return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize);\n}\n\nZSTDv02_Dctx* ZSTDv02_createDCtx(void)\n{\n    return (ZSTDv02_Dctx*)ZSTD_createDCtx();\n}\n\nsize_t ZSTDv02_freeDCtx(ZSTDv02_Dctx* dctx)\n{\n    return ZSTD_freeDCtx((ZSTD_DCtx*)dctx);\n}\n\nsize_t ZSTDv02_resetDCtx(ZSTDv02_Dctx* dctx)\n{\n    return ZSTD_resetDCtx((ZSTD_DCtx*)dctx);\n}\n\nsize_t ZSTDv02_nextSrcSizeToDecompress(ZSTDv02_Dctx* dctx)\n{\n    return ZSTD_nextSrcSizeToDecompress((ZSTD_DCtx*)dctx);\n}\n\nsize_t ZSTDv02_decompressContinue(ZSTDv02_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    return ZSTD_decompressContinue((ZSTD_DCtx*)dctx, dst, maxDstSize, src, srcSize);\n}\n"
  },
  {
    "path": "lib/legacy/zstd_v02.h",
    "content": "/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_V02_H_4174539423\n#define ZSTD_V02_H_4174539423\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* *************************************\n*  Includes\n***************************************/\n#include <stddef.h>   /* size_t */\n\n\n/* *************************************\n*  Simple one-step function\n***************************************/\n/**\nZSTDv02_decompress() : decompress ZSTD frames compliant with v0.2.x format\n    compressedSize : is the exact source size\n    maxOriginalSize : is the size of the 'dst' buffer, which must be already allocated.\n                      It must be equal or larger than originalSize, otherwise decompression will fail.\n    return : the number of bytes decompressed into destination buffer (originalSize)\n             or an errorCode if it fails (which can be tested using ZSTDv01_isError())\n*/\nsize_t ZSTDv02_decompress( void* dst, size_t maxOriginalSize,\n                     const void* src, size_t compressedSize);\n\n /**\n ZSTDv02_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.2.x format\n     srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'\n     cSize (output parameter)  : the number of bytes that would be read to decompress this frame\n                                 or an error code if it fails (which can be tested using ZSTDv01_isError())\n     dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame\n                                 or ZSTD_CONTENTSIZE_ERROR if an error occurs\n\n    note : assumes `cSize` and `dBound` are _not_ NULL.\n */\nvoid ZSTDv02_findFrameSizeInfoLegacy(const void *src, size_t srcSize,\n                                     size_t* cSize, unsigned long long* dBound);\n\n/**\nZSTDv02_isError() : tells if the result of ZSTDv02_decompress() is an error\n*/\nunsigned ZSTDv02_isError(size_t code);\n\n\n/* *************************************\n*  Advanced functions\n***************************************/\ntypedef struct ZSTDv02_Dctx_s ZSTDv02_Dctx;\nZSTDv02_Dctx* ZSTDv02_createDCtx(void);\nsize_t ZSTDv02_freeDCtx(ZSTDv02_Dctx* dctx);\n\nsize_t ZSTDv02_decompressDCtx(void* ctx,\n                              void* dst, size_t maxOriginalSize,\n                        const void* src, size_t compressedSize);\n\n/* *************************************\n*  Streaming functions\n***************************************/\nsize_t ZSTDv02_resetDCtx(ZSTDv02_Dctx* dctx);\n\nsize_t ZSTDv02_nextSrcSizeToDecompress(ZSTDv02_Dctx* dctx);\nsize_t ZSTDv02_decompressContinue(ZSTDv02_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize);\n/**\n  Use above functions alternatively.\n  ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue().\n  ZSTD_decompressContinue() will use previous data blocks to improve compression if they are located prior to current block.\n  Result is the number of bytes regenerated within 'dst'.\n  It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header.\n*/\n\n/* *************************************\n*  Prefix - version detection\n***************************************/\n#define ZSTDv02_magicNumber 0xFD2FB522   /* v0.2 */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* ZSTD_V02_H_4174539423 */\n"
  },
  {
    "path": "lib/legacy/zstd_v03.c",
    "content": "/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n#include <stddef.h>    /* size_t, ptrdiff_t */\n#include \"zstd_v03.h\"\n#include \"../common/compiler.h\"\n#include \"../common/error_private.h\"\n\n\n/******************************************\n*  Compiler-specific\n******************************************/\n#if defined(_MSC_VER)   /* Visual Studio */\n#   include <stdlib.h>  /* _byteswap_ulong */\n#   include <intrin.h>  /* _byteswap_* */\n#endif\n\n\n\n/* ******************************************************************\n   mem.h\n   low-level memory access routines\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef MEM_H_MODULE\n#define MEM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/******************************************\n*  Includes\n******************************************/\n#include <stddef.h>    /* size_t, ptrdiff_t */\n#include <string.h>    /* memcpy */\n\n\n/****************************************************************\n*  Basic Types\n*****************************************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n# if defined(_AIX)\n#  include <inttypes.h>\n# else\n#  include <stdint.h> /* intptr_t */\n# endif\n  typedef  uint8_t BYTE;\n  typedef uint16_t U16;\n  typedef  int16_t S16;\n  typedef uint32_t U32;\n  typedef  int32_t S32;\n  typedef uint64_t U64;\n  typedef  int64_t S64;\n#else\n  typedef unsigned char       BYTE;\n  typedef unsigned short      U16;\n  typedef   signed short      S16;\n  typedef unsigned int        U32;\n  typedef   signed int        S32;\n  typedef unsigned long long  U64;\n  typedef   signed long long  S64;\n#endif\n\n\n/****************************************************************\n*  Memory I/O\n*****************************************************************/\n\nMEM_STATIC unsigned MEM_32bits(void) { return sizeof(void*)==4; }\nMEM_STATIC unsigned MEM_64bits(void) { return sizeof(void*)==8; }\n\nMEM_STATIC unsigned MEM_isLittleEndian(void)\n{\n    const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */\n    return one.c[0];\n}\n\nMEM_STATIC U16 MEM_read16(const void* memPtr)\n{\n    U16 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U32 MEM_read32(const void* memPtr)\n{\n    U32 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U64 MEM_read64(const void* memPtr)\n{\n    U64 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value)\n{\n    memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC U16 MEM_readLE16(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read16(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U16)(p[0] + (p[1]<<8));\n    }\n}\n\nMEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)\n{\n    if (MEM_isLittleEndian())\n    {\n        MEM_write16(memPtr, val);\n    }\n    else\n    {\n        BYTE* p = (BYTE*)memPtr;\n        p[0] = (BYTE)val;\n        p[1] = (BYTE)(val>>8);\n    }\n}\n\nMEM_STATIC U32 MEM_readLE24(const void* memPtr)\n{\n    return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16);\n}\n\nMEM_STATIC U32 MEM_readLE32(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read32(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U32)((U32)p[0] + ((U32)p[1]<<8) + ((U32)p[2]<<16) + ((U32)p[3]<<24));\n    }\n}\n\nMEM_STATIC U64 MEM_readLE64(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read64(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U64)((U64)p[0] + ((U64)p[1]<<8) + ((U64)p[2]<<16) + ((U64)p[3]<<24)\n                     + ((U64)p[4]<<32) + ((U64)p[5]<<40) + ((U64)p[6]<<48) + ((U64)p[7]<<56));\n    }\n}\n\n\nMEM_STATIC size_t MEM_readLEST(const void* memPtr)\n{\n    if (MEM_32bits())\n        return (size_t)MEM_readLE32(memPtr);\n    else\n        return (size_t)MEM_readLE64(memPtr);\n}\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* MEM_H_MODULE */\n\n\n/* ******************************************************************\n   bitstream\n   Part of NewGen Entropy library\n   header file (to include)\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef BITSTREAM_H_MODULE\n#define BITSTREAM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/*\n*  This API consists of small unitary functions, which highly benefit from being inlined.\n*  Since link-time-optimization is not available for all compilers,\n*  these functions are defined into a .h to be included.\n*/\n\n\n/**********************************************\n*  bitStream decompression API (read backward)\n**********************************************/\ntypedef struct\n{\n    size_t   bitContainer;\n    unsigned bitsConsumed;\n    const char* ptr;\n    const char* start;\n} BIT_DStream_t;\n\ntypedef enum { BIT_DStream_unfinished = 0,\n               BIT_DStream_endOfBuffer = 1,\n               BIT_DStream_completed = 2,\n               BIT_DStream_overflow = 3 } BIT_DStream_status;  /* result of BIT_reloadDStream() */\n               /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */\n\nMEM_STATIC size_t   BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize);\nMEM_STATIC size_t   BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);\nMEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD);\nMEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);\n\n\n\n/******************************************\n*  unsafe API\n******************************************/\nMEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);\n/* faster, but works only if nbBits >= 1 */\n\n\n\n/****************************************************************\n*  Helper functions\n****************************************************************/\nMEM_STATIC unsigned BIT_highbit32 (U32 val)\n{\n#   if defined(_MSC_VER)   /* Visual */\n    unsigned long r;\n    return _BitScanReverse(&r, val) ? (unsigned)r : 0;\n#   elif defined(__GNUC__) && (__GNUC__ >= 3)   /* Use GCC Intrinsic */\n    return __builtin_clz (val) ^ 31;\n#   else   /* Software version */\n    static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };\n    U32 v = val;\n    unsigned r;\n    v |= v >> 1;\n    v |= v >> 2;\n    v |= v >> 4;\n    v |= v >> 8;\n    v |= v >> 16;\n    r = DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];\n    return r;\n#   endif\n}\n\n\n\n/**********************************************************\n* bitStream decoding\n**********************************************************/\n\n/*!BIT_initDStream\n*  Initialize a BIT_DStream_t.\n*  @bitD : a pointer to an already allocated BIT_DStream_t structure\n*  @srcBuffer must point at the beginning of a bitStream\n*  @srcSize must be the exact size of the bitStream\n*  @result : size of stream (== srcSize) or an errorCode if a problem is detected\n*/\nMEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize)\n{\n    if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }\n\n    if (srcSize >=  sizeof(size_t))   /* normal case */\n    {\n        U32 contain32;\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = (const char*)srcBuffer + srcSize - sizeof(size_t);\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        contain32 = ((const BYTE*)srcBuffer)[srcSize-1];\n        if (contain32 == 0) return ERROR(GENERIC);   /* endMark not present */\n        bitD->bitsConsumed = 8 - BIT_highbit32(contain32);\n    }\n    else\n    {\n        U32 contain32;\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = bitD->start;\n        bitD->bitContainer = *(const BYTE*)(bitD->start);\n        switch(srcSize)\n        {\n            case 7: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[6]) << (sizeof(size_t)*8 - 16);\n                    /* fallthrough */\n            case 6: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[5]) << (sizeof(size_t)*8 - 24);\n                    /* fallthrough */\n            case 5: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[4]) << (sizeof(size_t)*8 - 32);\n                    /* fallthrough */\n            case 4: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[3]) << 24;\n                    /* fallthrough */\n            case 3: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[2]) << 16;\n                    /* fallthrough */\n            case 2: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[1]) <<  8;\n                    /* fallthrough */\n            default:;\n        }\n        contain32 = ((const BYTE*)srcBuffer)[srcSize-1];\n        if (contain32 == 0) return ERROR(GENERIC);   /* endMark not present */\n        bitD->bitsConsumed = 8 - BIT_highbit32(contain32);\n        bitD->bitsConsumed += (U32)(sizeof(size_t) - srcSize)*8;\n    }\n\n    return srcSize;\n}\nMEM_STATIC size_t BIT_lookBits(BIT_DStream_t* bitD, U32 nbBits)\n{\n    const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);\n}\n\n/*! BIT_lookBitsFast :\n*   unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BIT_lookBitsFast(BIT_DStream_t* bitD, U32 nbBits)\n{\n    const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);\n}\n\nMEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)\n{\n    bitD->bitsConsumed += nbBits;\n}\n\nMEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits)\n{\n    size_t value = BIT_lookBits(bitD, nbBits);\n    BIT_skipBits(bitD, nbBits);\n    return value;\n}\n\n/*!BIT_readBitsFast :\n*  unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)\n{\n    size_t value = BIT_lookBitsFast(bitD, nbBits);\n    BIT_skipBits(bitD, nbBits);\n    return value;\n}\n\nMEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)\n{\n    if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */\n        return BIT_DStream_overflow;\n\n    if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer))\n    {\n        bitD->ptr -= bitD->bitsConsumed >> 3;\n        bitD->bitsConsumed &= 7;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        return BIT_DStream_unfinished;\n    }\n    if (bitD->ptr == bitD->start)\n    {\n        if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;\n        return BIT_DStream_completed;\n    }\n    {\n        U32 nbBytes = bitD->bitsConsumed >> 3;\n        BIT_DStream_status result = BIT_DStream_unfinished;\n        if (bitD->ptr - nbBytes < bitD->start)\n        {\n            nbBytes = (U32)(bitD->ptr - bitD->start);  /* ptr > start */\n            result = BIT_DStream_endOfBuffer;\n        }\n        bitD->ptr -= nbBytes;\n        bitD->bitsConsumed -= nbBytes*8;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);   /* reminder : srcSize > sizeof(bitD) */\n        return result;\n    }\n}\n\n/*! BIT_endOfDStream\n*   @return Tells if DStream has reached its exact end\n*/\nMEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)\n{\n    return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));\n}\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* BITSTREAM_H_MODULE */\n/* ******************************************************************\n   Error codes and messages\n   Copyright (C) 2013-2015, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef ERROR_H_MODULE\n#define ERROR_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/******************************************\n*  Compiler-specific\n******************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n#  define ERR_STATIC static inline\n#elif defined(_MSC_VER)\n#  define ERR_STATIC static __inline\n#elif defined(__GNUC__)\n#  define ERR_STATIC static __attribute__((unused))\n#else\n#  define ERR_STATIC static  /* this version may generate warnings for unused static functions; disable the relevant warning */\n#endif\n\n\n/******************************************\n*  Error Management\n******************************************/\n#define PREFIX(name) ZSTD_error_##name\n\n#define ERROR(name) (size_t)-PREFIX(name)\n\n#define ERROR_LIST(ITEM) \\\n        ITEM(PREFIX(No_Error)) ITEM(PREFIX(GENERIC)) \\\n        ITEM(PREFIX(dstSize_tooSmall)) ITEM(PREFIX(srcSize_wrong)) \\\n        ITEM(PREFIX(prefix_unknown)) ITEM(PREFIX(corruption_detected)) \\\n        ITEM(PREFIX(tableLog_tooLarge)) ITEM(PREFIX(maxSymbolValue_tooLarge)) ITEM(PREFIX(maxSymbolValue_tooSmall)) \\\n        ITEM(PREFIX(maxCode))\n\n#define ERROR_GENERATE_ENUM(ENUM) ENUM,\ntypedef enum { ERROR_LIST(ERROR_GENERATE_ENUM) } ERR_codes;  /* enum is exposed, to detect & handle specific errors; compare function result to -enum value */\n\n#define ERROR_CONVERTTOSTRING(STRING) #STRING,\n#define ERROR_GENERATE_STRING(EXPR) ERROR_CONVERTTOSTRING(EXPR)\nstatic const char* ERR_strings[] = { ERROR_LIST(ERROR_GENERATE_STRING) };\n\nERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }\n\nERR_STATIC const char* ERR_getErrorName(size_t code)\n{\n    static const char* codeError = \"Unspecified error code\";\n    if (ERR_isError(code)) return ERR_strings[-(int)(code)];\n    return codeError;\n}\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* ERROR_H_MODULE */\n/*\nConstructor and Destructor of type FSE_CTable\n    Note that its size depends on 'tableLog' and 'maxSymbolValue' */\ntypedef unsigned FSE_CTable;   /* don't allocate that. It's just a way to be more restrictive than void* */\ntypedef unsigned FSE_DTable;   /* don't allocate that. It's just a way to be more restrictive than void* */\n\n\n/* ******************************************************************\n   FSE : Finite State Entropy coder\n   header file for static linking (only)\n   Copyright (C) 2013-2015, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/******************************************\n*  Static allocation\n******************************************/\n/* FSE buffer bounds */\n#define FSE_NCOUNTBOUND 512\n#define FSE_BLOCKBOUND(size) (size + (size>>7))\n#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size))   /* Macro version, useful for static allocation */\n\n/* You can statically allocate FSE CTable/DTable as a table of unsigned using below macro */\n#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue)   (1 + (1<<(maxTableLog-1)) + ((maxSymbolValue+1)*2))\n#define FSE_DTABLE_SIZE_U32(maxTableLog)                   (1 + (1<<maxTableLog))\n\n\n/******************************************\n*  FSE advanced API\n******************************************/\nstatic size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits);\n/* build a fake FSE_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */\n\nstatic size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue);\n/* build a fake FSE_DTable, designed to always generate the same symbolValue */\n\n\n/******************************************\n*  FSE symbol decompression API\n******************************************/\ntypedef struct\n{\n    size_t      state;\n    const void* table;   /* precise table may vary, depending on U16 */\n} FSE_DState_t;\n\n\nstatic void     FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt);\n\nstatic unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);\n\nstatic unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr);\n\n\n/******************************************\n*  FSE unsafe API\n******************************************/\nstatic unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);\n/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */\n\n\n/******************************************\n*  Implementation of inline functions\n******************************************/\n\n/* decompression */\n\ntypedef struct {\n    U16 tableLog;\n    U16 fastMode;\n} FSE_DTableHeader;   /* sizeof U32 */\n\ntypedef struct\n{\n    unsigned short newState;\n    unsigned char  symbol;\n    unsigned char  nbBits;\n} FSE_decode_t;   /* size == U32 */\n\nMEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt)\n{\n    FSE_DTableHeader DTableH;\n    memcpy(&DTableH, dt, sizeof(DTableH));\n    DStatePtr->state = BIT_readBits(bitD, DTableH.tableLog);\n    BIT_reloadDStream(bitD);\n    DStatePtr->table = dt + 1;\n}\n\nMEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)\n{\n    const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    const U32  nbBits = DInfo.nbBits;\n    BYTE symbol = DInfo.symbol;\n    size_t lowBits = BIT_readBits(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\nMEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)\n{\n    const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    const U32 nbBits = DInfo.nbBits;\n    BYTE symbol = DInfo.symbol;\n    size_t lowBits = BIT_readBitsFast(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\nMEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)\n{\n    return DStatePtr->state == 0;\n}\n\n\n#if defined (__cplusplus)\n}\n#endif\n/* ******************************************************************\n   Huff0 : Huffman coder, part of New Generation Entropy library\n   header file for static linking (only)\n   Copyright (C) 2013-2015, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/******************************************\n*  Static allocation macros\n******************************************/\n/* Huff0 buffer bounds */\n#define HUF_CTABLEBOUND 129\n#define HUF_BLOCKBOUND(size) (size + (size>>8) + 8)   /* only true if incompressible pre-filtered with fast heuristic */\n#define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size))   /* Macro version, useful for static allocation */\n\n/* static allocation of Huff0's DTable */\n#define HUF_DTABLE_SIZE(maxTableLog)   (1 + (1<<maxTableLog))  /* nb Cells; use unsigned short for X2, unsigned int for X4 */\n#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \\\n        unsigned short DTable[HUF_DTABLE_SIZE(maxTableLog)] = { maxTableLog }\n#define HUF_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \\\n        unsigned int DTable[HUF_DTABLE_SIZE(maxTableLog)] = { maxTableLog }\n#define HUF_CREATE_STATIC_DTABLEX6(DTable, maxTableLog) \\\n        unsigned int DTable[HUF_DTABLE_SIZE(maxTableLog) * 3 / 2] = { maxTableLog }\n\n\n/******************************************\n*  Advanced functions\n******************************************/\nstatic size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */\nstatic size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbols decoder */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n/*\n    zstd - standard compression library\n    Header File\n    Copyright (C) 2014-2015, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n    - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* *************************************\n*  Includes\n***************************************/\n#include <stddef.h>   /* size_t */\n\n\n/* *************************************\n*  Version\n***************************************/\n#define ZSTD_VERSION_MAJOR    0    /* for breaking interface changes  */\n#define ZSTD_VERSION_MINOR    2    /* for new (non-breaking) interface capabilities */\n#define ZSTD_VERSION_RELEASE  2    /* for tweaks, bug-fixes, or development */\n#define ZSTD_VERSION_NUMBER  (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)\n\n\n/* *************************************\n*  Advanced functions\n***************************************/\ntypedef struct ZSTD_CCtx_s ZSTD_CCtx;   /* incomplete type */\n\n#if defined (__cplusplus)\n}\n#endif\n/*\n    zstd - standard compression library\n    Header File for static linking only\n    Copyright (C) 2014-2015, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n    - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n\n/* The objects defined into this file should be considered experimental.\n * They are not labelled stable, as their prototype may change in the future.\n * You can use them for tests, provide feedback, or if you can endure risk of future changes.\n */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* *************************************\n*  Streaming functions\n***************************************/\n\ntypedef struct ZSTDv03_Dctx_s ZSTD_DCtx;\n\n/*\n  Use above functions alternatively.\n  ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue().\n  ZSTD_decompressContinue() will use previous data blocks to improve compression if they are located prior to current block.\n  Result is the number of bytes regenerated within 'dst'.\n  It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header.\n*/\n\n/* *************************************\n*  Prefix - version detection\n***************************************/\n#define ZSTD_magicNumber 0xFD2FB523   /* v0.3 */\n\n\n#if defined (__cplusplus)\n}\n#endif\n/* ******************************************************************\n   FSE : Finite State Entropy coder\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n#ifndef FSE_COMMONDEFS_ONLY\n\n/****************************************************************\n*  Tuning parameters\n****************************************************************/\n/* MEMORY_USAGE :\n*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n*  Increasing memory usage improves compression ratio\n*  Reduced memory usage can improve speed, due to cache effect\n*  Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */\n#define FSE_MAX_MEMORY_USAGE 14\n#define FSE_DEFAULT_MEMORY_USAGE 13\n\n/* FSE_MAX_SYMBOL_VALUE :\n*  Maximum symbol value authorized.\n*  Required for proper stack allocation */\n#define FSE_MAX_SYMBOL_VALUE 255\n\n\n/****************************************************************\n*  template functions type & suffix\n****************************************************************/\n#define FSE_FUNCTION_TYPE BYTE\n#define FSE_FUNCTION_EXTENSION\n\n\n/****************************************************************\n*  Byte symbol type\n****************************************************************/\n#endif   /* !FSE_COMMONDEFS_ONLY */\n\n\n/****************************************************************\n*  Compiler specifics\n****************************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  define FORCE_INLINE static __forceinline\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4214)        /* disable: C4214: non-int bitfields */\n#else\n#  if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */\n#    ifdef __GNUC__\n#      define FORCE_INLINE static inline __attribute__((always_inline))\n#    else\n#      define FORCE_INLINE static inline\n#    endif\n#  else\n#    define FORCE_INLINE static\n#  endif /* __STDC_VERSION__ */\n#endif\n\n\n/****************************************************************\n*  Includes\n****************************************************************/\n#include <stdlib.h>     /* malloc, free, qsort */\n#include <string.h>     /* memcpy, memset */\n#include <stdio.h>      /* printf (debug) */\n\n/****************************************************************\n*  Constants\n*****************************************************************/\n#define FSE_MAX_TABLELOG  (FSE_MAX_MEMORY_USAGE-2)\n#define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG)\n#define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1)\n#define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2)\n#define FSE_MIN_TABLELOG 5\n\n#define FSE_TABLELOG_ABSOLUTE_MAX 15\n#if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX\n#error \"FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported\"\n#endif\n\n\n/****************************************************************\n*  Error Management\n****************************************************************/\n#define FSE_STATIC_ASSERT(c) { enum { FSE_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n/****************************************************************\n*  Complex types\n****************************************************************/\ntypedef U32 DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)];\n\n\n/****************************************************************\n*  Templates\n****************************************************************/\n/*\n  designed to be included\n  for type-specific functions (template emulation in C)\n  Objective is to write these functions only once, for improved maintenance\n*/\n\n/* safety checks */\n#ifndef FSE_FUNCTION_EXTENSION\n#  error \"FSE_FUNCTION_EXTENSION must be defined\"\n#endif\n#ifndef FSE_FUNCTION_TYPE\n#  error \"FSE_FUNCTION_TYPE must be defined\"\n#endif\n\n/* Function names */\n#define FSE_CAT(X,Y) X##Y\n#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y)\n#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y)\n\n\n/* Function templates */\n\n#define FSE_DECODE_TYPE FSE_decode_t\n\nstatic U32 FSE_tableStep(U32 tableSize) { return (tableSize>>1) + (tableSize>>3) + 3; }\n\nstatic size_t FSE_buildDTable\n(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)\n{\n    void* ptr = dt+1;\n    FSE_DTableHeader DTableH;\n    FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*)ptr;\n    const U32 tableSize = 1 << tableLog;\n    const U32 tableMask = tableSize-1;\n    const U32 step = FSE_tableStep(tableSize);\n    U16 symbolNext[FSE_MAX_SYMBOL_VALUE+1];\n    U32 position = 0;\n    U32 highThreshold = tableSize-1;\n    const S16 largeLimit= (S16)(1 << (tableLog-1));\n    U32 noLarge = 1;\n    U32 s;\n\n    /* Sanity Checks */\n    if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);\n    if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);\n\n    /* Init, lay down lowprob symbols */\n    DTableH.tableLog = (U16)tableLog;\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        if (normalizedCounter[s]==-1)\n        {\n            tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s;\n            symbolNext[s] = 1;\n        }\n        else\n        {\n            if (normalizedCounter[s] >= largeLimit) noLarge=0;\n            symbolNext[s] = normalizedCounter[s];\n        }\n    }\n\n    /* Spread symbols */\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        int i;\n        for (i=0; i<normalizedCounter[s]; i++)\n        {\n            tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;\n            position = (position + step) & tableMask;\n            while (position > highThreshold) position = (position + step) & tableMask;   /* lowprob area */\n        }\n    }\n\n    if (position!=0) return ERROR(GENERIC);   /* position must reach all cells once, otherwise normalizedCounter is incorrect */\n\n    /* Build Decoding table */\n    {\n        U32 i;\n        for (i=0; i<tableSize; i++)\n        {\n            FSE_FUNCTION_TYPE symbol = (FSE_FUNCTION_TYPE)(tableDecode[i].symbol);\n            U16 nextState = symbolNext[symbol]++;\n            tableDecode[i].nbBits = (BYTE) (tableLog - BIT_highbit32 ((U32)nextState) );\n            tableDecode[i].newState = (U16) ( (nextState << tableDecode[i].nbBits) - tableSize);\n        }\n    }\n\n    DTableH.fastMode = (U16)noLarge;\n    memcpy(dt, &DTableH, sizeof(DTableH));\n    return 0;\n}\n\n\n#ifndef FSE_COMMONDEFS_ONLY\n/******************************************\n*  FSE helper functions\n******************************************/\nstatic unsigned FSE_isError(size_t code) { return ERR_isError(code); }\n\n\n/****************************************************************\n*  FSE NCount encoding-decoding\n****************************************************************/\nstatic short FSE_abs(short a)\n{\n    return a<0 ? (short)-a : a;\n}\n\nstatic size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n                 const void* headerBuffer, size_t hbSize)\n{\n    const BYTE* const istart = (const BYTE*) headerBuffer;\n    const BYTE* const iend = istart + hbSize;\n    const BYTE* ip = istart;\n    int nbBits;\n    int remaining;\n    int threshold;\n    U32 bitStream;\n    int bitCount;\n    unsigned charnum = 0;\n    int previous0 = 0;\n\n    if (hbSize < 4) return ERROR(srcSize_wrong);\n    bitStream = MEM_readLE32(ip);\n    nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG;   /* extract tableLog */\n    if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);\n    bitStream >>= 4;\n    bitCount = 4;\n    *tableLogPtr = nbBits;\n    remaining = (1<<nbBits)+1;\n    threshold = 1<<nbBits;\n    nbBits++;\n\n    while ((remaining>1) && (charnum<=*maxSVPtr))\n    {\n        if (previous0)\n        {\n            unsigned n0 = charnum;\n            while ((bitStream & 0xFFFF) == 0xFFFF)\n            {\n                n0+=24;\n                if (ip < iend-5)\n                {\n                    ip+=2;\n                    bitStream = MEM_readLE32(ip) >> bitCount;\n                }\n                else\n                {\n                    bitStream >>= 16;\n                    bitCount+=16;\n                }\n            }\n            while ((bitStream & 3) == 3)\n            {\n                n0+=3;\n                bitStream>>=2;\n                bitCount+=2;\n            }\n            n0 += bitStream & 3;\n            bitCount += 2;\n            if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);\n            while (charnum < n0) normalizedCounter[charnum++] = 0;\n            if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4))\n            {\n                ip += bitCount>>3;\n                bitCount &= 7;\n                bitStream = MEM_readLE32(ip) >> bitCount;\n            }\n            else\n                bitStream >>= 2;\n        }\n        {\n            const short max = (short)((2*threshold-1)-remaining);\n            short count;\n\n            if ((bitStream & (threshold-1)) < (U32)max)\n            {\n                count = (short)(bitStream & (threshold-1));\n                bitCount   += nbBits-1;\n            }\n            else\n            {\n                count = (short)(bitStream & (2*threshold-1));\n                if (count >= threshold) count -= max;\n                bitCount   += nbBits;\n            }\n\n            count--;   /* extra accuracy */\n            remaining -= FSE_abs(count);\n            normalizedCounter[charnum++] = count;\n            previous0 = !count;\n            while (remaining < threshold)\n            {\n                nbBits--;\n                threshold >>= 1;\n            }\n\n            {\n                if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4))\n                {\n                    ip += bitCount>>3;\n                    bitCount &= 7;\n                }\n                else\n                {\n                    bitCount -= (int)(8 * (iend - 4 - ip));\n                    ip = iend - 4;\n                }\n                bitStream = MEM_readLE32(ip) >> (bitCount & 31);\n            }\n        }\n    }\n    if (remaining != 1) return ERROR(GENERIC);\n    *maxSVPtr = charnum-1;\n\n    ip += (bitCount+7)>>3;\n    if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong);\n    return ip-istart;\n}\n\n\n/*********************************************************\n*  Decompression (Byte symbols)\n*********************************************************/\nstatic size_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue)\n{\n    void* ptr = dt;\n    FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;\n    FSE_decode_t* const cell = (FSE_decode_t*)(ptr) + 1;\n\n    DTableH->tableLog = 0;\n    DTableH->fastMode = 0;\n\n    cell->newState = 0;\n    cell->symbol = symbolValue;\n    cell->nbBits = 0;\n\n    return 0;\n}\n\n\nstatic size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits)\n{\n    void* ptr = dt;\n    FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;\n    FSE_decode_t* const dinfo = (FSE_decode_t*)(ptr) + 1;\n    const unsigned tableSize = 1 << nbBits;\n    const unsigned tableMask = tableSize - 1;\n    const unsigned maxSymbolValue = tableMask;\n    unsigned s;\n\n    /* Sanity checks */\n    if (nbBits < 1) return ERROR(GENERIC);         /* min size */\n\n    /* Build Decoding Table */\n    DTableH->tableLog = (U16)nbBits;\n    DTableH->fastMode = 1;\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        dinfo[s].newState = 0;\n        dinfo[s].symbol = (BYTE)s;\n        dinfo[s].nbBits = (BYTE)nbBits;\n    }\n\n    return 0;\n}\n\nFORCE_INLINE size_t FSE_decompress_usingDTable_generic(\n          void* dst, size_t maxDstSize,\n    const void* cSrc, size_t cSrcSize,\n    const FSE_DTable* dt, const unsigned fast)\n{\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* op = ostart;\n    BYTE* const omax = op + maxDstSize;\n    BYTE* const olimit = omax-3;\n\n    BIT_DStream_t bitD;\n    FSE_DState_t state1;\n    FSE_DState_t state2;\n    size_t errorCode;\n\n    /* Init */\n    errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize);   /* replaced last arg by maxCompressed Size */\n    if (FSE_isError(errorCode)) return errorCode;\n\n    FSE_initDState(&state1, &bitD, dt);\n    FSE_initDState(&state2, &bitD, dt);\n\n#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD)\n\n    /* 4 symbols per loop */\n    for ( ; (BIT_reloadDStream(&bitD)==BIT_DStream_unfinished) && (op<olimit) ; op+=4)\n    {\n        op[0] = FSE_GETSYMBOL(&state1);\n\n        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BIT_reloadDStream(&bitD);\n\n        op[1] = FSE_GETSYMBOL(&state2);\n\n        if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            { if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) { op+=2; break; } }\n\n        op[2] = FSE_GETSYMBOL(&state1);\n\n        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BIT_reloadDStream(&bitD);\n\n        op[3] = FSE_GETSYMBOL(&state2);\n    }\n\n    /* tail */\n    /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */\n    while (1)\n    {\n        if ( (BIT_reloadDStream(&bitD)>BIT_DStream_completed) || (op==omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state1))) )\n            break;\n\n        *op++ = FSE_GETSYMBOL(&state1);\n\n        if ( (BIT_reloadDStream(&bitD)>BIT_DStream_completed) || (op==omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state2))) )\n            break;\n\n        *op++ = FSE_GETSYMBOL(&state2);\n    }\n\n    /* end ? */\n    if (BIT_endOfDStream(&bitD) && FSE_endOfDState(&state1) && FSE_endOfDState(&state2))\n        return op-ostart;\n\n    if (op==omax) return ERROR(dstSize_tooSmall);   /* dst buffer is full, but cSrc unfinished */\n\n    return ERROR(corruption_detected);\n}\n\n\nstatic size_t FSE_decompress_usingDTable(void* dst, size_t originalSize,\n                            const void* cSrc, size_t cSrcSize,\n                            const FSE_DTable* dt)\n{\n    FSE_DTableHeader DTableH;\n    memcpy(&DTableH, dt, sizeof(DTableH));\n\n    /* select fast mode (static) */\n    if (DTableH.fastMode) return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);\n    return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);\n}\n\n\nstatic size_t FSE_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)\n{\n    const BYTE* const istart = (const BYTE*)cSrc;\n    const BYTE* ip = istart;\n    short counting[FSE_MAX_SYMBOL_VALUE+1];\n    DTable_max_t dt;   /* Static analyzer seems unable to understand this table will be properly initialized later */\n    unsigned tableLog;\n    unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;\n    size_t errorCode;\n\n    if (cSrcSize<2) return ERROR(srcSize_wrong);   /* too small input size */\n\n    /* normal FSE decoding mode */\n    errorCode = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);\n    if (FSE_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);   /* too small input size */\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    errorCode = FSE_buildDTable (dt, counting, maxSymbolValue, tableLog);\n    if (FSE_isError(errorCode)) return errorCode;\n\n    /* always return, even if it is an error code */\n    return FSE_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt);\n}\n\n\n\n#endif   /* FSE_COMMONDEFS_ONLY */\n/* ******************************************************************\n   Huff0 : Huffman coder, part of New Generation Entropy library\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE+Huff0 source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n/****************************************************************\n*  Compiler specifics\n****************************************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n/* inline is defined */\n#elif defined(_MSC_VER)\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  define inline __inline\n#else\n#  define inline /* disable inline */\n#endif\n\n\n/****************************************************************\n*  Includes\n****************************************************************/\n#include <stdlib.h>     /* malloc, free, qsort */\n#include <string.h>     /* memcpy, memset */\n#include <stdio.h>      /* printf (debug) */\n\n/****************************************************************\n*  Error Management\n****************************************************************/\n#define HUF_STATIC_ASSERT(c) { enum { HUF_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n/******************************************\n*  Helper functions\n******************************************/\nstatic unsigned HUF_isError(size_t code) { return ERR_isError(code); }\n\n#define HUF_ABSOLUTEMAX_TABLELOG  16   /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */\n#define HUF_MAX_TABLELOG  12           /* max configured tableLog (for static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */\n#define HUF_DEFAULT_TABLELOG  HUF_MAX_TABLELOG   /* tableLog by default, when not specified */\n#define HUF_MAX_SYMBOL_VALUE 255\n#if (HUF_MAX_TABLELOG > HUF_ABSOLUTEMAX_TABLELOG)\n#  error \"HUF_MAX_TABLELOG is too large !\"\n#endif\n\n\n\n/*********************************************************\n*  Huff0 : Huffman block decompression\n*********************************************************/\ntypedef struct { BYTE byte; BYTE nbBits; } HUF_DEltX2;   /* single-symbol decoding */\n\ntypedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX4;  /* double-symbols decoding */\n\ntypedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;\n\n/*! HUF_readStats\n    Read compact Huffman tree, saved by HUF_writeCTable\n    @huffWeight : destination buffer\n    @return : size read from `src`\n*/\nstatic size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                            U32* nbSymbolsPtr, U32* tableLogPtr,\n                            const void* src, size_t srcSize)\n{\n    U32 weightTotal;\n    U32 tableLog;\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize;\n    size_t oSize;\n    U32 n;\n\n    if (!srcSize) return ERROR(srcSize_wrong);\n    iSize = ip[0];\n    //memset(huffWeight, 0, hwSize);   /* is not necessary, even though some analyzer complain ... */\n\n    if (iSize >= 128)  /* special header */\n    {\n        if (iSize >= (242))   /* RLE */\n        {\n            static int l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };\n            oSize = l[iSize-242];\n            memset(huffWeight, 1, hwSize);\n            iSize = 0;\n        }\n        else   /* Incompressible */\n        {\n            oSize = iSize - 127;\n            iSize = ((oSize+1)/2);\n            if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n            if (oSize >= hwSize) return ERROR(corruption_detected);\n            ip += 1;\n            for (n=0; n<oSize; n+=2)\n            {\n                huffWeight[n]   = ip[n/2] >> 4;\n                huffWeight[n+1] = ip[n/2] & 15;\n            }\n        }\n    }\n    else  /* header compressed with FSE (normal case) */\n    {\n        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n        oSize = FSE_decompress(huffWeight, hwSize-1, ip+1, iSize);   /* max (hwSize-1) values decoded, as last one is implied */\n        if (FSE_isError(oSize)) return oSize;\n    }\n\n    /* collect weight stats */\n    memset(rankStats, 0, (HUF_ABSOLUTEMAX_TABLELOG + 1) * sizeof(U32));\n    weightTotal = 0;\n    for (n=0; n<oSize; n++)\n    {\n        if (huffWeight[n] >= HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);\n        rankStats[huffWeight[n]]++;\n        weightTotal += (1 << huffWeight[n]) >> 1;\n    }\n    if (weightTotal == 0) return ERROR(corruption_detected);\n\n    /* get last non-null symbol weight (implied, total must be 2^n) */\n    tableLog = BIT_highbit32(weightTotal) + 1;\n    if (tableLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);\n    {\n        U32 total = 1 << tableLog;\n        U32 rest = total - weightTotal;\n        U32 verif = 1 << BIT_highbit32(rest);\n        U32 lastWeight = BIT_highbit32(rest) + 1;\n        if (verif != rest) return ERROR(corruption_detected);    /* last value must be a clean power of 2 */\n        huffWeight[oSize] = (BYTE)lastWeight;\n        rankStats[lastWeight]++;\n    }\n\n    /* check tree construction validity */\n    if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected);   /* by construction : at least 2 elts of rank 1, must be even */\n\n    /* results */\n    *nbSymbolsPtr = (U32)(oSize+1);\n    *tableLogPtr = tableLog;\n    return iSize+1;\n}\n\n\n/**************************/\n/* single-symbol decoding */\n/**************************/\n\nstatic size_t HUF_readDTableX2 (U16* DTable, const void* src, size_t srcSize)\n{\n    BYTE huffWeight[HUF_MAX_SYMBOL_VALUE + 1];\n    U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];   /* large enough for values from 0 to 16 */\n    U32 tableLog = 0;\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize = ip[0];\n    U32 nbSymbols = 0;\n    U32 n;\n    U32 nextRankStart;\n    void* ptr = DTable+1;\n    HUF_DEltX2* const dt = (HUF_DEltX2*)(ptr);\n\n    HUF_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(U16));   /* if compilation fails here, assertion is false */\n    //memset(huffWeight, 0, sizeof(huffWeight));   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUF_readStats(huffWeight, HUF_MAX_SYMBOL_VALUE + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);\n    if (HUF_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > DTable[0]) return ERROR(tableLog_tooLarge);   /* DTable is too small */\n    DTable[0] = (U16)tableLog;   /* maybe should separate sizeof DTable, as allocated, from used size of DTable, in case of DTable re-use */\n\n    /* Prepare ranks */\n    nextRankStart = 0;\n    for (n=1; n<=tableLog; n++)\n    {\n        U32 current = nextRankStart;\n        nextRankStart += (rankVal[n] << (n-1));\n        rankVal[n] = current;\n    }\n\n    /* fill DTable */\n    for (n=0; n<nbSymbols; n++)\n    {\n        const U32 w = huffWeight[n];\n        const U32 length = (1 << w) >> 1;\n        U32 i;\n        HUF_DEltX2 D;\n        D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w);\n        for (i = rankVal[w]; i < rankVal[w] + length; i++)\n            dt[i] = D;\n        rankVal[w] += length;\n    }\n\n    return iSize;\n}\n\nstatic BYTE HUF_decodeSymbolX2(BIT_DStream_t* Dstream, const HUF_DEltX2* dt, const U32 dtLog)\n{\n        const size_t val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */\n        const BYTE c = dt[val].byte;\n        BIT_skipBits(Dstream, dt[val].nbBits);\n        return c;\n}\n\n#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \\\n    *ptr++ = HUF_decodeSymbolX2(DStreamPtr, dt, dtLog)\n\n#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \\\n        HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\n#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\nstatic inline size_t HUF_decodeStreamX2(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX2* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 4 symbols at a time */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-4))\n    {\n        HUF_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX2_1(p, bitDPtr);\n        HUF_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n    }\n\n    /* closer to the end */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd))\n        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    /* no more data to retrieve from bitstream, hence no need to reload */\n    while (p < pEnd)\n        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    return pEnd-pStart;\n}\n\n\nstatic size_t HUF_decompress4X2_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U16* DTable)\n{\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n\n    {\n        const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n\n        const void* ptr = DTable;\n        const HUF_DEltX2* const dt = ((const HUF_DEltX2*)ptr) +1;\n        const U32 dtLog = DTable[0];\n        size_t errorCode;\n\n        /* Init */\n        BIT_DStream_t bitD1;\n        BIT_DStream_t bitD2;\n        BIT_DStream_t bitD3;\n        BIT_DStream_t bitD4;\n        const size_t length1 = MEM_readLE16(istart);\n        const size_t length2 = MEM_readLE16(istart+2);\n        const size_t length3 = MEM_readLE16(istart+4);\n        size_t length4;\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n\n        length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        errorCode = BIT_initDStream(&bitD1, istart1, length1);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD2, istart2, length2);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD3, istart3, length3);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD4, istart4, length4);\n        if (HUF_isError(errorCode)) return errorCode;\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        for ( ; (endSignal==BIT_DStream_unfinished) && (op4<(oend-7)) ; )\n        {\n            HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_1(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_1(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_1(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_1(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_0(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_0(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_0(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_0(op4, &bitD4);\n\n            endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);\n        HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);\n        HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);\n        HUF_decodeStreamX2(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nstatic size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n    size_t errorCode;\n\n    errorCode = HUF_readDTableX2 (DTable, cSrc, cSrcSize);\n    if (HUF_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    return HUF_decompress4X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\n/***************************/\n/* double-symbols decoding */\n/***************************/\n\nstatic void HUF_fillDTableX4Level2(HUF_DEltX4* DTable, U32 sizeLog, const U32 consumed,\n                           const U32* rankValOrigin, const int minWeight,\n                           const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,\n                           U32 nbBitsBaseline, U16 baseSeq)\n{\n    HUF_DEltX4 DElt;\n    U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];\n    U32 s;\n\n    /* get pre-calculated rankVal */\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill skipped values */\n    if (minWeight>1)\n    {\n        U32 i, skipSize = rankVal[minWeight];\n        MEM_writeLE16(&(DElt.sequence), baseSeq);\n        DElt.nbBits   = (BYTE)(consumed);\n        DElt.length   = 1;\n        for (i = 0; i < skipSize; i++)\n            DTable[i] = DElt;\n    }\n\n    /* fill DTable */\n    for (s=0; s<sortedListSize; s++)   /* note : sortedSymbols already skipped */\n    {\n        const U32 symbol = sortedSymbols[s].symbol;\n        const U32 weight = sortedSymbols[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 length = 1 << (sizeLog-nbBits);\n        const U32 start = rankVal[weight];\n        U32 i = start;\n        const U32 end = start + length;\n\n        MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));\n        DElt.nbBits = (BYTE)(nbBits + consumed);\n        DElt.length = 2;\n        do { DTable[i++] = DElt; } while (i<end);   /* since length >= 1 */\n\n        rankVal[weight] += length;\n    }\n}\n\ntypedef U32 rankVal_t[HUF_ABSOLUTEMAX_TABLELOG][HUF_ABSOLUTEMAX_TABLELOG + 1];\n\nstatic void HUF_fillDTableX4(HUF_DEltX4* DTable, const U32 targetLog,\n                           const sortedSymbol_t* sortedList, const U32 sortedListSize,\n                           const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,\n                           const U32 nbBitsBaseline)\n{\n    U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];\n    const int scaleLog = nbBitsBaseline - targetLog;   /* note : targetLog >= srcLog, hence scaleLog <= 1 */\n    const U32 minBits  = nbBitsBaseline - maxWeight;\n    U32 s;\n\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill DTable */\n    for (s=0; s<sortedListSize; s++)\n    {\n        const U16 symbol = sortedList[s].symbol;\n        const U32 weight = sortedList[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 start = rankVal[weight];\n        const U32 length = 1 << (targetLog-nbBits);\n\n        if (targetLog-nbBits >= minBits)   /* enough room for a second symbol */\n        {\n            U32 sortedRank;\n            int minWeight = nbBits + scaleLog;\n            if (minWeight < 1) minWeight = 1;\n            sortedRank = rankStart[minWeight];\n            HUF_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits,\n                           rankValOrigin[nbBits], minWeight,\n                           sortedList+sortedRank, sortedListSize-sortedRank,\n                           nbBitsBaseline, symbol);\n        }\n        else\n        {\n            U32 i;\n            const U32 end = start + length;\n            HUF_DEltX4 DElt;\n\n            MEM_writeLE16(&(DElt.sequence), symbol);\n            DElt.nbBits   = (BYTE)(nbBits);\n            DElt.length   = 1;\n            for (i = start; i < end; i++)\n                DTable[i] = DElt;\n        }\n        rankVal[weight] += length;\n    }\n}\n\nstatic size_t HUF_readDTableX4 (U32* DTable, const void* src, size_t srcSize)\n{\n    BYTE weightList[HUF_MAX_SYMBOL_VALUE + 1];\n    sortedSymbol_t sortedSymbol[HUF_MAX_SYMBOL_VALUE + 1];\n    U32 rankStats[HUF_ABSOLUTEMAX_TABLELOG + 1] = { 0 };\n    U32 rankStart0[HUF_ABSOLUTEMAX_TABLELOG + 2] = { 0 };\n    U32* const rankStart = rankStart0+1;\n    rankVal_t rankVal;\n    U32 tableLog, maxW, sizeOfSort, nbSymbols;\n    const U32 memLog = DTable[0];\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize = ip[0];\n    void* ptr = DTable;\n    HUF_DEltX4* const dt = ((HUF_DEltX4*)ptr) + 1;\n\n    HUF_STATIC_ASSERT(sizeof(HUF_DEltX4) == sizeof(U32));   /* if compilation fails here, assertion is false */\n    if (memLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge);\n    //memset(weightList, 0, sizeof(weightList));   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUF_readStats(weightList, HUF_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);\n    if (HUF_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > memLog) return ERROR(tableLog_tooLarge);   /* DTable can't fit code depth */\n\n    /* find maxWeight */\n    for (maxW = tableLog; rankStats[maxW]==0; maxW--)\n        { if (!maxW) return ERROR(GENERIC); }  /* necessarily finds a solution before maxW==0 */\n\n    /* Get start index of each weight */\n    {\n        U32 w, nextRankStart = 0;\n        for (w=1; w<=maxW; w++)\n        {\n            U32 current = nextRankStart;\n            nextRankStart += rankStats[w];\n            rankStart[w] = current;\n        }\n        rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/\n        sizeOfSort = nextRankStart;\n    }\n\n    /* sort symbols by weight */\n    {\n        U32 s;\n        for (s=0; s<nbSymbols; s++)\n        {\n            U32 w = weightList[s];\n            U32 r = rankStart[w]++;\n            sortedSymbol[r].symbol = (BYTE)s;\n            sortedSymbol[r].weight = (BYTE)w;\n        }\n        rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */\n    }\n\n    /* Build rankVal */\n    {\n        const U32 minBits = tableLog+1 - maxW;\n        U32 nextRankVal = 0;\n        U32 w, consumed;\n        const int rescale = (memLog-tableLog) - 1;   /* tableLog <= memLog */\n        U32* rankVal0 = rankVal[0];\n        for (w=1; w<=maxW; w++)\n        {\n            U32 current = nextRankVal;\n            nextRankVal += rankStats[w] << (w+rescale);\n            rankVal0[w] = current;\n        }\n        for (consumed = minBits; consumed <= memLog - minBits; consumed++)\n        {\n            U32* rankValPtr = rankVal[consumed];\n            for (w = 1; w <= maxW; w++)\n            {\n                rankValPtr[w] = rankVal0[w] >> consumed;\n            }\n        }\n    }\n\n    HUF_fillDTableX4(dt, memLog,\n                   sortedSymbol, sizeOfSort,\n                   rankStart0, rankVal, maxW,\n                   tableLog+1);\n\n    return iSize;\n}\n\n\nstatic U32 HUF_decodeSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 2);\n    BIT_skipBits(DStream, dt[val].nbBits);\n    return dt[val].length;\n}\n\nstatic U32 HUF_decodeLastSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 1);\n    if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits);\n    else\n    {\n        if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8))\n        {\n            BIT_skipBits(DStream, dt[val].nbBits);\n            if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))\n                DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);   /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */\n        }\n    }\n    return 1;\n}\n\n\n#define HUF_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \\\n    ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUF_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \\\n        ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUF_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\nstatic inline size_t HUF_decodeStreamX4(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd, const HUF_DEltX4* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 8 symbols at a time */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd-7))\n    {\n        HUF_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX4_1(p, bitDPtr);\n        HUF_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX4_0(p, bitDPtr);\n    }\n\n    /* closer to the end */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-2))\n        HUF_DECODE_SYMBOLX4_0(p, bitDPtr);\n\n    while (p <= pEnd-2)\n        HUF_DECODE_SYMBOLX4_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */\n\n    if (p < pEnd)\n        p += HUF_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);\n\n    return p-pStart;\n}\n\n\n\nstatic size_t HUF_decompress4X4_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U32* DTable)\n{\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n\n    {\n        const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n\n        const void* ptr = DTable;\n        const HUF_DEltX4* const dt = ((const HUF_DEltX4*)ptr) +1;\n        const U32 dtLog = DTable[0];\n        size_t errorCode;\n\n        /* Init */\n        BIT_DStream_t bitD1;\n        BIT_DStream_t bitD2;\n        BIT_DStream_t bitD3;\n        BIT_DStream_t bitD4;\n        const size_t length1 = MEM_readLE16(istart);\n        const size_t length2 = MEM_readLE16(istart+2);\n        const size_t length3 = MEM_readLE16(istart+4);\n        size_t length4;\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n\n        length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        errorCode = BIT_initDStream(&bitD1, istart1, length1);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD2, istart2, length2);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD3, istart3, length3);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD4, istart4, length4);\n        if (HUF_isError(errorCode)) return errorCode;\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        for ( ; (endSignal==BIT_DStream_unfinished) && (op4<(oend-7)) ; )\n        {\n            HUF_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX4_1(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_1(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_1(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_1(op4, &bitD4);\n            HUF_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX4_0(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_0(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_0(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_0(op4, &bitD4);\n\n            endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUF_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);\n        HUF_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);\n        HUF_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);\n        HUF_decodeStreamX4(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nstatic size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUF_CREATE_STATIC_DTABLEX4(DTable, HUF_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t hSize = HUF_readDTableX4 (DTable, cSrc, cSrcSize);\n    if (HUF_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize;\n    cSrcSize -= hSize;\n\n    return HUF_decompress4X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\n/**********************************/\n/* Generic decompression selector */\n/**********************************/\n\ntypedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;\nstatic const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =\n{\n    /* single, double, quad */\n    {{0,0}, {1,1}, {2,2}},  /* Q==0 : impossible */\n    {{0,0}, {1,1}, {2,2}},  /* Q==1 : impossible */\n    {{  38,130}, {1313, 74}, {2151, 38}},   /* Q == 2 : 12-18% */\n    {{ 448,128}, {1353, 74}, {2238, 41}},   /* Q == 3 : 18-25% */\n    {{ 556,128}, {1353, 74}, {2238, 47}},   /* Q == 4 : 25-32% */\n    {{ 714,128}, {1418, 74}, {2436, 53}},   /* Q == 5 : 32-38% */\n    {{ 883,128}, {1437, 74}, {2464, 61}},   /* Q == 6 : 38-44% */\n    {{ 897,128}, {1515, 75}, {2622, 68}},   /* Q == 7 : 44-50% */\n    {{ 926,128}, {1613, 75}, {2730, 75}},   /* Q == 8 : 50-56% */\n    {{ 947,128}, {1729, 77}, {3359, 77}},   /* Q == 9 : 56-62% */\n    {{1107,128}, {2083, 81}, {4006, 84}},   /* Q ==10 : 62-69% */\n    {{1177,128}, {2379, 87}, {4785, 88}},   /* Q ==11 : 69-75% */\n    {{1242,128}, {2415, 93}, {5155, 84}},   /* Q ==12 : 75-81% */\n    {{1349,128}, {2644,106}, {5260,106}},   /* Q ==13 : 81-87% */\n    {{1455,128}, {2422,124}, {4174,124}},   /* Q ==14 : 87-93% */\n    {{ 722,128}, {1891,145}, {1936,146}},   /* Q ==15 : 93-99% */\n};\n\ntypedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);\n\nstatic size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    static const decompressionAlgo decompress[3] = { HUF_decompress4X2, HUF_decompress4X4, NULL };\n    /* estimate decompression time */\n    U32 Q;\n    const U32 D256 = (U32)(dstSize >> 8);\n    U32 Dtime[3];\n    U32 algoNb = 0;\n    int n;\n\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */\n    if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */\n    if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */\n\n    /* decoder timing evaluation */\n    Q = (U32)(cSrcSize * 16 / dstSize);   /* Q < 16 since dstSize > cSrcSize */\n    for (n=0; n<3; n++)\n        Dtime[n] = algoTime[Q][n].tableTime + (algoTime[Q][n].decode256Time * D256);\n\n    Dtime[1] += Dtime[1] >> 4; Dtime[2] += Dtime[2] >> 3; /* advantage to algorithms using less memory, for cache eviction */\n\n    if (Dtime[1] < Dtime[0]) algoNb = 1;\n\n    return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);\n\n    //return HUF_decompress4X2(dst, dstSize, cSrc, cSrcSize);   /* multi-streams single-symbol decoding */\n    //return HUF_decompress4X4(dst, dstSize, cSrc, cSrcSize);   /* multi-streams double-symbols decoding */\n    //return HUF_decompress4X6(dst, dstSize, cSrc, cSrcSize);   /* multi-streams quad-symbols decoding */\n}\n/*\n    zstd - standard compression library\n    Copyright (C) 2014-2015, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n    - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n\n/* ***************************************************************\n*  Tuning parameters\n*****************************************************************/\n/*!\n*  MEMORY_USAGE :\n*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n*  Increasing memory usage improves compression ratio\n*  Reduced memory usage can improve speed, due to cache effect\n*/\n#define ZSTD_MEMORY_USAGE 17\n\n/*!\n * HEAPMODE :\n * Select how default compression functions will allocate memory for their hash table,\n * in memory stack (0, fastest), or in memory heap (1, requires malloc())\n * Note that compression context is fairly large, as a consequence heap memory is recommended.\n */\n#ifndef ZSTD_HEAPMODE\n#  define ZSTD_HEAPMODE 1\n#endif /* ZSTD_HEAPMODE */\n\n/*!\n*  LEGACY_SUPPORT :\n*  decompressor can decode older formats (starting from Zstd 0.1+)\n*/\n#ifndef ZSTD_LEGACY_SUPPORT\n#  define ZSTD_LEGACY_SUPPORT 1\n#endif\n\n\n/* *******************************************************\n*  Includes\n*********************************************************/\n#include <stdlib.h>      /* calloc */\n#include <string.h>      /* memcpy, memmove */\n#include <stdio.h>       /* debug : printf */\n\n\n/* *******************************************************\n*  Compiler specifics\n*********************************************************/\n#ifdef __AVX2__\n#  include <immintrin.h>   /* AVX2 intrinsics */\n#endif\n\n#ifdef _MSC_VER    /* Visual Studio */\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4324)        /* disable: C4324: padded structure */\n#else\n#  define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)\n#endif\n\n\n/* *******************************************************\n*  Constants\n*********************************************************/\n#define HASH_LOG (ZSTD_MEMORY_USAGE - 2)\n#define HASH_TABLESIZE (1 << HASH_LOG)\n#define HASH_MASK (HASH_TABLESIZE - 1)\n\n#define KNUTH 2654435761\n\n#define BIT7 128\n#define BIT6  64\n#define BIT5  32\n#define BIT4  16\n#define BIT1   2\n#define BIT0   1\n\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\n#define BLOCKSIZE (128 KB)                 /* define, for static allocation */\n#define MIN_SEQUENCES_SIZE (2 /*seqNb*/ + 2 /*dumps*/ + 3 /*seqTables*/ + 1 /*bitStream*/)\n#define MIN_CBLOCK_SIZE (3 /*litCSize*/ + MIN_SEQUENCES_SIZE)\n#define IS_RAW BIT0\n#define IS_RLE BIT1\n\n#define WORKPLACESIZE (BLOCKSIZE*3)\n#define MINMATCH 4\n#define MLbits   7\n#define LLbits   6\n#define Offbits  5\n#define MaxML  ((1<<MLbits )-1)\n#define MaxLL  ((1<<LLbits )-1)\n#define MaxOff   31\n#define LitFSELog  11\n#define MLFSELog   10\n#define LLFSELog   10\n#define OffFSELog   9\n#define MAX(a,b) ((a)<(b)?(b):(a))\n#define MaxSeq MAX(MaxLL, MaxML)\n\n#define LITERAL_NOENTROPY 63\n#define COMMAND_NOENTROPY 7   /* to remove */\n\n#define ZSTD_CONTENTSIZE_ERROR   (0ULL - 2)\n\nstatic const size_t ZSTD_blockHeaderSize = 3;\nstatic const size_t ZSTD_frameHeaderSize = 4;\n\n\n/* *******************************************************\n*  Memory operations\n**********************************************************/\nstatic void   ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }\n\nstatic void   ZSTD_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }\n\n#define COPY8(d,s) { ZSTD_copy8(d,s); d+=8; s+=8; }\n\n/*! ZSTD_wildcopy : custom version of memcpy(), can copy up to 7-8 bytes too many */\nstatic void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length)\n{\n    const BYTE* ip = (const BYTE*)src;\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + length;\n    do COPY8(op, ip) while (op < oend);\n}\n\n\n/* **************************************\n*  Local structures\n****************************************/\ntypedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;\n\ntypedef struct\n{\n    blockType_t blockType;\n    U32 origSize;\n} blockProperties_t;\n\ntypedef struct {\n    void* buffer;\n    U32*  offsetStart;\n    U32*  offset;\n    BYTE* offCodeStart;\n    BYTE* offCode;\n    BYTE* litStart;\n    BYTE* lit;\n    BYTE* litLengthStart;\n    BYTE* litLength;\n    BYTE* matchLengthStart;\n    BYTE* matchLength;\n    BYTE* dumpsStart;\n    BYTE* dumps;\n} SeqStore_t;\n\n\n/* *************************************\n*  Error Management\n***************************************/\n/*! ZSTD_isError\n*   tells if a return value is an error code */\nstatic unsigned ZSTD_isError(size_t code) { return ERR_isError(code); }\n\n\n\n/* *************************************************************\n*   Decompression section\n***************************************************************/\nstruct ZSTDv03_Dctx_s\n{\n    U32 LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];\n    U32 OffTable[FSE_DTABLE_SIZE_U32(OffFSELog)];\n    U32 MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];\n    void* previousDstEnd;\n    void* base;\n    size_t expected;\n    blockType_t bType;\n    U32 phase;\n    const BYTE* litPtr;\n    size_t litSize;\n    BYTE litBuffer[BLOCKSIZE + 8 /* margin for wildcopy */];\n};   /* typedef'd to ZSTD_Dctx within \"zstd_static.h\" */\n\n\nstatic size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)\n{\n    const BYTE* const in = (const BYTE* const)src;\n    BYTE headerFlags;\n    U32 cSize;\n\n    if (srcSize < 3) return ERROR(srcSize_wrong);\n\n    headerFlags = *in;\n    cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);\n\n    bpPtr->blockType = (blockType_t)(headerFlags >> 6);\n    bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;\n\n    if (bpPtr->blockType == bt_end) return 0;\n    if (bpPtr->blockType == bt_rle) return 1;\n    return cSize;\n}\n\nstatic size_t ZSTD_copyUncompressedBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall);\n    if (srcSize > 0) {\n        memcpy(dst, src, srcSize);\n    }\n    return srcSize;\n}\n\n\n/** ZSTD_decompressLiterals\n    @return : nb of bytes read from src, or an error code*/\nstatic size_t ZSTD_decompressLiterals(void* dst, size_t* maxDstSizePtr,\n                                const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n\n    const size_t litSize = (MEM_readLE32(src) & 0x1FFFFF) >> 2;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n    const size_t litCSize = (MEM_readLE32(ip+2) & 0xFFFFFF) >> 5;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n\n    if (litSize > *maxDstSizePtr) return ERROR(corruption_detected);\n    if (litCSize + 5 > srcSize) return ERROR(corruption_detected);\n\n    if (HUF_isError(HUF_decompress(dst, litSize, ip+5, litCSize))) return ERROR(corruption_detected);\n\n    *maxDstSizePtr = litSize;\n    return litCSize + 5;\n}\n\n\n/** ZSTD_decodeLiteralsBlock\n    @return : nb of bytes read from src (< srcSize )*/\nstatic size_t ZSTD_decodeLiteralsBlock(void* ctx,\n                          const void* src, size_t srcSize)\n{\n    ZSTD_DCtx* dctx = (ZSTD_DCtx*)ctx;\n    const BYTE* const istart = (const BYTE* const)src;\n\n    /* any compressed block with literals segment must be at least this size */\n    if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);\n\n    switch(*istart & 3)\n    {\n    default:\n    case 0:\n        {\n            size_t litSize = BLOCKSIZE;\n            const size_t readSize = ZSTD_decompressLiterals(dctx->litBuffer, &litSize, src, srcSize);\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            memset(dctx->litBuffer + dctx->litSize, 0, 8);\n            return readSize;   /* works if it's an error too */\n        }\n    case IS_RAW:\n        {\n            const size_t litSize = (MEM_readLE32(istart) & 0xFFFFFF) >> 2;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n            if (litSize > srcSize-11)   /* risk of reading too far with wildcopy */\n            {\n                if (litSize > BLOCKSIZE) return ERROR(corruption_detected);\n                if (litSize > srcSize-3) return ERROR(corruption_detected);\n                memcpy(dctx->litBuffer, istart, litSize);\n                dctx->litPtr = dctx->litBuffer;\n                dctx->litSize = litSize;\n                memset(dctx->litBuffer + dctx->litSize, 0, 8);\n                return litSize+3;\n            }\n            /* direct reference into compressed stream */\n            dctx->litPtr = istart+3;\n            dctx->litSize = litSize;\n            return litSize+3;\n        }\n    case IS_RLE:\n        {\n            const size_t litSize = (MEM_readLE32(istart) & 0xFFFFFF) >> 2;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n            if (litSize > BLOCKSIZE) return ERROR(corruption_detected);\n            memset(dctx->litBuffer, istart[3], litSize + 8);\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            return 4;\n        }\n    }\n}\n\n\nstatic size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLengthPtr,\n                         FSE_DTable* DTableLL, FSE_DTable* DTableML, FSE_DTable* DTableOffb,\n                         const void* src, size_t srcSize)\n{\n    const BYTE* const istart = (const BYTE* const)src;\n    const BYTE* ip = istart;\n    const BYTE* const iend = istart + srcSize;\n    U32 LLtype, Offtype, MLtype;\n    U32 LLlog, Offlog, MLlog;\n    size_t dumpsLength;\n\n    /* check */\n    if (srcSize < 5) return ERROR(srcSize_wrong);\n\n    /* SeqHead */\n    *nbSeq = MEM_readLE16(ip); ip+=2;\n    LLtype  = *ip >> 6;\n    Offtype = (*ip >> 4) & 3;\n    MLtype  = (*ip >> 2) & 3;\n    if (*ip & 2)\n    {\n        dumpsLength  = ip[2];\n        dumpsLength += ip[1] << 8;\n        ip += 3;\n    }\n    else\n    {\n        dumpsLength  = ip[1];\n        dumpsLength += (ip[0] & 1) << 8;\n        ip += 2;\n    }\n    *dumpsPtr = ip;\n    ip += dumpsLength;\n    *dumpsLengthPtr = dumpsLength;\n\n    /* check */\n    if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are \"raw\", hence no header, but at least xxLog bits per type */\n\n    /* sequences */\n    {\n        S16 norm[MaxML+1];    /* assumption : MaxML >= MaxLL and MaxOff */\n        size_t headerSize;\n\n        /* Build DTables */\n        switch(LLtype)\n        {\n        case bt_rle :\n            LLlog = 0;\n            FSE_buildDTable_rle(DTableLL, *ip++); break;\n        case bt_raw :\n            LLlog = LLbits;\n            FSE_buildDTable_raw(DTableLL, LLbits); break;\n        default :\n            {   U32 max = MaxLL;\n                headerSize = FSE_readNCount(norm, &max, &LLlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (LLlog > LLFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableLL, norm, max, LLlog);\n        }   }\n\n        switch(Offtype)\n        {\n        case bt_rle :\n            Offlog = 0;\n            if (ip > iend-2) return ERROR(srcSize_wrong);   /* min : \"raw\", hence no header, but at least xxLog bits */\n            FSE_buildDTable_rle(DTableOffb, *ip++ & MaxOff); /* if *ip > MaxOff, data is corrupted */\n            break;\n        case bt_raw :\n            Offlog = Offbits;\n            FSE_buildDTable_raw(DTableOffb, Offbits); break;\n        default :\n            {   U32 max = MaxOff;\n                headerSize = FSE_readNCount(norm, &max, &Offlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (Offlog > OffFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableOffb, norm, max, Offlog);\n        }   }\n\n        switch(MLtype)\n        {\n        case bt_rle :\n            MLlog = 0;\n            if (ip > iend-2) return ERROR(srcSize_wrong); /* min : \"raw\", hence no header, but at least xxLog bits */\n            FSE_buildDTable_rle(DTableML, *ip++); break;\n        case bt_raw :\n            MLlog = MLbits;\n            FSE_buildDTable_raw(DTableML, MLbits); break;\n        default :\n            {   U32 max = MaxML;\n                headerSize = FSE_readNCount(norm, &max, &MLlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (MLlog > MLFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableML, norm, max, MLlog);\n    }   }   }\n\n    return ip-istart;\n}\n\n\ntypedef struct {\n    size_t litLength;\n    size_t offset;\n    size_t matchLength;\n} seq_t;\n\ntypedef struct {\n    BIT_DStream_t DStream;\n    FSE_DState_t stateLL;\n    FSE_DState_t stateOffb;\n    FSE_DState_t stateML;\n    size_t prevOffset;\n    const BYTE* dumps;\n    const BYTE* dumpsEnd;\n} seqState_t;\n\n\nstatic void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)\n{\n    size_t litLength;\n    size_t prevOffset;\n    size_t offset;\n    size_t matchLength;\n    const BYTE* dumps = seqState->dumps;\n    const BYTE* const de = seqState->dumpsEnd;\n\n    /* Literal length */\n    litLength = FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream));\n    prevOffset = litLength ? seq->offset : seqState->prevOffset;\n    seqState->prevOffset = seq->offset;\n    if (litLength == MaxLL)\n    {\n        const U32 add = dumps<de ? *dumps++ : 0;\n        if (add < 255) litLength += add;\n        else if (dumps + 3 <= de)\n        {\n            litLength = MEM_readLE24(dumps);\n            dumps += 3;\n        }\n        if (dumps >= de) dumps = de-1;   /* late correction, to avoid read overflow (data is now corrupted anyway) */\n    }\n\n    /* Offset */\n    {\n        static const size_t offsetPrefix[MaxOff+1] = {  /* note : size_t faster than U32 */\n                1 /*fake*/, 1, 2, 4, 8, 16, 32, 64, 128, 256,\n                512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144,\n                524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, /*fake*/ 1, 1, 1, 1, 1 };\n        U32 offsetCode, nbBits;\n        offsetCode = FSE_decodeSymbol(&(seqState->stateOffb), &(seqState->DStream));   /* <= maxOff, by table construction */\n        if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));\n        nbBits = offsetCode - 1;\n        if (offsetCode==0) nbBits = 0;   /* cmove */\n        offset = offsetPrefix[offsetCode] + BIT_readBits(&(seqState->DStream), nbBits);\n        if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));\n        if (offsetCode==0) offset = prevOffset;   /* cmove */\n    }\n\n    /* MatchLength */\n    matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream));\n    if (matchLength == MaxML)\n    {\n        const U32 add = dumps<de ? *dumps++ : 0;\n        if (add < 255) matchLength += add;\n        else if (dumps + 3 <= de)\n        {\n            matchLength = MEM_readLE24(dumps);\n            dumps += 3;\n        }\n        if (dumps >= de) dumps = de-1;   /* late correction, to avoid read overflow (data is now corrupted anyway) */\n    }\n    matchLength += MINMATCH;\n\n    /* save result */\n    seq->litLength = litLength;\n    seq->offset = offset;\n    seq->matchLength = matchLength;\n    seqState->dumps = dumps;\n}\n\n\nstatic size_t ZSTD_execSequence(BYTE* op,\n                                seq_t sequence,\n                                const BYTE** litPtr, const BYTE* const litLimit,\n                                BYTE* const base, BYTE* const oend)\n{\n    static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4};   /* added */\n    static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11};   /* subtracted */\n    const BYTE* const ostart = op;\n    BYTE* const oLitEnd = op + sequence.litLength;\n    BYTE* const oMatchEnd = op + sequence.litLength + sequence.matchLength;   /* risk : address space overflow (32-bits) */\n    BYTE* const oend_8 = oend-8;\n    const BYTE* const litEnd = *litPtr + sequence.litLength;\n\n    /* checks */\n    size_t const seqLength = sequence.litLength + sequence.matchLength;\n\n    if (seqLength > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);\n    if (sequence.litLength > (size_t)(litLimit - *litPtr)) return ERROR(corruption_detected);\n    /* Now we know there are no overflow in literal nor match lengths, can use pointer checks */\n    if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall);\n    if (sequence.offset > (U32)(oLitEnd - base)) return ERROR(corruption_detected);\n\n    if (oMatchEnd > oend) return ERROR(dstSize_tooSmall);   /* overwrite beyond dst buffer */\n    if (litEnd > litLimit) return ERROR(corruption_detected);   /* overRead beyond lit buffer */\n\n    /* copy Literals */\n    ZSTD_wildcopy(op, *litPtr, (ptrdiff_t)sequence.litLength);   /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */\n    op = oLitEnd;\n    *litPtr = litEnd;   /* update for next sequence */\n\n    /* copy Match */\n    {   const BYTE* match = op - sequence.offset;\n\n        /* check */\n        if (sequence.offset > (size_t)op) return ERROR(corruption_detected);   /* address space overflow test (this test seems kept by clang optimizer) */\n        //if (match > op) return ERROR(corruption_detected);   /* address space overflow test (is clang optimizer removing this test ?) */\n        if (match < base) return ERROR(corruption_detected);\n\n        /* close range match, overlap */\n        if (sequence.offset < 8)\n        {\n            const int dec64 = dec64table[sequence.offset];\n            op[0] = match[0];\n            op[1] = match[1];\n            op[2] = match[2];\n            op[3] = match[3];\n            match += dec32table[sequence.offset];\n            ZSTD_copy4(op+4, match);\n            match -= dec64;\n        }\n        else\n        {\n            ZSTD_copy8(op, match);\n        }\n        op += 8; match += 8;\n\n        if (oMatchEnd > oend-(16-MINMATCH))\n        {\n            if (op < oend_8)\n            {\n                ZSTD_wildcopy(op, match, oend_8 - op);\n                match += oend_8 - op;\n                op = oend_8;\n            }\n            while (op < oMatchEnd) *op++ = *match++;\n        }\n        else\n        {\n            ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8);   /* works even if matchLength < 8 */\n        }\n    }\n\n    return oMatchEnd - ostart;\n}\n\nstatic size_t ZSTD_decompressSequences(\n                               void* ctx,\n                               void* dst, size_t maxDstSize,\n                         const void* seqStart, size_t seqSize)\n{\n    ZSTD_DCtx* dctx = (ZSTD_DCtx*)ctx;\n    const BYTE* ip = (const BYTE*)seqStart;\n    const BYTE* const iend = ip + seqSize;\n    BYTE* const ostart = (BYTE* const)dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + maxDstSize;\n    size_t errorCode, dumpsLength;\n    const BYTE* litPtr = dctx->litPtr;\n    const BYTE* const litEnd = litPtr + dctx->litSize;\n    int nbSeq;\n    const BYTE* dumps;\n    U32* DTableLL = dctx->LLTable;\n    U32* DTableML = dctx->MLTable;\n    U32* DTableOffb = dctx->OffTable;\n    BYTE* const base = (BYTE*) (dctx->base);\n\n    /* Build Decoding Tables */\n    errorCode = ZSTD_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,\n                                      DTableLL, DTableML, DTableOffb,\n                                      ip, iend-ip);\n    if (ZSTD_isError(errorCode)) return errorCode;\n    ip += errorCode;\n\n    /* Regen sequences */\n    {\n        seq_t sequence;\n        seqState_t seqState;\n\n        memset(&sequence, 0, sizeof(sequence));\n        seqState.dumps = dumps;\n        seqState.dumpsEnd = dumps + dumpsLength;\n        seqState.prevOffset = sequence.offset = 4;\n        errorCode = BIT_initDStream(&(seqState.DStream), ip, iend-ip);\n        if (ERR_isError(errorCode)) return ERROR(corruption_detected);\n        FSE_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);\n        FSE_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);\n        FSE_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);\n\n        for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (nbSeq>0) ; )\n        {\n            size_t oneSeqSize;\n            nbSeq--;\n            ZSTD_decodeSequence(&sequence, &seqState);\n            oneSeqSize = ZSTD_execSequence(op, sequence, &litPtr, litEnd, base, oend);\n            if (ZSTD_isError(oneSeqSize)) return oneSeqSize;\n            op += oneSeqSize;\n        }\n\n        /* check if reached exact end */\n        if ( !BIT_endOfDStream(&(seqState.DStream)) ) return ERROR(corruption_detected);   /* requested too much : data is corrupted */\n        if (nbSeq<0) return ERROR(corruption_detected);   /* requested too many sequences : data is corrupted */\n\n        /* last literal segment */\n        {\n            size_t lastLLSize = litEnd - litPtr;\n            if (litPtr > litEnd) return ERROR(corruption_detected);\n            if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);\n            if (lastLLSize > 0) {\n                if (op != litPtr) memmove(op, litPtr, lastLLSize);\n                op += lastLLSize;\n            }\n        }\n    }\n\n    return op-ostart;\n}\n\n\nstatic size_t ZSTD_decompressBlock(\n                            void* ctx,\n                            void* dst, size_t maxDstSize,\n                      const void* src, size_t srcSize)\n{\n    /* blockType == blockCompressed */\n    const BYTE* ip = (const BYTE*)src;\n\n    /* Decode literals sub-block */\n    size_t litCSize = ZSTD_decodeLiteralsBlock(ctx, src, srcSize);\n    if (ZSTD_isError(litCSize)) return litCSize;\n    ip += litCSize;\n    srcSize -= litCSize;\n\n    return ZSTD_decompressSequences(ctx, dst, maxDstSize, ip, srcSize);\n}\n\n\nstatic size_t ZSTD_decompressDCtx(void* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n    const BYTE* iend = ip + srcSize;\n    BYTE* const ostart = (BYTE* const)dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + maxDstSize;\n    size_t remainingSize = srcSize;\n    U32 magicNumber;\n    blockProperties_t blockProperties;\n\n    /* Frame Header */\n    if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);\n    magicNumber = MEM_readLE32(src);\n    if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);\n    ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;\n\n    /* Loop on each block */\n    while (1)\n    {\n        size_t decodedSize=0;\n        size_t cBlockSize = ZSTD_getcBlockSize(ip, iend-ip, &blockProperties);\n        if (ZSTD_isError(cBlockSize)) return cBlockSize;\n\n        ip += ZSTD_blockHeaderSize;\n        remainingSize -= ZSTD_blockHeaderSize;\n        if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);\n\n        switch(blockProperties.blockType)\n        {\n        case bt_compressed:\n            decodedSize = ZSTD_decompressBlock(ctx, op, oend-op, ip, cBlockSize);\n            break;\n        case bt_raw :\n            decodedSize = ZSTD_copyUncompressedBlock(op, oend-op, ip, cBlockSize);\n            break;\n        case bt_rle :\n            return ERROR(GENERIC);   /* not yet supported */\n            break;\n        case bt_end :\n            /* end of frame */\n            if (remainingSize) return ERROR(srcSize_wrong);\n            break;\n        default:\n            return ERROR(GENERIC);   /* impossible */\n        }\n        if (cBlockSize == 0) break;   /* bt_end */\n\n        if (ZSTD_isError(decodedSize)) return decodedSize;\n        op += decodedSize;\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n    }\n\n    return op-ostart;\n}\n\nstatic size_t ZSTD_decompress(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    ZSTD_DCtx ctx;\n    ctx.base = dst;\n    return ZSTD_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize);\n}\n\n/* ZSTD_errorFrameSizeInfoLegacy() :\n   assumes `cSize` and `dBound` are _not_ NULL */\nMEM_STATIC void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)\n{\n    *cSize = ret;\n    *dBound = ZSTD_CONTENTSIZE_ERROR;\n}\n\nvoid ZSTDv03_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)\n{\n    const BYTE* ip = (const BYTE*)src;\n    size_t remainingSize = srcSize;\n    size_t nbBlocks = 0;\n    U32 magicNumber;\n    blockProperties_t blockProperties;\n\n    /* Frame Header */\n    if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) {\n        ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n        return;\n    }\n    magicNumber = MEM_readLE32(src);\n    if (magicNumber != ZSTD_magicNumber) {\n        ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));\n        return;\n    }\n    ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;\n\n    /* Loop on each block */\n    while (1)\n    {\n        size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);\n        if (ZSTD_isError(cBlockSize)) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);\n            return;\n        }\n\n        ip += ZSTD_blockHeaderSize;\n        remainingSize -= ZSTD_blockHeaderSize;\n        if (cBlockSize > remainingSize) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n            return;\n        }\n\n        if (cBlockSize == 0) break;   /* bt_end */\n\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n        nbBlocks++;\n    }\n\n    *cSize = ip - (const BYTE*)src;\n    *dBound = nbBlocks * BLOCKSIZE;\n}\n\n\n/*******************************\n*  Streaming Decompression API\n*******************************/\n\nstatic size_t ZSTD_resetDCtx(ZSTD_DCtx* dctx)\n{\n    dctx->expected = ZSTD_frameHeaderSize;\n    dctx->phase = 0;\n    dctx->previousDstEnd = NULL;\n    dctx->base = NULL;\n    return 0;\n}\n\nstatic ZSTD_DCtx* ZSTD_createDCtx(void)\n{\n    ZSTD_DCtx* dctx = (ZSTD_DCtx*)malloc(sizeof(ZSTD_DCtx));\n    if (dctx==NULL) return NULL;\n    ZSTD_resetDCtx(dctx);\n    return dctx;\n}\n\nstatic size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)\n{\n    free(dctx);\n    return 0;\n}\n\nstatic size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx)\n{\n    return dctx->expected;\n}\n\nstatic size_t ZSTD_decompressContinue(ZSTD_DCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    /* Sanity check */\n    if (srcSize != ctx->expected) return ERROR(srcSize_wrong);\n    if (dst != ctx->previousDstEnd)  /* not contiguous */\n        ctx->base = dst;\n\n    /* Decompress : frame header */\n    if (ctx->phase == 0)\n    {\n        /* Check frame magic header */\n        U32 magicNumber = MEM_readLE32(src);\n        if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);\n        ctx->phase = 1;\n        ctx->expected = ZSTD_blockHeaderSize;\n        return 0;\n    }\n\n    /* Decompress : block header */\n    if (ctx->phase == 1)\n    {\n        blockProperties_t bp;\n        size_t blockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);\n        if (ZSTD_isError(blockSize)) return blockSize;\n        if (bp.blockType == bt_end)\n        {\n            ctx->expected = 0;\n            ctx->phase = 0;\n        }\n        else\n        {\n            ctx->expected = blockSize;\n            ctx->bType = bp.blockType;\n            ctx->phase = 2;\n        }\n\n        return 0;\n    }\n\n    /* Decompress : block content */\n    {\n        size_t rSize;\n        switch(ctx->bType)\n        {\n        case bt_compressed:\n            rSize = ZSTD_decompressBlock(ctx, dst, maxDstSize, src, srcSize);\n            break;\n        case bt_raw :\n            rSize = ZSTD_copyUncompressedBlock(dst, maxDstSize, src, srcSize);\n            break;\n        case bt_rle :\n            return ERROR(GENERIC);   /* not yet handled */\n            break;\n        case bt_end :   /* should never happen (filtered at phase 1) */\n            rSize = 0;\n            break;\n        default:\n            return ERROR(GENERIC);\n        }\n        ctx->phase = 1;\n        ctx->expected = ZSTD_blockHeaderSize;\n        if (ZSTD_isError(rSize)) return rSize;\n        ctx->previousDstEnd = (void*)( ((char*)dst) + rSize);\n        return rSize;\n    }\n\n}\n\n\n/* wrapper layer */\n\nunsigned ZSTDv03_isError(size_t code)\n{\n    return ZSTD_isError(code);\n}\n\nsize_t ZSTDv03_decompress( void* dst, size_t maxOriginalSize,\n                     const void* src, size_t compressedSize)\n{\n    return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize);\n}\n\nZSTDv03_Dctx* ZSTDv03_createDCtx(void)\n{\n    return (ZSTDv03_Dctx*)ZSTD_createDCtx();\n}\n\nsize_t ZSTDv03_freeDCtx(ZSTDv03_Dctx* dctx)\n{\n    return ZSTD_freeDCtx((ZSTD_DCtx*)dctx);\n}\n\nsize_t ZSTDv03_resetDCtx(ZSTDv03_Dctx* dctx)\n{\n    return ZSTD_resetDCtx((ZSTD_DCtx*)dctx);\n}\n\nsize_t ZSTDv03_nextSrcSizeToDecompress(ZSTDv03_Dctx* dctx)\n{\n    return ZSTD_nextSrcSizeToDecompress((ZSTD_DCtx*)dctx);\n}\n\nsize_t ZSTDv03_decompressContinue(ZSTDv03_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    return ZSTD_decompressContinue((ZSTD_DCtx*)dctx, dst, maxDstSize, src, srcSize);\n}\n"
  },
  {
    "path": "lib/legacy/zstd_v03.h",
    "content": "/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_V03_H_298734209782\n#define ZSTD_V03_H_298734209782\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* *************************************\n*  Includes\n***************************************/\n#include <stddef.h>   /* size_t */\n\n\n/* *************************************\n*  Simple one-step function\n***************************************/\n/**\nZSTDv03_decompress() : decompress ZSTD frames compliant with v0.3.x format\n    compressedSize : is the exact source size\n    maxOriginalSize : is the size of the 'dst' buffer, which must be already allocated.\n                      It must be equal or larger than originalSize, otherwise decompression will fail.\n    return : the number of bytes decompressed into destination buffer (originalSize)\n             or an errorCode if it fails (which can be tested using ZSTDv01_isError())\n*/\nsize_t ZSTDv03_decompress( void* dst, size_t maxOriginalSize,\n                     const void* src, size_t compressedSize);\n\n /**\n ZSTDv03_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.3.x format\n     srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'\n     cSize (output parameter)  : the number of bytes that would be read to decompress this frame\n                                 or an error code if it fails (which can be tested using ZSTDv01_isError())\n     dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame\n                                 or ZSTD_CONTENTSIZE_ERROR if an error occurs\n\n    note : assumes `cSize` and `dBound` are _not_ NULL.\n */\n void ZSTDv03_findFrameSizeInfoLegacy(const void *src, size_t srcSize,\n                                      size_t* cSize, unsigned long long* dBound);\n\n    /**\nZSTDv03_isError() : tells if the result of ZSTDv03_decompress() is an error\n*/\nunsigned ZSTDv03_isError(size_t code);\n\n\n/* *************************************\n*  Advanced functions\n***************************************/\ntypedef struct ZSTDv03_Dctx_s ZSTDv03_Dctx;\nZSTDv03_Dctx* ZSTDv03_createDCtx(void);\nsize_t ZSTDv03_freeDCtx(ZSTDv03_Dctx* dctx);\n\nsize_t ZSTDv03_decompressDCtx(void* ctx,\n                              void* dst, size_t maxOriginalSize,\n                        const void* src, size_t compressedSize);\n\n/* *************************************\n*  Streaming functions\n***************************************/\nsize_t ZSTDv03_resetDCtx(ZSTDv03_Dctx* dctx);\n\nsize_t ZSTDv03_nextSrcSizeToDecompress(ZSTDv03_Dctx* dctx);\nsize_t ZSTDv03_decompressContinue(ZSTDv03_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize);\n/**\n  Use above functions alternatively.\n  ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue().\n  ZSTD_decompressContinue() will use previous data blocks to improve compression if they are located prior to current block.\n  Result is the number of bytes regenerated within 'dst'.\n  It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header.\n*/\n\n/* *************************************\n*  Prefix - version detection\n***************************************/\n#define ZSTDv03_magicNumber 0xFD2FB523   /* v0.3 */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* ZSTD_V03_H_298734209782 */\n"
  },
  {
    "path": "lib/legacy/zstd_v04.c",
    "content": "/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n /******************************************\n *  Includes\n ******************************************/\n#include <stddef.h>    /* size_t, ptrdiff_t */\n#include <string.h>    /* memcpy */\n\n#include \"zstd_v04.h\"\n#include \"../common/compiler.h\"\n#include \"../common/error_private.h\"\n\n\n/* ******************************************************************\n *   mem.h\n *******************************************************************/\n#ifndef MEM_H_MODULE\n#define MEM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/******************************************\n*  Compiler-specific\n******************************************/\n#if defined(_MSC_VER)   /* Visual Studio */\n#   include <stdlib.h>  /* _byteswap_ulong */\n#   include <intrin.h>  /* _byteswap_* */\n#endif\n\n\n/****************************************************************\n*  Basic Types\n*****************************************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n# if defined(_AIX)\n#  include <inttypes.h>\n# else\n#  include <stdint.h> /* intptr_t */\n# endif\n  typedef  uint8_t BYTE;\n  typedef uint16_t U16;\n  typedef  int16_t S16;\n  typedef uint32_t U32;\n  typedef  int32_t S32;\n  typedef uint64_t U64;\n  typedef  int64_t S64;\n#else\n  typedef unsigned char       BYTE;\n  typedef unsigned short      U16;\n  typedef   signed short      S16;\n  typedef unsigned int        U32;\n  typedef   signed int        S32;\n  typedef unsigned long long  U64;\n  typedef   signed long long  S64;\n#endif\n\n\n/*-*************************************\n*  Debug\n***************************************/\n#include \"../common/debug.h\"\n#ifndef assert\n#  define assert(condition) ((void)0)\n#endif\n\n\n/****************************************************************\n*  Memory I/O\n*****************************************************************/\n\nMEM_STATIC unsigned MEM_32bits(void) { return sizeof(void*)==4; }\nMEM_STATIC unsigned MEM_64bits(void) { return sizeof(void*)==8; }\n\nMEM_STATIC unsigned MEM_isLittleEndian(void)\n{\n    const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */\n    return one.c[0];\n}\n\nMEM_STATIC U16 MEM_read16(const void* memPtr)\n{\n    U16 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U32 MEM_read32(const void* memPtr)\n{\n    U32 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U64 MEM_read64(const void* memPtr)\n{\n    U64 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value)\n{\n    memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC U16 MEM_readLE16(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read16(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U16)(p[0] + (p[1]<<8));\n    }\n}\n\nMEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)\n{\n    if (MEM_isLittleEndian())\n    {\n        MEM_write16(memPtr, val);\n    }\n    else\n    {\n        BYTE* p = (BYTE*)memPtr;\n        p[0] = (BYTE)val;\n        p[1] = (BYTE)(val>>8);\n    }\n}\n\nMEM_STATIC U32 MEM_readLE24(const void* memPtr)\n{\n    return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16);\n}\n\nMEM_STATIC U32 MEM_readLE32(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read32(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U32)((U32)p[0] + ((U32)p[1]<<8) + ((U32)p[2]<<16) + ((U32)p[3]<<24));\n    }\n}\n\n\nMEM_STATIC U64 MEM_readLE64(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read64(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U64)((U64)p[0] + ((U64)p[1]<<8) + ((U64)p[2]<<16) + ((U64)p[3]<<24)\n                     + ((U64)p[4]<<32) + ((U64)p[5]<<40) + ((U64)p[6]<<48) + ((U64)p[7]<<56));\n    }\n}\n\n\nMEM_STATIC size_t MEM_readLEST(const void* memPtr)\n{\n    if (MEM_32bits())\n        return (size_t)MEM_readLE32(memPtr);\n    else\n        return (size_t)MEM_readLE64(memPtr);\n}\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* MEM_H_MODULE */\n\n/*\n    zstd - standard compression library\n    Header File for static linking only\n*/\n#ifndef ZSTD_STATIC_H\n#define ZSTD_STATIC_H\n\n\n/* *************************************\n*  Types\n***************************************/\n#define ZSTD_WINDOWLOG_ABSOLUTEMIN 11\n\n/** from faster to stronger */\ntypedef enum { ZSTD_fast, ZSTD_greedy, ZSTD_lazy, ZSTD_lazy2, ZSTD_btlazy2 } ZSTD_strategy;\n\ntypedef struct\n{\n    U64 srcSize;       /* optional : tells how much bytes are present in the frame. Use 0 if not known. */\n    U32 windowLog;     /* largest match distance : larger == more compression, more memory needed during decompression */\n    U32 contentLog;    /* full search segment : larger == more compression, slower, more memory (useless for fast) */\n    U32 hashLog;       /* dispatch table : larger == more memory, faster */\n    U32 searchLog;     /* nb of searches : larger == more compression, slower */\n    U32 searchLength;  /* size of matches : larger == faster decompression, sometimes less compression */\n    ZSTD_strategy strategy;\n} ZSTD_parameters;\n\ntypedef ZSTDv04_Dctx ZSTD_DCtx;\n\n/* *************************************\n*  Advanced functions\n***************************************/\n/** ZSTD_decompress_usingDict\n*   Same as ZSTD_decompressDCtx, using a Dictionary content as prefix\n*   Note : dict can be NULL, in which case, it's equivalent to ZSTD_decompressDCtx() */\nstatic size_t ZSTD_decompress_usingDict(ZSTD_DCtx* ctx,\n                                             void* dst, size_t maxDstSize,\n                                       const void* src, size_t srcSize,\n                                       const void* dict,size_t dictSize);\n\n\n/* **************************************\n*  Streaming functions (direct mode)\n****************************************/\nstatic size_t ZSTD_resetDCtx(ZSTD_DCtx* dctx);\nstatic size_t ZSTD_getFrameParams(ZSTD_parameters* params, const void* src, size_t srcSize);\nstatic void   ZSTD_decompress_insertDictionary(ZSTD_DCtx* ctx, const void* src, size_t srcSize);\n\nstatic size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx);\nstatic size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize);\n\n/**\n  Streaming decompression, bufferless mode\n\n  A ZSTD_DCtx object is required to track streaming operations.\n  Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it.\n  A ZSTD_DCtx object can be re-used multiple times. Use ZSTD_resetDCtx() to return to fresh status.\n\n  First operation is to retrieve frame parameters, using ZSTD_getFrameParams().\n  This function doesn't consume its input. It needs enough input data to properly decode the frame header.\n  Objective is to retrieve *params.windowlog, to know minimum amount of memory required during decoding.\n  Result : 0 when successful, it means the ZSTD_parameters structure has been filled.\n           >0 : means there is not enough data into src. Provides the expected size to successfully decode header.\n           errorCode, which can be tested using ZSTD_isError() (For example, if it's not a ZSTD header)\n\n  Then, you can optionally insert a dictionary.\n  This operation must mimic the compressor behavior, otherwise decompression will fail or be corrupted.\n\n  Then it's possible to start decompression.\n  Use ZSTD_nextSrcSizeToDecompress() and ZSTD_decompressContinue() alternatively.\n  ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue().\n  ZSTD_decompressContinue() requires this exact amount of bytes, or it will fail.\n  ZSTD_decompressContinue() needs previous data blocks during decompression, up to (1 << windowlog).\n  They should preferably be located contiguously, prior to current block. Alternatively, a round buffer is also possible.\n\n  @result of ZSTD_decompressContinue() is the number of bytes regenerated within 'dst'.\n  It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header.\n\n  A frame is fully decoded when ZSTD_nextSrcSizeToDecompress() returns zero.\n  Context can then be reset to start a new decompression.\n*/\n\n\n\n\n#endif  /* ZSTD_STATIC_H */\n\n\n/*\n    zstd_internal - common functions to include\n    Header File for include\n*/\n#ifndef ZSTD_CCOMMON_H_MODULE\n#define ZSTD_CCOMMON_H_MODULE\n\n/* *************************************\n*  Common macros\n***************************************/\n#define MIN(a,b) ((a)<(b) ? (a) : (b))\n#define MAX(a,b) ((a)>(b) ? (a) : (b))\n\n\n/* *************************************\n*  Common constants\n***************************************/\n#define ZSTD_MAGICNUMBER 0xFD2FB524   /* v0.4 */\n\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\n#define BLOCKSIZE (128 KB)                 /* define, for static allocation */\n\nstatic const size_t ZSTD_blockHeaderSize = 3;\nstatic const size_t ZSTD_frameHeaderSize_min = 5;\n#define ZSTD_frameHeaderSize_max 5         /* define, for static allocation */\n\n#define BIT7 128\n#define BIT6  64\n#define BIT5  32\n#define BIT4  16\n#define BIT1   2\n#define BIT0   1\n\n#define IS_RAW BIT0\n#define IS_RLE BIT1\n\n#define MINMATCH 4\n#define REPCODE_STARTVALUE 4\n\n#define MLbits   7\n#define LLbits   6\n#define Offbits  5\n#define MaxML  ((1<<MLbits) - 1)\n#define MaxLL  ((1<<LLbits) - 1)\n#define MaxOff ((1<<Offbits)- 1)\n#define MLFSELog   10\n#define LLFSELog   10\n#define OffFSELog   9\n#define MaxSeq MAX(MaxLL, MaxML)\n\n#define MIN_SEQUENCES_SIZE (2 /*seqNb*/ + 2 /*dumps*/ + 3 /*seqTables*/ + 1 /*bitStream*/)\n#define MIN_CBLOCK_SIZE (3 /*litCSize*/ + MIN_SEQUENCES_SIZE)\n\n#define ZSTD_CONTENTSIZE_ERROR   (0ULL - 2)\n\ntypedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;\n\n\n/* ******************************************\n*  Shared functions to include for inlining\n********************************************/\nstatic void ZSTD_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }\n\n#define COPY8(d,s) { ZSTD_copy8(d,s); d+=8; s+=8; }\n\n/*! ZSTD_wildcopy : custom version of memcpy(), can copy up to 7-8 bytes too many */\nstatic void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length)\n{\n    const BYTE* ip = (const BYTE*)src;\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + length;\n    do\n        COPY8(op, ip)\n    while (op < oend);\n}\n\n\n\n/* ******************************************************************\n   FSE : Finite State Entropy coder\n   header file\n****************************************************************** */\n#ifndef FSE_H\n#define FSE_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/* *****************************************\n*  Includes\n******************************************/\n#include <stddef.h>    /* size_t, ptrdiff_t */\n\n\n/* *****************************************\n*  FSE simple functions\n******************************************/\nstatic size_t FSE_decompress(void* dst,  size_t maxDstSize,\n                const void* cSrc, size_t cSrcSize);\n/*!\nFSE_decompress():\n    Decompress FSE data from buffer 'cSrc', of size 'cSrcSize',\n    into already allocated destination buffer 'dst', of size 'maxDstSize'.\n    return : size of regenerated data (<= maxDstSize)\n             or an error code, which can be tested using FSE_isError()\n\n    ** Important ** : FSE_decompress() doesn't decompress non-compressible nor RLE data !!!\n    Why ? : making this distinction requires a header.\n    Header management is intentionally delegated to the user layer, which can better manage special cases.\n*/\n\n\n/* *****************************************\n*  Tool functions\n******************************************/\n/* Error Management */\nstatic unsigned    FSE_isError(size_t code);        /* tells if a return value is an error code */\n\n\n\n/* *****************************************\n*  FSE detailed API\n******************************************/\n/*!\nFSE_compress() does the following:\n1. count symbol occurrence from source[] into table count[]\n2. normalize counters so that sum(count[]) == Power_of_2 (2^tableLog)\n3. save normalized counters to memory buffer using writeNCount()\n4. build encoding table 'CTable' from normalized counters\n5. encode the data stream using encoding table 'CTable'\n\nFSE_decompress() does the following:\n1. read normalized counters with readNCount()\n2. build decoding table 'DTable' from normalized counters\n3. decode the data stream using decoding table 'DTable'\n\nThe following API allows targeting specific sub-functions for advanced tasks.\nFor example, it's possible to compress several blocks using the same 'CTable',\nor to save and provide normalized distribution using external method.\n*/\n\n\n/* *** DECOMPRESSION *** */\n\n/*!\nFSE_readNCount():\n   Read compactly saved 'normalizedCounter' from 'rBuffer'.\n   return : size read from 'rBuffer'\n            or an errorCode, which can be tested using FSE_isError()\n            maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */\nstatic  size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, const void* rBuffer, size_t rBuffSize);\n\n/*!\nConstructor and Destructor of type FSE_DTable\n    Note that its size depends on 'tableLog' */\ntypedef unsigned FSE_DTable;   /* don't allocate that. It's just a way to be more restrictive than void* */\n\n/*!\nFSE_buildDTable():\n   Builds 'dt', which must be already allocated, using FSE_createDTable()\n   return : 0,\n            or an errorCode, which can be tested using FSE_isError() */\nstatic size_t FSE_buildDTable ( FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);\n\n/*!\nFSE_decompress_usingDTable():\n   Decompress compressed source 'cSrc' of size 'cSrcSize' using 'dt'\n   into 'dst' which must be already allocated.\n   return : size of regenerated data (necessarily <= maxDstSize)\n            or an errorCode, which can be tested using FSE_isError() */\nstatic  size_t FSE_decompress_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const FSE_DTable* dt);\n\n/*!\nTutorial :\n----------\n(Note : these functions only decompress FSE-compressed blocks.\n If block is uncompressed, use memcpy() instead\n If block is a single repeated byte, use memset() instead )\n\nThe first step is to obtain the normalized frequencies of symbols.\nThis can be performed by FSE_readNCount() if it was saved using FSE_writeNCount().\n'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short.\nIn practice, that means it's necessary to know 'maxSymbolValue' beforehand,\nor size the table to handle worst case situations (typically 256).\nFSE_readNCount() will provide 'tableLog' and 'maxSymbolValue'.\nThe result of FSE_readNCount() is the number of bytes read from 'rBuffer'.\nNote that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that.\nIf there is an error, the function will return an error code, which can be tested using FSE_isError().\n\nThe next step is to build the decompression tables 'FSE_DTable' from 'normalizedCounter'.\nThis is performed by the function FSE_buildDTable().\nThe space required by 'FSE_DTable' must be already allocated using FSE_createDTable().\nIf there is an error, the function will return an error code, which can be tested using FSE_isError().\n\n'FSE_DTable' can then be used to decompress 'cSrc', with FSE_decompress_usingDTable().\n'cSrcSize' must be strictly correct, otherwise decompression will fail.\nFSE_decompress_usingDTable() result will tell how many bytes were regenerated (<=maxDstSize).\nIf there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small)\n*/\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* FSE_H */\n\n\n/* ******************************************************************\n   bitstream\n   Part of NewGen Entropy library\n   header file (to include)\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef BITSTREAM_H_MODULE\n#define BITSTREAM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/*\n*  This API consists of small unitary functions, which highly benefit from being inlined.\n*  Since link-time-optimization is not available for all compilers,\n*  these functions are defined into a .h to be included.\n*/\n\n/**********************************************\n*  bitStream decompression API (read backward)\n**********************************************/\ntypedef struct\n{\n    size_t   bitContainer;\n    unsigned bitsConsumed;\n    const char* ptr;\n    const char* start;\n} BIT_DStream_t;\n\ntypedef enum { BIT_DStream_unfinished = 0,\n               BIT_DStream_endOfBuffer = 1,\n               BIT_DStream_completed = 2,\n               BIT_DStream_overflow = 3 } BIT_DStream_status;  /* result of BIT_reloadDStream() */\n               /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */\n\nMEM_STATIC size_t   BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize);\nMEM_STATIC size_t   BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);\nMEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD);\nMEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);\n\n\n\n\n/******************************************\n*  unsafe API\n******************************************/\nMEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);\n/* faster, but works only if nbBits >= 1 */\n\n\n\n/****************************************************************\n*  Helper functions\n****************************************************************/\nMEM_STATIC unsigned BIT_highbit32 (U32 val)\n{\n#   if defined(_MSC_VER)   /* Visual */\n    unsigned long r;\n    return _BitScanReverse(&r, val) ? (unsigned)r : 0;\n#   elif defined(__GNUC__) && (__GNUC__ >= 3)   /* Use GCC Intrinsic */\n    return __builtin_clz (val) ^ 31;\n#   else   /* Software version */\n    static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };\n    U32 v = val;\n    unsigned r;\n    v |= v >> 1;\n    v |= v >> 2;\n    v |= v >> 4;\n    v |= v >> 8;\n    v |= v >> 16;\n    r = DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];\n    return r;\n#   endif\n}\n\n\n/**********************************************************\n* bitStream decoding\n**********************************************************/\n\n/*!BIT_initDStream\n*  Initialize a BIT_DStream_t.\n*  @bitD : a pointer to an already allocated BIT_DStream_t structure\n*  @srcBuffer must point at the beginning of a bitStream\n*  @srcSize must be the exact size of the bitStream\n*  @result : size of stream (== srcSize) or an errorCode if a problem is detected\n*/\nMEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize)\n{\n    if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }\n\n    if (srcSize >=  sizeof(size_t))   /* normal case */\n    {\n        U32 contain32;\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = (const char*)srcBuffer + srcSize - sizeof(size_t);\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        contain32 = ((const BYTE*)srcBuffer)[srcSize-1];\n        if (contain32 == 0) return ERROR(GENERIC);   /* endMark not present */\n        bitD->bitsConsumed = 8 - BIT_highbit32(contain32);\n    }\n    else\n    {\n        U32 contain32;\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = bitD->start;\n        bitD->bitContainer = *(const BYTE*)(bitD->start);\n        switch(srcSize)\n        {\n            case 7: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[6]) << (sizeof(size_t)*8 - 16);/* fall-through */\n            case 6: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[5]) << (sizeof(size_t)*8 - 24);/* fall-through */\n            case 5: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[4]) << (sizeof(size_t)*8 - 32);/* fall-through */\n            case 4: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[3]) << 24; /* fall-through */\n            case 3: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[2]) << 16; /* fall-through */\n            case 2: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[1]) <<  8; /* fall-through */\n            default: break;\n        }\n        contain32 = ((const BYTE*)srcBuffer)[srcSize-1];\n        if (contain32 == 0) return ERROR(GENERIC);   /* endMark not present */\n        bitD->bitsConsumed = 8 - BIT_highbit32(contain32);\n        bitD->bitsConsumed += (U32)(sizeof(size_t) - srcSize)*8;\n    }\n\n    return srcSize;\n}\n\nMEM_STATIC size_t BIT_lookBits(BIT_DStream_t* bitD, U32 nbBits)\n{\n    const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);\n}\n\n/*! BIT_lookBitsFast :\n*   unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BIT_lookBitsFast(BIT_DStream_t* bitD, U32 nbBits)\n{\n    const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);\n}\n\nMEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)\n{\n    bitD->bitsConsumed += nbBits;\n}\n\nMEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits)\n{\n    size_t value = BIT_lookBits(bitD, nbBits);\n    BIT_skipBits(bitD, nbBits);\n    return value;\n}\n\n/*!BIT_readBitsFast :\n*  unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)\n{\n    size_t value = BIT_lookBitsFast(bitD, nbBits);\n    BIT_skipBits(bitD, nbBits);\n    return value;\n}\n\nMEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)\n{\n    if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */\n        return BIT_DStream_overflow;\n\n    if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer))\n    {\n        bitD->ptr -= bitD->bitsConsumed >> 3;\n        bitD->bitsConsumed &= 7;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        return BIT_DStream_unfinished;\n    }\n    if (bitD->ptr == bitD->start)\n    {\n        if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;\n        return BIT_DStream_completed;\n    }\n    {\n        U32 nbBytes = bitD->bitsConsumed >> 3;\n        BIT_DStream_status result = BIT_DStream_unfinished;\n        if (bitD->ptr - nbBytes < bitD->start)\n        {\n            nbBytes = (U32)(bitD->ptr - bitD->start);  /* ptr > start */\n            result = BIT_DStream_endOfBuffer;\n        }\n        bitD->ptr -= nbBytes;\n        bitD->bitsConsumed -= nbBytes*8;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);   /* reminder : srcSize > sizeof(bitD) */\n        return result;\n    }\n}\n\n/*! BIT_endOfDStream\n*   @return Tells if DStream has reached its exact end\n*/\nMEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)\n{\n    return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));\n}\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* BITSTREAM_H_MODULE */\n\n\n\n/* ******************************************************************\n   FSE : Finite State Entropy coder\n   header file for static linking (only)\n   Copyright (C) 2013-2015, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef FSE_STATIC_H\n#define FSE_STATIC_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/* *****************************************\n*  Static allocation\n*******************************************/\n/* FSE buffer bounds */\n#define FSE_NCOUNTBOUND 512\n#define FSE_BLOCKBOUND(size) (size + (size>>7))\n#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size))   /* Macro version, useful for static allocation */\n\n/* It is possible to statically allocate FSE CTable/DTable as a table of unsigned using below macros */\n#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue)   (1 + (1<<(maxTableLog-1)) + ((maxSymbolValue+1)*2))\n#define FSE_DTABLE_SIZE_U32(maxTableLog)                   (1 + (1<<maxTableLog))\n\n\n/* *****************************************\n*  FSE advanced API\n*******************************************/\nstatic size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits);\n/* build a fake FSE_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */\n\nstatic size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue);\n/* build a fake FSE_DTable, designed to always generate the same symbolValue */\n\n\n\n/* *****************************************\n*  FSE symbol decompression API\n*******************************************/\ntypedef struct\n{\n    size_t      state;\n    const void* table;   /* precise table may vary, depending on U16 */\n} FSE_DState_t;\n\n\nstatic void     FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt);\n\nstatic unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);\n\nstatic unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr);\n\n\n/* *****************************************\n*  FSE unsafe API\n*******************************************/\nstatic unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);\n/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */\n\n\n/* *****************************************\n*  Implementation of inlined functions\n*******************************************/\n/* decompression */\n\ntypedef struct {\n    U16 tableLog;\n    U16 fastMode;\n} FSE_DTableHeader;   /* sizeof U32 */\n\ntypedef struct\n{\n    unsigned short newState;\n    unsigned char  symbol;\n    unsigned char  nbBits;\n} FSE_decode_t;   /* size == U32 */\n\nMEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt)\n{\n    FSE_DTableHeader DTableH;\n    memcpy(&DTableH, dt, sizeof(DTableH));\n    DStatePtr->state = BIT_readBits(bitD, DTableH.tableLog);\n    BIT_reloadDStream(bitD);\n    DStatePtr->table = dt + 1;\n}\n\nMEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)\n{\n    const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    const U32  nbBits = DInfo.nbBits;\n    BYTE symbol = DInfo.symbol;\n    size_t lowBits = BIT_readBits(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\nMEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)\n{\n    const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    const U32 nbBits = DInfo.nbBits;\n    BYTE symbol = DInfo.symbol;\n    size_t lowBits = BIT_readBitsFast(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\nMEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)\n{\n    return DStatePtr->state == 0;\n}\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* FSE_STATIC_H */\n\n/* ******************************************************************\n   FSE : Finite State Entropy coder\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n#ifndef FSE_COMMONDEFS_ONLY\n\n/* **************************************************************\n*  Tuning parameters\n****************************************************************/\n/*!MEMORY_USAGE :\n*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n*  Increasing memory usage improves compression ratio\n*  Reduced memory usage can improve speed, due to cache effect\n*  Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */\n#define FSE_MAX_MEMORY_USAGE 14\n#define FSE_DEFAULT_MEMORY_USAGE 13\n\n/*!FSE_MAX_SYMBOL_VALUE :\n*  Maximum symbol value authorized.\n*  Required for proper stack allocation */\n#define FSE_MAX_SYMBOL_VALUE 255\n\n\n/* **************************************************************\n*  template functions type & suffix\n****************************************************************/\n#define FSE_FUNCTION_TYPE BYTE\n#define FSE_FUNCTION_EXTENSION\n#define FSE_DECODE_TYPE FSE_decode_t\n\n\n#endif   /* !FSE_COMMONDEFS_ONLY */\n\n/* **************************************************************\n*  Compiler specifics\n****************************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  define FORCE_INLINE static __forceinline\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4214)        /* disable: C4214: non-int bitfields */\n#else\n#  if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */\n#    ifdef __GNUC__\n#      define FORCE_INLINE static inline __attribute__((always_inline))\n#    else\n#      define FORCE_INLINE static inline\n#    endif\n#  else\n#    define FORCE_INLINE static\n#  endif /* __STDC_VERSION__ */\n#endif\n\n\n/* **************************************************************\n*  Dependencies\n****************************************************************/\n#include <stdlib.h>     /* malloc, free, qsort */\n#include <string.h>     /* memcpy, memset */\n#include <stdio.h>      /* printf (debug) */\n\n\n/* ***************************************************************\n*  Constants\n*****************************************************************/\n#define FSE_MAX_TABLELOG  (FSE_MAX_MEMORY_USAGE-2)\n#define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG)\n#define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1)\n#define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2)\n#define FSE_MIN_TABLELOG 5\n\n#define FSE_TABLELOG_ABSOLUTE_MAX 15\n#if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX\n#error \"FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported\"\n#endif\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n#define FSE_STATIC_ASSERT(c) { enum { FSE_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n/* **************************************************************\n*  Complex types\n****************************************************************/\ntypedef U32 DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)];\n\n\n/*-**************************************************************\n*  Templates\n****************************************************************/\n/*\n  designed to be included\n  for type-specific functions (template emulation in C)\n  Objective is to write these functions only once, for improved maintenance\n*/\n\n/* safety checks */\n#ifndef FSE_FUNCTION_EXTENSION\n#  error \"FSE_FUNCTION_EXTENSION must be defined\"\n#endif\n#ifndef FSE_FUNCTION_TYPE\n#  error \"FSE_FUNCTION_TYPE must be defined\"\n#endif\n\n/* Function names */\n#define FSE_CAT(X,Y) X##Y\n#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y)\n#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y)\n\nstatic U32 FSE_tableStep(U32 tableSize) { return (tableSize>>1) + (tableSize>>3) + 3; }\n\n\nstatic size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)\n{\n    FSE_DTableHeader DTableH;\n    void* const tdPtr = dt+1;   /* because dt is unsigned, 32-bits aligned on 32-bits */\n    FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*) (tdPtr);\n    const U32 tableSize = 1 << tableLog;\n    const U32 tableMask = tableSize-1;\n    const U32 step = FSE_tableStep(tableSize);\n    U16 symbolNext[FSE_MAX_SYMBOL_VALUE+1];\n    U32 position = 0;\n    U32 highThreshold = tableSize-1;\n    const S16 largeLimit= (S16)(1 << (tableLog-1));\n    U32 noLarge = 1;\n    U32 s;\n\n    /* Sanity Checks */\n    if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);\n    if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);\n\n    /* Init, lay down lowprob symbols */\n    memset(tableDecode, 0, sizeof(FSE_DECODE_TYPE) * (maxSymbolValue+1) );   /* useless init, but keep static analyzer happy, and we don't need to performance optimize legacy decoders */\n    DTableH.tableLog = (U16)tableLog;\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        if (normalizedCounter[s]==-1)\n        {\n            tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s;\n            symbolNext[s] = 1;\n        }\n        else\n        {\n            if (normalizedCounter[s] >= largeLimit) noLarge=0;\n            symbolNext[s] = normalizedCounter[s];\n        }\n    }\n\n    /* Spread symbols */\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        int i;\n        for (i=0; i<normalizedCounter[s]; i++)\n        {\n            tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;\n            position = (position + step) & tableMask;\n            while (position > highThreshold) position = (position + step) & tableMask;   /* lowprob area */\n        }\n    }\n\n    if (position!=0) return ERROR(GENERIC);   /* position must reach all cells once, otherwise normalizedCounter is incorrect */\n\n    /* Build Decoding table */\n    {\n        U32 i;\n        for (i=0; i<tableSize; i++)\n        {\n            FSE_FUNCTION_TYPE symbol = (FSE_FUNCTION_TYPE)(tableDecode[i].symbol);\n            U16 nextState = symbolNext[symbol]++;\n            tableDecode[i].nbBits = (BYTE) (tableLog - BIT_highbit32 ((U32)nextState) );\n            tableDecode[i].newState = (U16) ( (nextState << tableDecode[i].nbBits) - tableSize);\n        }\n    }\n\n    DTableH.fastMode = (U16)noLarge;\n    memcpy(dt, &DTableH, sizeof(DTableH));\n    return 0;\n}\n\n\n#ifndef FSE_COMMONDEFS_ONLY\n/******************************************\n*  FSE helper functions\n******************************************/\nstatic unsigned FSE_isError(size_t code) { return ERR_isError(code); }\n\n\n/****************************************************************\n*  FSE NCount encoding-decoding\n****************************************************************/\nstatic short FSE_abs(short a)\n{\n    return a<0 ? (short)-a : a;\n}\n\nstatic size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n                 const void* headerBuffer, size_t hbSize)\n{\n    const BYTE* const istart = (const BYTE*) headerBuffer;\n    const BYTE* const iend = istart + hbSize;\n    const BYTE* ip = istart;\n    int nbBits;\n    int remaining;\n    int threshold;\n    U32 bitStream;\n    int bitCount;\n    unsigned charnum = 0;\n    int previous0 = 0;\n\n    if (hbSize < 4) return ERROR(srcSize_wrong);\n    bitStream = MEM_readLE32(ip);\n    nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG;   /* extract tableLog */\n    if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);\n    bitStream >>= 4;\n    bitCount = 4;\n    *tableLogPtr = nbBits;\n    remaining = (1<<nbBits)+1;\n    threshold = 1<<nbBits;\n    nbBits++;\n\n    while ((remaining>1) && (charnum<=*maxSVPtr))\n    {\n        if (previous0)\n        {\n            unsigned n0 = charnum;\n            while ((bitStream & 0xFFFF) == 0xFFFF)\n            {\n                n0+=24;\n                if (ip < iend-5)\n                {\n                    ip+=2;\n                    bitStream = MEM_readLE32(ip) >> bitCount;\n                }\n                else\n                {\n                    bitStream >>= 16;\n                    bitCount+=16;\n                }\n            }\n            while ((bitStream & 3) == 3)\n            {\n                n0+=3;\n                bitStream>>=2;\n                bitCount+=2;\n            }\n            n0 += bitStream & 3;\n            bitCount += 2;\n            if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);\n            while (charnum < n0) normalizedCounter[charnum++] = 0;\n            if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4))\n            {\n                ip += bitCount>>3;\n                bitCount &= 7;\n                bitStream = MEM_readLE32(ip) >> bitCount;\n            }\n            else\n                bitStream >>= 2;\n        }\n        {\n            const short max = (short)((2*threshold-1)-remaining);\n            short count;\n\n            if ((bitStream & (threshold-1)) < (U32)max)\n            {\n                count = (short)(bitStream & (threshold-1));\n                bitCount   += nbBits-1;\n            }\n            else\n            {\n                count = (short)(bitStream & (2*threshold-1));\n                if (count >= threshold) count -= max;\n                bitCount   += nbBits;\n            }\n\n            count--;   /* extra accuracy */\n            remaining -= FSE_abs(count);\n            normalizedCounter[charnum++] = count;\n            previous0 = !count;\n            while (remaining < threshold)\n            {\n                nbBits--;\n                threshold >>= 1;\n            }\n\n            {\n                if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4))\n                {\n                    ip += bitCount>>3;\n                    bitCount &= 7;\n                }\n                else\n                {\n                    bitCount -= (int)(8 * (iend - 4 - ip));\n                    ip = iend - 4;\n                }\n                bitStream = MEM_readLE32(ip) >> (bitCount & 31);\n            }\n        }\n    }\n    if (remaining != 1) return ERROR(GENERIC);\n    *maxSVPtr = charnum-1;\n\n    ip += (bitCount+7)>>3;\n    if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong);\n    return ip-istart;\n}\n\n\n/*********************************************************\n*  Decompression (Byte symbols)\n*********************************************************/\nstatic size_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue)\n{\n    void* ptr = dt;\n    FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;\n    void* dPtr = dt + 1;\n    FSE_decode_t* const cell = (FSE_decode_t*)dPtr;\n\n    DTableH->tableLog = 0;\n    DTableH->fastMode = 0;\n\n    cell->newState = 0;\n    cell->symbol = symbolValue;\n    cell->nbBits = 0;\n\n    return 0;\n}\n\n\nstatic size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits)\n{\n    void* ptr = dt;\n    FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;\n    void* dPtr = dt + 1;\n    FSE_decode_t* const dinfo = (FSE_decode_t*)dPtr;\n    const unsigned tableSize = 1 << nbBits;\n    const unsigned tableMask = tableSize - 1;\n    const unsigned maxSymbolValue = tableMask;\n    unsigned s;\n\n    /* Sanity checks */\n    if (nbBits < 1) return ERROR(GENERIC);         /* min size */\n\n    /* Build Decoding Table */\n    DTableH->tableLog = (U16)nbBits;\n    DTableH->fastMode = 1;\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        dinfo[s].newState = 0;\n        dinfo[s].symbol = (BYTE)s;\n        dinfo[s].nbBits = (BYTE)nbBits;\n    }\n\n    return 0;\n}\n\nFORCE_INLINE size_t FSE_decompress_usingDTable_generic(\n          void* dst, size_t maxDstSize,\n    const void* cSrc, size_t cSrcSize,\n    const FSE_DTable* dt, const unsigned fast)\n{\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* op = ostart;\n    BYTE* const omax = op + maxDstSize;\n    BYTE* const olimit = omax-3;\n\n    BIT_DStream_t bitD;\n    FSE_DState_t state1;\n    FSE_DState_t state2;\n    size_t errorCode;\n\n    /* Init */\n    errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize);   /* replaced last arg by maxCompressed Size */\n    if (FSE_isError(errorCode)) return errorCode;\n\n    FSE_initDState(&state1, &bitD, dt);\n    FSE_initDState(&state2, &bitD, dt);\n\n#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD)\n\n    /* 4 symbols per loop */\n    for ( ; (BIT_reloadDStream(&bitD)==BIT_DStream_unfinished) && (op<olimit) ; op+=4)\n    {\n        op[0] = FSE_GETSYMBOL(&state1);\n\n        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BIT_reloadDStream(&bitD);\n\n        op[1] = FSE_GETSYMBOL(&state2);\n\n        if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            { if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) { op+=2; break; } }\n\n        op[2] = FSE_GETSYMBOL(&state1);\n\n        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BIT_reloadDStream(&bitD);\n\n        op[3] = FSE_GETSYMBOL(&state2);\n    }\n\n    /* tail */\n    /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */\n    while (1)\n    {\n        if ( (BIT_reloadDStream(&bitD)>BIT_DStream_completed) || (op==omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state1))) )\n            break;\n\n        *op++ = FSE_GETSYMBOL(&state1);\n\n        if ( (BIT_reloadDStream(&bitD)>BIT_DStream_completed) || (op==omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state2))) )\n            break;\n\n        *op++ = FSE_GETSYMBOL(&state2);\n    }\n\n    /* end ? */\n    if (BIT_endOfDStream(&bitD) && FSE_endOfDState(&state1) && FSE_endOfDState(&state2))\n        return op-ostart;\n\n    if (op==omax) return ERROR(dstSize_tooSmall);   /* dst buffer is full, but cSrc unfinished */\n\n    return ERROR(corruption_detected);\n}\n\n\nstatic size_t FSE_decompress_usingDTable(void* dst, size_t originalSize,\n                            const void* cSrc, size_t cSrcSize,\n                            const FSE_DTable* dt)\n{\n    FSE_DTableHeader DTableH;\n    U32 fastMode;\n\n    memcpy(&DTableH, dt, sizeof(DTableH));\n    fastMode = DTableH.fastMode;\n\n    /* select fast mode (static) */\n    if (fastMode) return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);\n    return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);\n}\n\n\nstatic size_t FSE_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)\n{\n    const BYTE* const istart = (const BYTE*)cSrc;\n    const BYTE* ip = istart;\n    short counting[FSE_MAX_SYMBOL_VALUE+1];\n    DTable_max_t dt;   /* Static analyzer seems unable to understand this table will be properly initialized later */\n    unsigned tableLog;\n    unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;\n    size_t errorCode;\n\n    if (cSrcSize<2) return ERROR(srcSize_wrong);   /* too small input size */\n\n    /* normal FSE decoding mode */\n    errorCode = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);\n    if (FSE_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);   /* too small input size */\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    errorCode = FSE_buildDTable (dt, counting, maxSymbolValue, tableLog);\n    if (FSE_isError(errorCode)) return errorCode;\n\n    /* always return, even if it is an error code */\n    return FSE_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt);\n}\n\n\n\n#endif   /* FSE_COMMONDEFS_ONLY */\n\n\n/* ******************************************************************\n   Huff0 : Huffman coder, part of New Generation Entropy library\n   header file\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef HUFF0_H\n#define HUFF0_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/* ****************************************\n*  Dependency\n******************************************/\n#include <stddef.h>    /* size_t */\n\n\n/* ****************************************\n*  Huff0 simple functions\n******************************************/\nstatic size_t HUF_decompress(void* dst,  size_t dstSize,\n                const void* cSrc, size_t cSrcSize);\n/*!\nHUF_decompress():\n    Decompress Huff0 data from buffer 'cSrc', of size 'cSrcSize',\n    into already allocated destination buffer 'dst', of size 'dstSize'.\n    'dstSize' must be the exact size of original (uncompressed) data.\n    Note : in contrast with FSE, HUF_decompress can regenerate RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data, because it knows size to regenerate.\n    @return : size of regenerated data (== dstSize)\n              or an error code, which can be tested using HUF_isError()\n*/\n\n\n/* ****************************************\n*  Tool functions\n******************************************/\n/* Error Management */\nstatic unsigned    HUF_isError(size_t code);        /* tells if a return value is an error code */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif   /* HUFF0_H */\n\n\n/* ******************************************************************\n   Huff0 : Huffman coder, part of New Generation Entropy library\n   header file for static linking (only)\n   Copyright (C) 2013-2015, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef HUFF0_STATIC_H\n#define HUFF0_STATIC_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n\n/* ****************************************\n*  Static allocation macros\n******************************************/\n/* static allocation of Huff0's DTable */\n#define HUF_DTABLE_SIZE(maxTableLog)   (1 + (1<<maxTableLog))  /* nb Cells; use unsigned short for X2, unsigned int for X4 */\n#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \\\n        unsigned short DTable[HUF_DTABLE_SIZE(maxTableLog)] = { maxTableLog }\n#define HUF_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \\\n        unsigned int DTable[HUF_DTABLE_SIZE(maxTableLog)] = { maxTableLog }\n#define HUF_CREATE_STATIC_DTABLEX6(DTable, maxTableLog) \\\n        unsigned int DTable[HUF_DTABLE_SIZE(maxTableLog) * 3 / 2] = { maxTableLog }\n\n\n/* ****************************************\n*  Advanced decompression functions\n******************************************/\nstatic size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */\nstatic size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbols decoder */\n\n\n/* ****************************************\n*  Huff0 detailed API\n******************************************/\n/*!\nHUF_decompress() does the following:\n1. select the decompression algorithm (X2, X4, X6) based on pre-computed heuristics\n2. build Huffman table from save, using HUF_readDTableXn()\n3. decode 1 or 4 segments in parallel using HUF_decompressSXn_usingDTable\n\n*/\nstatic size_t HUF_readDTableX2 (unsigned short* DTable, const void* src, size_t srcSize);\nstatic size_t HUF_readDTableX4 (unsigned* DTable, const void* src, size_t srcSize);\n\nstatic size_t HUF_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable);\nstatic size_t HUF_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable);\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* HUFF0_STATIC_H */\n\n\n\n/* ******************************************************************\n   Huff0 : Huffman coder, part of New Generation Entropy library\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE+Huff0 source repository : https://github.com/Cyan4973/FiniteStateEntropy\n****************************************************************** */\n\n/* **************************************************************\n*  Compiler specifics\n****************************************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n/* inline is defined */\n#elif defined(_MSC_VER)\n#  define inline __inline\n#else\n#  define inline /* disable inline */\n#endif\n\n\n#ifdef _MSC_VER    /* Visual Studio */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#endif\n\n\n/* **************************************************************\n*  Includes\n****************************************************************/\n#include <stdlib.h>     /* malloc, free, qsort */\n#include <string.h>     /* memcpy, memset */\n#include <stdio.h>      /* printf (debug) */\n\n\n/* **************************************************************\n*  Constants\n****************************************************************/\n#define HUF_ABSOLUTEMAX_TABLELOG  16   /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */\n#define HUF_MAX_TABLELOG  12           /* max configured tableLog (for static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */\n#define HUF_DEFAULT_TABLELOG  HUF_MAX_TABLELOG   /* tableLog by default, when not specified */\n#define HUF_MAX_SYMBOL_VALUE 255\n#if (HUF_MAX_TABLELOG > HUF_ABSOLUTEMAX_TABLELOG)\n#  error \"HUF_MAX_TABLELOG is too large !\"\n#endif\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\nstatic unsigned HUF_isError(size_t code) { return ERR_isError(code); }\n#define HUF_STATIC_ASSERT(c) { enum { HUF_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n\n/*-*******************************************************\n*  Huff0 : Huffman block decompression\n*********************************************************/\ntypedef struct { BYTE byte; BYTE nbBits; } HUF_DEltX2;   /* single-symbol decoding */\n\ntypedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX4;  /* double-symbols decoding */\n\ntypedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;\n\n/*! HUF_readStats\n    Read compact Huffman tree, saved by HUF_writeCTable\n    @huffWeight : destination buffer\n    @return : size read from `src`\n*/\nstatic size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                            U32* nbSymbolsPtr, U32* tableLogPtr,\n                            const void* src, size_t srcSize)\n{\n    U32 weightTotal;\n    U32 tableLog;\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize;\n    size_t oSize;\n    U32 n;\n\n    if (!srcSize) return ERROR(srcSize_wrong);\n    iSize = ip[0];\n    //memset(huffWeight, 0, hwSize);   /* is not necessary, even though some analyzer complain ... */\n\n    if (iSize >= 128)  /* special header */\n    {\n        if (iSize >= (242))   /* RLE */\n        {\n            static int l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };\n            oSize = l[iSize-242];\n            memset(huffWeight, 1, hwSize);\n            iSize = 0;\n        }\n        else   /* Incompressible */\n        {\n            oSize = iSize - 127;\n            iSize = ((oSize+1)/2);\n            if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n            if (oSize >= hwSize) return ERROR(corruption_detected);\n            ip += 1;\n            for (n=0; n<oSize; n+=2)\n            {\n                huffWeight[n]   = ip[n/2] >> 4;\n                huffWeight[n+1] = ip[n/2] & 15;\n            }\n        }\n    }\n    else  /* header compressed with FSE (normal case) */\n    {\n        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n        oSize = FSE_decompress(huffWeight, hwSize-1, ip+1, iSize);   /* max (hwSize-1) values decoded, as last one is implied */\n        if (FSE_isError(oSize)) return oSize;\n    }\n\n    /* collect weight stats */\n    memset(rankStats, 0, (HUF_ABSOLUTEMAX_TABLELOG + 1) * sizeof(U32));\n    weightTotal = 0;\n    for (n=0; n<oSize; n++)\n    {\n        if (huffWeight[n] >= HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);\n        rankStats[huffWeight[n]]++;\n        weightTotal += (1 << huffWeight[n]) >> 1;\n    }\n    if (weightTotal == 0) return ERROR(corruption_detected);\n\n    /* get last non-null symbol weight (implied, total must be 2^n) */\n    tableLog = BIT_highbit32(weightTotal) + 1;\n    if (tableLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);\n    {\n        U32 total = 1 << tableLog;\n        U32 rest = total - weightTotal;\n        U32 verif = 1 << BIT_highbit32(rest);\n        U32 lastWeight = BIT_highbit32(rest) + 1;\n        if (verif != rest) return ERROR(corruption_detected);    /* last value must be a clean power of 2 */\n        huffWeight[oSize] = (BYTE)lastWeight;\n        rankStats[lastWeight]++;\n    }\n\n    /* check tree construction validity */\n    if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected);   /* by construction : at least 2 elts of rank 1, must be even */\n\n    /* results */\n    *nbSymbolsPtr = (U32)(oSize+1);\n    *tableLogPtr = tableLog;\n    return iSize+1;\n}\n\n\n/**************************/\n/* single-symbol decoding */\n/**************************/\n\nstatic size_t HUF_readDTableX2 (U16* DTable, const void* src, size_t srcSize)\n{\n    BYTE huffWeight[HUF_MAX_SYMBOL_VALUE + 1];\n    U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];   /* large enough for values from 0 to 16 */\n    U32 tableLog = 0;\n    size_t iSize;\n    U32 nbSymbols = 0;\n    U32 n;\n    U32 nextRankStart;\n    void* const dtPtr = DTable + 1;\n    HUF_DEltX2* const dt = (HUF_DEltX2*)dtPtr;\n\n    HUF_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(U16));   /* if compilation fails here, assertion is false */\n    //memset(huffWeight, 0, sizeof(huffWeight));   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUF_readStats(huffWeight, HUF_MAX_SYMBOL_VALUE + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);\n    if (HUF_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > DTable[0]) return ERROR(tableLog_tooLarge);   /* DTable is too small */\n    DTable[0] = (U16)tableLog;   /* maybe should separate sizeof DTable, as allocated, from used size of DTable, in case of DTable re-use */\n\n    /* Prepare ranks */\n    nextRankStart = 0;\n    for (n=1; n<=tableLog; n++)\n    {\n        U32 current = nextRankStart;\n        nextRankStart += (rankVal[n] << (n-1));\n        rankVal[n] = current;\n    }\n\n    /* fill DTable */\n    for (n=0; n<nbSymbols; n++)\n    {\n        const U32 w = huffWeight[n];\n        const U32 length = (1 << w) >> 1;\n        U32 i;\n        HUF_DEltX2 D;\n        D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w);\n        for (i = rankVal[w]; i < rankVal[w] + length; i++)\n            dt[i] = D;\n        rankVal[w] += length;\n    }\n\n    return iSize;\n}\n\nstatic BYTE HUF_decodeSymbolX2(BIT_DStream_t* Dstream, const HUF_DEltX2* dt, const U32 dtLog)\n{\n        const size_t val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */\n        const BYTE c = dt[val].byte;\n        BIT_skipBits(Dstream, dt[val].nbBits);\n        return c;\n}\n\n#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \\\n    *ptr++ = HUF_decodeSymbolX2(DStreamPtr, dt, dtLog)\n\n#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \\\n        HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\n#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\nstatic inline size_t HUF_decodeStreamX2(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX2* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 4 symbols at a time */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-4))\n    {\n        HUF_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX2_1(p, bitDPtr);\n        HUF_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n    }\n\n    /* closer to the end */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd))\n        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    /* no more data to retrieve from bitstream, hence no need to reload */\n    while (p < pEnd)\n        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    return pEnd-pStart;\n}\n\n\nstatic size_t HUF_decompress4X2_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U16* DTable)\n{\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n\n    {\n        const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        const void* const dtPtr = DTable;\n        const HUF_DEltX2* const dt = ((const HUF_DEltX2*)dtPtr) +1;\n        const U32 dtLog = DTable[0];\n        size_t errorCode;\n\n        /* Init */\n        BIT_DStream_t bitD1;\n        BIT_DStream_t bitD2;\n        BIT_DStream_t bitD3;\n        BIT_DStream_t bitD4;\n        const size_t length1 = MEM_readLE16(istart);\n        const size_t length2 = MEM_readLE16(istart+2);\n        const size_t length3 = MEM_readLE16(istart+4);\n        size_t length4;\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n\n        length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        errorCode = BIT_initDStream(&bitD1, istart1, length1);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD2, istart2, length2);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD3, istart3, length3);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD4, istart4, length4);\n        if (HUF_isError(errorCode)) return errorCode;\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        for ( ; (endSignal==BIT_DStream_unfinished) && (op4<(oend-7)) ; )\n        {\n            HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_1(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_1(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_1(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_1(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_0(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_0(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_0(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_0(op4, &bitD4);\n\n            endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);\n        HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);\n        HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);\n        HUF_decodeStreamX2(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nstatic size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n    size_t errorCode;\n\n    errorCode = HUF_readDTableX2 (DTable, cSrc, cSrcSize);\n    if (HUF_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    return HUF_decompress4X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\n/***************************/\n/* double-symbols decoding */\n/***************************/\n\nstatic void HUF_fillDTableX4Level2(HUF_DEltX4* DTable, U32 sizeLog, const U32 consumed,\n                           const U32* rankValOrigin, const int minWeight,\n                           const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,\n                           U32 nbBitsBaseline, U16 baseSeq)\n{\n    HUF_DEltX4 DElt;\n    U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];\n    U32 s;\n\n    /* get pre-calculated rankVal */\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill skipped values */\n    if (minWeight>1)\n    {\n        U32 i, skipSize = rankVal[minWeight];\n        MEM_writeLE16(&(DElt.sequence), baseSeq);\n        DElt.nbBits   = (BYTE)(consumed);\n        DElt.length   = 1;\n        for (i = 0; i < skipSize; i++)\n            DTable[i] = DElt;\n    }\n\n    /* fill DTable */\n    for (s=0; s<sortedListSize; s++)   /* note : sortedSymbols already skipped */\n    {\n        const U32 symbol = sortedSymbols[s].symbol;\n        const U32 weight = sortedSymbols[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 length = 1 << (sizeLog-nbBits);\n        const U32 start = rankVal[weight];\n        U32 i = start;\n        const U32 end = start + length;\n\n        MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));\n        DElt.nbBits = (BYTE)(nbBits + consumed);\n        DElt.length = 2;\n        do { DTable[i++] = DElt; } while (i<end);   /* since length >= 1 */\n\n        rankVal[weight] += length;\n    }\n}\n\ntypedef U32 rankVal_t[HUF_ABSOLUTEMAX_TABLELOG][HUF_ABSOLUTEMAX_TABLELOG + 1];\n\nstatic void HUF_fillDTableX4(HUF_DEltX4* DTable, const U32 targetLog,\n                           const sortedSymbol_t* sortedList, const U32 sortedListSize,\n                           const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,\n                           const U32 nbBitsBaseline)\n{\n    U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];\n    const int scaleLog = nbBitsBaseline - targetLog;   /* note : targetLog >= srcLog, hence scaleLog <= 1 */\n    const U32 minBits  = nbBitsBaseline - maxWeight;\n    U32 s;\n\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill DTable */\n    for (s=0; s<sortedListSize; s++)\n    {\n        const U16 symbol = sortedList[s].symbol;\n        const U32 weight = sortedList[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 start = rankVal[weight];\n        const U32 length = 1 << (targetLog-nbBits);\n\n        if (targetLog-nbBits >= minBits)   /* enough room for a second symbol */\n        {\n            U32 sortedRank;\n            int minWeight = nbBits + scaleLog;\n            if (minWeight < 1) minWeight = 1;\n            sortedRank = rankStart[minWeight];\n            HUF_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits,\n                           rankValOrigin[nbBits], minWeight,\n                           sortedList+sortedRank, sortedListSize-sortedRank,\n                           nbBitsBaseline, symbol);\n        }\n        else\n        {\n            U32 i;\n            const U32 end = start + length;\n            HUF_DEltX4 DElt;\n\n            MEM_writeLE16(&(DElt.sequence), symbol);\n            DElt.nbBits   = (BYTE)(nbBits);\n            DElt.length   = 1;\n            for (i = start; i < end; i++)\n                DTable[i] = DElt;\n        }\n        rankVal[weight] += length;\n    }\n}\n\nstatic size_t HUF_readDTableX4 (U32* DTable, const void* src, size_t srcSize)\n{\n    BYTE weightList[HUF_MAX_SYMBOL_VALUE + 1];\n    sortedSymbol_t sortedSymbol[HUF_MAX_SYMBOL_VALUE + 1];\n    U32 rankStats[HUF_ABSOLUTEMAX_TABLELOG + 1] = { 0 };\n    U32 rankStart0[HUF_ABSOLUTEMAX_TABLELOG + 2] = { 0 };\n    U32* const rankStart = rankStart0+1;\n    rankVal_t rankVal;\n    U32 tableLog, maxW, sizeOfSort, nbSymbols;\n    const U32 memLog = DTable[0];\n    size_t iSize;\n    void* dtPtr = DTable;\n    HUF_DEltX4* const dt = ((HUF_DEltX4*)dtPtr) + 1;\n\n    HUF_STATIC_ASSERT(sizeof(HUF_DEltX4) == sizeof(U32));   /* if compilation fails here, assertion is false */\n    if (memLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge);\n    //memset(weightList, 0, sizeof(weightList));   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUF_readStats(weightList, HUF_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);\n    if (HUF_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > memLog) return ERROR(tableLog_tooLarge);   /* DTable can't fit code depth */\n\n    /* find maxWeight */\n    for (maxW = tableLog; rankStats[maxW]==0; maxW--)\n        { if (!maxW) return ERROR(GENERIC); }  /* necessarily finds a solution before maxW==0 */\n\n    /* Get start index of each weight */\n    {\n        U32 w, nextRankStart = 0;\n        for (w=1; w<=maxW; w++)\n        {\n            U32 current = nextRankStart;\n            nextRankStart += rankStats[w];\n            rankStart[w] = current;\n        }\n        rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/\n        sizeOfSort = nextRankStart;\n    }\n\n    /* sort symbols by weight */\n    {\n        U32 s;\n        for (s=0; s<nbSymbols; s++)\n        {\n            U32 w = weightList[s];\n            U32 r = rankStart[w]++;\n            sortedSymbol[r].symbol = (BYTE)s;\n            sortedSymbol[r].weight = (BYTE)w;\n        }\n        rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */\n    }\n\n    /* Build rankVal */\n    {\n        const U32 minBits = tableLog+1 - maxW;\n        U32 nextRankVal = 0;\n        U32 w, consumed;\n        const int rescale = (memLog-tableLog) - 1;   /* tableLog <= memLog */\n        U32* rankVal0 = rankVal[0];\n        for (w=1; w<=maxW; w++)\n        {\n            U32 current = nextRankVal;\n            nextRankVal += rankStats[w] << (w+rescale);\n            rankVal0[w] = current;\n        }\n        for (consumed = minBits; consumed <= memLog - minBits; consumed++)\n        {\n            U32* rankValPtr = rankVal[consumed];\n            for (w = 1; w <= maxW; w++)\n            {\n                rankValPtr[w] = rankVal0[w] >> consumed;\n            }\n        }\n    }\n\n    HUF_fillDTableX4(dt, memLog,\n                   sortedSymbol, sizeOfSort,\n                   rankStart0, rankVal, maxW,\n                   tableLog+1);\n\n    return iSize;\n}\n\n\nstatic U32 HUF_decodeSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 2);\n    BIT_skipBits(DStream, dt[val].nbBits);\n    return dt[val].length;\n}\n\nstatic U32 HUF_decodeLastSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 1);\n    if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits);\n    else\n    {\n        if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8))\n        {\n            BIT_skipBits(DStream, dt[val].nbBits);\n            if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))\n                DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);   /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */\n        }\n    }\n    return 1;\n}\n\n\n#define HUF_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \\\n    ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUF_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \\\n        ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUF_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\nstatic inline size_t HUF_decodeStreamX4(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd, const HUF_DEltX4* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 8 symbols at a time */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd-7))\n    {\n        HUF_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX4_1(p, bitDPtr);\n        HUF_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX4_0(p, bitDPtr);\n    }\n\n    /* closer to the end */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-2))\n        HUF_DECODE_SYMBOLX4_0(p, bitDPtr);\n\n    while (p <= pEnd-2)\n        HUF_DECODE_SYMBOLX4_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */\n\n    if (p < pEnd)\n        p += HUF_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);\n\n    return p-pStart;\n}\n\nstatic size_t HUF_decompress4X4_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U32* DTable)\n{\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n\n    {\n        const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        const void* const dtPtr = DTable;\n        const HUF_DEltX4* const dt = ((const HUF_DEltX4*)dtPtr) +1;\n        const U32 dtLog = DTable[0];\n        size_t errorCode;\n\n        /* Init */\n        BIT_DStream_t bitD1;\n        BIT_DStream_t bitD2;\n        BIT_DStream_t bitD3;\n        BIT_DStream_t bitD4;\n        const size_t length1 = MEM_readLE16(istart);\n        const size_t length2 = MEM_readLE16(istart+2);\n        const size_t length3 = MEM_readLE16(istart+4);\n        size_t length4;\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n\n        length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        errorCode = BIT_initDStream(&bitD1, istart1, length1);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD2, istart2, length2);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD3, istart3, length3);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD4, istart4, length4);\n        if (HUF_isError(errorCode)) return errorCode;\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        for ( ; (endSignal==BIT_DStream_unfinished) && (op4<(oend-7)) ; )\n        {\n            HUF_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX4_1(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_1(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_1(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_1(op4, &bitD4);\n            HUF_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX4_0(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_0(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_0(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_0(op4, &bitD4);\n\n            endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUF_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);\n        HUF_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);\n        HUF_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);\n        HUF_decodeStreamX4(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nstatic size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUF_CREATE_STATIC_DTABLEX4(DTable, HUF_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t hSize = HUF_readDTableX4 (DTable, cSrc, cSrcSize);\n    if (HUF_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize;\n    cSrcSize -= hSize;\n\n    return HUF_decompress4X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\n/**********************************/\n/* Generic decompression selector */\n/**********************************/\n\ntypedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;\nstatic const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =\n{\n    /* single, double, quad */\n    {{0,0}, {1,1}, {2,2}},  /* Q==0 : impossible */\n    {{0,0}, {1,1}, {2,2}},  /* Q==1 : impossible */\n    {{  38,130}, {1313, 74}, {2151, 38}},   /* Q == 2 : 12-18% */\n    {{ 448,128}, {1353, 74}, {2238, 41}},   /* Q == 3 : 18-25% */\n    {{ 556,128}, {1353, 74}, {2238, 47}},   /* Q == 4 : 25-32% */\n    {{ 714,128}, {1418, 74}, {2436, 53}},   /* Q == 5 : 32-38% */\n    {{ 883,128}, {1437, 74}, {2464, 61}},   /* Q == 6 : 38-44% */\n    {{ 897,128}, {1515, 75}, {2622, 68}},   /* Q == 7 : 44-50% */\n    {{ 926,128}, {1613, 75}, {2730, 75}},   /* Q == 8 : 50-56% */\n    {{ 947,128}, {1729, 77}, {3359, 77}},   /* Q == 9 : 56-62% */\n    {{1107,128}, {2083, 81}, {4006, 84}},   /* Q ==10 : 62-69% */\n    {{1177,128}, {2379, 87}, {4785, 88}},   /* Q ==11 : 69-75% */\n    {{1242,128}, {2415, 93}, {5155, 84}},   /* Q ==12 : 75-81% */\n    {{1349,128}, {2644,106}, {5260,106}},   /* Q ==13 : 81-87% */\n    {{1455,128}, {2422,124}, {4174,124}},   /* Q ==14 : 87-93% */\n    {{ 722,128}, {1891,145}, {1936,146}},   /* Q ==15 : 93-99% */\n};\n\ntypedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);\n\nstatic size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    static const decompressionAlgo decompress[3] = { HUF_decompress4X2, HUF_decompress4X4, NULL };\n    /* estimate decompression time */\n    U32 Q;\n    const U32 D256 = (U32)(dstSize >> 8);\n    U32 Dtime[3];\n    U32 algoNb = 0;\n    int n;\n\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */\n    if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */\n    if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */\n\n    /* decoder timing evaluation */\n    Q = (U32)(cSrcSize * 16 / dstSize);   /* Q < 16 since dstSize > cSrcSize */\n    for (n=0; n<3; n++)\n        Dtime[n] = algoTime[Q][n].tableTime + (algoTime[Q][n].decode256Time * D256);\n\n    Dtime[1] += Dtime[1] >> 4; Dtime[2] += Dtime[2] >> 3; /* advantage to algorithms using less memory, for cache eviction */\n\n    if (Dtime[1] < Dtime[0]) algoNb = 1;\n\n    return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);\n\n    //return HUF_decompress4X2(dst, dstSize, cSrc, cSrcSize);   /* multi-streams single-symbol decoding */\n    //return HUF_decompress4X4(dst, dstSize, cSrc, cSrcSize);   /* multi-streams double-symbols decoding */\n    //return HUF_decompress4X6(dst, dstSize, cSrc, cSrcSize);   /* multi-streams quad-symbols decoding */\n}\n\n\n\n#endif   /* ZSTD_CCOMMON_H_MODULE */\n\n\n/*\n    zstd - decompression module fo v0.4 legacy format\n    Copyright (C) 2015-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n    - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n\n/* ***************************************************************\n*  Tuning parameters\n*****************************************************************/\n/*!\n * HEAPMODE :\n * Select how default decompression function ZSTD_decompress() will allocate memory,\n * in memory stack (0), or in memory heap (1, requires malloc())\n */\n#ifndef ZSTD_HEAPMODE\n#  define ZSTD_HEAPMODE 1\n#endif\n\n\n/* *******************************************************\n*  Includes\n*********************************************************/\n#include <stdlib.h>      /* calloc */\n#include <string.h>      /* memcpy, memmove */\n#include <stdio.h>       /* debug : printf */\n\n\n/* *******************************************************\n*  Compiler specifics\n*********************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4324)        /* disable: C4324: padded structure */\n#endif\n\n\n/* *************************************\n*  Local types\n***************************************/\ntypedef struct\n{\n    blockType_t blockType;\n    U32 origSize;\n} blockProperties_t;\n\n\n/* *******************************************************\n*  Memory operations\n**********************************************************/\nstatic void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }\n\n\n/* *************************************\n*  Error Management\n***************************************/\n\n/*! ZSTD_isError\n*   tells if a return value is an error code */\nstatic unsigned ZSTD_isError(size_t code) { return ERR_isError(code); }\n\n\n/* *************************************************************\n*   Context management\n***************************************************************/\ntypedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,\n               ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock } ZSTD_dStage;\n\nstruct ZSTDv04_Dctx_s\n{\n    U32 LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];\n    U32 OffTable[FSE_DTABLE_SIZE_U32(OffFSELog)];\n    U32 MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];\n    const void* previousDstEnd;\n    const void* base;\n    const void* vBase;\n    const void* dictEnd;\n    size_t expected;\n    size_t headerSize;\n    ZSTD_parameters params;\n    blockType_t bType;\n    ZSTD_dStage stage;\n    const BYTE* litPtr;\n    size_t litSize;\n    BYTE litBuffer[BLOCKSIZE + 8 /* margin for wildcopy */];\n    BYTE headerBuffer[ZSTD_frameHeaderSize_max];\n};  /* typedef'd to ZSTD_DCtx within \"zstd_static.h\" */\n\nstatic size_t ZSTD_resetDCtx(ZSTD_DCtx* dctx)\n{\n    dctx->expected = ZSTD_frameHeaderSize_min;\n    dctx->stage = ZSTDds_getFrameHeaderSize;\n    dctx->previousDstEnd = NULL;\n    dctx->base = NULL;\n    dctx->vBase = NULL;\n    dctx->dictEnd = NULL;\n    return 0;\n}\n\nstatic ZSTD_DCtx* ZSTD_createDCtx(void)\n{\n    ZSTD_DCtx* dctx = (ZSTD_DCtx*)malloc(sizeof(ZSTD_DCtx));\n    if (dctx==NULL) return NULL;\n    ZSTD_resetDCtx(dctx);\n    return dctx;\n}\n\nstatic size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)\n{\n    free(dctx);\n    return 0;\n}\n\n\n/* *************************************************************\n*   Decompression section\n***************************************************************/\n/** ZSTD_decodeFrameHeader_Part1\n*   decode the 1st part of the Frame Header, which tells Frame Header size.\n*   srcSize must be == ZSTD_frameHeaderSize_min\n*   @return : the full size of the Frame Header */\nstatic size_t ZSTD_decodeFrameHeader_Part1(ZSTD_DCtx* zc, const void* src, size_t srcSize)\n{\n    U32 magicNumber;\n    if (srcSize != ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong);\n    magicNumber = MEM_readLE32(src);\n    if (magicNumber != ZSTD_MAGICNUMBER) return ERROR(prefix_unknown);\n    zc->headerSize = ZSTD_frameHeaderSize_min;\n    return zc->headerSize;\n}\n\n\nstatic size_t ZSTD_getFrameParams(ZSTD_parameters* params, const void* src, size_t srcSize)\n{\n    U32 magicNumber;\n    if (srcSize < ZSTD_frameHeaderSize_min) return ZSTD_frameHeaderSize_max;\n    magicNumber = MEM_readLE32(src);\n    if (magicNumber != ZSTD_MAGICNUMBER) return ERROR(prefix_unknown);\n    memset(params, 0, sizeof(*params));\n    params->windowLog = (((const BYTE*)src)[4] & 15) + ZSTD_WINDOWLOG_ABSOLUTEMIN;\n    if ((((const BYTE*)src)[4] >> 4) != 0) return ERROR(frameParameter_unsupported);   /* reserved bits */\n    return 0;\n}\n\n/** ZSTD_decodeFrameHeader_Part2\n*   decode the full Frame Header\n*   srcSize must be the size provided by ZSTD_decodeFrameHeader_Part1\n*   @return : 0, or an error code, which can be tested using ZSTD_isError() */\nstatic size_t ZSTD_decodeFrameHeader_Part2(ZSTD_DCtx* zc, const void* src, size_t srcSize)\n{\n    size_t result;\n    if (srcSize != zc->headerSize) return ERROR(srcSize_wrong);\n    result = ZSTD_getFrameParams(&(zc->params), src, srcSize);\n    if ((MEM_32bits()) && (zc->params.windowLog > 25)) return ERROR(frameParameter_unsupported);\n    return result;\n}\n\n\nstatic size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)\n{\n    const BYTE* const in = (const BYTE* const)src;\n    BYTE headerFlags;\n    U32 cSize;\n\n    if (srcSize < 3) return ERROR(srcSize_wrong);\n\n    headerFlags = *in;\n    cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);\n\n    bpPtr->blockType = (blockType_t)(headerFlags >> 6);\n    bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;\n\n    if (bpPtr->blockType == bt_end) return 0;\n    if (bpPtr->blockType == bt_rle) return 1;\n    return cSize;\n}\n\nstatic size_t ZSTD_copyRawBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall);\n    if (srcSize > 0) {\n        memcpy(dst, src, srcSize);\n    }\n    return srcSize;\n}\n\n\n/** ZSTD_decompressLiterals\n    @return : nb of bytes read from src, or an error code*/\nstatic size_t ZSTD_decompressLiterals(void* dst, size_t* maxDstSizePtr,\n                                const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n\n    const size_t litSize = (MEM_readLE32(src) & 0x1FFFFF) >> 2;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n    const size_t litCSize = (MEM_readLE32(ip+2) & 0xFFFFFF) >> 5;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n\n    if (litSize > *maxDstSizePtr) return ERROR(corruption_detected);\n    if (litCSize + 5 > srcSize) return ERROR(corruption_detected);\n\n    if (HUF_isError(HUF_decompress(dst, litSize, ip+5, litCSize))) return ERROR(corruption_detected);\n\n    *maxDstSizePtr = litSize;\n    return litCSize + 5;\n}\n\n\n/** ZSTD_decodeLiteralsBlock\n    @return : nb of bytes read from src (< srcSize ) */\nstatic size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,\n                          const void* src, size_t srcSize)   /* note : srcSize < BLOCKSIZE */\n{\n    const BYTE* const istart = (const BYTE*) src;\n\n    /* any compressed block with literals segment must be at least this size */\n    if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);\n\n    switch(*istart & 3)\n    {\n    /* compressed */\n    case 0:\n        {\n            size_t litSize = BLOCKSIZE;\n            const size_t readSize = ZSTD_decompressLiterals(dctx->litBuffer, &litSize, src, srcSize);\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            memset(dctx->litBuffer + dctx->litSize, 0, 8);\n            return readSize;   /* works if it's an error too */\n        }\n    case IS_RAW:\n        {\n            const size_t litSize = (MEM_readLE32(istart) & 0xFFFFFF) >> 2;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n            if (litSize > srcSize-11)   /* risk of reading too far with wildcopy */\n            {\n                if (litSize > BLOCKSIZE) return ERROR(corruption_detected);\n                if (litSize > srcSize-3) return ERROR(corruption_detected);\n                memcpy(dctx->litBuffer, istart, litSize);\n                dctx->litPtr = dctx->litBuffer;\n                dctx->litSize = litSize;\n                memset(dctx->litBuffer + dctx->litSize, 0, 8);\n                return litSize+3;\n            }\n            /* direct reference into compressed stream */\n            dctx->litPtr = istart+3;\n            dctx->litSize = litSize;\n            return litSize+3;        }\n    case IS_RLE:\n        {\n            const size_t litSize = (MEM_readLE32(istart) & 0xFFFFFF) >> 2;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n            if (litSize > BLOCKSIZE) return ERROR(corruption_detected);\n            memset(dctx->litBuffer, istart[3], litSize + 8);\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            return 4;\n        }\n    default:\n        return ERROR(corruption_detected);   /* forbidden nominal case */\n    }\n}\n\n\nstatic size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLengthPtr,\n                         FSE_DTable* DTableLL, FSE_DTable* DTableML, FSE_DTable* DTableOffb,\n                         const void* src, size_t srcSize)\n{\n    const BYTE* const istart = (const BYTE* const)src;\n    const BYTE* ip = istart;\n    const BYTE* const iend = istart + srcSize;\n    U32 LLtype, Offtype, MLtype;\n    U32 LLlog, Offlog, MLlog;\n    size_t dumpsLength;\n\n    /* check */\n    if (srcSize < 5) return ERROR(srcSize_wrong);\n\n    /* SeqHead */\n    *nbSeq = MEM_readLE16(ip); ip+=2;\n    LLtype  = *ip >> 6;\n    Offtype = (*ip >> 4) & 3;\n    MLtype  = (*ip >> 2) & 3;\n    if (*ip & 2)\n    {\n        dumpsLength  = ip[2];\n        dumpsLength += ip[1] << 8;\n        ip += 3;\n    }\n    else\n    {\n        dumpsLength  = ip[1];\n        dumpsLength += (ip[0] & 1) << 8;\n        ip += 2;\n    }\n    *dumpsPtr = ip;\n    ip += dumpsLength;\n    *dumpsLengthPtr = dumpsLength;\n\n    /* check */\n    if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are \"raw\", hence no header, but at least xxLog bits per type */\n\n    /* sequences */\n    {\n        S16 norm[MaxML+1];    /* assumption : MaxML >= MaxLL >= MaxOff */\n        size_t headerSize;\n\n        /* Build DTables */\n        switch(LLtype)\n        {\n        case bt_rle :\n            LLlog = 0;\n            FSE_buildDTable_rle(DTableLL, *ip++); break;\n        case bt_raw :\n            LLlog = LLbits;\n            FSE_buildDTable_raw(DTableLL, LLbits); break;\n        default :\n            {   U32 max = MaxLL;\n                headerSize = FSE_readNCount(norm, &max, &LLlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (LLlog > LLFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableLL, norm, max, LLlog);\n        }   }\n\n        switch(Offtype)\n        {\n        case bt_rle :\n            Offlog = 0;\n            if (ip > iend-2) return ERROR(srcSize_wrong);   /* min : \"raw\", hence no header, but at least xxLog bits */\n            FSE_buildDTable_rle(DTableOffb, *ip++ & MaxOff); /* if *ip > MaxOff, data is corrupted */\n            break;\n        case bt_raw :\n            Offlog = Offbits;\n            FSE_buildDTable_raw(DTableOffb, Offbits); break;\n        default :\n            {   U32 max = MaxOff;\n                headerSize = FSE_readNCount(norm, &max, &Offlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (Offlog > OffFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableOffb, norm, max, Offlog);\n        }   }\n\n        switch(MLtype)\n        {\n        case bt_rle :\n            MLlog = 0;\n            if (ip > iend-2) return ERROR(srcSize_wrong); /* min : \"raw\", hence no header, but at least xxLog bits */\n            FSE_buildDTable_rle(DTableML, *ip++); break;\n        case bt_raw :\n            MLlog = MLbits;\n            FSE_buildDTable_raw(DTableML, MLbits); break;\n        default :\n            {   U32 max = MaxML;\n                headerSize = FSE_readNCount(norm, &max, &MLlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (MLlog > MLFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableML, norm, max, MLlog);\n    }   }   }\n\n    return ip-istart;\n}\n\n\ntypedef struct {\n    size_t litLength;\n    size_t offset;\n    size_t matchLength;\n} seq_t;\n\ntypedef struct {\n    BIT_DStream_t DStream;\n    FSE_DState_t stateLL;\n    FSE_DState_t stateOffb;\n    FSE_DState_t stateML;\n    size_t prevOffset;\n    const BYTE* dumps;\n    const BYTE* dumpsEnd;\n} seqState_t;\n\n\nstatic void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)\n{\n    size_t litLength;\n    size_t prevOffset;\n    size_t offset;\n    size_t matchLength;\n    const BYTE* dumps = seqState->dumps;\n    const BYTE* const de = seqState->dumpsEnd;\n\n    /* Literal length */\n    litLength = FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream));\n    prevOffset = litLength ? seq->offset : seqState->prevOffset;\n    if (litLength == MaxLL) {\n        const U32 add = dumps<de ? *dumps++ : 0;\n        if (add < 255) litLength += add;\n        else if (dumps + 3 <= de) {\n            litLength = MEM_readLE24(dumps);\n            dumps += 3;\n        }\n        if (dumps >= de) { dumps = de-1; }  /* late correction, to avoid read overflow (data is now corrupted anyway) */\n    }\n\n    /* Offset */\n    {   static const U32 offsetPrefix[MaxOff+1] = {\n                1 /*fake*/, 1, 2, 4, 8, 16, 32, 64, 128, 256,\n                512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144,\n                524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, /*fake*/ 1, 1, 1, 1, 1 };\n        U32 offsetCode, nbBits;\n        offsetCode = FSE_decodeSymbol(&(seqState->stateOffb), &(seqState->DStream));   /* <= maxOff, by table construction */\n        if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));\n        nbBits = offsetCode - 1;\n        if (offsetCode==0) nbBits = 0;   /* cmove */\n        offset = offsetPrefix[offsetCode] + BIT_readBits(&(seqState->DStream), nbBits);\n        if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));\n        if (offsetCode==0) offset = prevOffset;   /* cmove */\n        if (offsetCode | !litLength) seqState->prevOffset = seq->offset;   /* cmove */\n    }\n\n    /* MatchLength */\n    matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream));\n    if (matchLength == MaxML) {\n        const U32 add = dumps<de ? *dumps++ : 0;\n        if (add < 255) matchLength += add;\n        else if (dumps + 3 <= de){\n            matchLength = MEM_readLE24(dumps);\n            dumps += 3;\n        }\n        if (dumps >= de) { dumps = de-1; }  /* late correction, to avoid read overflow (data is now corrupted anyway) */\n    }\n    matchLength += MINMATCH;\n\n    /* save result */\n    seq->litLength = litLength;\n    seq->offset = offset;\n    seq->matchLength = matchLength;\n    seqState->dumps = dumps;\n}\n\n\nstatic size_t ZSTD_execSequence(BYTE* op,\n                                BYTE* const oend, seq_t sequence,\n                                const BYTE** litPtr, const BYTE* const litLimit,\n                                const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)\n{\n    static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 };   /* added */\n    static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 };   /* subtracted */\n    BYTE* const oLitEnd = op + sequence.litLength;\n    const size_t sequenceLength = sequence.litLength + sequence.matchLength;\n    BYTE* const oMatchEnd = op + sequenceLength;   /* risk : address space overflow (32-bits) */\n    BYTE* const oend_8 = oend-8;\n    const BYTE* const litEnd = *litPtr + sequence.litLength;\n    const BYTE* match = oLitEnd - sequence.offset;\n\n    /* checks */\n    size_t const seqLength = sequence.litLength + sequence.matchLength;\n\n    if (seqLength > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);\n    if (sequence.litLength > (size_t)(litLimit - *litPtr)) return ERROR(corruption_detected);\n    /* Now we know there are no overflow in literal nor match lengths, can use pointer checks */\n    if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall);\n\n    if (oMatchEnd > oend) return ERROR(dstSize_tooSmall);   /* overwrite beyond dst buffer */\n    if (litEnd > litLimit) return ERROR(corruption_detected);   /* overRead beyond lit buffer */\n\n    /* copy Literals */\n    ZSTD_wildcopy(op, *litPtr, (ptrdiff_t)sequence.litLength);   /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */\n    op = oLitEnd;\n    *litPtr = litEnd;   /* update for next sequence */\n\n    /* copy Match */\n    if (sequence.offset > (size_t)(oLitEnd - base))\n    {\n        /* offset beyond prefix */\n        if (sequence.offset > (size_t)(oLitEnd - vBase))\n            return ERROR(corruption_detected);\n        match = dictEnd - (base-match);\n        if (match + sequence.matchLength <= dictEnd)\n        {\n            memmove(oLitEnd, match, sequence.matchLength);\n            return sequenceLength;\n        }\n        /* span extDict & currentPrefixSegment */\n        {\n            size_t length1 = dictEnd - match;\n            memmove(oLitEnd, match, length1);\n            op = oLitEnd + length1;\n            sequence.matchLength -= length1;\n            match = base;\n            if (op > oend_8 || sequence.matchLength < MINMATCH) {\n              while (op < oMatchEnd) *op++ = *match++;\n              return sequenceLength;\n            }\n        }\n    }\n    /* Requirement: op <= oend_8 */\n\n    /* match within prefix */\n    if (sequence.offset < 8) {\n        /* close range match, overlap */\n        const int sub2 = dec64table[sequence.offset];\n        op[0] = match[0];\n        op[1] = match[1];\n        op[2] = match[2];\n        op[3] = match[3];\n        match += dec32table[sequence.offset];\n        ZSTD_copy4(op+4, match);\n        match -= sub2;\n    } else {\n        ZSTD_copy8(op, match);\n    }\n    op += 8; match += 8;\n\n    if (oMatchEnd > oend-(16-MINMATCH))\n    {\n        if (op < oend_8)\n        {\n            ZSTD_wildcopy(op, match, oend_8 - op);\n            match += oend_8 - op;\n            op = oend_8;\n        }\n        while (op < oMatchEnd) *op++ = *match++;\n    }\n    else\n    {\n        ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8);   /* works even if matchLength < 8, but must be signed */\n    }\n    return sequenceLength;\n}\n\n\nstatic size_t ZSTD_decompressSequences(\n                               ZSTD_DCtx* dctx,\n                               void* dst, size_t maxDstSize,\n                         const void* seqStart, size_t seqSize)\n{\n    const BYTE* ip = (const BYTE*)seqStart;\n    const BYTE* const iend = ip + seqSize;\n    BYTE* const ostart = (BYTE* const)dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + maxDstSize;\n    size_t errorCode, dumpsLength;\n    const BYTE* litPtr = dctx->litPtr;\n    const BYTE* const litEnd = litPtr + dctx->litSize;\n    int nbSeq;\n    const BYTE* dumps;\n    U32* DTableLL = dctx->LLTable;\n    U32* DTableML = dctx->MLTable;\n    U32* DTableOffb = dctx->OffTable;\n    const BYTE* const base = (const BYTE*) (dctx->base);\n    const BYTE* const vBase = (const BYTE*) (dctx->vBase);\n    const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);\n\n    /* Build Decoding Tables */\n    errorCode = ZSTD_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,\n                                      DTableLL, DTableML, DTableOffb,\n                                      ip, iend-ip);\n    if (ZSTD_isError(errorCode)) return errorCode;\n    ip += errorCode;\n\n    /* Regen sequences */\n    {\n        seq_t sequence;\n        seqState_t seqState;\n\n        memset(&sequence, 0, sizeof(sequence));\n        sequence.offset = 4;\n        seqState.dumps = dumps;\n        seqState.dumpsEnd = dumps + dumpsLength;\n        seqState.prevOffset = 4;\n        errorCode = BIT_initDStream(&(seqState.DStream), ip, iend-ip);\n        if (ERR_isError(errorCode)) return ERROR(corruption_detected);\n        FSE_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);\n        FSE_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);\n        FSE_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);\n\n        for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq ; )\n        {\n            size_t oneSeqSize;\n            nbSeq--;\n            ZSTD_decodeSequence(&sequence, &seqState);\n            oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);\n            if (ZSTD_isError(oneSeqSize)) return oneSeqSize;\n            op += oneSeqSize;\n        }\n\n        /* check if reached exact end */\n        if ( !BIT_endOfDStream(&(seqState.DStream)) ) return ERROR(corruption_detected);   /* DStream should be entirely and exactly consumed; otherwise data is corrupted */\n\n        /* last literal segment */\n        {\n            size_t lastLLSize = litEnd - litPtr;\n            if (litPtr > litEnd) return ERROR(corruption_detected);\n            if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);\n            if (lastLLSize > 0) {\n                if (op != litPtr) memcpy(op, litPtr, lastLLSize);\n                op += lastLLSize;\n            }\n        }\n    }\n\n    return op-ostart;\n}\n\n\nstatic void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst)\n{\n    if (dst != dctx->previousDstEnd)   /* not contiguous */\n    {\n        dctx->dictEnd = dctx->previousDstEnd;\n        dctx->vBase = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));\n        dctx->base = dst;\n        dctx->previousDstEnd = dst;\n    }\n}\n\n\nstatic size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,\n                            void* dst, size_t maxDstSize,\n                      const void* src, size_t srcSize)\n{\n    /* blockType == blockCompressed */\n    const BYTE* ip = (const BYTE*)src;\n    size_t litCSize;\n\n    if (srcSize > BLOCKSIZE) return ERROR(corruption_detected);\n\n    /* Decode literals sub-block */\n    litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);\n    if (ZSTD_isError(litCSize)) return litCSize;\n    ip += litCSize;\n    srcSize -= litCSize;\n\n    return ZSTD_decompressSequences(dctx, dst, maxDstSize, ip, srcSize);\n}\n\n\nstatic size_t ZSTD_decompress_usingDict(ZSTD_DCtx* ctx,\n                                 void* dst, size_t maxDstSize,\n                                 const void* src, size_t srcSize,\n                                 const void* dict, size_t dictSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n    const BYTE* iend = ip + srcSize;\n    BYTE* const ostart = (BYTE* const)dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + maxDstSize;\n    size_t remainingSize = srcSize;\n    blockProperties_t blockProperties;\n\n    /* init */\n    ZSTD_resetDCtx(ctx);\n    if (dict)\n    {\n        ZSTD_decompress_insertDictionary(ctx, dict, dictSize);\n        ctx->dictEnd = ctx->previousDstEnd;\n        ctx->vBase = (const char*)dst - ((const char*)(ctx->previousDstEnd) - (const char*)(ctx->base));\n        ctx->base = dst;\n    }\n    else\n    {\n        ctx->vBase = ctx->base = ctx->dictEnd = dst;\n    }\n\n    /* Frame Header */\n    {\n        size_t frameHeaderSize;\n        if (srcSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);\n        frameHeaderSize = ZSTD_decodeFrameHeader_Part1(ctx, src, ZSTD_frameHeaderSize_min);\n        if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;\n        if (srcSize < frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);\n        ip += frameHeaderSize; remainingSize -= frameHeaderSize;\n        frameHeaderSize = ZSTD_decodeFrameHeader_Part2(ctx, src, frameHeaderSize);\n        if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;\n    }\n\n    /* Loop on each block */\n    while (1)\n    {\n        size_t decodedSize=0;\n        size_t cBlockSize = ZSTD_getcBlockSize(ip, iend-ip, &blockProperties);\n        if (ZSTD_isError(cBlockSize)) return cBlockSize;\n\n        ip += ZSTD_blockHeaderSize;\n        remainingSize -= ZSTD_blockHeaderSize;\n        if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);\n\n        switch(blockProperties.blockType)\n        {\n        case bt_compressed:\n            decodedSize = ZSTD_decompressBlock_internal(ctx, op, oend-op, ip, cBlockSize);\n            break;\n        case bt_raw :\n            decodedSize = ZSTD_copyRawBlock(op, oend-op, ip, cBlockSize);\n            break;\n        case bt_rle :\n            return ERROR(GENERIC);   /* not yet supported */\n            break;\n        case bt_end :\n            /* end of frame */\n            if (remainingSize) return ERROR(srcSize_wrong);\n            break;\n        default:\n            return ERROR(GENERIC);   /* impossible */\n        }\n        if (cBlockSize == 0) break;   /* bt_end */\n\n        if (ZSTD_isError(decodedSize)) return decodedSize;\n        op += decodedSize;\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n    }\n\n    return op-ostart;\n}\n\n/* ZSTD_errorFrameSizeInfoLegacy() :\n   assumes `cSize` and `dBound` are _not_ NULL */\nstatic void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)\n{\n    *cSize = ret;\n    *dBound = ZSTD_CONTENTSIZE_ERROR;\n}\n\nvoid ZSTDv04_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)\n{\n    const BYTE* ip = (const BYTE*)src;\n    size_t remainingSize = srcSize;\n    size_t nbBlocks = 0;\n    blockProperties_t blockProperties;\n\n    /* Frame Header */\n    if (srcSize < ZSTD_frameHeaderSize_min) {\n        ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n        return;\n    }\n    if (MEM_readLE32(src) != ZSTD_MAGICNUMBER) {\n        ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));\n        return;\n    }\n    ip += ZSTD_frameHeaderSize_min; remainingSize -= ZSTD_frameHeaderSize_min;\n\n    /* Loop on each block */\n    while (1)\n    {\n        size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);\n        if (ZSTD_isError(cBlockSize)) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);\n            return;\n        }\n\n        ip += ZSTD_blockHeaderSize;\n        remainingSize -= ZSTD_blockHeaderSize;\n        if (cBlockSize > remainingSize) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n            return;\n        }\n\n        if (cBlockSize == 0) break;   /* bt_end */\n\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n        nbBlocks++;\n    }\n\n    *cSize = ip - (const BYTE*)src;\n    *dBound = nbBlocks * BLOCKSIZE;\n}\n\n/* ******************************\n*  Streaming Decompression API\n********************************/\nstatic size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx)\n{\n    return dctx->expected;\n}\n\nstatic size_t ZSTD_decompressContinue(ZSTD_DCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    /* Sanity check */\n    if (srcSize != ctx->expected) return ERROR(srcSize_wrong);\n    ZSTD_checkContinuity(ctx, dst);\n\n    /* Decompress : frame header; part 1 */\n    switch (ctx->stage)\n    {\n    case ZSTDds_getFrameHeaderSize :\n        /* get frame header size */\n        if (srcSize != ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong);   /* impossible */\n        ctx->headerSize = ZSTD_decodeFrameHeader_Part1(ctx, src, ZSTD_frameHeaderSize_min);\n        if (ZSTD_isError(ctx->headerSize)) return ctx->headerSize;\n        memcpy(ctx->headerBuffer, src, ZSTD_frameHeaderSize_min);\n        if (ctx->headerSize > ZSTD_frameHeaderSize_min) return ERROR(GENERIC);   /* impossible */\n        ctx->expected = 0;   /* not necessary to copy more */\n        /* fallthrough */\n    case ZSTDds_decodeFrameHeader:\n        /* get frame header */\n        {   size_t const result = ZSTD_decodeFrameHeader_Part2(ctx, ctx->headerBuffer, ctx->headerSize);\n            if (ZSTD_isError(result)) return result;\n            ctx->expected = ZSTD_blockHeaderSize;\n            ctx->stage = ZSTDds_decodeBlockHeader;\n            return 0;\n        }\n    case ZSTDds_decodeBlockHeader:\n        /* Decode block header */\n        {   blockProperties_t bp;\n            size_t const blockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);\n            if (ZSTD_isError(blockSize)) return blockSize;\n            if (bp.blockType == bt_end)\n            {\n                ctx->expected = 0;\n                ctx->stage = ZSTDds_getFrameHeaderSize;\n            }\n            else\n            {\n                ctx->expected = blockSize;\n                ctx->bType = bp.blockType;\n                ctx->stage = ZSTDds_decompressBlock;\n            }\n            return 0;\n        }\n    case ZSTDds_decompressBlock:\n        {\n            /* Decompress : block content */\n            size_t rSize;\n            switch(ctx->bType)\n            {\n            case bt_compressed:\n                rSize = ZSTD_decompressBlock_internal(ctx, dst, maxDstSize, src, srcSize);\n                break;\n            case bt_raw :\n                rSize = ZSTD_copyRawBlock(dst, maxDstSize, src, srcSize);\n                break;\n            case bt_rle :\n                return ERROR(GENERIC);   /* not yet handled */\n                break;\n            case bt_end :   /* should never happen (filtered at phase 1) */\n                rSize = 0;\n                break;\n            default:\n                return ERROR(GENERIC);\n            }\n            ctx->stage = ZSTDds_decodeBlockHeader;\n            ctx->expected = ZSTD_blockHeaderSize;\n            if (ZSTD_isError(rSize)) return rSize;\n            ctx->previousDstEnd = (char*)dst + rSize;\n            return rSize;\n        }\n    default:\n        return ERROR(GENERIC);   /* impossible */\n    }\n}\n\n\nstatic void ZSTD_decompress_insertDictionary(ZSTD_DCtx* ctx, const void* dict, size_t dictSize)\n{\n    ctx->dictEnd = ctx->previousDstEnd;\n    ctx->vBase = (const char*)dict - ((const char*)(ctx->previousDstEnd) - (const char*)(ctx->base));\n    ctx->base = dict;\n    ctx->previousDstEnd = (const char*)dict + dictSize;\n}\n\n\n\n/*\n    Buffered version of Zstd compression library\n    Copyright (C) 2015, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n    - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n\n/* The objects defined into this file should be considered experimental.\n * They are not labelled stable, as their prototype may change in the future.\n * You can use them for tests, provide feedback, or if you can endure risk of future changes.\n */\n\n/* *************************************\n*  Includes\n***************************************/\n#include <stdlib.h>\n\n\n/** ************************************************\n*  Streaming decompression\n*\n*  A ZBUFF_DCtx object is required to track streaming operation.\n*  Use ZBUFF_createDCtx() and ZBUFF_freeDCtx() to create/release resources.\n*  Use ZBUFF_decompressInit() to start a new decompression operation.\n*  ZBUFF_DCtx objects can be reused multiple times.\n*\n*  Use ZBUFF_decompressContinue() repetitively to consume your input.\n*  *srcSizePtr and *maxDstSizePtr can be any size.\n*  The function will report how many bytes were read or written by modifying *srcSizePtr and *maxDstSizePtr.\n*  Note that it may not consume the entire input, in which case it's up to the caller to call again the function with remaining input.\n*  The content of dst will be overwritten (up to *maxDstSizePtr) at each function call, so save its content if it matters or change dst .\n*  return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to improve latency)\n*            or 0 when a frame is completely decoded\n*            or an error code, which can be tested using ZBUFF_isError().\n*\n*  Hint : recommended buffer sizes (not compulsory)\n*  output : 128 KB block size is the internal unit, it ensures it's always possible to write a full block when it's decoded.\n*  input : just follow indications from ZBUFF_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .\n* **************************************************/\n\ntypedef enum { ZBUFFds_init, ZBUFFds_readHeader, ZBUFFds_loadHeader, ZBUFFds_decodeHeader,\n               ZBUFFds_read, ZBUFFds_load, ZBUFFds_flush } ZBUFF_dStage;\n\n/* *** Resource management *** */\n\n#define ZSTD_frameHeaderSize_max 5   /* too magical, should come from reference */\nstruct ZBUFFv04_DCtx_s {\n    ZSTD_DCtx* zc;\n    ZSTD_parameters params;\n    char* inBuff;\n    size_t inBuffSize;\n    size_t inPos;\n    char* outBuff;\n    size_t outBuffSize;\n    size_t outStart;\n    size_t outEnd;\n    size_t hPos;\n    const char* dict;\n    size_t dictSize;\n    ZBUFF_dStage stage;\n    unsigned char headerBuffer[ZSTD_frameHeaderSize_max];\n};   /* typedef'd to ZBUFF_DCtx within \"zstd_buffered.h\" */\n\ntypedef ZBUFFv04_DCtx ZBUFF_DCtx;\n\n\nstatic ZBUFF_DCtx* ZBUFF_createDCtx(void)\n{\n    ZBUFF_DCtx* zbc = (ZBUFF_DCtx*)malloc(sizeof(ZBUFF_DCtx));\n    if (zbc==NULL) return NULL;\n    memset(zbc, 0, sizeof(*zbc));\n    zbc->zc = ZSTD_createDCtx();\n    zbc->stage = ZBUFFds_init;\n    return zbc;\n}\n\nstatic size_t ZBUFF_freeDCtx(ZBUFF_DCtx* zbc)\n{\n    if (zbc==NULL) return 0;   /* support free on null */\n    ZSTD_freeDCtx(zbc->zc);\n    free(zbc->inBuff);\n    free(zbc->outBuff);\n    free(zbc);\n    return 0;\n}\n\n\n/* *** Initialization *** */\n\nstatic size_t ZBUFF_decompressInit(ZBUFF_DCtx* zbc)\n{\n    zbc->stage = ZBUFFds_readHeader;\n    zbc->hPos = zbc->inPos = zbc->outStart = zbc->outEnd = zbc->dictSize = 0;\n    return ZSTD_resetDCtx(zbc->zc);\n}\n\n\nstatic size_t ZBUFF_decompressWithDictionary(ZBUFF_DCtx* zbc, const void* src, size_t srcSize)\n{\n    zbc->dict = (const char*)src;\n    zbc->dictSize = srcSize;\n    return 0;\n}\n\nstatic size_t ZBUFF_limitCopy(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    size_t length = MIN(maxDstSize, srcSize);\n    if (length > 0) {\n        memcpy(dst, src, length);\n    }\n    return length;\n}\n\n/* *** Decompression *** */\n\nstatic size_t ZBUFF_decompressContinue(ZBUFF_DCtx* zbc, void* dst, size_t* maxDstSizePtr, const void* src, size_t* srcSizePtr)\n{\n    const char* const istart = (const char*)src;\n    const char* ip = istart;\n    const char* const iend = istart + *srcSizePtr;\n    char* const ostart = (char*)dst;\n    char* op = ostart;\n    char* const oend = ostart + *maxDstSizePtr;\n    U32 notDone = 1;\n\n    DEBUGLOG(5, \"ZBUFF_decompressContinue\");\n    while (notDone)\n    {\n        switch(zbc->stage)\n        {\n\n        case ZBUFFds_init :\n            DEBUGLOG(5, \"ZBUFF_decompressContinue: stage==ZBUFFds_init => ERROR(init_missing)\");\n            return ERROR(init_missing);\n\n        case ZBUFFds_readHeader :\n            /* read header from src */\n            {   size_t const headerSize = ZSTD_getFrameParams(&(zbc->params), src, *srcSizePtr);\n                if (ZSTD_isError(headerSize)) return headerSize;\n                if (headerSize) {\n                    /* not enough input to decode header : tell how many bytes would be necessary */\n                    memcpy(zbc->headerBuffer+zbc->hPos, src, *srcSizePtr);\n                    zbc->hPos += *srcSizePtr;\n                    *maxDstSizePtr = 0;\n                    zbc->stage = ZBUFFds_loadHeader;\n                    return headerSize - zbc->hPos;\n                }\n                zbc->stage = ZBUFFds_decodeHeader;\n                break;\n            }\n\n        case ZBUFFds_loadHeader:\n            /* complete header from src */\n            {   size_t headerSize = ZBUFF_limitCopy(\n                    zbc->headerBuffer + zbc->hPos, ZSTD_frameHeaderSize_max - zbc->hPos,\n                    src, *srcSizePtr);\n                zbc->hPos += headerSize;\n                ip += headerSize;\n                headerSize = ZSTD_getFrameParams(&(zbc->params), zbc->headerBuffer, zbc->hPos);\n                if (ZSTD_isError(headerSize)) return headerSize;\n                if (headerSize) {\n                    /* not enough input to decode header : tell how many bytes would be necessary */\n                    *maxDstSizePtr = 0;\n                    return headerSize - zbc->hPos;\n            }   }\n            /* intentional fallthrough */\n\n        case ZBUFFds_decodeHeader:\n                /* apply header to create / resize buffers */\n                {   size_t const neededOutSize = (size_t)1 << zbc->params.windowLog;\n                    size_t const neededInSize = BLOCKSIZE;   /* a block is never > BLOCKSIZE */\n                    if (zbc->inBuffSize < neededInSize) {\n                        free(zbc->inBuff);\n                        zbc->inBuffSize = neededInSize;\n                        zbc->inBuff = (char*)malloc(neededInSize);\n                        if (zbc->inBuff == NULL) return ERROR(memory_allocation);\n                    }\n                    if (zbc->outBuffSize < neededOutSize) {\n                        free(zbc->outBuff);\n                        zbc->outBuffSize = neededOutSize;\n                        zbc->outBuff = (char*)malloc(neededOutSize);\n                        if (zbc->outBuff == NULL) return ERROR(memory_allocation);\n                }   }\n                if (zbc->dictSize)\n                    ZSTD_decompress_insertDictionary(zbc->zc, zbc->dict, zbc->dictSize);\n                if (zbc->hPos) {\n                    /* some data already loaded into headerBuffer : transfer into inBuff */\n                    memcpy(zbc->inBuff, zbc->headerBuffer, zbc->hPos);\n                    zbc->inPos = zbc->hPos;\n                    zbc->hPos = 0;\n                    zbc->stage = ZBUFFds_load;\n                    break;\n                }\n                zbc->stage = ZBUFFds_read;\n\t\t/* fall-through */\n        case ZBUFFds_read:\n            {\n                size_t neededInSize = ZSTD_nextSrcSizeToDecompress(zbc->zc);\n                if (neededInSize==0)   /* end of frame */\n                {\n                    zbc->stage = ZBUFFds_init;\n                    notDone = 0;\n                    break;\n                }\n                if ((size_t)(iend-ip) >= neededInSize)\n                {\n                    /* directly decode from src */\n                    size_t decodedSize = ZSTD_decompressContinue(zbc->zc,\n                        zbc->outBuff + zbc->outStart, zbc->outBuffSize - zbc->outStart,\n                        ip, neededInSize);\n                    if (ZSTD_isError(decodedSize)) return decodedSize;\n                    ip += neededInSize;\n                    if (!decodedSize) break;   /* this was just a header */\n                    zbc->outEnd = zbc->outStart +  decodedSize;\n                    zbc->stage = ZBUFFds_flush;\n                    break;\n                }\n                if (ip==iend) { notDone = 0; break; }   /* no more input */\n                zbc->stage = ZBUFFds_load;\n            }\n\t    /* fall-through */\n        case ZBUFFds_load:\n            {\n                size_t neededInSize = ZSTD_nextSrcSizeToDecompress(zbc->zc);\n                size_t toLoad = neededInSize - zbc->inPos;   /* should always be <= remaining space within inBuff */\n                size_t loadedSize;\n                if (toLoad > zbc->inBuffSize - zbc->inPos) return ERROR(corruption_detected);   /* should never happen */\n                loadedSize = ZBUFF_limitCopy(zbc->inBuff + zbc->inPos, toLoad, ip, iend-ip);\n                ip += loadedSize;\n                zbc->inPos += loadedSize;\n                if (loadedSize < toLoad) { notDone = 0; break; }   /* not enough input, wait for more */\n                {\n                    size_t decodedSize = ZSTD_decompressContinue(zbc->zc,\n                        zbc->outBuff + zbc->outStart, zbc->outBuffSize - zbc->outStart,\n                        zbc->inBuff, neededInSize);\n                    if (ZSTD_isError(decodedSize)) return decodedSize;\n                    zbc->inPos = 0;   /* input is consumed */\n                    if (!decodedSize) { zbc->stage = ZBUFFds_read; break; }   /* this was just a header */\n                    zbc->outEnd = zbc->outStart +  decodedSize;\n                    zbc->stage = ZBUFFds_flush;\n                    /* ZBUFFds_flush follows */\n                }\n            }\n\t    /* fall-through */\n        case ZBUFFds_flush:\n            {\n                size_t toFlushSize = zbc->outEnd - zbc->outStart;\n                size_t flushedSize = ZBUFF_limitCopy(op, oend-op, zbc->outBuff + zbc->outStart, toFlushSize);\n                op += flushedSize;\n                zbc->outStart += flushedSize;\n                if (flushedSize == toFlushSize)\n                {\n                    zbc->stage = ZBUFFds_read;\n                    if (zbc->outStart + BLOCKSIZE > zbc->outBuffSize)\n                        zbc->outStart = zbc->outEnd = 0;\n                    break;\n                }\n                /* cannot flush everything */\n                notDone = 0;\n                break;\n            }\n        default: return ERROR(GENERIC);   /* impossible */\n        }\n    }\n\n    *srcSizePtr = ip-istart;\n    *maxDstSizePtr = op-ostart;\n\n    {\n        size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zbc->zc);\n        if (nextSrcSizeHint > 3) nextSrcSizeHint+= 3;   /* get the next block header while at it */\n        nextSrcSizeHint -= zbc->inPos;   /* already loaded*/\n        return nextSrcSizeHint;\n    }\n}\n\n\n/* *************************************\n*  Tool functions\n***************************************/\nunsigned ZBUFFv04_isError(size_t errorCode) { return ERR_isError(errorCode); }\nconst char* ZBUFFv04_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }\n\nsize_t ZBUFFv04_recommendedDInSize(void)  { return BLOCKSIZE + 3; }\nsize_t ZBUFFv04_recommendedDOutSize(void) { return BLOCKSIZE; }\n\n\n\n/*- ========================================================================= -*/\n\n/* final wrapping stage */\n\nsize_t ZSTDv04_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    return ZSTD_decompress_usingDict(dctx, dst, maxDstSize, src, srcSize, NULL, 0);\n}\n\nsize_t ZSTDv04_decompress(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE==1)\n    size_t regenSize;\n    ZSTD_DCtx* dctx = ZSTD_createDCtx();\n    if (dctx==NULL) return ERROR(memory_allocation);\n    regenSize = ZSTDv04_decompressDCtx(dctx, dst, maxDstSize, src, srcSize);\n    ZSTD_freeDCtx(dctx);\n    return regenSize;\n#else\n    ZSTD_DCtx dctx;\n    return ZSTDv04_decompressDCtx(&dctx, dst, maxDstSize, src, srcSize);\n#endif\n}\n\nsize_t ZSTDv04_resetDCtx(ZSTDv04_Dctx* dctx) { return ZSTD_resetDCtx(dctx); }\n\nsize_t ZSTDv04_nextSrcSizeToDecompress(ZSTDv04_Dctx* dctx)\n{\n    return ZSTD_nextSrcSizeToDecompress(dctx);\n}\n\nsize_t ZSTDv04_decompressContinue(ZSTDv04_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    return ZSTD_decompressContinue(dctx, dst, maxDstSize, src, srcSize);\n}\n\n\n\nZBUFFv04_DCtx* ZBUFFv04_createDCtx(void) { return ZBUFF_createDCtx(); }\nsize_t ZBUFFv04_freeDCtx(ZBUFFv04_DCtx* dctx) { return ZBUFF_freeDCtx(dctx); }\n\nsize_t ZBUFFv04_decompressInit(ZBUFFv04_DCtx* dctx) { return ZBUFF_decompressInit(dctx); }\nsize_t ZBUFFv04_decompressWithDictionary(ZBUFFv04_DCtx* dctx, const void* src, size_t srcSize)\n{ return ZBUFF_decompressWithDictionary(dctx, src, srcSize); }\n\nsize_t ZBUFFv04_decompressContinue(ZBUFFv04_DCtx* dctx, void* dst, size_t* maxDstSizePtr, const void* src, size_t* srcSizePtr)\n{\n    DEBUGLOG(5, \"ZBUFFv04_decompressContinue\");\n    return ZBUFF_decompressContinue(dctx, dst, maxDstSizePtr, src, srcSizePtr);\n}\n\nZSTD_DCtx* ZSTDv04_createDCtx(void) { return ZSTD_createDCtx(); }\nsize_t ZSTDv04_freeDCtx(ZSTD_DCtx* dctx) { return ZSTD_freeDCtx(dctx); }\n"
  },
  {
    "path": "lib/legacy/zstd_v04.h",
    "content": "/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_V04_H_91868324769238\n#define ZSTD_V04_H_91868324769238\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* *************************************\n*  Includes\n***************************************/\n#include <stddef.h>   /* size_t */\n\n\n/* *************************************\n*  Simple one-step function\n***************************************/\n/**\nZSTDv04_decompress() : decompress ZSTD frames compliant with v0.4.x format\n    compressedSize : is the exact source size\n    maxOriginalSize : is the size of the 'dst' buffer, which must be already allocated.\n                      It must be equal or larger than originalSize, otherwise decompression will fail.\n    return : the number of bytes decompressed into destination buffer (originalSize)\n             or an errorCode if it fails (which can be tested using ZSTDv01_isError())\n*/\nsize_t ZSTDv04_decompress( void* dst, size_t maxOriginalSize,\n                     const void* src, size_t compressedSize);\n\n /**\n ZSTDv04_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.4.x format\n     srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'\n     cSize (output parameter)  : the number of bytes that would be read to decompress this frame\n                                 or an error code if it fails (which can be tested using ZSTDv01_isError())\n     dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame\n                                 or ZSTD_CONTENTSIZE_ERROR if an error occurs\n\n    note : assumes `cSize` and `dBound` are _not_ NULL.\n */\n void ZSTDv04_findFrameSizeInfoLegacy(const void *src, size_t srcSize,\n                                      size_t* cSize, unsigned long long* dBound);\n\n/**\nZSTDv04_isError() : tells if the result of ZSTDv04_decompress() is an error\n*/\nunsigned ZSTDv04_isError(size_t code);\n\n\n/* *************************************\n*  Advanced functions\n***************************************/\ntypedef struct ZSTDv04_Dctx_s ZSTDv04_Dctx;\nZSTDv04_Dctx* ZSTDv04_createDCtx(void);\nsize_t ZSTDv04_freeDCtx(ZSTDv04_Dctx* dctx);\n\nsize_t ZSTDv04_decompressDCtx(ZSTDv04_Dctx* dctx,\n                              void* dst, size_t maxOriginalSize,\n                        const void* src, size_t compressedSize);\n\n\n/* *************************************\n*  Direct Streaming\n***************************************/\nsize_t ZSTDv04_resetDCtx(ZSTDv04_Dctx* dctx);\n\nsize_t ZSTDv04_nextSrcSizeToDecompress(ZSTDv04_Dctx* dctx);\nsize_t ZSTDv04_decompressContinue(ZSTDv04_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize);\n/**\n  Use above functions alternatively.\n  ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue().\n  ZSTD_decompressContinue() will use previous data blocks to improve compression if they are located prior to current block.\n  Result is the number of bytes regenerated within 'dst'.\n  It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header.\n*/\n\n\n/* *************************************\n*  Buffered Streaming\n***************************************/\ntypedef struct ZBUFFv04_DCtx_s ZBUFFv04_DCtx;\nZBUFFv04_DCtx* ZBUFFv04_createDCtx(void);\nsize_t         ZBUFFv04_freeDCtx(ZBUFFv04_DCtx* dctx);\n\nsize_t ZBUFFv04_decompressInit(ZBUFFv04_DCtx* dctx);\nsize_t ZBUFFv04_decompressWithDictionary(ZBUFFv04_DCtx* dctx, const void* dict, size_t dictSize);\n\nsize_t ZBUFFv04_decompressContinue(ZBUFFv04_DCtx* dctx, void* dst, size_t* maxDstSizePtr, const void* src, size_t* srcSizePtr);\n\n/** ************************************************\n*  Streaming decompression\n*\n*  A ZBUFF_DCtx object is required to track streaming operation.\n*  Use ZBUFF_createDCtx() and ZBUFF_freeDCtx() to create/release resources.\n*  Use ZBUFF_decompressInit() to start a new decompression operation.\n*  ZBUFF_DCtx objects can be reused multiple times.\n*\n*  Optionally, a reference to a static dictionary can be set, using ZBUFF_decompressWithDictionary()\n*  It must be the same content as the one set during compression phase.\n*  Dictionary content must remain accessible during the decompression process.\n*\n*  Use ZBUFF_decompressContinue() repetitively to consume your input.\n*  *srcSizePtr and *maxDstSizePtr can be any size.\n*  The function will report how many bytes were read or written by modifying *srcSizePtr and *maxDstSizePtr.\n*  Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again.\n*  The content of dst will be overwritten (up to *maxDstSizePtr) at each function call, so save its content if it matters or change dst.\n*  @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to improve latency)\n*            or 0 when a frame is completely decoded\n*            or an error code, which can be tested using ZBUFF_isError().\n*\n*  Hint : recommended buffer sizes (not compulsory) : ZBUFF_recommendedDInSize / ZBUFF_recommendedDOutSize\n*  output : ZBUFF_recommendedDOutSize==128 KB block size is the internal unit, it ensures it's always possible to write a full block when it's decoded.\n*  input : ZBUFF_recommendedDInSize==128Kb+3; just follow indications from ZBUFF_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .\n* **************************************************/\nunsigned ZBUFFv04_isError(size_t errorCode);\nconst char* ZBUFFv04_getErrorName(size_t errorCode);\n\n\n/** The below functions provide recommended buffer sizes for Compression or Decompression operations.\n*   These sizes are not compulsory, they just tend to offer better latency */\nsize_t ZBUFFv04_recommendedDInSize(void);\nsize_t ZBUFFv04_recommendedDOutSize(void);\n\n\n/* *************************************\n*  Prefix - version detection\n***************************************/\n#define ZSTDv04_magicNumber 0xFD2FB524   /* v0.4 */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* ZSTD_V04_H_91868324769238 */\n"
  },
  {
    "path": "lib/legacy/zstd_v05.c",
    "content": "/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/*- Dependencies -*/\n#include \"zstd_v05.h\"\n#include \"../common/error_private.h\"\n\n\n/* ******************************************************************\n   mem.h\n   low-level memory access routines\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSEv05 source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef MEM_H_MODULE\n#define MEM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/*-****************************************\n*  Dependencies\n******************************************/\n#include <stddef.h>    /* size_t, ptrdiff_t */\n#include <string.h>    /* memcpy */\n\n\n/*-****************************************\n*  Compiler specifics\n******************************************/\n#if defined(__GNUC__)\n#  define MEM_STATIC static __attribute__((unused))\n#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n#  define MEM_STATIC static inline\n#elif defined(_MSC_VER)\n#  define MEM_STATIC static __inline\n#else\n#  define MEM_STATIC static  /* this version may generate warnings for unused static functions; disable the relevant warning */\n#endif\n\n\n/*-**************************************************************\n*  Basic Types\n*****************************************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n# if defined(_AIX)\n#  include <inttypes.h>\n# else\n#  include <stdint.h> /* intptr_t */\n# endif\n  typedef  uint8_t BYTE;\n  typedef uint16_t U16;\n  typedef  int16_t S16;\n  typedef uint32_t U32;\n  typedef  int32_t S32;\n  typedef uint64_t U64;\n  typedef  int64_t S64;\n#else\n  typedef unsigned char       BYTE;\n  typedef unsigned short      U16;\n  typedef   signed short      S16;\n  typedef unsigned int        U32;\n  typedef   signed int        S32;\n  typedef unsigned long long  U64;\n  typedef   signed long long  S64;\n#endif\n\n\n/*-**************************************************************\n*  Memory I/O\n*****************************************************************/\n\nMEM_STATIC unsigned MEM_32bits(void) { return sizeof(void*)==4; }\nMEM_STATIC unsigned MEM_64bits(void) { return sizeof(void*)==8; }\n\nMEM_STATIC unsigned MEM_isLittleEndian(void)\n{\n    const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */\n    return one.c[0];\n}\n\nMEM_STATIC U16 MEM_read16(const void* memPtr)\n{\n    U16 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U32 MEM_read32(const void* memPtr)\n{\n    U32 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U64 MEM_read64(const void* memPtr)\n{\n    U64 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value)\n{\n    memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC void MEM_write32(void* memPtr, U32 value)\n{\n    memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC void MEM_write64(void* memPtr, U64 value)\n{\n    memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC U16 MEM_readLE16(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read16(memPtr);\n    else {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U16)(p[0] + (p[1]<<8));\n    }\n}\n\nMEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)\n{\n    if (MEM_isLittleEndian()) {\n        MEM_write16(memPtr, val);\n    } else {\n        BYTE* p = (BYTE*)memPtr;\n        p[0] = (BYTE)val;\n        p[1] = (BYTE)(val>>8);\n    }\n}\n\nMEM_STATIC U32 MEM_readLE32(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read32(memPtr);\n    else {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U32)((U32)p[0] + ((U32)p[1]<<8) + ((U32)p[2]<<16) + ((U32)p[3]<<24));\n    }\n}\n\n\nMEM_STATIC U64 MEM_readLE64(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read64(memPtr);\n    else {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U64)((U64)p[0] + ((U64)p[1]<<8) + ((U64)p[2]<<16) + ((U64)p[3]<<24)\n                     + ((U64)p[4]<<32) + ((U64)p[5]<<40) + ((U64)p[6]<<48) + ((U64)p[7]<<56));\n    }\n}\n\n\nMEM_STATIC size_t MEM_readLEST(const void* memPtr)\n{\n    if (MEM_32bits())\n        return (size_t)MEM_readLE32(memPtr);\n    else\n        return (size_t)MEM_readLE64(memPtr);\n}\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* MEM_H_MODULE */\n\n/*\n    zstd - standard compression library\n    Header File for static linking only\n    Copyright (C) 2014-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd homepage : https://facebook.github.io/zstd\n*/\n#ifndef ZSTD_STATIC_H\n#define ZSTD_STATIC_H\n\n/* The prototypes defined within this file are considered experimental.\n * They should not be used in the context DLL as they may change in the future.\n * Prefer static linking if you need them, to control breaking version changes issues.\n */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n\n/*-*************************************\n*  Types\n***************************************/\n#define ZSTDv05_WINDOWLOG_ABSOLUTEMIN 11\n\n\n/*-*************************************\n*  Advanced functions\n***************************************/\n/*- Advanced Decompression functions -*/\n\n/*! ZSTDv05_decompress_usingPreparedDCtx() :\n*   Same as ZSTDv05_decompress_usingDict, but using a reference context `preparedDCtx`, where dictionary has been loaded.\n*   It avoids reloading the dictionary each time.\n*   `preparedDCtx` must have been properly initialized using ZSTDv05_decompressBegin_usingDict().\n*   Requires 2 contexts : 1 for reference, which will not be modified, and 1 to run the decompression operation */\nsize_t ZSTDv05_decompress_usingPreparedDCtx(\n                                             ZSTDv05_DCtx* dctx, const ZSTDv05_DCtx* preparedDCtx,\n                                             void* dst, size_t dstCapacity,\n                                       const void* src, size_t srcSize);\n\n\n/* **************************************\n*  Streaming functions (direct mode)\n****************************************/\nsize_t ZSTDv05_decompressBegin(ZSTDv05_DCtx* dctx);\n\n/*\n  Streaming decompression, direct mode (bufferless)\n\n  A ZSTDv05_DCtx object is required to track streaming operations.\n  Use ZSTDv05_createDCtx() / ZSTDv05_freeDCtx() to manage it.\n  A ZSTDv05_DCtx object can be re-used multiple times.\n\n  First typical operation is to retrieve frame parameters, using ZSTDv05_getFrameParams().\n  This operation is independent, and just needs enough input data to properly decode the frame header.\n  Objective is to retrieve *params.windowlog, to know minimum amount of memory required during decoding.\n  Result : 0 when successful, it means the ZSTDv05_parameters structure has been filled.\n           >0 : means there is not enough data into src. Provides the expected size to successfully decode header.\n           errorCode, which can be tested using ZSTDv05_isError()\n\n  Start decompression, with ZSTDv05_decompressBegin() or ZSTDv05_decompressBegin_usingDict()\n  Alternatively, you can copy a prepared context, using ZSTDv05_copyDCtx()\n\n  Then use ZSTDv05_nextSrcSizeToDecompress() and ZSTDv05_decompressContinue() alternatively.\n  ZSTDv05_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTDv05_decompressContinue().\n  ZSTDv05_decompressContinue() requires this exact amount of bytes, or it will fail.\n  ZSTDv05_decompressContinue() needs previous data blocks during decompression, up to (1 << windowlog).\n  They should preferably be located contiguously, prior to current block. Alternatively, a round buffer is also possible.\n\n  @result of ZSTDv05_decompressContinue() is the number of bytes regenerated within 'dst'.\n  It can be zero, which is not an error; it just means ZSTDv05_decompressContinue() has decoded some header.\n\n  A frame is fully decoded when ZSTDv05_nextSrcSizeToDecompress() returns zero.\n  Context can then be reset to start a new decompression.\n*/\n\n\n/* **************************************\n*  Block functions\n****************************************/\n/*! Block functions produce and decode raw zstd blocks, without frame metadata.\n    User will have to take in charge required information to regenerate data, such as block sizes.\n\n    A few rules to respect :\n    - Uncompressed block size must be <= 128 KB\n    - Compressing or decompressing requires a context structure\n      + Use ZSTDv05_createCCtx() and ZSTDv05_createDCtx()\n    - It is necessary to init context before starting\n      + compression : ZSTDv05_compressBegin()\n      + decompression : ZSTDv05_decompressBegin()\n      + variants _usingDict() are also allowed\n      + copyCCtx() and copyDCtx() work too\n    - When a block is considered not compressible enough, ZSTDv05_compressBlock() result will be zero.\n      In which case, nothing is produced into `dst`.\n      + User must test for such outcome and deal directly with uncompressed data\n      + ZSTDv05_decompressBlock() doesn't accept uncompressed data as input !!\n*/\n\nsize_t ZSTDv05_decompressBlock(ZSTDv05_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* ZSTDv05_STATIC_H */\n\n\n/*\n    zstd_internal - common functions to include\n    Header File for include\n    Copyright (C) 2014-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n*/\n#ifndef ZSTD_CCOMMON_H_MODULE\n#define ZSTD_CCOMMON_H_MODULE\n\n\n\n/*-*************************************\n*  Common macros\n***************************************/\n#define MIN(a,b) ((a)<(b) ? (a) : (b))\n#define MAX(a,b) ((a)>(b) ? (a) : (b))\n\n\n/*-*************************************\n*  Common constants\n***************************************/\n#define ZSTDv05_DICT_MAGIC  0xEC30A435\n\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\n#define BLOCKSIZE (128 KB)                 /* define, for static allocation */\n\nstatic const size_t ZSTDv05_blockHeaderSize = 3;\nstatic const size_t ZSTDv05_frameHeaderSize_min = 5;\n#define ZSTDv05_frameHeaderSize_max 5         /* define, for static allocation */\n\n#define BITv057 128\n#define BITv056  64\n#define BITv055  32\n#define BITv054  16\n#define BITv051   2\n#define BITv050   1\n\n#define IS_HUFv05 0\n#define IS_PCH 1\n#define IS_RAW 2\n#define IS_RLE 3\n\n#define MINMATCH 4\n#define REPCODE_STARTVALUE 1\n\n#define Litbits  8\n#define MLbits   7\n#define LLbits   6\n#define Offbits  5\n#define MaxLit ((1<<Litbits) - 1)\n#define MaxML  ((1<<MLbits) - 1)\n#define MaxLL  ((1<<LLbits) - 1)\n#define MaxOff ((1<<Offbits)- 1)\n#define MLFSEv05Log   10\n#define LLFSEv05Log   10\n#define OffFSEv05Log   9\n#define MaxSeq MAX(MaxLL, MaxML)\n\n#define FSEv05_ENCODING_RAW     0\n#define FSEv05_ENCODING_RLE     1\n#define FSEv05_ENCODING_STATIC  2\n#define FSEv05_ENCODING_DYNAMIC 3\n\n\n#define ZSTD_HUFFDTABLE_CAPACITY_LOG 12\n\n#define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */\n#define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */)   /* for a non-null block */\n\n#define WILDCOPY_OVERLENGTH 8\n\n#define ZSTD_CONTENTSIZE_ERROR   (0ULL - 2)\n\ntypedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;\n\n\n/*-*******************************************\n*  Shared functions to include for inlining\n*********************************************/\nstatic void ZSTDv05_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }\n\n#define COPY8(d,s) { ZSTDv05_copy8(d,s); d+=8; s+=8; }\n\n/*! ZSTDv05_wildcopy() :\n*   custom version of memcpy(), can copy up to 7 bytes too many (8 bytes if length==0) */\nMEM_STATIC void ZSTDv05_wildcopy(void* dst, const void* src, ptrdiff_t length)\n{\n    const BYTE* ip = (const BYTE*)src;\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + length;\n    do\n        COPY8(op, ip)\n    while (op < oend);\n}\n\n\n/*-*******************************************\n*  Private interfaces\n*********************************************/\ntypedef struct {\n    void* buffer;\n    U32*  offsetStart;\n    U32*  offset;\n    BYTE* offCodeStart;\n    BYTE* offCode;\n    BYTE* litStart;\n    BYTE* lit;\n    BYTE* litLengthStart;\n    BYTE* litLength;\n    BYTE* matchLengthStart;\n    BYTE* matchLength;\n    BYTE* dumpsStart;\n    BYTE* dumps;\n    /* opt */\n    U32* matchLengthFreq;\n    U32* litLengthFreq;\n    U32* litFreq;\n    U32* offCodeFreq;\n    U32  matchLengthSum;\n    U32  litLengthSum;\n    U32  litSum;\n    U32  offCodeSum;\n} SeqStore_t;\n\n\n\n#endif   /* ZSTDv05_CCOMMON_H_MODULE */\n/* ******************************************************************\n   FSEv05 : Finite State Entropy coder\n   header file\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef FSEv05_H\n#define FSEv05_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/* *****************************************\n*  Includes\n******************************************/\n#include <stddef.h>    /* size_t, ptrdiff_t */\n\n\n/*-****************************************\n*  FSEv05 simple functions\n******************************************/\nsize_t FSEv05_decompress(void* dst,  size_t maxDstSize,\n                const void* cSrc, size_t cSrcSize);\n/*!\nFSEv05_decompress():\n    Decompress FSEv05 data from buffer 'cSrc', of size 'cSrcSize',\n    into already allocated destination buffer 'dst', of size 'maxDstSize'.\n    return : size of regenerated data (<= maxDstSize)\n             or an error code, which can be tested using FSEv05_isError()\n\n    ** Important ** : FSEv05_decompress() doesn't decompress non-compressible nor RLE data !!!\n    Why ? : making this distinction requires a header.\n    Header management is intentionally delegated to the user layer, which can better manage special cases.\n*/\n\n\n/* *****************************************\n*  Tool functions\n******************************************/\n/* Error Management */\nunsigned    FSEv05_isError(size_t code);        /* tells if a return value is an error code */\nconst char* FSEv05_getErrorName(size_t code);   /* provides error code string (useful for debugging) */\n\n\n\n\n/* *****************************************\n*  FSEv05 detailed API\n******************************************/\n/* *** DECOMPRESSION *** */\n\n/*!\nFSEv05_readNCount():\n   Read compactly saved 'normalizedCounter' from 'rBuffer'.\n   return : size read from 'rBuffer'\n            or an errorCode, which can be tested using FSEv05_isError()\n            maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */\nsize_t FSEv05_readNCount (short* normalizedCounter, unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, const void* rBuffer, size_t rBuffSize);\n\n/*!\nConstructor and Destructor of type FSEv05_DTable\n    Note that its size depends on 'tableLog' */\ntypedef unsigned FSEv05_DTable;   /* don't allocate that. It's just a way to be more restrictive than void* */\nFSEv05_DTable* FSEv05_createDTable(unsigned tableLog);\nvoid        FSEv05_freeDTable(FSEv05_DTable* dt);\n\n/*!\nFSEv05_buildDTable():\n   Builds 'dt', which must be already allocated, using FSEv05_createDTable()\n   @return : 0,\n             or an errorCode, which can be tested using FSEv05_isError() */\nsize_t FSEv05_buildDTable (FSEv05_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);\n\n/*!\nFSEv05_decompress_usingDTable():\n   Decompress compressed source @cSrc of size @cSrcSize using `dt`\n   into `dst` which must be already allocated.\n   @return : size of regenerated data (necessarily <= @dstCapacity)\n             or an errorCode, which can be tested using FSEv05_isError() */\nsize_t FSEv05_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSEv05_DTable* dt);\n\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* FSEv05_H */\n/* ******************************************************************\n   bitstream\n   Part of FSEv05 library\n   header file (to include)\n   Copyright (C) 2013-2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n****************************************************************** */\n#ifndef BITv05STREAM_H_MODULE\n#define BITv05STREAM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/*\n*  This API consists of small unitary functions, which highly benefit from being inlined.\n*  Since link-time-optimization is not available for all compilers,\n*  these functions are defined into a .h to be included.\n*/\n\n\n\n/*-********************************************\n*  bitStream decoding API (read backward)\n**********************************************/\ntypedef struct\n{\n    size_t   bitContainer;\n    unsigned bitsConsumed;\n    const char* ptr;\n    const char* start;\n} BITv05_DStream_t;\n\ntypedef enum { BITv05_DStream_unfinished = 0,\n               BITv05_DStream_endOfBuffer = 1,\n               BITv05_DStream_completed = 2,\n               BITv05_DStream_overflow = 3 } BITv05_DStream_status;  /* result of BITv05_reloadDStream() */\n               /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */\n\nMEM_STATIC size_t   BITv05_initDStream(BITv05_DStream_t* bitD, const void* srcBuffer, size_t srcSize);\nMEM_STATIC size_t   BITv05_readBits(BITv05_DStream_t* bitD, unsigned nbBits);\nMEM_STATIC BITv05_DStream_status BITv05_reloadDStream(BITv05_DStream_t* bitD);\nMEM_STATIC unsigned BITv05_endOfDStream(const BITv05_DStream_t* bitD);\n\n\n/*-****************************************\n*  unsafe API\n******************************************/\nMEM_STATIC size_t BITv05_readBitsFast(BITv05_DStream_t* bitD, unsigned nbBits);\n/* faster, but works only if nbBits >= 1 */\n\n\n\n/*-**************************************************************\n*  Helper functions\n****************************************************************/\nMEM_STATIC unsigned BITv05_highbit32 (U32 val)\n{\n#   if defined(_MSC_VER)   /* Visual */\n    unsigned long r;\n    return _BitScanReverse(&r, val) ? (unsigned)r : 0;\n#   elif defined(__GNUC__) && (__GNUC__ >= 3)   /* Use GCC Intrinsic */\n    return __builtin_clz (val) ^ 31;\n#   else   /* Software version */\n    static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };\n    U32 v = val;\n    unsigned r;\n    v |= v >> 1;\n    v |= v >> 2;\n    v |= v >> 4;\n    v |= v >> 8;\n    v |= v >> 16;\n    r = DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];\n    return r;\n#   endif\n}\n\n\n\n/*-********************************************************\n* bitStream decoding\n**********************************************************/\n/*!BITv05_initDStream\n*  Initialize a BITv05_DStream_t.\n*  @bitD : a pointer to an already allocated BITv05_DStream_t structure\n*  @srcBuffer must point at the beginning of a bitStream\n*  @srcSize must be the exact size of the bitStream\n*  @result : size of stream (== srcSize) or an errorCode if a problem is detected\n*/\nMEM_STATIC size_t BITv05_initDStream(BITv05_DStream_t* bitD, const void* srcBuffer, size_t srcSize)\n{\n    if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }\n\n    if (srcSize >=  sizeof(size_t)) {  /* normal case */\n        U32 contain32;\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = (const char*)srcBuffer + srcSize - sizeof(size_t);\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        contain32 = ((const BYTE*)srcBuffer)[srcSize-1];\n        if (contain32 == 0) return ERROR(GENERIC);   /* endMark not present */\n        bitD->bitsConsumed = 8 - BITv05_highbit32(contain32);\n    } else {\n        U32 contain32;\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = bitD->start;\n        bitD->bitContainer = *(const BYTE*)(bitD->start);\n        switch(srcSize)\n        {\n            case 7: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[6]) << (sizeof(size_t)*8 - 16);/* fall-through */\n            case 6: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[5]) << (sizeof(size_t)*8 - 24);/* fall-through */\n            case 5: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[4]) << (sizeof(size_t)*8 - 32);/* fall-through */\n            case 4: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[3]) << 24; /* fall-through */\n            case 3: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[2]) << 16; /* fall-through */\n            case 2: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[1]) <<  8; /* fall-through */\n            default: break;\n        }\n        contain32 = ((const BYTE*)srcBuffer)[srcSize-1];\n        if (contain32 == 0) return ERROR(GENERIC);   /* endMark not present */\n        bitD->bitsConsumed = 8 - BITv05_highbit32(contain32);\n        bitD->bitsConsumed += (U32)(sizeof(size_t) - srcSize)*8;\n    }\n\n    return srcSize;\n}\n\nMEM_STATIC size_t BITv05_lookBits(BITv05_DStream_t* bitD, U32 nbBits)\n{\n    const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);\n}\n\n/*! BITv05_lookBitsFast :\n*   unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BITv05_lookBitsFast(BITv05_DStream_t* bitD, U32 nbBits)\n{\n    const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);\n}\n\nMEM_STATIC void BITv05_skipBits(BITv05_DStream_t* bitD, U32 nbBits)\n{\n    bitD->bitsConsumed += nbBits;\n}\n\nMEM_STATIC size_t BITv05_readBits(BITv05_DStream_t* bitD, unsigned nbBits)\n{\n    size_t value = BITv05_lookBits(bitD, nbBits);\n    BITv05_skipBits(bitD, nbBits);\n    return value;\n}\n\n/*!BITv05_readBitsFast :\n*  unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BITv05_readBitsFast(BITv05_DStream_t* bitD, unsigned nbBits)\n{\n    size_t value = BITv05_lookBitsFast(bitD, nbBits);\n    BITv05_skipBits(bitD, nbBits);\n    return value;\n}\n\nMEM_STATIC BITv05_DStream_status BITv05_reloadDStream(BITv05_DStream_t* bitD)\n{\n    if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */\n        return BITv05_DStream_overflow;\n\n    if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {\n        bitD->ptr -= bitD->bitsConsumed >> 3;\n        bitD->bitsConsumed &= 7;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        return BITv05_DStream_unfinished;\n    }\n    if (bitD->ptr == bitD->start) {\n        if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BITv05_DStream_endOfBuffer;\n        return BITv05_DStream_completed;\n    }\n    {\n        U32 nbBytes = bitD->bitsConsumed >> 3;\n        BITv05_DStream_status result = BITv05_DStream_unfinished;\n        if (bitD->ptr - nbBytes < bitD->start) {\n            nbBytes = (U32)(bitD->ptr - bitD->start);  /* ptr > start */\n            result = BITv05_DStream_endOfBuffer;\n        }\n        bitD->ptr -= nbBytes;\n        bitD->bitsConsumed -= nbBytes*8;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);   /* reminder : srcSize > sizeof(bitD) */\n        return result;\n    }\n}\n\n/*! BITv05_endOfDStream\n*   @return Tells if DStream has reached its exact end\n*/\nMEM_STATIC unsigned BITv05_endOfDStream(const BITv05_DStream_t* DStream)\n{\n    return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));\n}\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* BITv05STREAM_H_MODULE */\n/* ******************************************************************\n   FSEv05 : Finite State Entropy coder\n   header file for static linking (only)\n   Copyright (C) 2013-2015, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef FSEv05_STATIC_H\n#define FSEv05_STATIC_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n\n/* *****************************************\n*  Static allocation\n*******************************************/\n/* It is possible to statically allocate FSEv05 CTable/DTable as a table of unsigned using below macros */\n#define FSEv05_DTABLE_SIZE_U32(maxTableLog)                   (1 + (1<<maxTableLog))\n\n\n/* *****************************************\n*  FSEv05 advanced API\n*******************************************/\nsize_t FSEv05_buildDTable_raw (FSEv05_DTable* dt, unsigned nbBits);\n/* build a fake FSEv05_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */\n\nsize_t FSEv05_buildDTable_rle (FSEv05_DTable* dt, unsigned char symbolValue);\n/* build a fake FSEv05_DTable, designed to always generate the same symbolValue */\n\n\n\n/* *****************************************\n*  FSEv05 symbol decompression API\n*******************************************/\ntypedef struct\n{\n    size_t      state;\n    const void* table;   /* precise table may vary, depending on U16 */\n} FSEv05_DState_t;\n\n\nstatic void     FSEv05_initDState(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD, const FSEv05_DTable* dt);\n\nstatic unsigned char FSEv05_decodeSymbol(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD);\n\nstatic unsigned FSEv05_endOfDState(const FSEv05_DState_t* DStatePtr);\n\n\n\n/* *****************************************\n*  FSEv05 unsafe API\n*******************************************/\nstatic unsigned char FSEv05_decodeSymbolFast(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD);\n/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */\n\n\n/* *****************************************\n*  Implementation of inlined functions\n*******************************************/\n/* decompression */\n\ntypedef struct {\n    U16 tableLog;\n    U16 fastMode;\n} FSEv05_DTableHeader;   /* sizeof U32 */\n\ntypedef struct\n{\n    unsigned short newState;\n    unsigned char  symbol;\n    unsigned char  nbBits;\n} FSEv05_decode_t;   /* size == U32 */\n\nMEM_STATIC void FSEv05_initDState(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD, const FSEv05_DTable* dt)\n{\n    const void* ptr = dt;\n    const FSEv05_DTableHeader* const DTableH = (const FSEv05_DTableHeader*)ptr;\n    DStatePtr->state = BITv05_readBits(bitD, DTableH->tableLog);\n    BITv05_reloadDStream(bitD);\n    DStatePtr->table = dt + 1;\n}\n\nMEM_STATIC BYTE FSEv05_peakSymbol(FSEv05_DState_t* DStatePtr)\n{\n    const FSEv05_decode_t DInfo = ((const FSEv05_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    return DInfo.symbol;\n}\n\nMEM_STATIC BYTE FSEv05_decodeSymbol(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD)\n{\n    const FSEv05_decode_t DInfo = ((const FSEv05_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    const U32  nbBits = DInfo.nbBits;\n    BYTE symbol = DInfo.symbol;\n    size_t lowBits = BITv05_readBits(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\nMEM_STATIC BYTE FSEv05_decodeSymbolFast(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD)\n{\n    const FSEv05_decode_t DInfo = ((const FSEv05_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    const U32 nbBits = DInfo.nbBits;\n    BYTE symbol = DInfo.symbol;\n    size_t lowBits = BITv05_readBitsFast(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\nMEM_STATIC unsigned FSEv05_endOfDState(const FSEv05_DState_t* DStatePtr)\n{\n    return DStatePtr->state == 0;\n}\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* FSEv05_STATIC_H */\n/* ******************************************************************\n   FSEv05 : Finite State Entropy coder\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSEv05 source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n#ifndef FSEv05_COMMONDEFS_ONLY\n\n/* **************************************************************\n*  Tuning parameters\n****************************************************************/\n/*!MEMORY_USAGE :\n*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n*  Increasing memory usage improves compression ratio\n*  Reduced memory usage can improve speed, due to cache effect\n*  Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */\n#define FSEv05_MAX_MEMORY_USAGE 14\n#define FSEv05_DEFAULT_MEMORY_USAGE 13\n\n/*!FSEv05_MAX_SYMBOL_VALUE :\n*  Maximum symbol value authorized.\n*  Required for proper stack allocation */\n#define FSEv05_MAX_SYMBOL_VALUE 255\n\n\n/* **************************************************************\n*  template functions type & suffix\n****************************************************************/\n#define FSEv05_FUNCTION_TYPE BYTE\n#define FSEv05_FUNCTION_EXTENSION\n#define FSEv05_DECODE_TYPE FSEv05_decode_t\n\n\n#endif   /* !FSEv05_COMMONDEFS_ONLY */\n\n/* **************************************************************\n*  Compiler specifics\n****************************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  define FORCE_INLINE static __forceinline\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4214)        /* disable: C4214: non-int bitfields */\n#else\n#  if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */\n#    ifdef __GNUC__\n#      define FORCE_INLINE static inline __attribute__((always_inline))\n#    else\n#      define FORCE_INLINE static inline\n#    endif\n#  else\n#    define FORCE_INLINE static\n#  endif /* __STDC_VERSION__ */\n#endif\n\n\n/* **************************************************************\n*  Includes\n****************************************************************/\n#include <stdlib.h>     /* malloc, free, qsort */\n#include <string.h>     /* memcpy, memset */\n#include <stdio.h>      /* printf (debug) */\n\n\n\n/* ***************************************************************\n*  Constants\n*****************************************************************/\n#define FSEv05_MAX_TABLELOG  (FSEv05_MAX_MEMORY_USAGE-2)\n#define FSEv05_MAX_TABLESIZE (1U<<FSEv05_MAX_TABLELOG)\n#define FSEv05_MAXTABLESIZE_MASK (FSEv05_MAX_TABLESIZE-1)\n#define FSEv05_DEFAULT_TABLELOG (FSEv05_DEFAULT_MEMORY_USAGE-2)\n#define FSEv05_MIN_TABLELOG 5\n\n#define FSEv05_TABLELOG_ABSOLUTE_MAX 15\n#if FSEv05_MAX_TABLELOG > FSEv05_TABLELOG_ABSOLUTE_MAX\n#error \"FSEv05_MAX_TABLELOG > FSEv05_TABLELOG_ABSOLUTE_MAX is not supported\"\n#endif\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n#define FSEv05_STATIC_ASSERT(c) { enum { FSEv05_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n/* **************************************************************\n*  Complex types\n****************************************************************/\ntypedef unsigned DTable_max_t[FSEv05_DTABLE_SIZE_U32(FSEv05_MAX_TABLELOG)];\n\n\n/* **************************************************************\n*  Templates\n****************************************************************/\n/*\n  designed to be included\n  for type-specific functions (template emulation in C)\n  Objective is to write these functions only once, for improved maintenance\n*/\n\n/* safety checks */\n#ifndef FSEv05_FUNCTION_EXTENSION\n#  error \"FSEv05_FUNCTION_EXTENSION must be defined\"\n#endif\n#ifndef FSEv05_FUNCTION_TYPE\n#  error \"FSEv05_FUNCTION_TYPE must be defined\"\n#endif\n\n/* Function names */\n#define FSEv05_CAT(X,Y) X##Y\n#define FSEv05_FUNCTION_NAME(X,Y) FSEv05_CAT(X,Y)\n#define FSEv05_TYPE_NAME(X,Y) FSEv05_CAT(X,Y)\n\n\n/* Function templates */\nstatic U32 FSEv05_tableStep(U32 tableSize) { return (tableSize>>1) + (tableSize>>3) + 3; }\n\n\n\nFSEv05_DTable* FSEv05_createDTable (unsigned tableLog)\n{\n    if (tableLog > FSEv05_TABLELOG_ABSOLUTE_MAX) tableLog = FSEv05_TABLELOG_ABSOLUTE_MAX;\n    return (FSEv05_DTable*)malloc( FSEv05_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );\n}\n\nvoid FSEv05_freeDTable (FSEv05_DTable* dt)\n{\n    free(dt);\n}\n\nsize_t FSEv05_buildDTable(FSEv05_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)\n{\n    FSEv05_DTableHeader DTableH;\n    void* const tdPtr = dt+1;   /* because dt is unsigned, 32-bits aligned on 32-bits */\n    FSEv05_DECODE_TYPE* const tableDecode = (FSEv05_DECODE_TYPE*) (tdPtr);\n    const U32 tableSize = 1 << tableLog;\n    const U32 tableMask = tableSize-1;\n    const U32 step = FSEv05_tableStep(tableSize);\n    U16 symbolNext[FSEv05_MAX_SYMBOL_VALUE+1];\n    U32 position = 0;\n    U32 highThreshold = tableSize-1;\n    const S16 largeLimit= (S16)(1 << (tableLog-1));\n    U32 noLarge = 1;\n    U32 s;\n\n    /* Sanity Checks */\n    if (maxSymbolValue > FSEv05_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);\n    if (tableLog > FSEv05_MAX_TABLELOG) return ERROR(tableLog_tooLarge);\n\n    /* Init, lay down lowprob symbols */\n    memset(tableDecode, 0, sizeof(FSEv05_FUNCTION_TYPE) * (maxSymbolValue+1) );   /* useless init, but keep static analyzer happy, and we don't need to performance optimize legacy decoders */\n    DTableH.tableLog = (U16)tableLog;\n    for (s=0; s<=maxSymbolValue; s++) {\n        if (normalizedCounter[s]==-1) {\n            tableDecode[highThreshold--].symbol = (FSEv05_FUNCTION_TYPE)s;\n            symbolNext[s] = 1;\n        } else {\n            if (normalizedCounter[s] >= largeLimit) noLarge=0;\n            symbolNext[s] = normalizedCounter[s];\n    }   }\n\n    /* Spread symbols */\n    for (s=0; s<=maxSymbolValue; s++) {\n        int i;\n        for (i=0; i<normalizedCounter[s]; i++) {\n            tableDecode[position].symbol = (FSEv05_FUNCTION_TYPE)s;\n            position = (position + step) & tableMask;\n            while (position > highThreshold) position = (position + step) & tableMask;   /* lowprob area */\n    }   }\n\n    if (position!=0) return ERROR(GENERIC);   /* position must reach all cells once, otherwise normalizedCounter is incorrect */\n\n    /* Build Decoding table */\n    {\n        U32 i;\n        for (i=0; i<tableSize; i++) {\n            FSEv05_FUNCTION_TYPE symbol = (FSEv05_FUNCTION_TYPE)(tableDecode[i].symbol);\n            U16 nextState = symbolNext[symbol]++;\n            tableDecode[i].nbBits = (BYTE) (tableLog - BITv05_highbit32 ((U32)nextState) );\n            tableDecode[i].newState = (U16) ( (nextState << tableDecode[i].nbBits) - tableSize);\n    }   }\n\n    DTableH.fastMode = (U16)noLarge;\n    memcpy(dt, &DTableH, sizeof(DTableH));\n    return 0;\n}\n\n\n#ifndef FSEv05_COMMONDEFS_ONLY\n/*-****************************************\n*  FSEv05 helper functions\n******************************************/\nunsigned FSEv05_isError(size_t code) { return ERR_isError(code); }\n\nconst char* FSEv05_getErrorName(size_t code) { return ERR_getErrorName(code); }\n\n\n/*-**************************************************************\n*  FSEv05 NCount encoding-decoding\n****************************************************************/\nstatic short FSEv05_abs(short a) { return a<0 ? (short)-a : a; }\n\n\nsize_t FSEv05_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n                 const void* headerBuffer, size_t hbSize)\n{\n    const BYTE* const istart = (const BYTE*) headerBuffer;\n    const BYTE* const iend = istart + hbSize;\n    const BYTE* ip = istart;\n    int nbBits;\n    int remaining;\n    int threshold;\n    U32 bitStream;\n    int bitCount;\n    unsigned charnum = 0;\n    int previous0 = 0;\n\n    if (hbSize < 4) return ERROR(srcSize_wrong);\n    bitStream = MEM_readLE32(ip);\n    nbBits = (bitStream & 0xF) + FSEv05_MIN_TABLELOG;   /* extract tableLog */\n    if (nbBits > FSEv05_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);\n    bitStream >>= 4;\n    bitCount = 4;\n    *tableLogPtr = nbBits;\n    remaining = (1<<nbBits)+1;\n    threshold = 1<<nbBits;\n    nbBits++;\n\n    while ((remaining>1) && (charnum<=*maxSVPtr)) {\n        if (previous0) {\n            unsigned n0 = charnum;\n            while ((bitStream & 0xFFFF) == 0xFFFF) {\n                n0+=24;\n                if (ip < iend-5) {\n                    ip+=2;\n                    bitStream = MEM_readLE32(ip) >> bitCount;\n                } else {\n                    bitStream >>= 16;\n                    bitCount+=16;\n            }   }\n            while ((bitStream & 3) == 3) {\n                n0+=3;\n                bitStream>>=2;\n                bitCount+=2;\n            }\n            n0 += bitStream & 3;\n            bitCount += 2;\n            if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);\n            while (charnum < n0) normalizedCounter[charnum++] = 0;\n            if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {\n                ip += bitCount>>3;\n                bitCount &= 7;\n                bitStream = MEM_readLE32(ip) >> bitCount;\n            }\n            else\n                bitStream >>= 2;\n        }\n        {\n            const short max = (short)((2*threshold-1)-remaining);\n            short count;\n\n            if ((bitStream & (threshold-1)) < (U32)max) {\n                count = (short)(bitStream & (threshold-1));\n                bitCount   += nbBits-1;\n            } else {\n                count = (short)(bitStream & (2*threshold-1));\n                if (count >= threshold) count -= max;\n                bitCount   += nbBits;\n            }\n\n            count--;   /* extra accuracy */\n            remaining -= FSEv05_abs(count);\n            normalizedCounter[charnum++] = count;\n            previous0 = !count;\n            while (remaining < threshold) {\n                nbBits--;\n                threshold >>= 1;\n            }\n\n            if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {\n                ip += bitCount>>3;\n                bitCount &= 7;\n            } else {\n                bitCount -= (int)(8 * (iend - 4 - ip));\n                ip = iend - 4;\n            }\n            bitStream = MEM_readLE32(ip) >> (bitCount & 31);\n    }   }\n    if (remaining != 1) return ERROR(GENERIC);\n    *maxSVPtr = charnum-1;\n\n    ip += (bitCount+7)>>3;\n    if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong);\n    return ip-istart;\n}\n\n\n\n/*-*******************************************************\n*  Decompression (Byte symbols)\n*********************************************************/\nsize_t FSEv05_buildDTable_rle (FSEv05_DTable* dt, BYTE symbolValue)\n{\n    void* ptr = dt;\n    FSEv05_DTableHeader* const DTableH = (FSEv05_DTableHeader*)ptr;\n    void* dPtr = dt + 1;\n    FSEv05_decode_t* const cell = (FSEv05_decode_t*)dPtr;\n\n    DTableH->tableLog = 0;\n    DTableH->fastMode = 0;\n\n    cell->newState = 0;\n    cell->symbol = symbolValue;\n    cell->nbBits = 0;\n\n    return 0;\n}\n\n\nsize_t FSEv05_buildDTable_raw (FSEv05_DTable* dt, unsigned nbBits)\n{\n    void* ptr = dt;\n    FSEv05_DTableHeader* const DTableH = (FSEv05_DTableHeader*)ptr;\n    void* dPtr = dt + 1;\n    FSEv05_decode_t* const dinfo = (FSEv05_decode_t*)dPtr;\n    const unsigned tableSize = 1 << nbBits;\n    const unsigned tableMask = tableSize - 1;\n    const unsigned maxSymbolValue = tableMask;\n    unsigned s;\n\n    /* Sanity checks */\n    if (nbBits < 1) return ERROR(GENERIC);         /* min size */\n\n    /* Build Decoding Table */\n    DTableH->tableLog = (U16)nbBits;\n    DTableH->fastMode = 1;\n    for (s=0; s<=maxSymbolValue; s++) {\n        dinfo[s].newState = 0;\n        dinfo[s].symbol = (BYTE)s;\n        dinfo[s].nbBits = (BYTE)nbBits;\n    }\n\n    return 0;\n}\n\nFORCE_INLINE size_t FSEv05_decompress_usingDTable_generic(\n          void* dst, size_t maxDstSize,\n    const void* cSrc, size_t cSrcSize,\n    const FSEv05_DTable* dt, const unsigned fast)\n{\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* op = ostart;\n    BYTE* const omax = op + maxDstSize;\n    BYTE* const olimit = omax-3;\n\n    BITv05_DStream_t bitD;\n    FSEv05_DState_t state1;\n    FSEv05_DState_t state2;\n    size_t errorCode;\n\n    /* Init */\n    errorCode = BITv05_initDStream(&bitD, cSrc, cSrcSize);   /* replaced last arg by maxCompressed Size */\n    if (FSEv05_isError(errorCode)) return errorCode;\n\n    FSEv05_initDState(&state1, &bitD, dt);\n    FSEv05_initDState(&state2, &bitD, dt);\n\n#define FSEv05_GETSYMBOL(statePtr) fast ? FSEv05_decodeSymbolFast(statePtr, &bitD) : FSEv05_decodeSymbol(statePtr, &bitD)\n\n    /* 4 symbols per loop */\n    for ( ; (BITv05_reloadDStream(&bitD)==BITv05_DStream_unfinished) && (op<olimit) ; op+=4) {\n        op[0] = FSEv05_GETSYMBOL(&state1);\n\n        if (FSEv05_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BITv05_reloadDStream(&bitD);\n\n        op[1] = FSEv05_GETSYMBOL(&state2);\n\n        if (FSEv05_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            { if (BITv05_reloadDStream(&bitD) > BITv05_DStream_unfinished) { op+=2; break; } }\n\n        op[2] = FSEv05_GETSYMBOL(&state1);\n\n        if (FSEv05_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BITv05_reloadDStream(&bitD);\n\n        op[3] = FSEv05_GETSYMBOL(&state2);\n    }\n\n    /* tail */\n    /* note : BITv05_reloadDStream(&bitD) >= FSEv05_DStream_partiallyFilled; Ends at exactly BITv05_DStream_completed */\n    while (1) {\n        if ( (BITv05_reloadDStream(&bitD)>BITv05_DStream_completed) || (op==omax) || (BITv05_endOfDStream(&bitD) && (fast || FSEv05_endOfDState(&state1))) )\n            break;\n\n        *op++ = FSEv05_GETSYMBOL(&state1);\n\n        if ( (BITv05_reloadDStream(&bitD)>BITv05_DStream_completed) || (op==omax) || (BITv05_endOfDStream(&bitD) && (fast || FSEv05_endOfDState(&state2))) )\n            break;\n\n        *op++ = FSEv05_GETSYMBOL(&state2);\n    }\n\n    /* end ? */\n    if (BITv05_endOfDStream(&bitD) && FSEv05_endOfDState(&state1) && FSEv05_endOfDState(&state2))\n        return op-ostart;\n\n    if (op==omax) return ERROR(dstSize_tooSmall);   /* dst buffer is full, but cSrc unfinished */\n\n    return ERROR(corruption_detected);\n}\n\n\nsize_t FSEv05_decompress_usingDTable(void* dst, size_t originalSize,\n                            const void* cSrc, size_t cSrcSize,\n                            const FSEv05_DTable* dt)\n{\n    const void* ptr = dt;\n    const FSEv05_DTableHeader* DTableH = (const FSEv05_DTableHeader*)ptr;\n    const U32 fastMode = DTableH->fastMode;\n\n    /* select fast mode (static) */\n    if (fastMode) return FSEv05_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);\n    return FSEv05_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);\n}\n\n\nsize_t FSEv05_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)\n{\n    const BYTE* const istart = (const BYTE*)cSrc;\n    const BYTE* ip = istart;\n    short counting[FSEv05_MAX_SYMBOL_VALUE+1];\n    DTable_max_t dt;   /* Static analyzer seems unable to understand this table will be properly initialized later */\n    unsigned tableLog;\n    unsigned maxSymbolValue = FSEv05_MAX_SYMBOL_VALUE;\n    size_t errorCode;\n\n    if (cSrcSize<2) return ERROR(srcSize_wrong);   /* too small input size */\n\n    /* normal FSEv05 decoding mode */\n    errorCode = FSEv05_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);\n    if (FSEv05_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);   /* too small input size */\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    errorCode = FSEv05_buildDTable (dt, counting, maxSymbolValue, tableLog);\n    if (FSEv05_isError(errorCode)) return errorCode;\n\n    /* always return, even if it is an error code */\n    return FSEv05_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt);\n}\n\n\n\n#endif   /* FSEv05_COMMONDEFS_ONLY */\n/* ******************************************************************\n   Huff0 : Huffman coder, part of New Generation Entropy library\n   header file\n   Copyright (C) 2013-2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n****************************************************************** */\n#ifndef HUFF0_H\n#define HUFF0_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n\n/* ****************************************\n*  Huff0 simple functions\n******************************************/\nsize_t HUFv05_decompress(void* dst,  size_t dstSize,\n                const void* cSrc, size_t cSrcSize);\n/*!\nHUFv05_decompress():\n    Decompress Huff0 data from buffer 'cSrc', of size 'cSrcSize',\n    into already allocated destination buffer 'dst', of size 'dstSize'.\n    @dstSize : must be the **exact** size of original (uncompressed) data.\n    Note : in contrast with FSEv05, HUFv05_decompress can regenerate\n           RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data,\n           because it knows size to regenerate.\n    @return : size of regenerated data (== dstSize)\n              or an error code, which can be tested using HUFv05_isError()\n*/\n\n\n/* ****************************************\n*  Tool functions\n******************************************/\n/* Error Management */\nunsigned    HUFv05_isError(size_t code);        /* tells if a return value is an error code */\nconst char* HUFv05_getErrorName(size_t code);   /* provides error code string (useful for debugging) */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif   /* HUF0_H */\n/* ******************************************************************\n   Huff0 : Huffman codec, part of New Generation Entropy library\n   header file, for static linking only\n   Copyright (C) 2013-2016, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n****************************************************************** */\n#ifndef HUF0_STATIC_H\n#define HUF0_STATIC_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n\n/* ****************************************\n*  Static allocation\n******************************************/\n/* static allocation of Huff0's DTable */\n#define HUFv05_DTABLE_SIZE(maxTableLog)   (1 + (1<<maxTableLog))\n#define HUFv05_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \\\n        unsigned short DTable[HUFv05_DTABLE_SIZE(maxTableLog)] = { maxTableLog }\n#define HUFv05_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \\\n        unsigned int DTable[HUFv05_DTABLE_SIZE(maxTableLog)] = { maxTableLog }\n#define HUFv05_CREATE_STATIC_DTABLEX6(DTable, maxTableLog) \\\n        unsigned int DTable[HUFv05_DTABLE_SIZE(maxTableLog) * 3 / 2] = { maxTableLog }\n\n\n/* ****************************************\n*  Advanced decompression functions\n******************************************/\nsize_t HUFv05_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */\nsize_t HUFv05_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbols decoder */\n\n\n/* ****************************************\n*  Huff0 detailed API\n******************************************/\n/*!\nHUFv05_decompress() does the following:\n1. select the decompression algorithm (X2, X4, X6) based on pre-computed heuristics\n2. build Huffman table from save, using HUFv05_readDTableXn()\n3. decode 1 or 4 segments in parallel using HUFv05_decompressSXn_usingDTable\n*/\nsize_t HUFv05_readDTableX2 (unsigned short* DTable, const void* src, size_t srcSize);\nsize_t HUFv05_readDTableX4 (unsigned* DTable, const void* src, size_t srcSize);\n\nsize_t HUFv05_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable);\nsize_t HUFv05_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable);\n\n\n/* single stream variants */\n\nsize_t HUFv05_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */\nsize_t HUFv05_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbol decoder */\n\nsize_t HUFv05_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable);\nsize_t HUFv05_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable);\n\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* HUF0_STATIC_H */\n/* ******************************************************************\n   Huff0 : Huffman coder, part of New Generation Entropy library\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSEv05+Huff0 source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n/* **************************************************************\n*  Compiler specifics\n****************************************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n/* inline is defined */\n#elif defined(_MSC_VER)\n#  define inline __inline\n#else\n#  define inline /* disable inline */\n#endif\n\n\n#ifdef _MSC_VER    /* Visual Studio */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#endif\n\n\n/* **************************************************************\n*  Includes\n****************************************************************/\n#include <stdlib.h>     /* malloc, free, qsort */\n#include <string.h>     /* memcpy, memset */\n#include <stdio.h>      /* printf (debug) */\n\n\n/* **************************************************************\n*  Constants\n****************************************************************/\n#define HUFv05_ABSOLUTEMAX_TABLELOG  16   /* absolute limit of HUFv05_MAX_TABLELOG. Beyond that value, code does not work */\n#define HUFv05_MAX_TABLELOG  12           /* max configured tableLog (for static allocation); can be modified up to HUFv05_ABSOLUTEMAX_TABLELOG */\n#define HUFv05_DEFAULT_TABLELOG  HUFv05_MAX_TABLELOG   /* tableLog by default, when not specified */\n#define HUFv05_MAX_SYMBOL_VALUE 255\n#if (HUFv05_MAX_TABLELOG > HUFv05_ABSOLUTEMAX_TABLELOG)\n#  error \"HUFv05_MAX_TABLELOG is too large !\"\n#endif\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\nunsigned HUFv05_isError(size_t code) { return ERR_isError(code); }\nconst char* HUFv05_getErrorName(size_t code) { return ERR_getErrorName(code); }\n#define HUFv05_STATIC_ASSERT(c) { enum { HUFv05_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n/* *******************************************************\n*  Huff0 : Huffman block decompression\n*********************************************************/\ntypedef struct { BYTE byte; BYTE nbBits; } HUFv05_DEltX2;   /* single-symbol decoding */\n\ntypedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUFv05_DEltX4;  /* double-symbols decoding */\n\ntypedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;\n\n/*! HUFv05_readStats\n    Read compact Huffman tree, saved by HUFv05_writeCTable\n    @huffWeight : destination buffer\n    @return : size read from `src`\n*/\nstatic size_t HUFv05_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                            U32* nbSymbolsPtr, U32* tableLogPtr,\n                            const void* src, size_t srcSize)\n{\n    U32 weightTotal;\n    U32 tableLog;\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize;\n    size_t oSize;\n    U32 n;\n\n    if (!srcSize) return ERROR(srcSize_wrong);\n    iSize = ip[0];\n    /* memset(huffWeight, 0, hwSize); */   /* is not necessary, even though some analyzer complain ... */\n\n    if (iSize >= 128)  { /* special header */\n        if (iSize >= (242)) {  /* RLE */\n            static int l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };\n            oSize = l[iSize-242];\n            memset(huffWeight, 1, hwSize);\n            iSize = 0;\n        }\n        else {   /* Incompressible */\n            oSize = iSize - 127;\n            iSize = ((oSize+1)/2);\n            if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n            if (oSize >= hwSize) return ERROR(corruption_detected);\n            ip += 1;\n            for (n=0; n<oSize; n+=2) {\n                huffWeight[n]   = ip[n/2] >> 4;\n                huffWeight[n+1] = ip[n/2] & 15;\n    }   }   }\n    else  {   /* header compressed with FSEv05 (normal case) */\n        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n        oSize = FSEv05_decompress(huffWeight, hwSize-1, ip+1, iSize);   /* max (hwSize-1) values decoded, as last one is implied */\n        if (FSEv05_isError(oSize)) return oSize;\n    }\n\n    /* collect weight stats */\n    memset(rankStats, 0, (HUFv05_ABSOLUTEMAX_TABLELOG + 1) * sizeof(U32));\n    weightTotal = 0;\n    for (n=0; n<oSize; n++) {\n        if (huffWeight[n] >= HUFv05_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);\n        rankStats[huffWeight[n]]++;\n        weightTotal += (1 << huffWeight[n]) >> 1;\n    }\n    if (weightTotal == 0) return ERROR(corruption_detected);\n\n    /* get last non-null symbol weight (implied, total must be 2^n) */\n    tableLog = BITv05_highbit32(weightTotal) + 1;\n    if (tableLog > HUFv05_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);\n    {   /* determine last weight */\n        U32 total = 1 << tableLog;\n        U32 rest = total - weightTotal;\n        U32 verif = 1 << BITv05_highbit32(rest);\n        U32 lastWeight = BITv05_highbit32(rest) + 1;\n        if (verif != rest) return ERROR(corruption_detected);    /* last value must be a clean power of 2 */\n        huffWeight[oSize] = (BYTE)lastWeight;\n        rankStats[lastWeight]++;\n    }\n\n    /* check tree construction validity */\n    if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected);   /* by construction : at least 2 elts of rank 1, must be even */\n\n    /* results */\n    *nbSymbolsPtr = (U32)(oSize+1);\n    *tableLogPtr = tableLog;\n    return iSize+1;\n}\n\n\n/*-***************************/\n/*  single-symbol decoding   */\n/*-***************************/\n\nsize_t HUFv05_readDTableX2 (U16* DTable, const void* src, size_t srcSize)\n{\n    BYTE huffWeight[HUFv05_MAX_SYMBOL_VALUE + 1];\n    U32 rankVal[HUFv05_ABSOLUTEMAX_TABLELOG + 1];   /* large enough for values from 0 to 16 */\n    U32 tableLog = 0;\n    size_t iSize;\n    U32 nbSymbols = 0;\n    U32 n;\n    U32 nextRankStart;\n    void* const dtPtr = DTable + 1;\n    HUFv05_DEltX2* const dt = (HUFv05_DEltX2*)dtPtr;\n\n    HUFv05_STATIC_ASSERT(sizeof(HUFv05_DEltX2) == sizeof(U16));   /* if compilation fails here, assertion is false */\n    /* memset(huffWeight, 0, sizeof(huffWeight)); */   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUFv05_readStats(huffWeight, HUFv05_MAX_SYMBOL_VALUE + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);\n    if (HUFv05_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > DTable[0]) return ERROR(tableLog_tooLarge);   /* DTable is too small */\n    DTable[0] = (U16)tableLog;   /* maybe should separate sizeof allocated DTable, from used size of DTable, in case of re-use */\n\n    /* Prepare ranks */\n    nextRankStart = 0;\n    for (n=1; n<=tableLog; n++) {\n        U32 current = nextRankStart;\n        nextRankStart += (rankVal[n] << (n-1));\n        rankVal[n] = current;\n    }\n\n    /* fill DTable */\n    for (n=0; n<nbSymbols; n++) {\n        const U32 w = huffWeight[n];\n        const U32 length = (1 << w) >> 1;\n        U32 i;\n        HUFv05_DEltX2 D;\n        D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w);\n        for (i = rankVal[w]; i < rankVal[w] + length; i++)\n            dt[i] = D;\n        rankVal[w] += length;\n    }\n\n    return iSize;\n}\n\nstatic BYTE HUFv05_decodeSymbolX2(BITv05_DStream_t* Dstream, const HUFv05_DEltX2* dt, const U32 dtLog)\n{\n        const size_t val = BITv05_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */\n        const BYTE c = dt[val].byte;\n        BITv05_skipBits(Dstream, dt[val].nbBits);\n        return c;\n}\n\n#define HUFv05_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \\\n    *ptr++ = HUFv05_decodeSymbolX2(DStreamPtr, dt, dtLog)\n\n#define HUFv05_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUFv05_MAX_TABLELOG<=12)) \\\n        HUFv05_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\n#define HUFv05_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        HUFv05_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\nstatic inline size_t HUFv05_decodeStreamX2(BYTE* p, BITv05_DStream_t* const bitDPtr, BYTE* const pEnd, const HUFv05_DEltX2* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 4 symbols at a time */\n    while ((BITv05_reloadDStream(bitDPtr) == BITv05_DStream_unfinished) && (p <= pEnd-4)) {\n        HUFv05_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUFv05_DECODE_SYMBOLX2_1(p, bitDPtr);\n        HUFv05_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUFv05_DECODE_SYMBOLX2_0(p, bitDPtr);\n    }\n\n    /* closer to the end */\n    while ((BITv05_reloadDStream(bitDPtr) == BITv05_DStream_unfinished) && (p < pEnd))\n        HUFv05_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    /* no more data to retrieve from bitstream, hence no need to reload */\n    while (p < pEnd)\n        HUFv05_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    return pEnd-pStart;\n}\n\nsize_t HUFv05_decompress1X2_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U16* DTable)\n{\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + dstSize;\n    const U32 dtLog = DTable[0];\n    const void* dtPtr = DTable;\n    const HUFv05_DEltX2* const dt = ((const HUFv05_DEltX2*)dtPtr)+1;\n    BITv05_DStream_t bitD;\n\n    if (dstSize <= cSrcSize) return ERROR(dstSize_tooSmall);\n    { size_t const errorCode = BITv05_initDStream(&bitD, cSrc, cSrcSize);\n      if (HUFv05_isError(errorCode)) return errorCode; }\n\n    HUFv05_decodeStreamX2(op, &bitD, oend, dt, dtLog);\n\n    /* check */\n    if (!BITv05_endOfDStream(&bitD)) return ERROR(corruption_detected);\n\n    return dstSize;\n}\n\nsize_t HUFv05_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv05_CREATE_STATIC_DTABLEX2(DTable, HUFv05_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n    size_t errorCode;\n\n    errorCode = HUFv05_readDTableX2 (DTable, cSrc, cSrcSize);\n    if (HUFv05_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    return HUFv05_decompress1X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\nsize_t HUFv05_decompress4X2_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U16* DTable)\n{\n    /* Check */\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n    {\n        const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        const void* const dtPtr = DTable;\n        const HUFv05_DEltX2* const dt = ((const HUFv05_DEltX2*)dtPtr) +1;\n        const U32 dtLog = DTable[0];\n        size_t errorCode;\n\n        /* Init */\n        BITv05_DStream_t bitD1;\n        BITv05_DStream_t bitD2;\n        BITv05_DStream_t bitD3;\n        BITv05_DStream_t bitD4;\n        const size_t length1 = MEM_readLE16(istart);\n        const size_t length2 = MEM_readLE16(istart+2);\n        const size_t length3 = MEM_readLE16(istart+4);\n        size_t length4;\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n\n        length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        errorCode = BITv05_initDStream(&bitD1, istart1, length1);\n        if (HUFv05_isError(errorCode)) return errorCode;\n        errorCode = BITv05_initDStream(&bitD2, istart2, length2);\n        if (HUFv05_isError(errorCode)) return errorCode;\n        errorCode = BITv05_initDStream(&bitD3, istart3, length3);\n        if (HUFv05_isError(errorCode)) return errorCode;\n        errorCode = BITv05_initDStream(&bitD4, istart4, length4);\n        if (HUFv05_isError(errorCode)) return errorCode;\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4);\n        for ( ; (endSignal==BITv05_DStream_unfinished) && (op4<(oend-7)) ; ) {\n            HUFv05_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUFv05_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUFv05_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUFv05_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUFv05_DECODE_SYMBOLX2_1(op1, &bitD1);\n            HUFv05_DECODE_SYMBOLX2_1(op2, &bitD2);\n            HUFv05_DECODE_SYMBOLX2_1(op3, &bitD3);\n            HUFv05_DECODE_SYMBOLX2_1(op4, &bitD4);\n            HUFv05_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUFv05_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUFv05_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUFv05_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUFv05_DECODE_SYMBOLX2_0(op1, &bitD1);\n            HUFv05_DECODE_SYMBOLX2_0(op2, &bitD2);\n            HUFv05_DECODE_SYMBOLX2_0(op3, &bitD3);\n            HUFv05_DECODE_SYMBOLX2_0(op4, &bitD4);\n            endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUFv05_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);\n        HUFv05_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);\n        HUFv05_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);\n        HUFv05_decodeStreamX2(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        endSignal = BITv05_endOfDStream(&bitD1) & BITv05_endOfDStream(&bitD2) & BITv05_endOfDStream(&bitD3) & BITv05_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nsize_t HUFv05_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv05_CREATE_STATIC_DTABLEX2(DTable, HUFv05_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n    size_t errorCode;\n\n    errorCode = HUFv05_readDTableX2 (DTable, cSrc, cSrcSize);\n    if (HUFv05_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    return HUFv05_decompress4X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\n/* *************************/\n/* double-symbols decoding */\n/* *************************/\n\nstatic void HUFv05_fillDTableX4Level2(HUFv05_DEltX4* DTable, U32 sizeLog, const U32 consumed,\n                           const U32* rankValOrigin, const int minWeight,\n                           const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,\n                           U32 nbBitsBaseline, U16 baseSeq)\n{\n    HUFv05_DEltX4 DElt;\n    U32 rankVal[HUFv05_ABSOLUTEMAX_TABLELOG + 1];\n    U32 s;\n\n    /* get pre-calculated rankVal */\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill skipped values */\n    if (minWeight>1) {\n        U32 i, skipSize = rankVal[minWeight];\n        MEM_writeLE16(&(DElt.sequence), baseSeq);\n        DElt.nbBits   = (BYTE)(consumed);\n        DElt.length   = 1;\n        for (i = 0; i < skipSize; i++)\n            DTable[i] = DElt;\n    }\n\n    /* fill DTable */\n    for (s=0; s<sortedListSize; s++) {   /* note : sortedSymbols already skipped */\n        const U32 symbol = sortedSymbols[s].symbol;\n        const U32 weight = sortedSymbols[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 length = 1 << (sizeLog-nbBits);\n        const U32 start = rankVal[weight];\n        U32 i = start;\n        const U32 end = start + length;\n\n        MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));\n        DElt.nbBits = (BYTE)(nbBits + consumed);\n        DElt.length = 2;\n        do { DTable[i++] = DElt; } while (i<end);   /* since length >= 1 */\n\n        rankVal[weight] += length;\n    }\n}\n\ntypedef U32 rankVal_t[HUFv05_ABSOLUTEMAX_TABLELOG][HUFv05_ABSOLUTEMAX_TABLELOG + 1];\n\nstatic void HUFv05_fillDTableX4(HUFv05_DEltX4* DTable, const U32 targetLog,\n                           const sortedSymbol_t* sortedList, const U32 sortedListSize,\n                           const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,\n                           const U32 nbBitsBaseline)\n{\n    U32 rankVal[HUFv05_ABSOLUTEMAX_TABLELOG + 1];\n    const int scaleLog = nbBitsBaseline - targetLog;   /* note : targetLog >= srcLog, hence scaleLog <= 1 */\n    const U32 minBits  = nbBitsBaseline - maxWeight;\n    U32 s;\n\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill DTable */\n    for (s=0; s<sortedListSize; s++) {\n        const U16 symbol = sortedList[s].symbol;\n        const U32 weight = sortedList[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 start = rankVal[weight];\n        const U32 length = 1 << (targetLog-nbBits);\n\n        if (targetLog-nbBits >= minBits) {   /* enough room for a second symbol */\n            U32 sortedRank;\n            int minWeight = nbBits + scaleLog;\n            if (minWeight < 1) minWeight = 1;\n            sortedRank = rankStart[minWeight];\n            HUFv05_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits,\n                           rankValOrigin[nbBits], minWeight,\n                           sortedList+sortedRank, sortedListSize-sortedRank,\n                           nbBitsBaseline, symbol);\n        } else {\n            U32 i;\n            const U32 end = start + length;\n            HUFv05_DEltX4 DElt;\n\n            MEM_writeLE16(&(DElt.sequence), symbol);\n            DElt.nbBits   = (BYTE)(nbBits);\n            DElt.length   = 1;\n            for (i = start; i < end; i++)\n                DTable[i] = DElt;\n        }\n        rankVal[weight] += length;\n    }\n}\n\nsize_t HUFv05_readDTableX4 (unsigned* DTable, const void* src, size_t srcSize)\n{\n    BYTE weightList[HUFv05_MAX_SYMBOL_VALUE + 1];\n    sortedSymbol_t sortedSymbol[HUFv05_MAX_SYMBOL_VALUE + 1];\n    U32 rankStats[HUFv05_ABSOLUTEMAX_TABLELOG + 1] = { 0 };\n    U32 rankStart0[HUFv05_ABSOLUTEMAX_TABLELOG + 2] = { 0 };\n    U32* const rankStart = rankStart0+1;\n    rankVal_t rankVal;\n    U32 tableLog, maxW, sizeOfSort, nbSymbols;\n    const U32 memLog = DTable[0];\n    size_t iSize;\n    void* dtPtr = DTable;\n    HUFv05_DEltX4* const dt = ((HUFv05_DEltX4*)dtPtr) + 1;\n\n    HUFv05_STATIC_ASSERT(sizeof(HUFv05_DEltX4) == sizeof(unsigned));   /* if compilation fails here, assertion is false */\n    if (memLog > HUFv05_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge);\n    /* memset(weightList, 0, sizeof(weightList)); */   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUFv05_readStats(weightList, HUFv05_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);\n    if (HUFv05_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > memLog) return ERROR(tableLog_tooLarge);   /* DTable can't fit code depth */\n\n    /* find maxWeight */\n    for (maxW = tableLog; rankStats[maxW]==0; maxW--) {}  /* necessarily finds a solution before 0 */\n\n    /* Get start index of each weight */\n    {\n        U32 w, nextRankStart = 0;\n        for (w=1; w<=maxW; w++) {\n            U32 current = nextRankStart;\n            nextRankStart += rankStats[w];\n            rankStart[w] = current;\n        }\n        rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/\n        sizeOfSort = nextRankStart;\n    }\n\n    /* sort symbols by weight */\n    {\n        U32 s;\n        for (s=0; s<nbSymbols; s++) {\n            U32 w = weightList[s];\n            U32 r = rankStart[w]++;\n            sortedSymbol[r].symbol = (BYTE)s;\n            sortedSymbol[r].weight = (BYTE)w;\n        }\n        rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */\n    }\n\n    /* Build rankVal */\n    {\n        const U32 minBits = tableLog+1 - maxW;\n        U32 nextRankVal = 0;\n        U32 w, consumed;\n        const int rescale = (memLog-tableLog) - 1;   /* tableLog <= memLog */\n        U32* rankVal0 = rankVal[0];\n        for (w=1; w<=maxW; w++) {\n            U32 current = nextRankVal;\n            nextRankVal += rankStats[w] << (w+rescale);\n            rankVal0[w] = current;\n        }\n        for (consumed = minBits; consumed <= memLog - minBits; consumed++) {\n            U32* rankValPtr = rankVal[consumed];\n            for (w = 1; w <= maxW; w++) {\n                rankValPtr[w] = rankVal0[w] >> consumed;\n    }   }   }\n\n    HUFv05_fillDTableX4(dt, memLog,\n                   sortedSymbol, sizeOfSort,\n                   rankStart0, rankVal, maxW,\n                   tableLog+1);\n\n    return iSize;\n}\n\n\nstatic U32 HUFv05_decodeSymbolX4(void* op, BITv05_DStream_t* DStream, const HUFv05_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BITv05_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 2);\n    BITv05_skipBits(DStream, dt[val].nbBits);\n    return dt[val].length;\n}\n\nstatic U32 HUFv05_decodeLastSymbolX4(void* op, BITv05_DStream_t* DStream, const HUFv05_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BITv05_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 1);\n    if (dt[val].length==1) BITv05_skipBits(DStream, dt[val].nbBits);\n    else {\n        if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {\n            BITv05_skipBits(DStream, dt[val].nbBits);\n            if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))\n                DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);   /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */\n    }   }\n    return 1;\n}\n\n\n#define HUFv05_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \\\n    ptr += HUFv05_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUFv05_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUFv05_MAX_TABLELOG<=12)) \\\n        ptr += HUFv05_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUFv05_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        ptr += HUFv05_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\nstatic inline size_t HUFv05_decodeStreamX4(BYTE* p, BITv05_DStream_t* bitDPtr, BYTE* const pEnd, const HUFv05_DEltX4* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 8 symbols at a time */\n    while ((BITv05_reloadDStream(bitDPtr) == BITv05_DStream_unfinished) && (p < pEnd-7)) {\n        HUFv05_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUFv05_DECODE_SYMBOLX4_1(p, bitDPtr);\n        HUFv05_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUFv05_DECODE_SYMBOLX4_0(p, bitDPtr);\n    }\n\n    /* closer to the end */\n    while ((BITv05_reloadDStream(bitDPtr) == BITv05_DStream_unfinished) && (p <= pEnd-2))\n        HUFv05_DECODE_SYMBOLX4_0(p, bitDPtr);\n\n    while (p <= pEnd-2)\n        HUFv05_DECODE_SYMBOLX4_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */\n\n    if (p < pEnd)\n        p += HUFv05_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);\n\n    return p-pStart;\n}\n\n\nsize_t HUFv05_decompress1X4_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const unsigned* DTable)\n{\n    const BYTE* const istart = (const BYTE*) cSrc;\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* const oend = ostart + dstSize;\n\n    const U32 dtLog = DTable[0];\n    const void* const dtPtr = DTable;\n    const HUFv05_DEltX4* const dt = ((const HUFv05_DEltX4*)dtPtr) +1;\n    size_t errorCode;\n\n    /* Init */\n    BITv05_DStream_t bitD;\n    errorCode = BITv05_initDStream(&bitD, istart, cSrcSize);\n    if (HUFv05_isError(errorCode)) return errorCode;\n\n    /* finish bitStreams one by one */\n    HUFv05_decodeStreamX4(ostart, &bitD, oend,     dt, dtLog);\n\n    /* check */\n    if (!BITv05_endOfDStream(&bitD)) return ERROR(corruption_detected);\n\n    /* decoded size */\n    return dstSize;\n}\n\nsize_t HUFv05_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv05_CREATE_STATIC_DTABLEX4(DTable, HUFv05_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t hSize = HUFv05_readDTableX4 (DTable, cSrc, cSrcSize);\n    if (HUFv05_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize;\n    cSrcSize -= hSize;\n\n    return HUFv05_decompress1X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\nsize_t HUFv05_decompress4X4_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const unsigned* DTable)\n{\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n\n    {\n        const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        const void* const dtPtr = DTable;\n        const HUFv05_DEltX4* const dt = ((const HUFv05_DEltX4*)dtPtr) +1;\n        const U32 dtLog = DTable[0];\n        size_t errorCode;\n\n        /* Init */\n        BITv05_DStream_t bitD1;\n        BITv05_DStream_t bitD2;\n        BITv05_DStream_t bitD3;\n        BITv05_DStream_t bitD4;\n        const size_t length1 = MEM_readLE16(istart);\n        const size_t length2 = MEM_readLE16(istart+2);\n        const size_t length3 = MEM_readLE16(istart+4);\n        size_t length4;\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n\n        length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        errorCode = BITv05_initDStream(&bitD1, istart1, length1);\n        if (HUFv05_isError(errorCode)) return errorCode;\n        errorCode = BITv05_initDStream(&bitD2, istart2, length2);\n        if (HUFv05_isError(errorCode)) return errorCode;\n        errorCode = BITv05_initDStream(&bitD3, istart3, length3);\n        if (HUFv05_isError(errorCode)) return errorCode;\n        errorCode = BITv05_initDStream(&bitD4, istart4, length4);\n        if (HUFv05_isError(errorCode)) return errorCode;\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4);\n        for ( ; (endSignal==BITv05_DStream_unfinished) && (op4<(oend-7)) ; ) {\n            HUFv05_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUFv05_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUFv05_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUFv05_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUFv05_DECODE_SYMBOLX4_1(op1, &bitD1);\n            HUFv05_DECODE_SYMBOLX4_1(op2, &bitD2);\n            HUFv05_DECODE_SYMBOLX4_1(op3, &bitD3);\n            HUFv05_DECODE_SYMBOLX4_1(op4, &bitD4);\n            HUFv05_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUFv05_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUFv05_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUFv05_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUFv05_DECODE_SYMBOLX4_0(op1, &bitD1);\n            HUFv05_DECODE_SYMBOLX4_0(op2, &bitD2);\n            HUFv05_DECODE_SYMBOLX4_0(op3, &bitD3);\n            HUFv05_DECODE_SYMBOLX4_0(op4, &bitD4);\n\n            endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUFv05_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);\n        HUFv05_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);\n        HUFv05_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);\n        HUFv05_decodeStreamX4(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        endSignal = BITv05_endOfDStream(&bitD1) & BITv05_endOfDStream(&bitD2) & BITv05_endOfDStream(&bitD3) & BITv05_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nsize_t HUFv05_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv05_CREATE_STATIC_DTABLEX4(DTable, HUFv05_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t hSize = HUFv05_readDTableX4 (DTable, cSrc, cSrcSize);\n    if (HUFv05_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize;\n    cSrcSize -= hSize;\n\n    return HUFv05_decompress4X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\n/* ********************************/\n/* Generic decompression selector */\n/* ********************************/\n\ntypedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;\nstatic const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =\n{\n    /* single, double, quad */\n    {{0,0}, {1,1}, {2,2}},  /* Q==0 : impossible */\n    {{0,0}, {1,1}, {2,2}},  /* Q==1 : impossible */\n    {{  38,130}, {1313, 74}, {2151, 38}},   /* Q == 2 : 12-18% */\n    {{ 448,128}, {1353, 74}, {2238, 41}},   /* Q == 3 : 18-25% */\n    {{ 556,128}, {1353, 74}, {2238, 47}},   /* Q == 4 : 25-32% */\n    {{ 714,128}, {1418, 74}, {2436, 53}},   /* Q == 5 : 32-38% */\n    {{ 883,128}, {1437, 74}, {2464, 61}},   /* Q == 6 : 38-44% */\n    {{ 897,128}, {1515, 75}, {2622, 68}},   /* Q == 7 : 44-50% */\n    {{ 926,128}, {1613, 75}, {2730, 75}},   /* Q == 8 : 50-56% */\n    {{ 947,128}, {1729, 77}, {3359, 77}},   /* Q == 9 : 56-62% */\n    {{1107,128}, {2083, 81}, {4006, 84}},   /* Q ==10 : 62-69% */\n    {{1177,128}, {2379, 87}, {4785, 88}},   /* Q ==11 : 69-75% */\n    {{1242,128}, {2415, 93}, {5155, 84}},   /* Q ==12 : 75-81% */\n    {{1349,128}, {2644,106}, {5260,106}},   /* Q ==13 : 81-87% */\n    {{1455,128}, {2422,124}, {4174,124}},   /* Q ==14 : 87-93% */\n    {{ 722,128}, {1891,145}, {1936,146}},   /* Q ==15 : 93-99% */\n};\n\ntypedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);\n\nsize_t HUFv05_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    static const decompressionAlgo decompress[3] = { HUFv05_decompress4X2, HUFv05_decompress4X4, NULL };\n    /* estimate decompression time */\n    U32 Q;\n    const U32 D256 = (U32)(dstSize >> 8);\n    U32 Dtime[3];\n    U32 algoNb = 0;\n    int n;\n\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize >= dstSize) return ERROR(corruption_detected);   /* invalid, or not compressed, but not compressed already dealt with */\n    if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */\n\n    /* decoder timing evaluation */\n    Q = (U32)(cSrcSize * 16 / dstSize);   /* Q < 16 since dstSize > cSrcSize */\n    for (n=0; n<3; n++)\n        Dtime[n] = algoTime[Q][n].tableTime + (algoTime[Q][n].decode256Time * D256);\n\n    Dtime[1] += Dtime[1] >> 4; Dtime[2] += Dtime[2] >> 3; /* advantage to algorithms using less memory, for cache eviction */\n\n    if (Dtime[1] < Dtime[0]) algoNb = 1;\n\n    return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);\n\n    /* return HUFv05_decompress4X2(dst, dstSize, cSrc, cSrcSize); */   /* multi-streams single-symbol decoding */\n    /* return HUFv05_decompress4X4(dst, dstSize, cSrc, cSrcSize); */   /* multi-streams double-symbols decoding */\n    /* return HUFv05_decompress4X6(dst, dstSize, cSrc, cSrcSize); */   /* multi-streams quad-symbols decoding */\n}\n/*\n    zstd - standard compression library\n    Copyright (C) 2014-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n*/\n\n/* ***************************************************************\n*  Tuning parameters\n*****************************************************************/\n/*!\n * HEAPMODE :\n * Select how default decompression function ZSTDv05_decompress() will allocate memory,\n * in memory stack (0), or in memory heap (1, requires malloc())\n */\n#ifndef ZSTDv05_HEAPMODE\n#  define ZSTDv05_HEAPMODE 1\n#endif\n\n\n/*-*******************************************************\n*  Dependencies\n*********************************************************/\n#include <stdlib.h>      /* calloc */\n#include <string.h>      /* memcpy, memmove */\n#include <stdio.h>       /* debug only : printf */\n\n\n/*-*******************************************************\n*  Compiler specifics\n*********************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4324)        /* disable: C4324: padded structure */\n#endif\n\n\n/*-*************************************\n*  Local types\n***************************************/\ntypedef struct\n{\n    blockType_t blockType;\n    U32 origSize;\n} blockProperties_t;\n\n\n/* *******************************************************\n*  Memory operations\n**********************************************************/\nstatic void ZSTDv05_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }\n\n\n/* *************************************\n*  Error Management\n***************************************/\n/*! ZSTDv05_isError() :\n*   tells if a return value is an error code */\nunsigned ZSTDv05_isError(size_t code) { return ERR_isError(code); }\n\n\n/*! ZSTDv05_getErrorName() :\n*   provides error code string (useful for debugging) */\nconst char* ZSTDv05_getErrorName(size_t code) { return ERR_getErrorName(code); }\n\n\n/* *************************************************************\n*   Context management\n***************************************************************/\ntypedef enum { ZSTDv05ds_getFrameHeaderSize, ZSTDv05ds_decodeFrameHeader,\n               ZSTDv05ds_decodeBlockHeader, ZSTDv05ds_decompressBlock } ZSTDv05_dStage;\n\nstruct ZSTDv05_DCtx_s\n{\n    FSEv05_DTable LLTable[FSEv05_DTABLE_SIZE_U32(LLFSEv05Log)];\n    FSEv05_DTable OffTable[FSEv05_DTABLE_SIZE_U32(OffFSEv05Log)];\n    FSEv05_DTable MLTable[FSEv05_DTABLE_SIZE_U32(MLFSEv05Log)];\n    unsigned   hufTableX4[HUFv05_DTABLE_SIZE(ZSTD_HUFFDTABLE_CAPACITY_LOG)];\n    const void* previousDstEnd;\n    const void* base;\n    const void* vBase;\n    const void* dictEnd;\n    size_t expected;\n    size_t headerSize;\n    ZSTDv05_parameters params;\n    blockType_t bType;   /* used in ZSTDv05_decompressContinue(), to transfer blockType between header decoding and block decoding stages */\n    ZSTDv05_dStage stage;\n    U32 flagStaticTables;\n    const BYTE* litPtr;\n    size_t litSize;\n    BYTE litBuffer[BLOCKSIZE + WILDCOPY_OVERLENGTH];\n    BYTE headerBuffer[ZSTDv05_frameHeaderSize_max];\n};  /* typedef'd to ZSTDv05_DCtx within \"zstd_static.h\" */\n\nsize_t ZSTDv05_sizeofDCtx (void); /* Hidden declaration */\nsize_t ZSTDv05_sizeofDCtx (void) { return sizeof(ZSTDv05_DCtx); }\n\nsize_t ZSTDv05_decompressBegin(ZSTDv05_DCtx* dctx)\n{\n    dctx->expected = ZSTDv05_frameHeaderSize_min;\n    dctx->stage = ZSTDv05ds_getFrameHeaderSize;\n    dctx->previousDstEnd = NULL;\n    dctx->base = NULL;\n    dctx->vBase = NULL;\n    dctx->dictEnd = NULL;\n    dctx->hufTableX4[0] = ZSTD_HUFFDTABLE_CAPACITY_LOG;\n    dctx->flagStaticTables = 0;\n    return 0;\n}\n\nZSTDv05_DCtx* ZSTDv05_createDCtx(void)\n{\n    ZSTDv05_DCtx* dctx = (ZSTDv05_DCtx*)malloc(sizeof(ZSTDv05_DCtx));\n    if (dctx==NULL) return NULL;\n    ZSTDv05_decompressBegin(dctx);\n    return dctx;\n}\n\nsize_t ZSTDv05_freeDCtx(ZSTDv05_DCtx* dctx)\n{\n    free(dctx);\n    return 0;   /* reserved as a potential error code in the future */\n}\n\nvoid ZSTDv05_copyDCtx(ZSTDv05_DCtx* dstDCtx, const ZSTDv05_DCtx* srcDCtx)\n{\n    memcpy(dstDCtx, srcDCtx,\n           sizeof(ZSTDv05_DCtx) - (BLOCKSIZE+WILDCOPY_OVERLENGTH + ZSTDv05_frameHeaderSize_max));  /* no need to copy workspace */\n}\n\n\n/* *************************************************************\n*   Decompression section\n***************************************************************/\n\n/* Frame format description\n   Frame Header -  [ Block Header - Block ] - Frame End\n   1) Frame Header\n      - 4 bytes - Magic Number : ZSTDv05_MAGICNUMBER (defined within zstd_internal.h)\n      - 1 byte  - Window Descriptor\n   2) Block Header\n      - 3 bytes, starting with a 2-bits descriptor\n                 Uncompressed, Compressed, Frame End, unused\n   3) Block\n      See Block Format Description\n   4) Frame End\n      - 3 bytes, compatible with Block Header\n*/\n\n/* Block format description\n\n   Block = Literal Section - Sequences Section\n   Prerequisite : size of (compressed) block, maximum size of regenerated data\n\n   1) Literal Section\n\n   1.1) Header : 1-5 bytes\n        flags: 2 bits\n            00 compressed by Huff0\n            01 unused\n            10 is Raw (uncompressed)\n            11 is Rle\n            Note : using 01 => Huff0 with precomputed table ?\n            Note : delta map ? => compressed ?\n\n   1.1.1) Huff0-compressed literal block : 3-5 bytes\n            srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream\n            srcSize < 1 KB => 3 bytes (2-2-10-10)\n            srcSize < 16KB => 4 bytes (2-2-14-14)\n            else           => 5 bytes (2-2-18-18)\n            big endian convention\n\n   1.1.2) Raw (uncompressed) literal block header : 1-3 bytes\n        size :  5 bits: (IS_RAW<<6) + (0<<4) + size\n               12 bits: (IS_RAW<<6) + (2<<4) + (size>>8)\n                        size&255\n               20 bits: (IS_RAW<<6) + (3<<4) + (size>>16)\n                        size>>8&255\n                        size&255\n\n   1.1.3) Rle (repeated single byte) literal block header : 1-3 bytes\n        size :  5 bits: (IS_RLE<<6) + (0<<4) + size\n               12 bits: (IS_RLE<<6) + (2<<4) + (size>>8)\n                        size&255\n               20 bits: (IS_RLE<<6) + (3<<4) + (size>>16)\n                        size>>8&255\n                        size&255\n\n   1.1.4) Huff0-compressed literal block, using precomputed CTables : 3-5 bytes\n            srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream\n            srcSize < 1 KB => 3 bytes (2-2-10-10)\n            srcSize < 16KB => 4 bytes (2-2-14-14)\n            else           => 5 bytes (2-2-18-18)\n            big endian convention\n\n        1- CTable available (stored into workspace ?)\n        2- Small input (fast heuristic ? Full comparison ? depend on clevel ?)\n\n\n   1.2) Literal block content\n\n   1.2.1) Huff0 block, using sizes from header\n        See Huff0 format\n\n   1.2.2) Huff0 block, using prepared table\n\n   1.2.3) Raw content\n\n   1.2.4) single byte\n\n\n   2) Sequences section\n      TO DO\n*/\n\n\n/** ZSTDv05_decodeFrameHeader_Part1() :\n*   decode the 1st part of the Frame Header, which tells Frame Header size.\n*   srcSize must be == ZSTDv05_frameHeaderSize_min.\n*   @return : the full size of the Frame Header */\nstatic size_t ZSTDv05_decodeFrameHeader_Part1(ZSTDv05_DCtx* zc, const void* src, size_t srcSize)\n{\n    U32 magicNumber;\n    if (srcSize != ZSTDv05_frameHeaderSize_min)\n        return ERROR(srcSize_wrong);\n    magicNumber = MEM_readLE32(src);\n    if (magicNumber != ZSTDv05_MAGICNUMBER) return ERROR(prefix_unknown);\n    zc->headerSize = ZSTDv05_frameHeaderSize_min;\n    return zc->headerSize;\n}\n\n\nsize_t ZSTDv05_getFrameParams(ZSTDv05_parameters* params, const void* src, size_t srcSize)\n{\n    U32 magicNumber;\n    if (srcSize < ZSTDv05_frameHeaderSize_min) return ZSTDv05_frameHeaderSize_max;\n    magicNumber = MEM_readLE32(src);\n    if (magicNumber != ZSTDv05_MAGICNUMBER) return ERROR(prefix_unknown);\n    memset(params, 0, sizeof(*params));\n    params->windowLog = (((const BYTE*)src)[4] & 15) + ZSTDv05_WINDOWLOG_ABSOLUTEMIN;\n    if ((((const BYTE*)src)[4] >> 4) != 0) return ERROR(frameParameter_unsupported);   /* reserved bits */\n    return 0;\n}\n\n/** ZSTDv05_decodeFrameHeader_Part2() :\n*   decode the full Frame Header.\n*   srcSize must be the size provided by ZSTDv05_decodeFrameHeader_Part1().\n*   @return : 0, or an error code, which can be tested using ZSTDv05_isError() */\nstatic size_t ZSTDv05_decodeFrameHeader_Part2(ZSTDv05_DCtx* zc, const void* src, size_t srcSize)\n{\n    size_t result;\n    if (srcSize != zc->headerSize)\n        return ERROR(srcSize_wrong);\n    result = ZSTDv05_getFrameParams(&(zc->params), src, srcSize);\n    if ((MEM_32bits()) && (zc->params.windowLog > 25)) return ERROR(frameParameter_unsupported);\n    return result;\n}\n\n\nstatic size_t ZSTDv05_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)\n{\n    const BYTE* const in = (const BYTE*)src;\n    BYTE headerFlags;\n    U32 cSize;\n\n    if (srcSize < 3)\n        return ERROR(srcSize_wrong);\n\n    headerFlags = *in;\n    cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);\n\n    bpPtr->blockType = (blockType_t)(headerFlags >> 6);\n    bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;\n\n    if (bpPtr->blockType == bt_end) return 0;\n    if (bpPtr->blockType == bt_rle) return 1;\n    return cSize;\n}\n\n\nstatic size_t ZSTDv05_copyRawBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    if (dst==NULL) return ERROR(dstSize_tooSmall);\n    if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall);\n    memcpy(dst, src, srcSize);\n    return srcSize;\n}\n\n\n/*! ZSTDv05_decodeLiteralsBlock() :\n    @return : nb of bytes read from src (< srcSize ) */\nstatic size_t ZSTDv05_decodeLiteralsBlock(ZSTDv05_DCtx* dctx,\n                                    const void* src, size_t srcSize)   /* note : srcSize < BLOCKSIZE */\n{\n    const BYTE* const istart = (const BYTE*) src;\n\n    /* any compressed block with literals segment must be at least this size */\n    if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);\n\n    switch(istart[0]>> 6)\n    {\n    case IS_HUFv05:\n        {\n            size_t litSize, litCSize, singleStream=0;\n            U32 lhSize = ((istart[0]) >> 4) & 3;\n            if (srcSize < 5) return ERROR(corruption_detected);   /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3 */\n            switch(lhSize)\n            {\n            case 0: case 1: default:   /* note : default is impossible, since lhSize into [0..3] */\n                /* 2 - 2 - 10 - 10 */\n                lhSize=3;\n                singleStream = istart[0] & 16;\n                litSize  = ((istart[0] & 15) << 6) + (istart[1] >> 2);\n                litCSize = ((istart[1] &  3) << 8) + istart[2];\n                break;\n            case 2:\n                /* 2 - 2 - 14 - 14 */\n                lhSize=4;\n                litSize  = ((istart[0] & 15) << 10) + (istart[1] << 2) + (istart[2] >> 6);\n                litCSize = ((istart[2] & 63) <<  8) + istart[3];\n                break;\n            case 3:\n                /* 2 - 2 - 18 - 18 */\n                lhSize=5;\n                litSize  = ((istart[0] & 15) << 14) + (istart[1] << 6) + (istart[2] >> 2);\n                litCSize = ((istart[2] &  3) << 16) + (istart[3] << 8) + istart[4];\n                break;\n            }\n            if (litSize > BLOCKSIZE) return ERROR(corruption_detected);\n            if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);\n\n            if (HUFv05_isError(singleStream ?\n                            HUFv05_decompress1X2(dctx->litBuffer, litSize, istart+lhSize, litCSize) :\n                            HUFv05_decompress   (dctx->litBuffer, litSize, istart+lhSize, litCSize) ))\n                return ERROR(corruption_detected);\n\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);\n            return litCSize + lhSize;\n        }\n    case IS_PCH:\n        {\n            size_t errorCode;\n            size_t litSize, litCSize;\n            U32 lhSize = ((istart[0]) >> 4) & 3;\n            if (lhSize != 1)  /* only case supported for now : small litSize, single stream */\n                return ERROR(corruption_detected);\n            if (!dctx->flagStaticTables)\n                return ERROR(dictionary_corrupted);\n\n            /* 2 - 2 - 10 - 10 */\n            lhSize=3;\n            litSize  = ((istart[0] & 15) << 6) + (istart[1] >> 2);\n            litCSize = ((istart[1] &  3) << 8) + istart[2];\n            if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);\n\n            errorCode = HUFv05_decompress1X4_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTableX4);\n            if (HUFv05_isError(errorCode)) return ERROR(corruption_detected);\n\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);\n            return litCSize + lhSize;\n        }\n    case IS_RAW:\n        {\n            size_t litSize;\n            U32 lhSize = ((istart[0]) >> 4) & 3;\n            switch(lhSize)\n            {\n            case 0: case 1: default:   /* note : default is impossible, since lhSize into [0..3] */\n                lhSize=1;\n                litSize = istart[0] & 31;\n                break;\n            case 2:\n                litSize = ((istart[0] & 15) << 8) + istart[1];\n                break;\n            case 3:\n                litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];\n                break;\n            }\n\n            if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) {  /* risk reading beyond src buffer with wildcopy */\n                if (litSize+lhSize > srcSize) return ERROR(corruption_detected);\n                memcpy(dctx->litBuffer, istart+lhSize, litSize);\n                dctx->litPtr = dctx->litBuffer;\n                dctx->litSize = litSize;\n                memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);\n                return lhSize+litSize;\n            }\n            /* direct reference into compressed stream */\n            dctx->litPtr = istart+lhSize;\n            dctx->litSize = litSize;\n            return lhSize+litSize;\n        }\n    case IS_RLE:\n        {\n            size_t litSize;\n            U32 lhSize = ((istart[0]) >> 4) & 3;\n            switch(lhSize)\n            {\n            case 0: case 1: default:   /* note : default is impossible, since lhSize into [0..3] */\n                lhSize = 1;\n                litSize = istart[0] & 31;\n                break;\n            case 2:\n                litSize = ((istart[0] & 15) << 8) + istart[1];\n                break;\n            case 3:\n                litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];\n                if (srcSize<4) return ERROR(corruption_detected);   /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */\n                break;\n            }\n            if (litSize > BLOCKSIZE) return ERROR(corruption_detected);\n            memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            return lhSize+1;\n        }\n    default:\n        return ERROR(corruption_detected);   /* impossible */\n    }\n}\n\n\nstatic size_t ZSTDv05_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLengthPtr,\n                         FSEv05_DTable* DTableLL, FSEv05_DTable* DTableML, FSEv05_DTable* DTableOffb,\n                         const void* src, size_t srcSize, U32 flagStaticTable)\n{\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* ip = istart;\n    const BYTE* const iend = istart + srcSize;\n    U32 LLtype, Offtype, MLtype;\n    unsigned LLlog, Offlog, MLlog;\n    size_t dumpsLength;\n\n    /* check */\n    if (srcSize < MIN_SEQUENCES_SIZE)\n        return ERROR(srcSize_wrong);\n\n    /* SeqHead */\n    *nbSeq = *ip++;\n    if (*nbSeq==0) return 1;\n    if (*nbSeq >= 128) {\n        if (ip >= iend) return ERROR(srcSize_wrong);\n        *nbSeq = ((nbSeq[0]-128)<<8) + *ip++;\n    }\n\n    if (ip >= iend) return ERROR(srcSize_wrong);\n    LLtype  = *ip >> 6;\n    Offtype = (*ip >> 4) & 3;\n    MLtype  = (*ip >> 2) & 3;\n    if (*ip & 2) {\n        if (ip+3 > iend) return ERROR(srcSize_wrong);\n        dumpsLength  = ip[2];\n        dumpsLength += ip[1] << 8;\n        ip += 3;\n    } else {\n        if (ip+2 > iend) return ERROR(srcSize_wrong);\n        dumpsLength  = ip[1];\n        dumpsLength += (ip[0] & 1) << 8;\n        ip += 2;\n    }\n    *dumpsPtr = ip;\n    ip += dumpsLength;\n    *dumpsLengthPtr = dumpsLength;\n\n    /* check */\n    if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are \"raw\", hence no header, but at least xxLog bits per type */\n\n    /* sequences */\n    {\n        S16 norm[MaxML+1];    /* assumption : MaxML >= MaxLL >= MaxOff */\n        size_t headerSize;\n\n        /* Build DTables */\n        switch(LLtype)\n        {\n        case FSEv05_ENCODING_RLE :\n            LLlog = 0;\n            FSEv05_buildDTable_rle(DTableLL, *ip++);\n            break;\n        case FSEv05_ENCODING_RAW :\n            LLlog = LLbits;\n            FSEv05_buildDTable_raw(DTableLL, LLbits);\n            break;\n        case FSEv05_ENCODING_STATIC:\n            if (!flagStaticTable) return ERROR(corruption_detected);\n            break;\n        case FSEv05_ENCODING_DYNAMIC :\n        default :   /* impossible */\n            {   unsigned max = MaxLL;\n                headerSize = FSEv05_readNCount(norm, &max, &LLlog, ip, iend-ip);\n                if (FSEv05_isError(headerSize)) return ERROR(GENERIC);\n                if (LLlog > LLFSEv05Log) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSEv05_buildDTable(DTableLL, norm, max, LLlog);\n        }   }\n\n        switch(Offtype)\n        {\n        case FSEv05_ENCODING_RLE :\n            Offlog = 0;\n            if (ip > iend-2) return ERROR(srcSize_wrong);   /* min : \"raw\", hence no header, but at least xxLog bits */\n            FSEv05_buildDTable_rle(DTableOffb, *ip++ & MaxOff); /* if *ip > MaxOff, data is corrupted */\n            break;\n        case FSEv05_ENCODING_RAW :\n            Offlog = Offbits;\n            FSEv05_buildDTable_raw(DTableOffb, Offbits);\n            break;\n        case FSEv05_ENCODING_STATIC:\n            if (!flagStaticTable) return ERROR(corruption_detected);\n            break;\n        case FSEv05_ENCODING_DYNAMIC :\n        default :   /* impossible */\n            {   unsigned max = MaxOff;\n                headerSize = FSEv05_readNCount(norm, &max, &Offlog, ip, iend-ip);\n                if (FSEv05_isError(headerSize)) return ERROR(GENERIC);\n                if (Offlog > OffFSEv05Log) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSEv05_buildDTable(DTableOffb, norm, max, Offlog);\n        }   }\n\n        switch(MLtype)\n        {\n        case FSEv05_ENCODING_RLE :\n            MLlog = 0;\n            if (ip > iend-2) return ERROR(srcSize_wrong); /* min : \"raw\", hence no header, but at least xxLog bits */\n            FSEv05_buildDTable_rle(DTableML, *ip++);\n            break;\n        case FSEv05_ENCODING_RAW :\n            MLlog = MLbits;\n            FSEv05_buildDTable_raw(DTableML, MLbits);\n            break;\n        case FSEv05_ENCODING_STATIC:\n            if (!flagStaticTable) return ERROR(corruption_detected);\n            break;\n        case FSEv05_ENCODING_DYNAMIC :\n        default :   /* impossible */\n            {   unsigned max = MaxML;\n                headerSize = FSEv05_readNCount(norm, &max, &MLlog, ip, iend-ip);\n                if (FSEv05_isError(headerSize)) return ERROR(GENERIC);\n                if (MLlog > MLFSEv05Log) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSEv05_buildDTable(DTableML, norm, max, MLlog);\n    }   }   }\n\n    return ip-istart;\n}\n\n\ntypedef struct {\n    size_t litLength;\n    size_t matchLength;\n    size_t offset;\n} seq_t;\n\ntypedef struct {\n    BITv05_DStream_t DStream;\n    FSEv05_DState_t stateLL;\n    FSEv05_DState_t stateOffb;\n    FSEv05_DState_t stateML;\n    size_t prevOffset;\n    const BYTE* dumps;\n    const BYTE* dumpsEnd;\n} seqState_t;\n\n\n\nstatic void ZSTDv05_decodeSequence(seq_t* seq, seqState_t* seqState)\n{\n    size_t litLength;\n    size_t prevOffset;\n    size_t offset;\n    size_t matchLength;\n    const BYTE* dumps = seqState->dumps;\n    const BYTE* const de = seqState->dumpsEnd;\n\n    /* Literal length */\n    litLength = FSEv05_peakSymbol(&(seqState->stateLL));\n    prevOffset = litLength ? seq->offset : seqState->prevOffset;\n    if (litLength == MaxLL) {\n        const U32 add = *dumps++;\n        if (add < 255) litLength += add;\n        else if (dumps + 2 <= de) {\n            litLength = MEM_readLE16(dumps);\n            dumps += 2;\n            if ((litLength & 1) && dumps < de) {\n                litLength += *dumps << 16;\n                dumps += 1;\n            }\n            litLength>>=1;\n        }\n        if (dumps >= de) { dumps = de-1; }  /* late correction, to avoid read overflow (data is now corrupted anyway) */\n    }\n\n    /* Offset */\n    {\n        static const U32 offsetPrefix[MaxOff+1] = {\n                1 /*fake*/, 1, 2, 4, 8, 16, 32, 64, 128, 256,\n                512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144,\n                524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, /*fake*/ 1, 1, 1, 1, 1 };\n        U32 offsetCode = FSEv05_peakSymbol(&(seqState->stateOffb));   /* <= maxOff, by table construction */\n        U32 nbBits = offsetCode - 1;\n        if (offsetCode==0) nbBits = 0;   /* cmove */\n        offset = offsetPrefix[offsetCode] + BITv05_readBits(&(seqState->DStream), nbBits);\n        if (MEM_32bits()) BITv05_reloadDStream(&(seqState->DStream));\n        if (offsetCode==0) offset = prevOffset;   /* repcode, cmove */\n        if (offsetCode | !litLength) seqState->prevOffset = seq->offset;   /* cmove */\n        FSEv05_decodeSymbol(&(seqState->stateOffb), &(seqState->DStream));    /* update */\n    }\n\n    /* Literal length update */\n    FSEv05_decodeSymbol(&(seqState->stateLL), &(seqState->DStream));   /* update */\n    if (MEM_32bits()) BITv05_reloadDStream(&(seqState->DStream));\n\n    /* MatchLength */\n    matchLength = FSEv05_decodeSymbol(&(seqState->stateML), &(seqState->DStream));\n    if (matchLength == MaxML) {\n        const U32 add = dumps<de ? *dumps++ : 0;\n        if (add < 255) matchLength += add;\n        else if (dumps + 2 <= de) {\n            matchLength = MEM_readLE16(dumps);\n            dumps += 2;\n            if ((matchLength & 1) && dumps < de) {\n                matchLength += *dumps << 16;\n                dumps += 1;\n            }\n            matchLength >>= 1;\n        }\n        if (dumps >= de) { dumps = de-1; }  /* late correction, to avoid read overflow (data is now corrupted anyway) */\n    }\n    matchLength += MINMATCH;\n\n    /* save result */\n    seq->litLength = litLength;\n    seq->offset = offset;\n    seq->matchLength = matchLength;\n    seqState->dumps = dumps;\n\n#if 0   /* debug */\n    {\n        static U64 totalDecoded = 0;\n        printf(\"pos %6u : %3u literals & match %3u bytes at distance %6u \\n\",\n           (U32)(totalDecoded), (U32)litLength, (U32)matchLength, (U32)offset);\n        totalDecoded += litLength + matchLength;\n    }\n#endif\n}\n\n\nstatic size_t ZSTDv05_execSequence(BYTE* op,\n                                BYTE* const oend, seq_t sequence,\n                                const BYTE** litPtr, const BYTE* const litLimit,\n                                const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)\n{\n    static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 };   /* added */\n    static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 };   /* subtracted */\n    BYTE* const oLitEnd = op + sequence.litLength;\n    const size_t sequenceLength = sequence.litLength + sequence.matchLength;\n    BYTE* const oMatchEnd = op + sequenceLength;   /* risk : address space overflow (32-bits) */\n    BYTE* const oend_8 = oend-8;\n    const BYTE* const litEnd = *litPtr + sequence.litLength;\n    const BYTE* match = oLitEnd - sequence.offset;\n\n    /* checks */\n    size_t const seqLength = sequence.litLength + sequence.matchLength;\n\n    if (seqLength > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);\n    if (sequence.litLength > (size_t)(litLimit - *litPtr)) return ERROR(corruption_detected);\n    /* Now we know there are no overflow in literal nor match lengths, can use pointer checks */\n    if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall);\n\n    if (oMatchEnd > oend) return ERROR(dstSize_tooSmall);   /* overwrite beyond dst buffer */\n    if (litEnd > litLimit) return ERROR(corruption_detected);   /* overRead beyond lit buffer */\n\n    /* copy Literals */\n    ZSTDv05_wildcopy(op, *litPtr, (ptrdiff_t)sequence.litLength);   /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */\n    op = oLitEnd;\n    *litPtr = litEnd;   /* update for next sequence */\n\n    /* copy Match */\n    if (sequence.offset > (size_t)(oLitEnd - base)) {\n        /* offset beyond prefix */\n        if (sequence.offset > (size_t)(oLitEnd - vBase))\n            return ERROR(corruption_detected);\n        match = dictEnd - (base-match);\n        if (match + sequence.matchLength <= dictEnd) {\n            memmove(oLitEnd, match, sequence.matchLength);\n            return sequenceLength;\n        }\n        /* span extDict & currentPrefixSegment */\n        {\n            size_t length1 = dictEnd - match;\n            memmove(oLitEnd, match, length1);\n            op = oLitEnd + length1;\n            sequence.matchLength -= length1;\n            match = base;\n            if (op > oend_8 || sequence.matchLength < MINMATCH) {\n              while (op < oMatchEnd) *op++ = *match++;\n              return sequenceLength;\n            }\n    }   }\n    /* Requirement: op <= oend_8 */\n\n    /* match within prefix */\n    if (sequence.offset < 8) {\n        /* close range match, overlap */\n        const int sub2 = dec64table[sequence.offset];\n        op[0] = match[0];\n        op[1] = match[1];\n        op[2] = match[2];\n        op[3] = match[3];\n        match += dec32table[sequence.offset];\n        ZSTDv05_copy4(op+4, match);\n        match -= sub2;\n    } else {\n        ZSTDv05_copy8(op, match);\n    }\n    op += 8; match += 8;\n\n    if (oMatchEnd > oend-(16-MINMATCH)) {\n        if (op < oend_8) {\n            ZSTDv05_wildcopy(op, match, oend_8 - op);\n            match += oend_8 - op;\n            op = oend_8;\n        }\n        while (op < oMatchEnd)\n            *op++ = *match++;\n    } else {\n        ZSTDv05_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8);   /* works even if matchLength < 8 */\n    }\n    return sequenceLength;\n}\n\n\nstatic size_t ZSTDv05_decompressSequences(\n                               ZSTDv05_DCtx* dctx,\n                               void* dst, size_t maxDstSize,\n                         const void* seqStart, size_t seqSize)\n{\n    const BYTE* ip = (const BYTE*)seqStart;\n    const BYTE* const iend = ip + seqSize;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + maxDstSize;\n    size_t errorCode, dumpsLength=0;\n    const BYTE* litPtr = dctx->litPtr;\n    const BYTE* const litEnd = litPtr + dctx->litSize;\n    int nbSeq=0;\n    const BYTE* dumps = NULL;\n    unsigned* DTableLL = dctx->LLTable;\n    unsigned* DTableML = dctx->MLTable;\n    unsigned* DTableOffb = dctx->OffTable;\n    const BYTE* const base = (const BYTE*) (dctx->base);\n    const BYTE* const vBase = (const BYTE*) (dctx->vBase);\n    const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);\n\n    /* Build Decoding Tables */\n    errorCode = ZSTDv05_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,\n                                      DTableLL, DTableML, DTableOffb,\n                                      ip, seqSize, dctx->flagStaticTables);\n    if (ZSTDv05_isError(errorCode)) return errorCode;\n    ip += errorCode;\n\n    /* Regen sequences */\n    if (nbSeq) {\n        seq_t sequence;\n        seqState_t seqState;\n\n        memset(&sequence, 0, sizeof(sequence));\n        sequence.offset = REPCODE_STARTVALUE;\n        seqState.dumps = dumps;\n        seqState.dumpsEnd = dumps + dumpsLength;\n        seqState.prevOffset = REPCODE_STARTVALUE;\n        errorCode = BITv05_initDStream(&(seqState.DStream), ip, iend-ip);\n        if (ERR_isError(errorCode)) return ERROR(corruption_detected);\n        FSEv05_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);\n        FSEv05_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);\n        FSEv05_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);\n\n        for ( ; (BITv05_reloadDStream(&(seqState.DStream)) <= BITv05_DStream_completed) && nbSeq ; ) {\n            size_t oneSeqSize;\n            nbSeq--;\n            ZSTDv05_decodeSequence(&sequence, &seqState);\n            oneSeqSize = ZSTDv05_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);\n            if (ZSTDv05_isError(oneSeqSize)) return oneSeqSize;\n            op += oneSeqSize;\n        }\n\n        /* check if reached exact end */\n        if (nbSeq) return ERROR(corruption_detected);\n    }\n\n    /* last literal segment */\n    {\n        size_t lastLLSize = litEnd - litPtr;\n        if (litPtr > litEnd) return ERROR(corruption_detected);   /* too many literals already used */\n        if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);\n        if (lastLLSize > 0) {\n            memcpy(op, litPtr, lastLLSize);\n            op += lastLLSize;\n        }\n    }\n\n    return op-ostart;\n}\n\n\nstatic void ZSTDv05_checkContinuity(ZSTDv05_DCtx* dctx, const void* dst)\n{\n    if (dst != dctx->previousDstEnd) {   /* not contiguous */\n        dctx->dictEnd = dctx->previousDstEnd;\n        dctx->vBase = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));\n        dctx->base = dst;\n        dctx->previousDstEnd = dst;\n    }\n}\n\n\nstatic size_t ZSTDv05_decompressBlock_internal(ZSTDv05_DCtx* dctx,\n                            void* dst, size_t dstCapacity,\n                      const void* src, size_t srcSize)\n{   /* blockType == blockCompressed */\n    const BYTE* ip = (const BYTE*)src;\n    size_t litCSize;\n\n    if (srcSize >= BLOCKSIZE) return ERROR(srcSize_wrong);\n\n    /* Decode literals sub-block */\n    litCSize = ZSTDv05_decodeLiteralsBlock(dctx, src, srcSize);\n    if (ZSTDv05_isError(litCSize)) return litCSize;\n    ip += litCSize;\n    srcSize -= litCSize;\n\n    return ZSTDv05_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);\n}\n\n\nsize_t ZSTDv05_decompressBlock(ZSTDv05_DCtx* dctx,\n                            void* dst, size_t dstCapacity,\n                      const void* src, size_t srcSize)\n{\n    ZSTDv05_checkContinuity(dctx, dst);\n    return ZSTDv05_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);\n}\n\n\n/*! ZSTDv05_decompress_continueDCtx\n*   dctx must have been properly initialized */\nstatic size_t ZSTDv05_decompress_continueDCtx(ZSTDv05_DCtx* dctx,\n                                 void* dst, size_t maxDstSize,\n                                 const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n    const BYTE* iend = ip + srcSize;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + maxDstSize;\n    size_t remainingSize = srcSize;\n    blockProperties_t blockProperties;\n    memset(&blockProperties, 0, sizeof(blockProperties));\n\n    /* Frame Header */\n    {   size_t frameHeaderSize;\n        if (srcSize < ZSTDv05_frameHeaderSize_min+ZSTDv05_blockHeaderSize) return ERROR(srcSize_wrong);\n        frameHeaderSize = ZSTDv05_decodeFrameHeader_Part1(dctx, src, ZSTDv05_frameHeaderSize_min);\n        if (ZSTDv05_isError(frameHeaderSize)) return frameHeaderSize;\n        if (srcSize < frameHeaderSize+ZSTDv05_blockHeaderSize) return ERROR(srcSize_wrong);\n        ip += frameHeaderSize; remainingSize -= frameHeaderSize;\n        frameHeaderSize = ZSTDv05_decodeFrameHeader_Part2(dctx, src, frameHeaderSize);\n        if (ZSTDv05_isError(frameHeaderSize)) return frameHeaderSize;\n    }\n\n    /* Loop on each block */\n    while (1)\n    {\n        size_t decodedSize=0;\n        size_t cBlockSize = ZSTDv05_getcBlockSize(ip, iend-ip, &blockProperties);\n        if (ZSTDv05_isError(cBlockSize)) return cBlockSize;\n\n        ip += ZSTDv05_blockHeaderSize;\n        remainingSize -= ZSTDv05_blockHeaderSize;\n        if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);\n\n        switch(blockProperties.blockType)\n        {\n        case bt_compressed:\n            decodedSize = ZSTDv05_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize);\n            break;\n        case bt_raw :\n            decodedSize = ZSTDv05_copyRawBlock(op, oend-op, ip, cBlockSize);\n            break;\n        case bt_rle :\n            return ERROR(GENERIC);   /* not yet supported */\n            break;\n        case bt_end :\n            /* end of frame */\n            if (remainingSize) return ERROR(srcSize_wrong);\n            break;\n        default:\n            return ERROR(GENERIC);   /* impossible */\n        }\n        if (cBlockSize == 0) break;   /* bt_end */\n\n        if (ZSTDv05_isError(decodedSize)) return decodedSize;\n        op += decodedSize;\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n    }\n\n    return op-ostart;\n}\n\n\nsize_t ZSTDv05_decompress_usingPreparedDCtx(ZSTDv05_DCtx* dctx, const ZSTDv05_DCtx* refDCtx,\n                                         void* dst, size_t maxDstSize,\n                                   const void* src, size_t srcSize)\n{\n    ZSTDv05_copyDCtx(dctx, refDCtx);\n    ZSTDv05_checkContinuity(dctx, dst);\n    return ZSTDv05_decompress_continueDCtx(dctx, dst, maxDstSize, src, srcSize);\n}\n\n\nsize_t ZSTDv05_decompress_usingDict(ZSTDv05_DCtx* dctx,\n                                 void* dst, size_t maxDstSize,\n                                 const void* src, size_t srcSize,\n                                 const void* dict, size_t dictSize)\n{\n    ZSTDv05_decompressBegin_usingDict(dctx, dict, dictSize);\n    ZSTDv05_checkContinuity(dctx, dst);\n    return ZSTDv05_decompress_continueDCtx(dctx, dst, maxDstSize, src, srcSize);\n}\n\n\nsize_t ZSTDv05_decompressDCtx(ZSTDv05_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    return ZSTDv05_decompress_usingDict(dctx, dst, maxDstSize, src, srcSize, NULL, 0);\n}\n\nsize_t ZSTDv05_decompress(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n#if defined(ZSTDv05_HEAPMODE) && (ZSTDv05_HEAPMODE==1)\n    size_t regenSize;\n    ZSTDv05_DCtx* dctx = ZSTDv05_createDCtx();\n    if (dctx==NULL) return ERROR(memory_allocation);\n    regenSize = ZSTDv05_decompressDCtx(dctx, dst, maxDstSize, src, srcSize);\n    ZSTDv05_freeDCtx(dctx);\n    return regenSize;\n#else\n    ZSTDv05_DCtx dctx;\n    return ZSTDv05_decompressDCtx(&dctx, dst, maxDstSize, src, srcSize);\n#endif\n}\n\n/* ZSTD_errorFrameSizeInfoLegacy() :\n   assumes `cSize` and `dBound` are _not_ NULL */\nstatic void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)\n{\n    *cSize = ret;\n    *dBound = ZSTD_CONTENTSIZE_ERROR;\n}\n\nvoid ZSTDv05_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)\n{\n    const BYTE* ip = (const BYTE*)src;\n    size_t remainingSize = srcSize;\n    size_t nbBlocks = 0;\n    blockProperties_t blockProperties;\n\n    /* Frame Header */\n    if (srcSize < ZSTDv05_frameHeaderSize_min) {\n        ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n        return;\n    }\n    if (MEM_readLE32(src) != ZSTDv05_MAGICNUMBER) {\n        ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));\n        return;\n    }\n    ip += ZSTDv05_frameHeaderSize_min; remainingSize -= ZSTDv05_frameHeaderSize_min;\n\n    /* Loop on each block */\n    while (1)\n    {\n        size_t cBlockSize = ZSTDv05_getcBlockSize(ip, remainingSize, &blockProperties);\n        if (ZSTDv05_isError(cBlockSize)) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);\n            return;\n        }\n\n        ip += ZSTDv05_blockHeaderSize;\n        remainingSize -= ZSTDv05_blockHeaderSize;\n        if (cBlockSize > remainingSize) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n            return;\n        }\n\n        if (cBlockSize == 0) break;   /* bt_end */\n\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n        nbBlocks++;\n    }\n\n    *cSize = ip - (const BYTE*)src;\n    *dBound = nbBlocks * BLOCKSIZE;\n}\n\n/* ******************************\n*  Streaming Decompression API\n********************************/\nsize_t ZSTDv05_nextSrcSizeToDecompress(ZSTDv05_DCtx* dctx)\n{\n    return dctx->expected;\n}\n\nsize_t ZSTDv05_decompressContinue(ZSTDv05_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    /* Sanity check */\n    if (srcSize != dctx->expected) return ERROR(srcSize_wrong);\n    ZSTDv05_checkContinuity(dctx, dst);\n\n    /* Decompress : frame header; part 1 */\n    switch (dctx->stage)\n    {\n    case ZSTDv05ds_getFrameHeaderSize :\n        /* get frame header size */\n        if (srcSize != ZSTDv05_frameHeaderSize_min) return ERROR(srcSize_wrong);   /* impossible */\n        dctx->headerSize = ZSTDv05_decodeFrameHeader_Part1(dctx, src, ZSTDv05_frameHeaderSize_min);\n        if (ZSTDv05_isError(dctx->headerSize)) return dctx->headerSize;\n        memcpy(dctx->headerBuffer, src, ZSTDv05_frameHeaderSize_min);\n        if (dctx->headerSize > ZSTDv05_frameHeaderSize_min) return ERROR(GENERIC); /* should never happen */\n        dctx->expected = 0;   /* not necessary to copy more */\n        /* fallthrough */\n    case ZSTDv05ds_decodeFrameHeader:\n        /* get frame header */\n        {   size_t const result = ZSTDv05_decodeFrameHeader_Part2(dctx, dctx->headerBuffer, dctx->headerSize);\n            if (ZSTDv05_isError(result)) return result;\n            dctx->expected = ZSTDv05_blockHeaderSize;\n            dctx->stage = ZSTDv05ds_decodeBlockHeader;\n            return 0;\n        }\n    case ZSTDv05ds_decodeBlockHeader:\n        {\n            /* Decode block header */\n            blockProperties_t bp;\n            size_t blockSize = ZSTDv05_getcBlockSize(src, ZSTDv05_blockHeaderSize, &bp);\n            if (ZSTDv05_isError(blockSize)) return blockSize;\n            if (bp.blockType == bt_end) {\n                dctx->expected = 0;\n                dctx->stage = ZSTDv05ds_getFrameHeaderSize;\n            }\n            else {\n                dctx->expected = blockSize;\n                dctx->bType = bp.blockType;\n                dctx->stage = ZSTDv05ds_decompressBlock;\n            }\n            return 0;\n        }\n    case ZSTDv05ds_decompressBlock:\n        {\n            /* Decompress : block content */\n            size_t rSize;\n            switch(dctx->bType)\n            {\n            case bt_compressed:\n                rSize = ZSTDv05_decompressBlock_internal(dctx, dst, maxDstSize, src, srcSize);\n                break;\n            case bt_raw :\n                rSize = ZSTDv05_copyRawBlock(dst, maxDstSize, src, srcSize);\n                break;\n            case bt_rle :\n                return ERROR(GENERIC);   /* not yet handled */\n                break;\n            case bt_end :   /* should never happen (filtered at phase 1) */\n                rSize = 0;\n                break;\n            default:\n                return ERROR(GENERIC);   /* impossible */\n            }\n            dctx->stage = ZSTDv05ds_decodeBlockHeader;\n            dctx->expected = ZSTDv05_blockHeaderSize;\n            if (ZSTDv05_isError(rSize)) return rSize;\n            dctx->previousDstEnd = (char*)dst + rSize;\n            return rSize;\n        }\n    default:\n        return ERROR(GENERIC);   /* impossible */\n    }\n}\n\n\nstatic void ZSTDv05_refDictContent(ZSTDv05_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    dctx->dictEnd = dctx->previousDstEnd;\n    dctx->vBase = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));\n    dctx->base = dict;\n    dctx->previousDstEnd = (const char*)dict + dictSize;\n}\n\nstatic size_t ZSTDv05_loadEntropy(ZSTDv05_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    size_t hSize, offcodeHeaderSize, matchlengthHeaderSize, errorCode, litlengthHeaderSize;\n    short offcodeNCount[MaxOff+1];\n    unsigned offcodeMaxValue=MaxOff, offcodeLog;\n    short matchlengthNCount[MaxML+1];\n    unsigned matchlengthMaxValue = MaxML, matchlengthLog;\n    short litlengthNCount[MaxLL+1];\n    unsigned litlengthMaxValue = MaxLL, litlengthLog;\n\n    hSize = HUFv05_readDTableX4(dctx->hufTableX4, dict, dictSize);\n    if (HUFv05_isError(hSize)) return ERROR(dictionary_corrupted);\n    dict = (const char*)dict + hSize;\n    dictSize -= hSize;\n\n    offcodeHeaderSize = FSEv05_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dict, dictSize);\n    if (FSEv05_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);\n    if (offcodeLog > OffFSEv05Log) return ERROR(dictionary_corrupted);\n    errorCode = FSEv05_buildDTable(dctx->OffTable, offcodeNCount, offcodeMaxValue, offcodeLog);\n    if (FSEv05_isError(errorCode)) return ERROR(dictionary_corrupted);\n    dict = (const char*)dict + offcodeHeaderSize;\n    dictSize -= offcodeHeaderSize;\n\n    matchlengthHeaderSize = FSEv05_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dict, dictSize);\n    if (FSEv05_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);\n    if (matchlengthLog > MLFSEv05Log) return ERROR(dictionary_corrupted);\n    errorCode = FSEv05_buildDTable(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);\n    if (FSEv05_isError(errorCode)) return ERROR(dictionary_corrupted);\n    dict = (const char*)dict + matchlengthHeaderSize;\n    dictSize -= matchlengthHeaderSize;\n\n    litlengthHeaderSize = FSEv05_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dict, dictSize);\n    if (litlengthLog > LLFSEv05Log) return ERROR(dictionary_corrupted);\n    if (FSEv05_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);\n    errorCode = FSEv05_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog);\n    if (FSEv05_isError(errorCode)) return ERROR(dictionary_corrupted);\n\n    dctx->flagStaticTables = 1;\n    return hSize + offcodeHeaderSize + matchlengthHeaderSize + litlengthHeaderSize;\n}\n\nstatic size_t ZSTDv05_decompress_insertDictionary(ZSTDv05_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    size_t eSize;\n    U32 magic = MEM_readLE32(dict);\n    if (magic != ZSTDv05_DICT_MAGIC) {\n        /* pure content mode */\n        ZSTDv05_refDictContent(dctx, dict, dictSize);\n        return 0;\n    }\n    /* load entropy tables */\n    dict = (const char*)dict + 4;\n    dictSize -= 4;\n    eSize = ZSTDv05_loadEntropy(dctx, dict, dictSize);\n    if (ZSTDv05_isError(eSize)) return ERROR(dictionary_corrupted);\n\n    /* reference dictionary content */\n    dict = (const char*)dict + eSize;\n    dictSize -= eSize;\n    ZSTDv05_refDictContent(dctx, dict, dictSize);\n\n    return 0;\n}\n\n\nsize_t ZSTDv05_decompressBegin_usingDict(ZSTDv05_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    size_t errorCode;\n    errorCode = ZSTDv05_decompressBegin(dctx);\n    if (ZSTDv05_isError(errorCode)) return errorCode;\n\n    if (dict && dictSize) {\n        errorCode = ZSTDv05_decompress_insertDictionary(dctx, dict, dictSize);\n        if (ZSTDv05_isError(errorCode)) return ERROR(dictionary_corrupted);\n    }\n\n    return 0;\n}\n\n/*\n    Buffered version of Zstd compression library\n    Copyright (C) 2015-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n    - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n\n/* The objects defined into this file should be considered experimental.\n * They are not labelled stable, as their prototype may change in the future.\n * You can use them for tests, provide feedback, or if you can endure risk of future changes.\n */\n\n\n\n/* *************************************\n*  Constants\n***************************************/\nstatic size_t ZBUFFv05_blockHeaderSize = 3;\n\n\n\n/* *** Compression *** */\n\nstatic size_t ZBUFFv05_limitCopy(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    size_t length = MIN(maxDstSize, srcSize);\n    if (length > 0) {\n        memcpy(dst, src, length);\n    }\n    return length;\n}\n\n\n\n\n/** ************************************************\n*  Streaming decompression\n*\n*  A ZBUFFv05_DCtx object is required to track streaming operation.\n*  Use ZBUFFv05_createDCtx() and ZBUFFv05_freeDCtx() to create/release resources.\n*  Use ZBUFFv05_decompressInit() to start a new decompression operation.\n*  ZBUFFv05_DCtx objects can be reused multiple times.\n*\n*  Use ZBUFFv05_decompressContinue() repetitively to consume your input.\n*  *srcSizePtr and *maxDstSizePtr can be any size.\n*  The function will report how many bytes were read or written by modifying *srcSizePtr and *maxDstSizePtr.\n*  Note that it may not consume the entire input, in which case it's up to the caller to call again the function with remaining input.\n*  The content of dst will be overwritten (up to *maxDstSizePtr) at each function call, so save its content if it matters or change dst .\n*  return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to improve latency)\n*            or 0 when a frame is completely decoded\n*            or an error code, which can be tested using ZBUFFv05_isError().\n*\n*  Hint : recommended buffer sizes (not compulsory)\n*  output : 128 KB block size is the internal unit, it ensures it's always possible to write a full block when it's decoded.\n*  input : just follow indications from ZBUFFv05_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .\n* **************************************************/\n\ntypedef enum { ZBUFFv05ds_init, ZBUFFv05ds_readHeader, ZBUFFv05ds_loadHeader, ZBUFFv05ds_decodeHeader,\n               ZBUFFv05ds_read, ZBUFFv05ds_load, ZBUFFv05ds_flush } ZBUFFv05_dStage;\n\n/* *** Resource management *** */\n\n#define ZSTDv05_frameHeaderSize_max 5   /* too magical, should come from reference */\nstruct ZBUFFv05_DCtx_s {\n    ZSTDv05_DCtx* zc;\n    ZSTDv05_parameters params;\n    char* inBuff;\n    size_t inBuffSize;\n    size_t inPos;\n    char* outBuff;\n    size_t outBuffSize;\n    size_t outStart;\n    size_t outEnd;\n    size_t hPos;\n    ZBUFFv05_dStage stage;\n    unsigned char headerBuffer[ZSTDv05_frameHeaderSize_max];\n};   /* typedef'd to ZBUFFv05_DCtx within \"zstd_buffered.h\" */\n\n\nZBUFFv05_DCtx* ZBUFFv05_createDCtx(void)\n{\n    ZBUFFv05_DCtx* zbc = (ZBUFFv05_DCtx*)malloc(sizeof(ZBUFFv05_DCtx));\n    if (zbc==NULL) return NULL;\n    memset(zbc, 0, sizeof(*zbc));\n    zbc->zc = ZSTDv05_createDCtx();\n    zbc->stage = ZBUFFv05ds_init;\n    return zbc;\n}\n\nsize_t ZBUFFv05_freeDCtx(ZBUFFv05_DCtx* zbc)\n{\n    if (zbc==NULL) return 0;   /* support free on null */\n    ZSTDv05_freeDCtx(zbc->zc);\n    free(zbc->inBuff);\n    free(zbc->outBuff);\n    free(zbc);\n    return 0;\n}\n\n\n/* *** Initialization *** */\n\nsize_t ZBUFFv05_decompressInitDictionary(ZBUFFv05_DCtx* zbc, const void* dict, size_t dictSize)\n{\n    zbc->stage = ZBUFFv05ds_readHeader;\n    zbc->hPos = zbc->inPos = zbc->outStart = zbc->outEnd = 0;\n    return ZSTDv05_decompressBegin_usingDict(zbc->zc, dict, dictSize);\n}\n\nsize_t ZBUFFv05_decompressInit(ZBUFFv05_DCtx* zbc)\n{\n    return ZBUFFv05_decompressInitDictionary(zbc, NULL, 0);\n}\n\n\n/* *** Decompression *** */\n\nsize_t ZBUFFv05_decompressContinue(ZBUFFv05_DCtx* zbc, void* dst, size_t* maxDstSizePtr, const void* src, size_t* srcSizePtr)\n{\n    const char* const istart = (const char*)src;\n    const char* ip = istart;\n    const char* const iend = istart + *srcSizePtr;\n    char* const ostart = (char*)dst;\n    char* op = ostart;\n    char* const oend = ostart + *maxDstSizePtr;\n    U32 notDone = 1;\n\n    while (notDone) {\n        switch(zbc->stage)\n        {\n        case ZBUFFv05ds_init :\n            return ERROR(init_missing);\n\n        case ZBUFFv05ds_readHeader :\n            /* read header from src */\n            {\n                size_t headerSize = ZSTDv05_getFrameParams(&(zbc->params), src, *srcSizePtr);\n                if (ZSTDv05_isError(headerSize)) return headerSize;\n                if (headerSize) {\n                    /* not enough input to decode header : tell how many bytes would be necessary */\n                    memcpy(zbc->headerBuffer+zbc->hPos, src, *srcSizePtr);\n                    zbc->hPos += *srcSizePtr;\n                    *maxDstSizePtr = 0;\n                    zbc->stage = ZBUFFv05ds_loadHeader;\n                    return headerSize - zbc->hPos;\n                }\n                zbc->stage = ZBUFFv05ds_decodeHeader;\n                break;\n            }\n\t    /* fall-through */\n        case ZBUFFv05ds_loadHeader:\n            /* complete header from src */\n            {\n                size_t headerSize = ZBUFFv05_limitCopy(\n                    zbc->headerBuffer + zbc->hPos, ZSTDv05_frameHeaderSize_max - zbc->hPos,\n                    src, *srcSizePtr);\n                zbc->hPos += headerSize;\n                ip += headerSize;\n                headerSize = ZSTDv05_getFrameParams(&(zbc->params), zbc->headerBuffer, zbc->hPos);\n                if (ZSTDv05_isError(headerSize)) return headerSize;\n                if (headerSize) {\n                    /* not enough input to decode header : tell how many bytes would be necessary */\n                    *maxDstSizePtr = 0;\n                    return headerSize - zbc->hPos;\n                }\n                /* zbc->stage = ZBUFFv05ds_decodeHeader; break; */   /* useless : stage follows */\n            }\n\t    /* fall-through */\n        case ZBUFFv05ds_decodeHeader:\n                /* apply header to create / resize buffers */\n                {\n                    size_t neededOutSize = (size_t)1 << zbc->params.windowLog;\n                    size_t neededInSize = BLOCKSIZE;   /* a block is never > BLOCKSIZE */\n                    if (zbc->inBuffSize < neededInSize) {\n                        free(zbc->inBuff);\n                        zbc->inBuffSize = neededInSize;\n                        zbc->inBuff = (char*)malloc(neededInSize);\n                        if (zbc->inBuff == NULL) return ERROR(memory_allocation);\n                    }\n                    if (zbc->outBuffSize < neededOutSize) {\n                        free(zbc->outBuff);\n                        zbc->outBuffSize = neededOutSize;\n                        zbc->outBuff = (char*)malloc(neededOutSize);\n                        if (zbc->outBuff == NULL) return ERROR(memory_allocation);\n                }   }\n                if (zbc->hPos) {\n                    /* some data already loaded into headerBuffer : transfer into inBuff */\n                    memcpy(zbc->inBuff, zbc->headerBuffer, zbc->hPos);\n                    zbc->inPos = zbc->hPos;\n                    zbc->hPos = 0;\n                    zbc->stage = ZBUFFv05ds_load;\n                    break;\n                }\n                zbc->stage = ZBUFFv05ds_read;\n\t\t/* fall-through */\n        case ZBUFFv05ds_read:\n            {\n                size_t neededInSize = ZSTDv05_nextSrcSizeToDecompress(zbc->zc);\n                if (neededInSize==0) {  /* end of frame */\n                    zbc->stage = ZBUFFv05ds_init;\n                    notDone = 0;\n                    break;\n                }\n                if ((size_t)(iend-ip) >= neededInSize) {\n                    /* directly decode from src */\n                    size_t decodedSize = ZSTDv05_decompressContinue(zbc->zc,\n                        zbc->outBuff + zbc->outStart, zbc->outBuffSize - zbc->outStart,\n                        ip, neededInSize);\n                    if (ZSTDv05_isError(decodedSize)) return decodedSize;\n                    ip += neededInSize;\n                    if (!decodedSize) break;   /* this was just a header */\n                    zbc->outEnd = zbc->outStart +  decodedSize;\n                    zbc->stage = ZBUFFv05ds_flush;\n                    break;\n                }\n                if (ip==iend) { notDone = 0; break; }   /* no more input */\n                zbc->stage = ZBUFFv05ds_load;\n            }\n\t    /* fall-through */\n        case ZBUFFv05ds_load:\n            {\n                size_t neededInSize = ZSTDv05_nextSrcSizeToDecompress(zbc->zc);\n                size_t toLoad = neededInSize - zbc->inPos;   /* should always be <= remaining space within inBuff */\n                size_t loadedSize;\n                if (toLoad > zbc->inBuffSize - zbc->inPos) return ERROR(corruption_detected);   /* should never happen */\n                loadedSize = ZBUFFv05_limitCopy(zbc->inBuff + zbc->inPos, toLoad, ip, iend-ip);\n                ip += loadedSize;\n                zbc->inPos += loadedSize;\n                if (loadedSize < toLoad) { notDone = 0; break; }   /* not enough input, wait for more */\n                {\n                    size_t decodedSize = ZSTDv05_decompressContinue(zbc->zc,\n                        zbc->outBuff + zbc->outStart, zbc->outBuffSize - zbc->outStart,\n                        zbc->inBuff, neededInSize);\n                    if (ZSTDv05_isError(decodedSize)) return decodedSize;\n                    zbc->inPos = 0;   /* input is consumed */\n                    if (!decodedSize) { zbc->stage = ZBUFFv05ds_read; break; }   /* this was just a header */\n                    zbc->outEnd = zbc->outStart +  decodedSize;\n                    zbc->stage = ZBUFFv05ds_flush;\n                    /* break; */  /* ZBUFFv05ds_flush follows */\n                }\n\t    }\n\t    /* fall-through */\n        case ZBUFFv05ds_flush:\n            {\n                size_t toFlushSize = zbc->outEnd - zbc->outStart;\n                size_t flushedSize = ZBUFFv05_limitCopy(op, oend-op, zbc->outBuff + zbc->outStart, toFlushSize);\n                op += flushedSize;\n                zbc->outStart += flushedSize;\n                if (flushedSize == toFlushSize) {\n                    zbc->stage = ZBUFFv05ds_read;\n                    if (zbc->outStart + BLOCKSIZE > zbc->outBuffSize) {\n                        /* Not enough room for next block - need to wrap buffer.\n                         * Preserve history: copy the last windowSize bytes to the\n                         * beginning so that back-references can still find valid data. */\n                        size_t const windowSize = (size_t)1 << zbc->params.windowLog;\n                        size_t const preserveSize = MIN(zbc->outEnd, windowSize);\n                        memmove(zbc->outBuff, zbc->outBuff + zbc->outEnd - preserveSize, preserveSize);\n                        zbc->outStart = zbc->outEnd = preserveSize;\n                    }\n                    break;\n                }\n                /* cannot flush everything */\n                notDone = 0;\n                break;\n            }\n        default: return ERROR(GENERIC);   /* impossible */\n    }   }\n\n    *srcSizePtr = ip-istart;\n    *maxDstSizePtr = op-ostart;\n\n    {   size_t nextSrcSizeHint = ZSTDv05_nextSrcSizeToDecompress(zbc->zc);\n        if (nextSrcSizeHint > ZBUFFv05_blockHeaderSize) nextSrcSizeHint+= ZBUFFv05_blockHeaderSize;   /* get next block header too */\n        nextSrcSizeHint -= zbc->inPos;   /* already loaded*/\n        return nextSrcSizeHint;\n    }\n}\n\n\n\n/* *************************************\n*  Tool functions\n***************************************/\nunsigned ZBUFFv05_isError(size_t errorCode) { return ERR_isError(errorCode); }\nconst char* ZBUFFv05_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }\n\nsize_t ZBUFFv05_recommendedDInSize(void)  { return BLOCKSIZE + ZBUFFv05_blockHeaderSize /* block header size*/ ; }\nsize_t ZBUFFv05_recommendedDOutSize(void) { return BLOCKSIZE; }\n"
  },
  {
    "path": "lib/legacy/zstd_v05.h",
    "content": "/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTDv05_H\n#define ZSTDv05_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/*-*************************************\n*  Dependencies\n***************************************/\n#include <stddef.h>   /* size_t */\n#include \"../common/mem.h\"      /* U64, U32 */\n\n\n/* *************************************\n*  Simple functions\n***************************************/\n/*! ZSTDv05_decompress() :\n    `compressedSize` : is the _exact_ size of the compressed blob, otherwise decompression will fail.\n    `dstCapacity` must be large enough, equal or larger than originalSize.\n    @return : the number of bytes decompressed into `dst` (<= `dstCapacity`),\n              or an errorCode if it fails (which can be tested using ZSTDv05_isError()) */\nsize_t ZSTDv05_decompress( void* dst, size_t dstCapacity,\n                     const void* src, size_t compressedSize);\n\n /**\n ZSTDv05_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.5.x format\n     srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'\n     cSize (output parameter)  : the number of bytes that would be read to decompress this frame\n                                 or an error code if it fails (which can be tested using ZSTDv01_isError())\n     dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame\n                                 or ZSTD_CONTENTSIZE_ERROR if an error occurs\n\n    note : assumes `cSize` and `dBound` are _not_ NULL.\n */\nvoid ZSTDv05_findFrameSizeInfoLegacy(const void *src, size_t srcSize,\n                                     size_t* cSize, unsigned long long* dBound);\n\n/* *************************************\n*  Helper functions\n***************************************/\n/* Error Management */\nunsigned    ZSTDv05_isError(size_t code);          /*!< tells if a `size_t` function result is an error code */\nconst char* ZSTDv05_getErrorName(size_t code);     /*!< provides readable string for an error code */\n\n\n/* *************************************\n*  Explicit memory management\n***************************************/\n/** Decompression context */\ntypedef struct ZSTDv05_DCtx_s ZSTDv05_DCtx;\nZSTDv05_DCtx* ZSTDv05_createDCtx(void);\nsize_t ZSTDv05_freeDCtx(ZSTDv05_DCtx* dctx);      /*!< @return : errorCode */\n\n/** ZSTDv05_decompressDCtx() :\n*   Same as ZSTDv05_decompress(), but requires an already allocated ZSTDv05_DCtx (see ZSTDv05_createDCtx()) */\nsize_t ZSTDv05_decompressDCtx(ZSTDv05_DCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n\n/*-***********************\n*  Simple Dictionary API\n*************************/\n/*! ZSTDv05_decompress_usingDict() :\n*   Decompression using a pre-defined Dictionary content (see dictBuilder).\n*   Dictionary must be identical to the one used during compression, otherwise regenerated data will be corrupted.\n*   Note : dict can be NULL, in which case, it's equivalent to ZSTDv05_decompressDCtx() */\nsize_t ZSTDv05_decompress_usingDict(ZSTDv05_DCtx* dctx,\n                                            void* dst, size_t dstCapacity,\n                                      const void* src, size_t srcSize,\n                                      const void* dict,size_t dictSize);\n\n/*-************************\n*  Advanced Streaming API\n***************************/\ntypedef enum { ZSTDv05_fast, ZSTDv05_greedy, ZSTDv05_lazy, ZSTDv05_lazy2, ZSTDv05_btlazy2, ZSTDv05_opt, ZSTDv05_btopt } ZSTDv05_strategy;\ntypedef struct {\n    U64 srcSize;\n    U32 windowLog;     /* the only useful information to retrieve */\n    U32 contentLog; U32 hashLog; U32 searchLog; U32 searchLength; U32 targetLength; ZSTDv05_strategy strategy;\n} ZSTDv05_parameters;\nsize_t ZSTDv05_getFrameParams(ZSTDv05_parameters* params, const void* src, size_t srcSize);\n\nsize_t ZSTDv05_decompressBegin_usingDict(ZSTDv05_DCtx* dctx, const void* dict, size_t dictSize);\nvoid   ZSTDv05_copyDCtx(ZSTDv05_DCtx* dstDCtx, const ZSTDv05_DCtx* srcDCtx);\nsize_t ZSTDv05_nextSrcSizeToDecompress(ZSTDv05_DCtx* dctx);\nsize_t ZSTDv05_decompressContinue(ZSTDv05_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n\n/*-***********************\n*  ZBUFF API\n*************************/\ntypedef struct ZBUFFv05_DCtx_s ZBUFFv05_DCtx;\nZBUFFv05_DCtx* ZBUFFv05_createDCtx(void);\nsize_t         ZBUFFv05_freeDCtx(ZBUFFv05_DCtx* dctx);\n\nsize_t ZBUFFv05_decompressInit(ZBUFFv05_DCtx* dctx);\nsize_t ZBUFFv05_decompressInitDictionary(ZBUFFv05_DCtx* dctx, const void* dict, size_t dictSize);\n\nsize_t ZBUFFv05_decompressContinue(ZBUFFv05_DCtx* dctx,\n                                            void* dst, size_t* dstCapacityPtr,\n                                      const void* src, size_t* srcSizePtr);\n\n/*-***************************************************************************\n*  Streaming decompression\n*\n*  A ZBUFFv05_DCtx object is required to track streaming operations.\n*  Use ZBUFFv05_createDCtx() and ZBUFFv05_freeDCtx() to create/release resources.\n*  Use ZBUFFv05_decompressInit() to start a new decompression operation,\n*   or ZBUFFv05_decompressInitDictionary() if decompression requires a dictionary.\n*  Note that ZBUFFv05_DCtx objects can be reused multiple times.\n*\n*  Use ZBUFFv05_decompressContinue() repetitively to consume your input.\n*  *srcSizePtr and *dstCapacityPtr can be any size.\n*  The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr.\n*  Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again.\n*  The content of @dst will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters or change @dst.\n*  @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to help latency)\n*            or 0 when a frame is completely decoded\n*            or an error code, which can be tested using ZBUFFv05_isError().\n*\n*  Hint : recommended buffer sizes (not compulsory) : ZBUFFv05_recommendedDInSize() / ZBUFFv05_recommendedDOutSize()\n*  output : ZBUFFv05_recommendedDOutSize==128 KB block size is the internal unit, it ensures it's always possible to write a full block when decoded.\n*  input  : ZBUFFv05_recommendedDInSize==128Kb+3; just follow indications from ZBUFFv05_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .\n* *******************************************************************************/\n\n\n/* *************************************\n*  Tool functions\n***************************************/\nunsigned ZBUFFv05_isError(size_t errorCode);\nconst char* ZBUFFv05_getErrorName(size_t errorCode);\n\n/** Functions below provide recommended buffer sizes for Compression or Decompression operations.\n*   These sizes are just hints, and tend to offer better latency */\nsize_t ZBUFFv05_recommendedDInSize(void);\nsize_t ZBUFFv05_recommendedDOutSize(void);\n\n\n\n/*-*************************************\n*  Constants\n***************************************/\n#define ZSTDv05_MAGICNUMBER 0xFD2FB525   /* v0.5 */\n\n\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* ZSTDv0505_H */\n"
  },
  {
    "path": "lib/legacy/zstd_v06.c",
    "content": "/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/*- Dependencies -*/\n#include \"zstd_v06.h\"\n#include <stddef.h>    /* size_t, ptrdiff_t */\n#include <string.h>    /* memcpy */\n#include <stdlib.h>    /* malloc, free, qsort */\n#include \"../common/compiler.h\"\n#include \"../common/error_private.h\"\n\n\n\n/* ******************************************************************\n   mem.h\n   low-level memory access routines\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef MEM_H_MODULE\n#define MEM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/*-****************************************\n*  Compiler specifics\n******************************************/\n#if defined(_MSC_VER)   /* Visual Studio */\n#   include <stdlib.h>  /* _byteswap_ulong */\n#   include <intrin.h>  /* _byteswap_* */\n#endif\n\n\n/*-**************************************************************\n*  Basic Types\n*****************************************************************/\n#if  !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )\n# if defined(_AIX)\n#  include <inttypes.h>\n# else\n#  include <stdint.h> /* intptr_t */\n# endif\n  typedef  uint8_t BYTE;\n  typedef uint16_t U16;\n  typedef  int16_t S16;\n  typedef uint32_t U32;\n  typedef  int32_t S32;\n  typedef uint64_t U64;\n  typedef  int64_t S64;\n#else\n  typedef unsigned char       BYTE;\n  typedef unsigned short      U16;\n  typedef   signed short      S16;\n  typedef unsigned int        U32;\n  typedef   signed int        S32;\n  typedef unsigned long long  U64;\n  typedef   signed long long  S64;\n#endif\n\n\n/*-**************************************************************\n*  Memory I/O\n*****************************************************************/\n\nMEM_STATIC unsigned MEM_32bits(void) { return sizeof(size_t)==4; }\nMEM_STATIC unsigned MEM_64bits(void) { return sizeof(size_t)==8; }\n\nMEM_STATIC unsigned MEM_isLittleEndian(void)\n{\n    const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */\n    return one.c[0];\n}\n\nMEM_STATIC U16 MEM_read16(const void* memPtr)\n{\n    U16 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U32 MEM_read32(const void* memPtr)\n{\n    U32 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U64 MEM_read64(const void* memPtr)\n{\n    U64 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value)\n{\n    memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC U32 MEM_swap32(U32 in)\n{\n#if defined(_MSC_VER)     /* Visual Studio */\n    return _byteswap_ulong(in);\n#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)\n    return __builtin_bswap32(in);\n#else\n    return  ((in << 24) & 0xff000000 ) |\n            ((in <<  8) & 0x00ff0000 ) |\n            ((in >>  8) & 0x0000ff00 ) |\n            ((in >> 24) & 0x000000ff );\n#endif\n}\n\nMEM_STATIC U64 MEM_swap64(U64 in)\n{\n#if defined(_MSC_VER)     /* Visual Studio */\n    return _byteswap_uint64(in);\n#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)\n    return __builtin_bswap64(in);\n#else\n    return  ((in << 56) & 0xff00000000000000ULL) |\n            ((in << 40) & 0x00ff000000000000ULL) |\n            ((in << 24) & 0x0000ff0000000000ULL) |\n            ((in << 8)  & 0x000000ff00000000ULL) |\n            ((in >> 8)  & 0x00000000ff000000ULL) |\n            ((in >> 24) & 0x0000000000ff0000ULL) |\n            ((in >> 40) & 0x000000000000ff00ULL) |\n            ((in >> 56) & 0x00000000000000ffULL);\n#endif\n}\n\n\n/*=== Little endian r/w ===*/\n\nMEM_STATIC U16 MEM_readLE16(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read16(memPtr);\n    else {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U16)(p[0] + (p[1]<<8));\n    }\n}\n\nMEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)\n{\n    if (MEM_isLittleEndian()) {\n        MEM_write16(memPtr, val);\n    } else {\n        BYTE* p = (BYTE*)memPtr;\n        p[0] = (BYTE)val;\n        p[1] = (BYTE)(val>>8);\n    }\n}\n\nMEM_STATIC U32 MEM_readLE32(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read32(memPtr);\n    else\n        return MEM_swap32(MEM_read32(memPtr));\n}\n\n\nMEM_STATIC U64 MEM_readLE64(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read64(memPtr);\n    else\n        return MEM_swap64(MEM_read64(memPtr));\n}\n\n\nMEM_STATIC size_t MEM_readLEST(const void* memPtr)\n{\n    if (MEM_32bits())\n        return (size_t)MEM_readLE32(memPtr);\n    else\n        return (size_t)MEM_readLE64(memPtr);\n}\n\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* MEM_H_MODULE */\n\n/*\n    zstd - standard compression library\n    Header File for static linking only\n    Copyright (C) 2014-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd homepage : https://facebook.github.io/zstd\n*/\n#ifndef ZSTDv06_STATIC_H\n#define ZSTDv06_STATIC_H\n\n/* The prototypes defined within this file are considered experimental.\n * They should not be used in the context DLL as they may change in the future.\n * Prefer static linking if you need them, to control breaking version changes issues.\n */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n\n/*- Advanced Decompression functions -*/\n\n/*! ZSTDv06_decompress_usingPreparedDCtx() :\n*   Same as ZSTDv06_decompress_usingDict, but using a reference context `preparedDCtx`, where dictionary has been loaded.\n*   It avoids reloading the dictionary each time.\n*   `preparedDCtx` must have been properly initialized using ZSTDv06_decompressBegin_usingDict().\n*   Requires 2 contexts : 1 for reference (preparedDCtx), which will not be modified, and 1 to run the decompression operation (dctx) */\nZSTDLIBv06_API size_t ZSTDv06_decompress_usingPreparedDCtx(\n                                           ZSTDv06_DCtx* dctx, const ZSTDv06_DCtx* preparedDCtx,\n                                           void* dst, size_t dstCapacity,\n                                     const void* src, size_t srcSize);\n\n\n\n#define ZSTDv06_FRAMEHEADERSIZE_MAX 13    /* for static allocation */\nstatic const size_t ZSTDv06_frameHeaderSize_min = 5;\nstatic const size_t ZSTDv06_frameHeaderSize_max = ZSTDv06_FRAMEHEADERSIZE_MAX;\n\nZSTDLIBv06_API size_t ZSTDv06_decompressBegin(ZSTDv06_DCtx* dctx);\n\n/*\n  Streaming decompression, direct mode (bufferless)\n\n  A ZSTDv06_DCtx object is required to track streaming operations.\n  Use ZSTDv06_createDCtx() / ZSTDv06_freeDCtx() to manage it.\n  A ZSTDv06_DCtx object can be re-used multiple times.\n\n  First optional operation is to retrieve frame parameters, using ZSTDv06_getFrameParams(), which doesn't consume the input.\n  It can provide the minimum size of rolling buffer required to properly decompress data,\n  and optionally the final size of uncompressed content.\n  (Note : content size is an optional info that may not be present. 0 means : content size unknown)\n  Frame parameters are extracted from the beginning of compressed frame.\n  The amount of data to read is variable, from ZSTDv06_frameHeaderSize_min to ZSTDv06_frameHeaderSize_max (so if `srcSize` >= ZSTDv06_frameHeaderSize_max, it will always work)\n  If `srcSize` is too small for operation to succeed, function will return the minimum size it requires to produce a result.\n  Result : 0 when successful, it means the ZSTDv06_frameParams structure has been filled.\n          >0 : means there is not enough data into `src`. Provides the expected size to successfully decode header.\n           errorCode, which can be tested using ZSTDv06_isError()\n\n  Start decompression, with ZSTDv06_decompressBegin() or ZSTDv06_decompressBegin_usingDict().\n  Alternatively, you can copy a prepared context, using ZSTDv06_copyDCtx().\n\n  Then use ZSTDv06_nextSrcSizeToDecompress() and ZSTDv06_decompressContinue() alternatively.\n  ZSTDv06_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTDv06_decompressContinue().\n  ZSTDv06_decompressContinue() requires this exact amount of bytes, or it will fail.\n  ZSTDv06_decompressContinue() needs previous data blocks during decompression, up to (1 << windowlog).\n  They should preferably be located contiguously, prior to current block. Alternatively, a round buffer is also possible.\n\n  @result of ZSTDv06_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity)\n  It can be zero, which is not an error; it just means ZSTDv06_decompressContinue() has decoded some header.\n\n  A frame is fully decoded when ZSTDv06_nextSrcSizeToDecompress() returns zero.\n  Context can then be reset to start a new decompression.\n*/\n\n\n/* **************************************\n*  Block functions\n****************************************/\n/*! Block functions produce and decode raw zstd blocks, without frame metadata.\n    User will have to take in charge required information to regenerate data, such as compressed and content sizes.\n\n    A few rules to respect :\n    - Uncompressed block size must be <= ZSTDv06_BLOCKSIZE_MAX (128 KB)\n    - Compressing or decompressing requires a context structure\n      + Use ZSTDv06_createCCtx() and ZSTDv06_createDCtx()\n    - It is necessary to init context before starting\n      + compression : ZSTDv06_compressBegin()\n      + decompression : ZSTDv06_decompressBegin()\n      + variants _usingDict() are also allowed\n      + copyCCtx() and copyDCtx() work too\n    - When a block is considered not compressible enough, ZSTDv06_compressBlock() result will be zero.\n      In which case, nothing is produced into `dst`.\n      + User must test for such outcome and deal directly with uncompressed data\n      + ZSTDv06_decompressBlock() doesn't accept uncompressed data as input !!\n*/\n\n#define ZSTDv06_BLOCKSIZE_MAX (128 * 1024)   /* define, for static allocation */\nZSTDLIBv06_API size_t ZSTDv06_decompressBlock(ZSTDv06_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* ZSTDv06_STATIC_H */\n/*\n    zstd_internal - common functions to include\n    Header File for include\n    Copyright (C) 2014-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd homepage : https://www.zstd.net\n*/\n#ifndef ZSTDv06_CCOMMON_H_MODULE\n#define ZSTDv06_CCOMMON_H_MODULE\n\n\n/*-*************************************\n*  Common macros\n***************************************/\n#define MIN(a,b) ((a)<(b) ? (a) : (b))\n#define MAX(a,b) ((a)>(b) ? (a) : (b))\n\n\n/*-*************************************\n*  Common constants\n***************************************/\n#define ZSTDv06_DICT_MAGIC  0xEC30A436\n\n#define ZSTDv06_REP_NUM    3\n#define ZSTDv06_REP_INIT   ZSTDv06_REP_NUM\n#define ZSTDv06_REP_MOVE   (ZSTDv06_REP_NUM-1)\n\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\n#define BIT7 128\n#define BIT6  64\n#define BIT5  32\n#define BIT4  16\n#define BIT1   2\n#define BIT0   1\n\n#define ZSTDv06_WINDOWLOG_ABSOLUTEMIN 12\nstatic const size_t ZSTDv06_fcs_fieldSize[4] = { 0, 1, 2, 8 };\n\n#define ZSTDv06_BLOCKHEADERSIZE 3   /* because C standard does not allow a static const value to be defined using another static const value .... :( */\nstatic const size_t ZSTDv06_blockHeaderSize = ZSTDv06_BLOCKHEADERSIZE;\ntypedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;\n\n#define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */\n#define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */)   /* for a non-null block */\n\n#define ZSTD_HUFFDTABLE_CAPACITY_LOG 12\n\n#define IS_HUF 0\n#define IS_PCH 1\n#define IS_RAW 2\n#define IS_RLE 3\n\n#define LONGNBSEQ 0x7F00\n\n#define MINMATCH 3\n#define EQUAL_READ32 4\n#define REPCODE_STARTVALUE 1\n\n#define Litbits  8\n#define MaxLit ((1<<Litbits) - 1)\n#define MaxML  52\n#define MaxLL  35\n#define MaxOff 28\n#define MaxSeq MAX(MaxLL, MaxML)   /* Assumption : MaxOff < MaxLL,MaxML */\n#define MLFSELog    9\n#define LLFSELog    9\n#define OffFSELog   8\n\n#define FSEv06_ENCODING_RAW     0\n#define FSEv06_ENCODING_RLE     1\n#define FSEv06_ENCODING_STATIC  2\n#define FSEv06_ENCODING_DYNAMIC 3\n\n#define ZSTD_CONTENTSIZE_ERROR   (0ULL - 2)\n\nstatic const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n                                      1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9,10,11,12,\n                                     13,14,15,16 };\nstatic const S16 LL_defaultNorm[MaxLL+1] = { 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,\n                                             2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1,\n                                            -1,-1,-1,-1 };\nstatic const U32 LL_defaultNormLog = 6;\n\nstatic const U32 ML_bits[MaxML+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n                                      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n                                      1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7, 8, 9,10,11,\n                                     12,13,14,15,16 };\nstatic const S16 ML_defaultNorm[MaxML+1] = { 1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,\n                                             1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n                                             1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,\n                                            -1,-1,-1,-1,-1 };\nstatic const U32 ML_defaultNormLog = 6;\n\nstatic const S16 OF_defaultNorm[MaxOff+1] = { 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,\n                                              1, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1 };\nstatic const U32 OF_defaultNormLog = 5;\n\n\n/*-*******************************************\n*  Shared functions to include for inlining\n*********************************************/\nstatic void ZSTDv06_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }\n#define COPY8(d,s) { ZSTDv06_copy8(d,s); d+=8; s+=8; }\n\n/*! ZSTDv06_wildcopy() :\n*   custom version of memcpy(), can copy up to 7 bytes too many (8 bytes if length==0) */\n#define WILDCOPY_OVERLENGTH 8\nMEM_STATIC void ZSTDv06_wildcopy(void* dst, const void* src, ptrdiff_t length)\n{\n    const BYTE* ip = (const BYTE*)src;\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + length;\n    do\n        COPY8(op, ip)\n    while (op < oend);\n}\n\n\n\n/*-*******************************************\n*  Private interfaces\n*********************************************/\ntypedef struct {\n    U32 off;\n    U32 len;\n} ZSTDv06_match_t;\n\ntypedef struct {\n    U32 price;\n    U32 off;\n    U32 mlen;\n    U32 litlen;\n    U32 rep[ZSTDv06_REP_INIT];\n} ZSTDv06_optimal_t;\n\ntypedef struct { U32  unused; } ZSTDv06_stats_t;\n\ntypedef struct {\n    void* buffer;\n    U32*  offsetStart;\n    U32*  offset;\n    BYTE* offCodeStart;\n    BYTE* litStart;\n    BYTE* lit;\n    U16*  litLengthStart;\n    U16*  litLength;\n    BYTE* llCodeStart;\n    U16*  matchLengthStart;\n    U16*  matchLength;\n    BYTE* mlCodeStart;\n    U32   longLengthID;   /* 0 == no longLength; 1 == Lit.longLength; 2 == Match.longLength; */\n    U32   longLengthPos;\n    /* opt */\n    ZSTDv06_optimal_t* priceTable;\n    ZSTDv06_match_t* matchTable;\n    U32* matchLengthFreq;\n    U32* litLengthFreq;\n    U32* litFreq;\n    U32* offCodeFreq;\n    U32  matchLengthSum;\n    U32  matchSum;\n    U32  litLengthSum;\n    U32  litSum;\n    U32  offCodeSum;\n    U32  log2matchLengthSum;\n    U32  log2matchSum;\n    U32  log2litLengthSum;\n    U32  log2litSum;\n    U32  log2offCodeSum;\n    U32  factor;\n    U32  cachedPrice;\n    U32  cachedLitLength;\n    const BYTE* cachedLiterals;\n    ZSTDv06_stats_t stats;\n} SeqStore_t;\n\nvoid ZSTDv06_seqToCodes(const SeqStore_t* seqStorePtr, size_t const nbSeq);\n\n\n#endif   /* ZSTDv06_CCOMMON_H_MODULE */\n/* ******************************************************************\n   FSE : Finite State Entropy codec\n   Public Prototypes declaration\n   Copyright (C) 2013-2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n****************************************************************** */\n#ifndef FSEv06_H\n#define FSEv06_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n\n/*-****************************************\n*  FSE simple functions\n******************************************/\n/*! FSEv06_decompress():\n    Decompress FSE data from buffer 'cSrc', of size 'cSrcSize',\n    into already allocated destination buffer 'dst', of size 'dstCapacity'.\n    @return : size of regenerated data (<= maxDstSize),\n              or an error code, which can be tested using FSEv06_isError() .\n\n    ** Important ** : FSEv06_decompress() does not decompress non-compressible nor RLE data !!!\n    Why ? : making this distinction requires a header.\n    Header management is intentionally delegated to the user layer, which can better manage special cases.\n*/\nsize_t FSEv06_decompress(void* dst,  size_t dstCapacity,\n                const void* cSrc, size_t cSrcSize);\n\n\n/*-*****************************************\n*  Tool functions\n******************************************/\nsize_t FSEv06_compressBound(size_t size);       /* maximum compressed size */\n\n/* Error Management */\nunsigned    FSEv06_isError(size_t code);        /* tells if a return value is an error code */\nconst char* FSEv06_getErrorName(size_t code);   /* provides error code string (useful for debugging) */\n\n\n\n/*-*****************************************\n*  FSE detailed API\n******************************************/\n/*!\n\nFSEv06_decompress() does the following:\n1. read normalized counters with readNCount()\n2. build decoding table 'DTable' from normalized counters\n3. decode the data stream using decoding table 'DTable'\n\nThe following API allows targeting specific sub-functions for advanced tasks.\nFor example, it's possible to compress several blocks using the same 'CTable',\nor to save and provide normalized distribution using external method.\n*/\n\n\n/* *** DECOMPRESSION *** */\n\n/*! FSEv06_readNCount():\n    Read compactly saved 'normalizedCounter' from 'rBuffer'.\n    @return : size read from 'rBuffer',\n              or an errorCode, which can be tested using FSEv06_isError().\n              maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */\nsize_t FSEv06_readNCount (short* normalizedCounter, unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, const void* rBuffer, size_t rBuffSize);\n\n/*! Constructor and Destructor of FSEv06_DTable.\n    Note that its size depends on 'tableLog' */\ntypedef unsigned FSEv06_DTable;   /* don't allocate that. It's just a way to be more restrictive than void* */\nFSEv06_DTable* FSEv06_createDTable(unsigned tableLog);\nvoid        FSEv06_freeDTable(FSEv06_DTable* dt);\n\n/*! FSEv06_buildDTable():\n    Builds 'dt', which must be already allocated, using FSEv06_createDTable().\n    return : 0, or an errorCode, which can be tested using FSEv06_isError() */\nsize_t FSEv06_buildDTable (FSEv06_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);\n\n/*! FSEv06_decompress_usingDTable():\n    Decompress compressed source `cSrc` of size `cSrcSize` using `dt`\n    into `dst` which must be already allocated.\n    @return : size of regenerated data (necessarily <= `dstCapacity`),\n              or an errorCode, which can be tested using FSEv06_isError() */\nsize_t FSEv06_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSEv06_DTable* dt);\n\n/*!\nTutorial :\n----------\n(Note : these functions only decompress FSE-compressed blocks.\n If block is uncompressed, use memcpy() instead\n If block is a single repeated byte, use memset() instead )\n\nThe first step is to obtain the normalized frequencies of symbols.\nThis can be performed by FSEv06_readNCount() if it was saved using FSEv06_writeNCount().\n'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short.\nIn practice, that means it's necessary to know 'maxSymbolValue' beforehand,\nor size the table to handle worst case situations (typically 256).\nFSEv06_readNCount() will provide 'tableLog' and 'maxSymbolValue'.\nThe result of FSEv06_readNCount() is the number of bytes read from 'rBuffer'.\nNote that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that.\nIf there is an error, the function will return an error code, which can be tested using FSEv06_isError().\n\nThe next step is to build the decompression tables 'FSEv06_DTable' from 'normalizedCounter'.\nThis is performed by the function FSEv06_buildDTable().\nThe space required by 'FSEv06_DTable' must be already allocated using FSEv06_createDTable().\nIf there is an error, the function will return an error code, which can be tested using FSEv06_isError().\n\n`FSEv06_DTable` can then be used to decompress `cSrc`, with FSEv06_decompress_usingDTable().\n`cSrcSize` must be strictly correct, otherwise decompression will fail.\nFSEv06_decompress_usingDTable() result will tell how many bytes were regenerated (<=`dstCapacity`).\nIf there is an error, the function will return an error code, which can be tested using FSEv06_isError(). (ex: dst buffer too small)\n*/\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* FSEv06_H */\n/* ******************************************************************\n   bitstream\n   Part of FSE library\n   header file (to include)\n   Copyright (C) 2013-2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n****************************************************************** */\n#ifndef BITSTREAM_H_MODULE\n#define BITSTREAM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/*\n*  This API consists of small unitary functions, which must be inlined for best performance.\n*  Since link-time-optimization is not available for all compilers,\n*  these functions are defined into a .h to be included.\n*/\n\n\n/*=========================================\n*  Target specific\n=========================================*/\n#if defined(__BMI__) && defined(__GNUC__)\n#  include <immintrin.h>   /* support for bextr (experimental) */\n#endif\n\n\n\n/*-********************************************\n*  bitStream decoding API (read backward)\n**********************************************/\ntypedef struct\n{\n    size_t   bitContainer;\n    unsigned bitsConsumed;\n    const char* ptr;\n    const char* start;\n} BITv06_DStream_t;\n\ntypedef enum { BITv06_DStream_unfinished = 0,\n               BITv06_DStream_endOfBuffer = 1,\n               BITv06_DStream_completed = 2,\n               BITv06_DStream_overflow = 3 } BITv06_DStream_status;  /* result of BITv06_reloadDStream() */\n               /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */\n\nMEM_STATIC size_t   BITv06_initDStream(BITv06_DStream_t* bitD, const void* srcBuffer, size_t srcSize);\nMEM_STATIC size_t   BITv06_readBits(BITv06_DStream_t* bitD, unsigned nbBits);\nMEM_STATIC BITv06_DStream_status BITv06_reloadDStream(BITv06_DStream_t* bitD);\nMEM_STATIC unsigned BITv06_endOfDStream(const BITv06_DStream_t* bitD);\n\n\n\n/*-****************************************\n*  unsafe API\n******************************************/\nMEM_STATIC size_t BITv06_readBitsFast(BITv06_DStream_t* bitD, unsigned nbBits);\n/* faster, but works only if nbBits >= 1 */\n\n\n\n/*-**************************************************************\n*  Internal functions\n****************************************************************/\nMEM_STATIC unsigned BITv06_highbit32 ( U32 val)\n{\n#   if defined(_MSC_VER)   /* Visual */\n    unsigned long r;\n    return _BitScanReverse(&r, val) ? (unsigned)r : 0;\n#   elif defined(__GNUC__) && (__GNUC__ >= 3)   /* Use GCC Intrinsic */\n    return __builtin_clz (val) ^ 31;\n#   else   /* Software version */\n    static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };\n    U32 v = val;\n    unsigned r;\n    v |= v >> 1;\n    v |= v >> 2;\n    v |= v >> 4;\n    v |= v >> 8;\n    v |= v >> 16;\n    r = DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];\n    return r;\n#   endif\n}\n\n\n\n/*-********************************************************\n* bitStream decoding\n**********************************************************/\n/*! BITv06_initDStream() :\n*   Initialize a BITv06_DStream_t.\n*   `bitD` : a pointer to an already allocated BITv06_DStream_t structure.\n*   `srcSize` must be the *exact* size of the bitStream, in bytes.\n*   @return : size of stream (== srcSize) or an errorCode if a problem is detected\n*/\nMEM_STATIC size_t BITv06_initDStream(BITv06_DStream_t* bitD, const void* srcBuffer, size_t srcSize)\n{\n    if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }\n\n    if (srcSize >=  sizeof(bitD->bitContainer)) {  /* normal case */\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer);\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];\n          if (lastByte == 0) return ERROR(GENERIC);   /* endMark not present */\n          bitD->bitsConsumed = 8 - BITv06_highbit32(lastByte); }\n    } else {\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = bitD->start;\n        bitD->bitContainer = *(const BYTE*)(bitD->start);\n        switch(srcSize)\n        {\n            case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);/* fall-through */\n            case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);/* fall-through */\n            case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);/* fall-through */\n            case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24; /* fall-through */\n            case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16; /* fall-through */\n            case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) <<  8; /* fall-through */\n            default: break;\n        }\n        { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];\n          if (lastByte == 0) return ERROR(GENERIC);   /* endMark not present */\n          bitD->bitsConsumed = 8 - BITv06_highbit32(lastByte); }\n        bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8;\n    }\n\n    return srcSize;\n}\n\n\n MEM_STATIC size_t BITv06_lookBits(const BITv06_DStream_t* bitD, U32 nbBits)\n{\n    U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);\n}\n\n/*! BITv06_lookBitsFast() :\n*   unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BITv06_lookBitsFast(const BITv06_DStream_t* bitD, U32 nbBits)\n{\n    U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);\n}\n\nMEM_STATIC void BITv06_skipBits(BITv06_DStream_t* bitD, U32 nbBits)\n{\n    bitD->bitsConsumed += nbBits;\n}\n\nMEM_STATIC size_t BITv06_readBits(BITv06_DStream_t* bitD, U32 nbBits)\n{\n    size_t const value = BITv06_lookBits(bitD, nbBits);\n    BITv06_skipBits(bitD, nbBits);\n    return value;\n}\n\n/*! BITv06_readBitsFast() :\n*   unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BITv06_readBitsFast(BITv06_DStream_t* bitD, U32 nbBits)\n{\n    size_t const value = BITv06_lookBitsFast(bitD, nbBits);\n    BITv06_skipBits(bitD, nbBits);\n    return value;\n}\n\nMEM_STATIC BITv06_DStream_status BITv06_reloadDStream(BITv06_DStream_t* bitD)\n{\n    if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */\n        return BITv06_DStream_overflow;\n\n    if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {\n        bitD->ptr -= bitD->bitsConsumed >> 3;\n        bitD->bitsConsumed &= 7;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        return BITv06_DStream_unfinished;\n    }\n    if (bitD->ptr == bitD->start) {\n        if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BITv06_DStream_endOfBuffer;\n        return BITv06_DStream_completed;\n    }\n    {   U32 nbBytes = bitD->bitsConsumed >> 3;\n        BITv06_DStream_status result = BITv06_DStream_unfinished;\n        if (bitD->ptr - nbBytes < bitD->start) {\n            nbBytes = (U32)(bitD->ptr - bitD->start);  /* ptr > start */\n            result = BITv06_DStream_endOfBuffer;\n        }\n        bitD->ptr -= nbBytes;\n        bitD->bitsConsumed -= nbBytes*8;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);   /* reminder : srcSize > sizeof(bitD) */\n        return result;\n    }\n}\n\n/*! BITv06_endOfDStream() :\n*   @return Tells if DStream has exactly reached its end (all bits consumed).\n*/\nMEM_STATIC unsigned BITv06_endOfDStream(const BITv06_DStream_t* DStream)\n{\n    return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));\n}\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* BITSTREAM_H_MODULE */\n/* ******************************************************************\n   FSE : Finite State Entropy coder\n   header file for static linking (only)\n   Copyright (C) 2013-2015, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef FSEv06_STATIC_H\n#define FSEv06_STATIC_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/* *****************************************\n*  Static allocation\n*******************************************/\n/* FSE buffer bounds */\n#define FSEv06_NCOUNTBOUND 512\n#define FSEv06_BLOCKBOUND(size) (size + (size>>7))\n#define FSEv06_COMPRESSBOUND(size) (FSEv06_NCOUNTBOUND + FSEv06_BLOCKBOUND(size))   /* Macro version, useful for static allocation */\n\n/* It is possible to statically allocate FSE CTable/DTable as a table of unsigned using below macros */\n#define FSEv06_DTABLE_SIZE_U32(maxTableLog)                   (1 + (1<<maxTableLog))\n\n\n/* *****************************************\n*  FSE advanced API\n*******************************************/\nsize_t FSEv06_countFast(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize);\n/* same as FSEv06_count(), but blindly trusts that all byte values within src are <= *maxSymbolValuePtr  */\n\nsize_t FSEv06_buildDTable_raw (FSEv06_DTable* dt, unsigned nbBits);\n/* build a fake FSEv06_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */\n\nsize_t FSEv06_buildDTable_rle (FSEv06_DTable* dt, unsigned char symbolValue);\n/* build a fake FSEv06_DTable, designed to always generate the same symbolValue */\n\n\n/* *****************************************\n*  FSE symbol decompression API\n*******************************************/\ntypedef struct\n{\n    size_t      state;\n    const void* table;   /* precise table may vary, depending on U16 */\n} FSEv06_DState_t;\n\n\nstatic void     FSEv06_initDState(FSEv06_DState_t* DStatePtr, BITv06_DStream_t* bitD, const FSEv06_DTable* dt);\n\nstatic unsigned char FSEv06_decodeSymbol(FSEv06_DState_t* DStatePtr, BITv06_DStream_t* bitD);\n\n\n/* *****************************************\n*  FSE unsafe API\n*******************************************/\nstatic unsigned char FSEv06_decodeSymbolFast(FSEv06_DState_t* DStatePtr, BITv06_DStream_t* bitD);\n/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */\n\n\n/* *****************************************\n*  Implementation of inlined functions\n*******************************************/\n\n\n/* ======    Decompression    ====== */\n\ntypedef struct {\n    U16 tableLog;\n    U16 fastMode;\n} FSEv06_DTableHeader;   /* sizeof U32 */\n\ntypedef struct\n{\n    unsigned short newState;\n    unsigned char  symbol;\n    unsigned char  nbBits;\n} FSEv06_decode_t;   /* size == U32 */\n\nMEM_STATIC void FSEv06_initDState(FSEv06_DState_t* DStatePtr, BITv06_DStream_t* bitD, const FSEv06_DTable* dt)\n{\n    const void* ptr = dt;\n    const FSEv06_DTableHeader* const DTableH = (const FSEv06_DTableHeader*)ptr;\n    DStatePtr->state = BITv06_readBits(bitD, DTableH->tableLog);\n    BITv06_reloadDStream(bitD);\n    DStatePtr->table = dt + 1;\n}\n\nMEM_STATIC BYTE FSEv06_peekSymbol(const FSEv06_DState_t* DStatePtr)\n{\n    FSEv06_decode_t const DInfo = ((const FSEv06_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    return DInfo.symbol;\n}\n\nMEM_STATIC void FSEv06_updateState(FSEv06_DState_t* DStatePtr, BITv06_DStream_t* bitD)\n{\n    FSEv06_decode_t const DInfo = ((const FSEv06_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    U32 const nbBits = DInfo.nbBits;\n    size_t const lowBits = BITv06_readBits(bitD, nbBits);\n    DStatePtr->state = DInfo.newState + lowBits;\n}\n\nMEM_STATIC BYTE FSEv06_decodeSymbol(FSEv06_DState_t* DStatePtr, BITv06_DStream_t* bitD)\n{\n    FSEv06_decode_t const DInfo = ((const FSEv06_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    U32 const nbBits = DInfo.nbBits;\n    BYTE const symbol = DInfo.symbol;\n    size_t const lowBits = BITv06_readBits(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\n/*! FSEv06_decodeSymbolFast() :\n    unsafe, only works if no symbol has a probability > 50% */\nMEM_STATIC BYTE FSEv06_decodeSymbolFast(FSEv06_DState_t* DStatePtr, BITv06_DStream_t* bitD)\n{\n    FSEv06_decode_t const DInfo = ((const FSEv06_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    U32 const nbBits = DInfo.nbBits;\n    BYTE const symbol = DInfo.symbol;\n    size_t const lowBits = BITv06_readBitsFast(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\n\n\n#ifndef FSEv06_COMMONDEFS_ONLY\n\n/* **************************************************************\n*  Tuning parameters\n****************************************************************/\n/*!MEMORY_USAGE :\n*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n*  Increasing memory usage improves compression ratio\n*  Reduced memory usage can improve speed, due to cache effect\n*  Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */\n#define FSEv06_MAX_MEMORY_USAGE 14\n#define FSEv06_DEFAULT_MEMORY_USAGE 13\n\n/*!FSEv06_MAX_SYMBOL_VALUE :\n*  Maximum symbol value authorized.\n*  Required for proper stack allocation */\n#define FSEv06_MAX_SYMBOL_VALUE 255\n\n\n/* **************************************************************\n*  template functions type & suffix\n****************************************************************/\n#define FSEv06_FUNCTION_TYPE BYTE\n#define FSEv06_FUNCTION_EXTENSION\n#define FSEv06_DECODE_TYPE FSEv06_decode_t\n\n\n#endif   /* !FSEv06_COMMONDEFS_ONLY */\n\n\n/* ***************************************************************\n*  Constants\n*****************************************************************/\n#define FSEv06_MAX_TABLELOG  (FSEv06_MAX_MEMORY_USAGE-2)\n#define FSEv06_MAX_TABLESIZE (1U<<FSEv06_MAX_TABLELOG)\n#define FSEv06_MAXTABLESIZE_MASK (FSEv06_MAX_TABLESIZE-1)\n#define FSEv06_DEFAULT_TABLELOG (FSEv06_DEFAULT_MEMORY_USAGE-2)\n#define FSEv06_MIN_TABLELOG 5\n\n#define FSEv06_TABLELOG_ABSOLUTE_MAX 15\n#if FSEv06_MAX_TABLELOG > FSEv06_TABLELOG_ABSOLUTE_MAX\n#error \"FSEv06_MAX_TABLELOG > FSEv06_TABLELOG_ABSOLUTE_MAX is not supported\"\n#endif\n\n#define FSEv06_TABLESTEP(tableSize) ((tableSize>>1) + (tableSize>>3) + 3)\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* FSEv06_STATIC_H */\n/*\n   Common functions of New Generation Entropy library\n   Copyright (C) 2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n*************************************************************************** */\n\n\n/*-****************************************\n*  FSE Error Management\n******************************************/\nunsigned FSEv06_isError(size_t code) { return ERR_isError(code); }\n\nconst char* FSEv06_getErrorName(size_t code) { return ERR_getErrorName(code); }\n\n\n/* **************************************************************\n*  HUF Error Management\n****************************************************************/\nstatic unsigned HUFv06_isError(size_t code) { return ERR_isError(code); }\n\n\n/*-**************************************************************\n*  FSE NCount encoding-decoding\n****************************************************************/\nstatic short FSEv06_abs(short a) { return a<0 ? (short)-a : a; }\n\nsize_t FSEv06_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n                 const void* headerBuffer, size_t hbSize)\n{\n    const BYTE* const istart = (const BYTE*) headerBuffer;\n    const BYTE* const iend = istart + hbSize;\n    const BYTE* ip = istart;\n    int nbBits;\n    int remaining;\n    int threshold;\n    U32 bitStream;\n    int bitCount;\n    unsigned charnum = 0;\n    int previous0 = 0;\n\n    if (hbSize < 4) return ERROR(srcSize_wrong);\n    bitStream = MEM_readLE32(ip);\n    nbBits = (bitStream & 0xF) + FSEv06_MIN_TABLELOG;   /* extract tableLog */\n    if (nbBits > FSEv06_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);\n    bitStream >>= 4;\n    bitCount = 4;\n    *tableLogPtr = nbBits;\n    remaining = (1<<nbBits)+1;\n    threshold = 1<<nbBits;\n    nbBits++;\n\n    while ((remaining>1) && (charnum<=*maxSVPtr)) {\n        if (previous0) {\n            unsigned n0 = charnum;\n            while ((bitStream & 0xFFFF) == 0xFFFF) {\n                n0+=24;\n                if (ip < iend-5) {\n                    ip+=2;\n                    bitStream = MEM_readLE32(ip) >> bitCount;\n                } else {\n                    bitStream >>= 16;\n                    bitCount+=16;\n            }   }\n            while ((bitStream & 3) == 3) {\n                n0+=3;\n                bitStream>>=2;\n                bitCount+=2;\n            }\n            n0 += bitStream & 3;\n            bitCount += 2;\n            if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);\n            while (charnum < n0) normalizedCounter[charnum++] = 0;\n            if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {\n                ip += bitCount>>3;\n                bitCount &= 7;\n                bitStream = MEM_readLE32(ip) >> bitCount;\n            }\n            else\n                bitStream >>= 2;\n        }\n        {   short const max = (short)((2*threshold-1)-remaining);\n            short count;\n\n            if ((bitStream & (threshold-1)) < (U32)max) {\n                count = (short)(bitStream & (threshold-1));\n                bitCount   += nbBits-1;\n            } else {\n                count = (short)(bitStream & (2*threshold-1));\n                if (count >= threshold) count -= max;\n                bitCount   += nbBits;\n            }\n\n            count--;   /* extra accuracy */\n            remaining -= FSEv06_abs(count);\n            normalizedCounter[charnum++] = count;\n            previous0 = !count;\n            while (remaining < threshold) {\n                nbBits--;\n                threshold >>= 1;\n            }\n\n            if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {\n                ip += bitCount>>3;\n                bitCount &= 7;\n            } else {\n                bitCount -= (int)(8 * (iend - 4 - ip));\n                ip = iend - 4;\n            }\n            bitStream = MEM_readLE32(ip) >> (bitCount & 31);\n    }   }   /* while ((remaining>1) && (charnum<=*maxSVPtr)) */\n    if (remaining != 1) return ERROR(GENERIC);\n    *maxSVPtr = charnum-1;\n\n    ip += (bitCount+7)>>3;\n    if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong);\n    return ip-istart;\n}\n/* ******************************************************************\n   FSE : Finite State Entropy decoder\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n\n/* **************************************************************\n*  Compiler specifics\n****************************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  define FORCE_INLINE static __forceinline\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4214)        /* disable: C4214: non-int bitfields */\n#else\n#  if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */\n#    ifdef __GNUC__\n#      define FORCE_INLINE static inline __attribute__((always_inline))\n#    else\n#      define FORCE_INLINE static inline\n#    endif\n#  else\n#    define FORCE_INLINE static\n#  endif /* __STDC_VERSION__ */\n#endif\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n#define FSEv06_isError ERR_isError\n#define FSEv06_STATIC_ASSERT(c) { enum { FSEv06_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n/* **************************************************************\n*  Complex types\n****************************************************************/\ntypedef U32 DTable_max_t[FSEv06_DTABLE_SIZE_U32(FSEv06_MAX_TABLELOG)];\n\n\n/* **************************************************************\n*  Templates\n****************************************************************/\n/*\n  designed to be included\n  for type-specific functions (template emulation in C)\n  Objective is to write these functions only once, for improved maintenance\n*/\n\n/* safety checks */\n#ifndef FSEv06_FUNCTION_EXTENSION\n#  error \"FSEv06_FUNCTION_EXTENSION must be defined\"\n#endif\n#ifndef FSEv06_FUNCTION_TYPE\n#  error \"FSEv06_FUNCTION_TYPE must be defined\"\n#endif\n\n/* Function names */\n#define FSEv06_CAT(X,Y) X##Y\n#define FSEv06_FUNCTION_NAME(X,Y) FSEv06_CAT(X,Y)\n#define FSEv06_TYPE_NAME(X,Y) FSEv06_CAT(X,Y)\n\n\n/* Function templates */\nFSEv06_DTable* FSEv06_createDTable (unsigned tableLog)\n{\n    if (tableLog > FSEv06_TABLELOG_ABSOLUTE_MAX) tableLog = FSEv06_TABLELOG_ABSOLUTE_MAX;\n    return (FSEv06_DTable*)malloc( FSEv06_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );\n}\n\nvoid FSEv06_freeDTable (FSEv06_DTable* dt)\n{\n    free(dt);\n}\n\nsize_t FSEv06_buildDTable(FSEv06_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)\n{\n    void* const tdPtr = dt+1;   /* because *dt is unsigned, 32-bits aligned on 32-bits */\n    FSEv06_DECODE_TYPE* const tableDecode = (FSEv06_DECODE_TYPE*) (tdPtr);\n    U16 symbolNext[FSEv06_MAX_SYMBOL_VALUE+1];\n\n    U32 const maxSV1 = maxSymbolValue + 1;\n    U32 const tableSize = 1 << tableLog;\n    U32 highThreshold = tableSize-1;\n\n    /* Sanity Checks */\n    if (maxSymbolValue > FSEv06_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);\n    if (tableLog > FSEv06_MAX_TABLELOG) return ERROR(tableLog_tooLarge);\n\n    /* Init, lay down lowprob symbols */\n    {   FSEv06_DTableHeader DTableH;\n        DTableH.tableLog = (U16)tableLog;\n        DTableH.fastMode = 1;\n        {   S16 const largeLimit= (S16)(1 << (tableLog-1));\n            U32 s;\n            for (s=0; s<maxSV1; s++) {\n                if (normalizedCounter[s]==-1) {\n                    tableDecode[highThreshold--].symbol = (FSEv06_FUNCTION_TYPE)s;\n                    symbolNext[s] = 1;\n                } else {\n                    if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;\n                    symbolNext[s] = normalizedCounter[s];\n        }   }   }\n        memcpy(dt, &DTableH, sizeof(DTableH));\n    }\n\n    /* Spread symbols */\n    {   U32 const tableMask = tableSize-1;\n        U32 const step = FSEv06_TABLESTEP(tableSize);\n        U32 s, position = 0;\n        for (s=0; s<maxSV1; s++) {\n            int i;\n            for (i=0; i<normalizedCounter[s]; i++) {\n                tableDecode[position].symbol = (FSEv06_FUNCTION_TYPE)s;\n                position = (position + step) & tableMask;\n                while (position > highThreshold) position = (position + step) & tableMask;   /* lowprob area */\n        }   }\n\n        if (position!=0) return ERROR(GENERIC);   /* position must reach all cells once, otherwise normalizedCounter is incorrect */\n    }\n\n    /* Build Decoding table */\n    {   U32 u;\n        for (u=0; u<tableSize; u++) {\n            FSEv06_FUNCTION_TYPE const symbol = (FSEv06_FUNCTION_TYPE)(tableDecode[u].symbol);\n            U16 nextState = symbolNext[symbol]++;\n            tableDecode[u].nbBits = (BYTE) (tableLog - BITv06_highbit32 ((U32)nextState) );\n            tableDecode[u].newState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);\n    }   }\n\n    return 0;\n}\n\n\n\n#ifndef FSEv06_COMMONDEFS_ONLY\n\n/*-*******************************************************\n*  Decompression (Byte symbols)\n*********************************************************/\nsize_t FSEv06_buildDTable_rle (FSEv06_DTable* dt, BYTE symbolValue)\n{\n    void* ptr = dt;\n    FSEv06_DTableHeader* const DTableH = (FSEv06_DTableHeader*)ptr;\n    void* dPtr = dt + 1;\n    FSEv06_decode_t* const cell = (FSEv06_decode_t*)dPtr;\n\n    DTableH->tableLog = 0;\n    DTableH->fastMode = 0;\n\n    cell->newState = 0;\n    cell->symbol = symbolValue;\n    cell->nbBits = 0;\n\n    return 0;\n}\n\n\nsize_t FSEv06_buildDTable_raw (FSEv06_DTable* dt, unsigned nbBits)\n{\n    void* ptr = dt;\n    FSEv06_DTableHeader* const DTableH = (FSEv06_DTableHeader*)ptr;\n    void* dPtr = dt + 1;\n    FSEv06_decode_t* const dinfo = (FSEv06_decode_t*)dPtr;\n    const unsigned tableSize = 1 << nbBits;\n    const unsigned tableMask = tableSize - 1;\n    const unsigned maxSV1 = tableMask+1;\n    unsigned s;\n\n    /* Sanity checks */\n    if (nbBits < 1) return ERROR(GENERIC);         /* min size */\n\n    /* Build Decoding Table */\n    DTableH->tableLog = (U16)nbBits;\n    DTableH->fastMode = 1;\n    for (s=0; s<maxSV1; s++) {\n        dinfo[s].newState = 0;\n        dinfo[s].symbol = (BYTE)s;\n        dinfo[s].nbBits = (BYTE)nbBits;\n    }\n\n    return 0;\n}\n\nFORCE_INLINE size_t FSEv06_decompress_usingDTable_generic(\n          void* dst, size_t maxDstSize,\n    const void* cSrc, size_t cSrcSize,\n    const FSEv06_DTable* dt, const unsigned fast)\n{\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* op = ostart;\n    BYTE* const omax = op + maxDstSize;\n    BYTE* const olimit = omax-3;\n\n    BITv06_DStream_t bitD;\n    FSEv06_DState_t state1;\n    FSEv06_DState_t state2;\n\n    /* Init */\n    { size_t const errorCode = BITv06_initDStream(&bitD, cSrc, cSrcSize);   /* replaced last arg by maxCompressed Size */\n      if (FSEv06_isError(errorCode)) return errorCode; }\n\n    FSEv06_initDState(&state1, &bitD, dt);\n    FSEv06_initDState(&state2, &bitD, dt);\n\n#define FSEv06_GETSYMBOL(statePtr) fast ? FSEv06_decodeSymbolFast(statePtr, &bitD) : FSEv06_decodeSymbol(statePtr, &bitD)\n\n    /* 4 symbols per loop */\n    for ( ; (BITv06_reloadDStream(&bitD)==BITv06_DStream_unfinished) && (op<olimit) ; op+=4) {\n        op[0] = FSEv06_GETSYMBOL(&state1);\n\n        if (FSEv06_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BITv06_reloadDStream(&bitD);\n\n        op[1] = FSEv06_GETSYMBOL(&state2);\n\n        if (FSEv06_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            { if (BITv06_reloadDStream(&bitD) > BITv06_DStream_unfinished) { op+=2; break; } }\n\n        op[2] = FSEv06_GETSYMBOL(&state1);\n\n        if (FSEv06_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BITv06_reloadDStream(&bitD);\n\n        op[3] = FSEv06_GETSYMBOL(&state2);\n    }\n\n    /* tail */\n    /* note : BITv06_reloadDStream(&bitD) >= FSEv06_DStream_partiallyFilled; Ends at exactly BITv06_DStream_completed */\n    while (1) {\n        if (op>(omax-2)) return ERROR(dstSize_tooSmall);\n\n        *op++ = FSEv06_GETSYMBOL(&state1);\n\n        if (BITv06_reloadDStream(&bitD)==BITv06_DStream_overflow) {\n            *op++ = FSEv06_GETSYMBOL(&state2);\n            break;\n        }\n\n        if (op>(omax-2)) return ERROR(dstSize_tooSmall);\n\n        *op++ = FSEv06_GETSYMBOL(&state2);\n\n        if (BITv06_reloadDStream(&bitD)==BITv06_DStream_overflow) {\n            *op++ = FSEv06_GETSYMBOL(&state1);\n            break;\n    }   }\n\n    return op-ostart;\n}\n\n\nsize_t FSEv06_decompress_usingDTable(void* dst, size_t originalSize,\n                            const void* cSrc, size_t cSrcSize,\n                            const FSEv06_DTable* dt)\n{\n    const void* ptr = dt;\n    const FSEv06_DTableHeader* DTableH = (const FSEv06_DTableHeader*)ptr;\n    const U32 fastMode = DTableH->fastMode;\n\n    /* select fast mode (static) */\n    if (fastMode) return FSEv06_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);\n    return FSEv06_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);\n}\n\n\nsize_t FSEv06_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)\n{\n    const BYTE* const istart = (const BYTE*)cSrc;\n    const BYTE* ip = istart;\n    short counting[FSEv06_MAX_SYMBOL_VALUE+1];\n    DTable_max_t dt;   /* Static analyzer seems unable to understand this table will be properly initialized later */\n    unsigned tableLog;\n    unsigned maxSymbolValue = FSEv06_MAX_SYMBOL_VALUE;\n\n    if (cSrcSize<2) return ERROR(srcSize_wrong);   /* too small input size */\n\n    /* normal FSE decoding mode */\n    {   size_t const NCountLength = FSEv06_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);\n        if (FSEv06_isError(NCountLength)) return NCountLength;\n        if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong);   /* too small input size */\n        ip += NCountLength;\n        cSrcSize -= NCountLength;\n    }\n\n    { size_t const errorCode = FSEv06_buildDTable (dt, counting, maxSymbolValue, tableLog);\n      if (FSEv06_isError(errorCode)) return errorCode; }\n\n    return FSEv06_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt);   /* always return, even if it is an error code */\n}\n\n\n\n#endif   /* FSEv06_COMMONDEFS_ONLY */\n/* ******************************************************************\n   Huffman coder, part of New Generation Entropy library\n   header file\n   Copyright (C) 2013-2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n****************************************************************** */\n#ifndef HUFv06_H\n#define HUFv06_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/* ****************************************\n*  HUF simple functions\n******************************************/\nsize_t HUFv06_decompress(void* dst,  size_t dstSize,\n                const void* cSrc, size_t cSrcSize);\n/*\nHUFv06_decompress() :\n    Decompress HUF data from buffer 'cSrc', of size 'cSrcSize',\n    into already allocated destination buffer 'dst', of size 'dstSize'.\n    `dstSize` : must be the **exact** size of original (uncompressed) data.\n    Note : in contrast with FSE, HUFv06_decompress can regenerate\n           RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data,\n           because it knows size to regenerate.\n    @return : size of regenerated data (== dstSize)\n              or an error code, which can be tested using HUFv06_isError()\n*/\n\n\n/* ****************************************\n*  Tool functions\n******************************************/\nsize_t HUFv06_compressBound(size_t size);       /**< maximum compressed size */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif   /* HUFv06_H */\n/* ******************************************************************\n   Huffman codec, part of New Generation Entropy library\n   header file, for static linking only\n   Copyright (C) 2013-2016, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n****************************************************************** */\n#ifndef HUFv06_STATIC_H\n#define HUFv06_STATIC_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/* ****************************************\n*  Static allocation\n******************************************/\n/* HUF buffer bounds */\n#define HUFv06_CTABLEBOUND 129\n#define HUFv06_BLOCKBOUND(size) (size + (size>>8) + 8)   /* only true if incompressible pre-filtered with fast heuristic */\n#define HUFv06_COMPRESSBOUND(size) (HUFv06_CTABLEBOUND + HUFv06_BLOCKBOUND(size))   /* Macro version, useful for static allocation */\n\n/* static allocation of HUF's DTable */\n#define HUFv06_DTABLE_SIZE(maxTableLog)   (1 + (1<<maxTableLog))\n#define HUFv06_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \\\n        unsigned short DTable[HUFv06_DTABLE_SIZE(maxTableLog)] = { maxTableLog }\n#define HUFv06_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \\\n        unsigned int DTable[HUFv06_DTABLE_SIZE(maxTableLog)] = { maxTableLog }\n#define HUFv06_CREATE_STATIC_DTABLEX6(DTable, maxTableLog) \\\n        unsigned int DTable[HUFv06_DTABLE_SIZE(maxTableLog) * 3 / 2] = { maxTableLog }\n\n\n/* ****************************************\n*  Advanced decompression functions\n******************************************/\nsize_t HUFv06_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */\nsize_t HUFv06_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbols decoder */\n\n\n\n/*!\nHUFv06_decompress() does the following:\n1. select the decompression algorithm (X2, X4, X6) based on pre-computed heuristics\n2. build Huffman table from save, using HUFv06_readDTableXn()\n3. decode 1 or 4 segments in parallel using HUFv06_decompressSXn_usingDTable\n*/\nsize_t HUFv06_readDTableX2 (unsigned short* DTable, const void* src, size_t srcSize);\nsize_t HUFv06_readDTableX4 (unsigned* DTable, const void* src, size_t srcSize);\n\nsize_t HUFv06_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable);\nsize_t HUFv06_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable);\n\n\n/* single stream variants */\nsize_t HUFv06_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */\nsize_t HUFv06_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbol decoder */\n\nsize_t HUFv06_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable);\nsize_t HUFv06_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable);\n\n\n\n/* **************************************************************\n*  Constants\n****************************************************************/\n#define HUFv06_ABSOLUTEMAX_TABLELOG  16   /* absolute limit of HUFv06_MAX_TABLELOG. Beyond that value, code does not work */\n#define HUFv06_MAX_TABLELOG  12           /* max configured tableLog (for static allocation); can be modified up to HUFv06_ABSOLUTEMAX_TABLELOG */\n#define HUFv06_DEFAULT_TABLELOG  HUFv06_MAX_TABLELOG   /* tableLog by default, when not specified */\n#define HUFv06_MAX_SYMBOL_VALUE 255\n#if (HUFv06_MAX_TABLELOG > HUFv06_ABSOLUTEMAX_TABLELOG)\n#  error \"HUFv06_MAX_TABLELOG is too large !\"\n#endif\n\n\n\n/*! HUFv06_readStats() :\n    Read compact Huffman tree, saved by HUFv06_writeCTable().\n    `huffWeight` is destination buffer.\n    @return : size read from `src`\n*/\nMEM_STATIC size_t HUFv06_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                            U32* nbSymbolsPtr, U32* tableLogPtr,\n                            const void* src, size_t srcSize)\n{\n    U32 weightTotal;\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize;\n    size_t oSize;\n\n    if (!srcSize) return ERROR(srcSize_wrong);\n    iSize = ip[0];\n    /* memset(huffWeight, 0, hwSize); */   /* is not necessary, even though some analyzer complain ... */\n\n    if (iSize >= 128)  { /* special header */\n        if (iSize >= (242)) {  /* RLE */\n            static U32 l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };\n            oSize = l[iSize-242];\n            memset(huffWeight, 1, hwSize);\n            iSize = 0;\n        }\n        else {   /* Incompressible */\n            oSize = iSize - 127;\n            iSize = ((oSize+1)/2);\n            if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n            if (oSize >= hwSize) return ERROR(corruption_detected);\n            ip += 1;\n            {   U32 n;\n                for (n=0; n<oSize; n+=2) {\n                    huffWeight[n]   = ip[n/2] >> 4;\n                    huffWeight[n+1] = ip[n/2] & 15;\n    }   }   }   }\n    else  {   /* header compressed with FSE (normal case) */\n        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n        oSize = FSEv06_decompress(huffWeight, hwSize-1, ip+1, iSize);   /* max (hwSize-1) values decoded, as last one is implied */\n        if (FSEv06_isError(oSize)) return oSize;\n    }\n\n    /* collect weight stats */\n    memset(rankStats, 0, (HUFv06_ABSOLUTEMAX_TABLELOG + 1) * sizeof(U32));\n    weightTotal = 0;\n    {   U32 n; for (n=0; n<oSize; n++) {\n            if (huffWeight[n] >= HUFv06_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);\n            rankStats[huffWeight[n]]++;\n            weightTotal += (1 << huffWeight[n]) >> 1;\n    }   }\n    if (weightTotal == 0) return ERROR(corruption_detected);\n\n    /* get last non-null symbol weight (implied, total must be 2^n) */\n    {   U32 const tableLog = BITv06_highbit32(weightTotal) + 1;\n        if (tableLog > HUFv06_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);\n        *tableLogPtr = tableLog;\n        /* determine last weight */\n        {   U32 const total = 1 << tableLog;\n            U32 const rest = total - weightTotal;\n            U32 const verif = 1 << BITv06_highbit32(rest);\n            U32 const lastWeight = BITv06_highbit32(rest) + 1;\n            if (verif != rest) return ERROR(corruption_detected);    /* last value must be a clean power of 2 */\n            huffWeight[oSize] = (BYTE)lastWeight;\n            rankStats[lastWeight]++;\n    }   }\n\n    /* check tree construction validity */\n    if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected);   /* by construction : at least 2 elts of rank 1, must be even */\n\n    /* results */\n    *nbSymbolsPtr = (U32)(oSize+1);\n    return iSize+1;\n}\n\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* HUFv06_STATIC_H */\n/* ******************************************************************\n   Huffman decoder, part of New Generation Entropy library\n   Copyright (C) 2013-2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n/* **************************************************************\n*  Compiler specifics\n****************************************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n/* inline is defined */\n#elif defined(_MSC_VER)\n#  define inline __inline\n#else\n#  define inline /* disable inline */\n#endif\n\n\n#ifdef _MSC_VER    /* Visual Studio */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#endif\n\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n#define HUFv06_STATIC_ASSERT(c) { enum { HUFv06_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n\n/* *******************************************************\n*  HUF : Huffman block decompression\n*********************************************************/\ntypedef struct { BYTE byte; BYTE nbBits; } HUFv06_DEltX2;   /* single-symbol decoding */\n\ntypedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUFv06_DEltX4;  /* double-symbols decoding */\n\ntypedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;\n\n\n\n/*-***************************/\n/*  single-symbol decoding   */\n/*-***************************/\n\nsize_t HUFv06_readDTableX2 (U16* DTable, const void* src, size_t srcSize)\n{\n    BYTE huffWeight[HUFv06_MAX_SYMBOL_VALUE + 1];\n    U32 rankVal[HUFv06_ABSOLUTEMAX_TABLELOG + 1];   /* large enough for values from 0 to 16 */\n    U32 tableLog = 0;\n    size_t iSize;\n    U32 nbSymbols = 0;\n    U32 n;\n    U32 nextRankStart;\n    void* const dtPtr = DTable + 1;\n    HUFv06_DEltX2* const dt = (HUFv06_DEltX2*)dtPtr;\n\n    HUFv06_STATIC_ASSERT(sizeof(HUFv06_DEltX2) == sizeof(U16));   /* if compilation fails here, assertion is false */\n    /* memset(huffWeight, 0, sizeof(huffWeight)); */   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUFv06_readStats(huffWeight, HUFv06_MAX_SYMBOL_VALUE + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);\n    if (HUFv06_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > DTable[0]) return ERROR(tableLog_tooLarge);   /* DTable is too small */\n    DTable[0] = (U16)tableLog;   /* maybe should separate sizeof allocated DTable, from used size of DTable, in case of re-use */\n\n    /* Prepare ranks */\n    nextRankStart = 0;\n    for (n=1; n<tableLog+1; n++) {\n        U32 current = nextRankStart;\n        nextRankStart += (rankVal[n] << (n-1));\n        rankVal[n] = current;\n    }\n\n    /* fill DTable */\n    for (n=0; n<nbSymbols; n++) {\n        const U32 w = huffWeight[n];\n        const U32 length = (1 << w) >> 1;\n        U32 i;\n        HUFv06_DEltX2 D;\n        D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w);\n        for (i = rankVal[w]; i < rankVal[w] + length; i++)\n            dt[i] = D;\n        rankVal[w] += length;\n    }\n\n    return iSize;\n}\n\n\nstatic BYTE HUFv06_decodeSymbolX2(BITv06_DStream_t* Dstream, const HUFv06_DEltX2* dt, const U32 dtLog)\n{\n    const size_t val = BITv06_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */\n    const BYTE c = dt[val].byte;\n    BITv06_skipBits(Dstream, dt[val].nbBits);\n    return c;\n}\n\n#define HUFv06_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \\\n    *ptr++ = HUFv06_decodeSymbolX2(DStreamPtr, dt, dtLog)\n\n#define HUFv06_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUFv06_MAX_TABLELOG<=12)) \\\n        HUFv06_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\n#define HUFv06_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        HUFv06_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\nstatic inline size_t HUFv06_decodeStreamX2(BYTE* p, BITv06_DStream_t* const bitDPtr, BYTE* const pEnd, const HUFv06_DEltX2* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 4 symbols at a time */\n    while ((BITv06_reloadDStream(bitDPtr) == BITv06_DStream_unfinished) && (p <= pEnd-4)) {\n        HUFv06_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUFv06_DECODE_SYMBOLX2_1(p, bitDPtr);\n        HUFv06_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUFv06_DECODE_SYMBOLX2_0(p, bitDPtr);\n    }\n\n    /* closer to the end */\n    while ((BITv06_reloadDStream(bitDPtr) == BITv06_DStream_unfinished) && (p < pEnd))\n        HUFv06_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    /* no more data to retrieve from bitstream, hence no need to reload */\n    while (p < pEnd)\n        HUFv06_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    return pEnd-pStart;\n}\n\nsize_t HUFv06_decompress1X2_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U16* DTable)\n{\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + dstSize;\n    const U32 dtLog = DTable[0];\n    const void* dtPtr = DTable;\n    const HUFv06_DEltX2* const dt = ((const HUFv06_DEltX2*)dtPtr)+1;\n    BITv06_DStream_t bitD;\n\n    { size_t const errorCode = BITv06_initDStream(&bitD, cSrc, cSrcSize);\n      if (HUFv06_isError(errorCode)) return errorCode; }\n\n    HUFv06_decodeStreamX2(op, &bitD, oend, dt, dtLog);\n\n    /* check */\n    if (!BITv06_endOfDStream(&bitD)) return ERROR(corruption_detected);\n\n    return dstSize;\n}\n\nsize_t HUFv06_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv06_CREATE_STATIC_DTABLEX2(DTable, HUFv06_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t const errorCode = HUFv06_readDTableX2 (DTable, cSrc, cSrcSize);\n    if (HUFv06_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    return HUFv06_decompress1X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\nsize_t HUFv06_decompress4X2_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U16* DTable)\n{\n    /* Check */\n    if (cSrcSize < 10) return ERROR(corruption_detected);  /* strict minimum : jump table + 1 byte per stream */\n\n    {   const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        const void* const dtPtr = DTable;\n        const HUFv06_DEltX2* const dt = ((const HUFv06_DEltX2*)dtPtr) +1;\n        const U32 dtLog = DTable[0];\n        size_t errorCode;\n\n        /* Init */\n        BITv06_DStream_t bitD1;\n        BITv06_DStream_t bitD2;\n        BITv06_DStream_t bitD3;\n        BITv06_DStream_t bitD4;\n        const size_t length1 = MEM_readLE16(istart);\n        const size_t length2 = MEM_readLE16(istart+2);\n        const size_t length3 = MEM_readLE16(istart+4);\n        size_t length4;\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n\n        length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        errorCode = BITv06_initDStream(&bitD1, istart1, length1);\n        if (HUFv06_isError(errorCode)) return errorCode;\n        errorCode = BITv06_initDStream(&bitD2, istart2, length2);\n        if (HUFv06_isError(errorCode)) return errorCode;\n        errorCode = BITv06_initDStream(&bitD3, istart3, length3);\n        if (HUFv06_isError(errorCode)) return errorCode;\n        errorCode = BITv06_initDStream(&bitD4, istart4, length4);\n        if (HUFv06_isError(errorCode)) return errorCode;\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BITv06_reloadDStream(&bitD1) | BITv06_reloadDStream(&bitD2) | BITv06_reloadDStream(&bitD3) | BITv06_reloadDStream(&bitD4);\n        for ( ; (endSignal==BITv06_DStream_unfinished) && (op4<(oend-7)) ; ) {\n            HUFv06_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUFv06_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUFv06_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUFv06_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUFv06_DECODE_SYMBOLX2_1(op1, &bitD1);\n            HUFv06_DECODE_SYMBOLX2_1(op2, &bitD2);\n            HUFv06_DECODE_SYMBOLX2_1(op3, &bitD3);\n            HUFv06_DECODE_SYMBOLX2_1(op4, &bitD4);\n            HUFv06_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUFv06_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUFv06_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUFv06_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUFv06_DECODE_SYMBOLX2_0(op1, &bitD1);\n            HUFv06_DECODE_SYMBOLX2_0(op2, &bitD2);\n            HUFv06_DECODE_SYMBOLX2_0(op3, &bitD3);\n            HUFv06_DECODE_SYMBOLX2_0(op4, &bitD4);\n            endSignal = BITv06_reloadDStream(&bitD1) | BITv06_reloadDStream(&bitD2) | BITv06_reloadDStream(&bitD3) | BITv06_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUFv06_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);\n        HUFv06_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);\n        HUFv06_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);\n        HUFv06_decodeStreamX2(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        endSignal = BITv06_endOfDStream(&bitD1) & BITv06_endOfDStream(&bitD2) & BITv06_endOfDStream(&bitD3) & BITv06_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nsize_t HUFv06_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv06_CREATE_STATIC_DTABLEX2(DTable, HUFv06_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t const errorCode = HUFv06_readDTableX2 (DTable, cSrc, cSrcSize);\n    if (HUFv06_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    return HUFv06_decompress4X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\n/* *************************/\n/* double-symbols decoding */\n/* *************************/\n\nstatic void HUFv06_fillDTableX4Level2(HUFv06_DEltX4* DTable, U32 sizeLog, const U32 consumed,\n                           const U32* rankValOrigin, const int minWeight,\n                           const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,\n                           U32 nbBitsBaseline, U16 baseSeq)\n{\n    HUFv06_DEltX4 DElt;\n    U32 rankVal[HUFv06_ABSOLUTEMAX_TABLELOG + 1];\n\n    /* get pre-calculated rankVal */\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill skipped values */\n    if (minWeight>1) {\n        U32 i, skipSize = rankVal[minWeight];\n        MEM_writeLE16(&(DElt.sequence), baseSeq);\n        DElt.nbBits   = (BYTE)(consumed);\n        DElt.length   = 1;\n        for (i = 0; i < skipSize; i++)\n            DTable[i] = DElt;\n    }\n\n    /* fill DTable */\n    { U32 s; for (s=0; s<sortedListSize; s++) {   /* note : sortedSymbols already skipped */\n        const U32 symbol = sortedSymbols[s].symbol;\n        const U32 weight = sortedSymbols[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 length = 1 << (sizeLog-nbBits);\n        const U32 start = rankVal[weight];\n        U32 i = start;\n        const U32 end = start + length;\n\n        MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));\n        DElt.nbBits = (BYTE)(nbBits + consumed);\n        DElt.length = 2;\n        do { DTable[i++] = DElt; } while (i<end);   /* since length >= 1 */\n\n        rankVal[weight] += length;\n    }}\n}\n\ntypedef U32 rankVal_t[HUFv06_ABSOLUTEMAX_TABLELOG][HUFv06_ABSOLUTEMAX_TABLELOG + 1];\n\nstatic void HUFv06_fillDTableX4(HUFv06_DEltX4* DTable, const U32 targetLog,\n                           const sortedSymbol_t* sortedList, const U32 sortedListSize,\n                           const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,\n                           const U32 nbBitsBaseline)\n{\n    U32 rankVal[HUFv06_ABSOLUTEMAX_TABLELOG + 1];\n    const int scaleLog = nbBitsBaseline - targetLog;   /* note : targetLog >= srcLog, hence scaleLog <= 1 */\n    const U32 minBits  = nbBitsBaseline - maxWeight;\n    U32 s;\n\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill DTable */\n    for (s=0; s<sortedListSize; s++) {\n        const U16 symbol = sortedList[s].symbol;\n        const U32 weight = sortedList[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 start = rankVal[weight];\n        const U32 length = 1 << (targetLog-nbBits);\n\n        if (targetLog-nbBits >= minBits) {   /* enough room for a second symbol */\n            U32 sortedRank;\n            int minWeight = nbBits + scaleLog;\n            if (minWeight < 1) minWeight = 1;\n            sortedRank = rankStart[minWeight];\n            HUFv06_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits,\n                           rankValOrigin[nbBits], minWeight,\n                           sortedList+sortedRank, sortedListSize-sortedRank,\n                           nbBitsBaseline, symbol);\n        } else {\n            HUFv06_DEltX4 DElt;\n            MEM_writeLE16(&(DElt.sequence), symbol);\n            DElt.nbBits = (BYTE)(nbBits);\n            DElt.length = 1;\n            {   U32 u;\n                const U32 end = start + length;\n                for (u = start; u < end; u++) DTable[u] = DElt;\n        }   }\n        rankVal[weight] += length;\n    }\n}\n\nsize_t HUFv06_readDTableX4 (U32* DTable, const void* src, size_t srcSize)\n{\n    BYTE weightList[HUFv06_MAX_SYMBOL_VALUE + 1];\n    sortedSymbol_t sortedSymbol[HUFv06_MAX_SYMBOL_VALUE + 1];\n    U32 rankStats[HUFv06_ABSOLUTEMAX_TABLELOG + 1] = { 0 };\n    U32 rankStart0[HUFv06_ABSOLUTEMAX_TABLELOG + 2] = { 0 };\n    U32* const rankStart = rankStart0+1;\n    rankVal_t rankVal;\n    U32 tableLog, maxW, sizeOfSort, nbSymbols;\n    const U32 memLog = DTable[0];\n    size_t iSize;\n    void* dtPtr = DTable;\n    HUFv06_DEltX4* const dt = ((HUFv06_DEltX4*)dtPtr) + 1;\n\n    HUFv06_STATIC_ASSERT(sizeof(HUFv06_DEltX4) == sizeof(U32));   /* if compilation fails here, assertion is false */\n    if (memLog > HUFv06_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge);\n    /* memset(weightList, 0, sizeof(weightList)); */   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUFv06_readStats(weightList, HUFv06_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);\n    if (HUFv06_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > memLog) return ERROR(tableLog_tooLarge);   /* DTable can't fit code depth */\n\n    /* find maxWeight */\n    for (maxW = tableLog; rankStats[maxW]==0; maxW--) {}  /* necessarily finds a solution before 0 */\n\n    /* Get start index of each weight */\n    {   U32 w, nextRankStart = 0;\n        for (w=1; w<maxW+1; w++) {\n            U32 current = nextRankStart;\n            nextRankStart += rankStats[w];\n            rankStart[w] = current;\n        }\n        rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/\n        sizeOfSort = nextRankStart;\n    }\n\n    /* sort symbols by weight */\n    {   U32 s;\n        for (s=0; s<nbSymbols; s++) {\n            U32 const w = weightList[s];\n            U32 const r = rankStart[w]++;\n            sortedSymbol[r].symbol = (BYTE)s;\n            sortedSymbol[r].weight = (BYTE)w;\n        }\n        rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */\n    }\n\n    /* Build rankVal */\n    {   U32* const rankVal0 = rankVal[0];\n        {   int const rescale = (memLog-tableLog) - 1;   /* tableLog <= memLog */\n            U32 nextRankVal = 0;\n            U32 w;\n            for (w=1; w<maxW+1; w++) {\n                U32 current = nextRankVal;\n                nextRankVal += rankStats[w] << (w+rescale);\n                rankVal0[w] = current;\n        }   }\n        {   U32 const minBits = tableLog+1 - maxW;\n            U32 consumed;\n            for (consumed = minBits; consumed < memLog - minBits + 1; consumed++) {\n                U32* const rankValPtr = rankVal[consumed];\n                U32 w;\n                for (w = 1; w < maxW+1; w++) {\n                    rankValPtr[w] = rankVal0[w] >> consumed;\n    }   }   }   }\n\n    HUFv06_fillDTableX4(dt, memLog,\n                   sortedSymbol, sizeOfSort,\n                   rankStart0, rankVal, maxW,\n                   tableLog+1);\n\n    return iSize;\n}\n\n\nstatic U32 HUFv06_decodeSymbolX4(void* op, BITv06_DStream_t* DStream, const HUFv06_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BITv06_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 2);\n    BITv06_skipBits(DStream, dt[val].nbBits);\n    return dt[val].length;\n}\n\nstatic U32 HUFv06_decodeLastSymbolX4(void* op, BITv06_DStream_t* DStream, const HUFv06_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BITv06_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 1);\n    if (dt[val].length==1) BITv06_skipBits(DStream, dt[val].nbBits);\n    else {\n        if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {\n            BITv06_skipBits(DStream, dt[val].nbBits);\n            if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))\n                DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);   /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */\n    }   }\n    return 1;\n}\n\n\n#define HUFv06_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \\\n    ptr += HUFv06_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUFv06_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUFv06_MAX_TABLELOG<=12)) \\\n        ptr += HUFv06_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUFv06_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        ptr += HUFv06_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\nstatic inline size_t HUFv06_decodeStreamX4(BYTE* p, BITv06_DStream_t* bitDPtr, BYTE* const pEnd, const HUFv06_DEltX4* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 8 symbols at a time */\n    while ((BITv06_reloadDStream(bitDPtr) == BITv06_DStream_unfinished) && (p < pEnd-7)) {\n        HUFv06_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUFv06_DECODE_SYMBOLX4_1(p, bitDPtr);\n        HUFv06_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUFv06_DECODE_SYMBOLX4_0(p, bitDPtr);\n    }\n\n    /* closer to the end */\n    while ((BITv06_reloadDStream(bitDPtr) == BITv06_DStream_unfinished) && (p <= pEnd-2))\n        HUFv06_DECODE_SYMBOLX4_0(p, bitDPtr);\n\n    while (p <= pEnd-2)\n        HUFv06_DECODE_SYMBOLX4_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */\n\n    if (p < pEnd)\n        p += HUFv06_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);\n\n    return p-pStart;\n}\n\n\nsize_t HUFv06_decompress1X4_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U32* DTable)\n{\n    const BYTE* const istart = (const BYTE*) cSrc;\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* const oend = ostart + dstSize;\n\n    const U32 dtLog = DTable[0];\n    const void* const dtPtr = DTable;\n    const HUFv06_DEltX4* const dt = ((const HUFv06_DEltX4*)dtPtr) +1;\n\n    /* Init */\n    BITv06_DStream_t bitD;\n    { size_t const errorCode = BITv06_initDStream(&bitD, istart, cSrcSize);\n      if (HUFv06_isError(errorCode)) return errorCode; }\n\n    /* decode */\n    HUFv06_decodeStreamX4(ostart, &bitD, oend, dt, dtLog);\n\n    /* check */\n    if (!BITv06_endOfDStream(&bitD)) return ERROR(corruption_detected);\n\n    /* decoded size */\n    return dstSize;\n}\n\nsize_t HUFv06_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv06_CREATE_STATIC_DTABLEX4(DTable, HUFv06_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t const hSize = HUFv06_readDTableX4 (DTable, cSrc, cSrcSize);\n    if (HUFv06_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize;\n    cSrcSize -= hSize;\n\n    return HUFv06_decompress1X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\nsize_t HUFv06_decompress4X4_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U32* DTable)\n{\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n\n    {   const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        const void* const dtPtr = DTable;\n        const HUFv06_DEltX4* const dt = ((const HUFv06_DEltX4*)dtPtr) +1;\n        const U32 dtLog = DTable[0];\n        size_t errorCode;\n\n        /* Init */\n        BITv06_DStream_t bitD1;\n        BITv06_DStream_t bitD2;\n        BITv06_DStream_t bitD3;\n        BITv06_DStream_t bitD4;\n        const size_t length1 = MEM_readLE16(istart);\n        const size_t length2 = MEM_readLE16(istart+2);\n        const size_t length3 = MEM_readLE16(istart+4);\n        size_t length4;\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n\n        length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        errorCode = BITv06_initDStream(&bitD1, istart1, length1);\n        if (HUFv06_isError(errorCode)) return errorCode;\n        errorCode = BITv06_initDStream(&bitD2, istart2, length2);\n        if (HUFv06_isError(errorCode)) return errorCode;\n        errorCode = BITv06_initDStream(&bitD3, istart3, length3);\n        if (HUFv06_isError(errorCode)) return errorCode;\n        errorCode = BITv06_initDStream(&bitD4, istart4, length4);\n        if (HUFv06_isError(errorCode)) return errorCode;\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BITv06_reloadDStream(&bitD1) | BITv06_reloadDStream(&bitD2) | BITv06_reloadDStream(&bitD3) | BITv06_reloadDStream(&bitD4);\n        for ( ; (endSignal==BITv06_DStream_unfinished) && (op4<(oend-7)) ; ) {\n            HUFv06_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUFv06_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUFv06_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUFv06_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUFv06_DECODE_SYMBOLX4_1(op1, &bitD1);\n            HUFv06_DECODE_SYMBOLX4_1(op2, &bitD2);\n            HUFv06_DECODE_SYMBOLX4_1(op3, &bitD3);\n            HUFv06_DECODE_SYMBOLX4_1(op4, &bitD4);\n            HUFv06_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUFv06_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUFv06_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUFv06_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUFv06_DECODE_SYMBOLX4_0(op1, &bitD1);\n            HUFv06_DECODE_SYMBOLX4_0(op2, &bitD2);\n            HUFv06_DECODE_SYMBOLX4_0(op3, &bitD3);\n            HUFv06_DECODE_SYMBOLX4_0(op4, &bitD4);\n\n            endSignal = BITv06_reloadDStream(&bitD1) | BITv06_reloadDStream(&bitD2) | BITv06_reloadDStream(&bitD3) | BITv06_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUFv06_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);\n        HUFv06_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);\n        HUFv06_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);\n        HUFv06_decodeStreamX4(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        endSignal = BITv06_endOfDStream(&bitD1) & BITv06_endOfDStream(&bitD2) & BITv06_endOfDStream(&bitD3) & BITv06_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nsize_t HUFv06_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv06_CREATE_STATIC_DTABLEX4(DTable, HUFv06_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t hSize = HUFv06_readDTableX4 (DTable, cSrc, cSrcSize);\n    if (HUFv06_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize;\n    cSrcSize -= hSize;\n\n    return HUFv06_decompress4X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\n\n\n/* ********************************/\n/* Generic decompression selector */\n/* ********************************/\n\ntypedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;\nstatic const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =\n{\n    /* single, double, quad */\n    {{0,0}, {1,1}, {2,2}},  /* Q==0 : impossible */\n    {{0,0}, {1,1}, {2,2}},  /* Q==1 : impossible */\n    {{  38,130}, {1313, 74}, {2151, 38}},   /* Q == 2 : 12-18% */\n    {{ 448,128}, {1353, 74}, {2238, 41}},   /* Q == 3 : 18-25% */\n    {{ 556,128}, {1353, 74}, {2238, 47}},   /* Q == 4 : 25-32% */\n    {{ 714,128}, {1418, 74}, {2436, 53}},   /* Q == 5 : 32-38% */\n    {{ 883,128}, {1437, 74}, {2464, 61}},   /* Q == 6 : 38-44% */\n    {{ 897,128}, {1515, 75}, {2622, 68}},   /* Q == 7 : 44-50% */\n    {{ 926,128}, {1613, 75}, {2730, 75}},   /* Q == 8 : 50-56% */\n    {{ 947,128}, {1729, 77}, {3359, 77}},   /* Q == 9 : 56-62% */\n    {{1107,128}, {2083, 81}, {4006, 84}},   /* Q ==10 : 62-69% */\n    {{1177,128}, {2379, 87}, {4785, 88}},   /* Q ==11 : 69-75% */\n    {{1242,128}, {2415, 93}, {5155, 84}},   /* Q ==12 : 75-81% */\n    {{1349,128}, {2644,106}, {5260,106}},   /* Q ==13 : 81-87% */\n    {{1455,128}, {2422,124}, {4174,124}},   /* Q ==14 : 87-93% */\n    {{ 722,128}, {1891,145}, {1936,146}},   /* Q ==15 : 93-99% */\n};\n\ntypedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);\n\nsize_t HUFv06_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    static const decompressionAlgo decompress[3] = { HUFv06_decompress4X2, HUFv06_decompress4X4, NULL };\n    U32 Dtime[3];   /* decompression time estimation */\n\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */\n    if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */\n    if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */\n\n    /* decoder timing evaluation */\n    {   U32 const Q = (U32)(cSrcSize * 16 / dstSize);   /* Q < 16 since dstSize > cSrcSize */\n        U32 const D256 = (U32)(dstSize >> 8);\n        U32 n; for (n=0; n<3; n++)\n            Dtime[n] = algoTime[Q][n].tableTime + (algoTime[Q][n].decode256Time * D256);\n    }\n\n    Dtime[1] += Dtime[1] >> 4; Dtime[2] += Dtime[2] >> 3; /* advantage to algorithms using less memory, for cache eviction */\n\n    {   U32 algoNb = 0;\n        if (Dtime[1] < Dtime[0]) algoNb = 1;\n        /* if (Dtime[2] < Dtime[algoNb]) algoNb = 2; */   /* current speed of HUFv06_decompress4X6 is not good */\n        return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);\n    }\n\n    /* return HUFv06_decompress4X2(dst, dstSize, cSrc, cSrcSize); */   /* multi-streams single-symbol decoding */\n    /* return HUFv06_decompress4X4(dst, dstSize, cSrc, cSrcSize); */   /* multi-streams double-symbols decoding */\n    /* return HUFv06_decompress4X6(dst, dstSize, cSrc, cSrcSize); */   /* multi-streams quad-symbols decoding */\n}\n/*\n    Common functions of Zstd compression library\n    Copyright (C) 2015-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd homepage : https://facebook.github.io/zstd/\n*/\n\n\n/*-****************************************\n*  Version\n******************************************/\n\n/*-****************************************\n*  ZSTD Error Management\n******************************************/\n/*! ZSTDv06_isError() :\n*   tells if a return value is an error code */\nunsigned ZSTDv06_isError(size_t code) { return ERR_isError(code); }\n\n/*! ZSTDv06_getErrorName() :\n*   provides error code string from function result (useful for debugging) */\nconst char* ZSTDv06_getErrorName(size_t code) { return ERR_getErrorName(code); }\n\n\n/* **************************************************************\n*  ZBUFF Error Management\n****************************************************************/\nunsigned ZBUFFv06_isError(size_t errorCode) { return ERR_isError(errorCode); }\n\nconst char* ZBUFFv06_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }\n/*\n    zstd - standard compression library\n    Copyright (C) 2014-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd homepage : https://facebook.github.io/zstd\n*/\n\n/* ***************************************************************\n*  Tuning parameters\n*****************************************************************/\n/*!\n * HEAPMODE :\n * Select how default decompression function ZSTDv06_decompress() will allocate memory,\n * in memory stack (0), or in memory heap (1, requires malloc())\n */\n#ifndef ZSTDv06_HEAPMODE\n#  define ZSTDv06_HEAPMODE 1\n#endif\n\n\n\n/*-*******************************************************\n*  Compiler specifics\n*********************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4324)        /* disable: C4324: padded structure */\n#endif\n\n\n/*-*************************************\n*  Macros\n***************************************/\n#define ZSTDv06_isError ERR_isError   /* for inlining */\n#define FSEv06_isError  ERR_isError\n#define HUFv06_isError  ERR_isError\n\n\n/*_*******************************************************\n*  Memory operations\n**********************************************************/\nstatic void ZSTDv06_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }\n\n\n/*-*************************************************************\n*   Context management\n***************************************************************/\ntypedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,\n               ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock } ZSTDv06_dStage;\n\nstruct ZSTDv06_DCtx_s\n{\n    FSEv06_DTable LLTable[FSEv06_DTABLE_SIZE_U32(LLFSELog)];\n    FSEv06_DTable OffTable[FSEv06_DTABLE_SIZE_U32(OffFSELog)];\n    FSEv06_DTable MLTable[FSEv06_DTABLE_SIZE_U32(MLFSELog)];\n    unsigned   hufTableX4[HUFv06_DTABLE_SIZE(ZSTD_HUFFDTABLE_CAPACITY_LOG)];\n    const void* previousDstEnd;\n    const void* base;\n    const void* vBase;\n    const void* dictEnd;\n    size_t expected;\n    size_t headerSize;\n    ZSTDv06_frameParams fParams;\n    blockType_t bType;   /* used in ZSTDv06_decompressContinue(), to transfer blockType between header decoding and block decoding stages */\n    ZSTDv06_dStage stage;\n    U32 flagRepeatTable;\n    const BYTE* litPtr;\n    size_t litSize;\n    BYTE litBuffer[ZSTDv06_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH];\n    BYTE headerBuffer[ZSTDv06_FRAMEHEADERSIZE_MAX];\n};  /* typedef'd to ZSTDv06_DCtx within \"zstd_static.h\" */\n\nsize_t ZSTDv06_sizeofDCtx (void); /* Hidden declaration */\nsize_t ZSTDv06_sizeofDCtx (void) { return sizeof(ZSTDv06_DCtx); }\n\nsize_t ZSTDv06_decompressBegin(ZSTDv06_DCtx* dctx)\n{\n    dctx->expected = ZSTDv06_frameHeaderSize_min;\n    dctx->stage = ZSTDds_getFrameHeaderSize;\n    dctx->previousDstEnd = NULL;\n    dctx->base = NULL;\n    dctx->vBase = NULL;\n    dctx->dictEnd = NULL;\n    dctx->hufTableX4[0] = ZSTD_HUFFDTABLE_CAPACITY_LOG;\n    dctx->flagRepeatTable = 0;\n    return 0;\n}\n\nZSTDv06_DCtx* ZSTDv06_createDCtx(void)\n{\n    ZSTDv06_DCtx* dctx = (ZSTDv06_DCtx*)malloc(sizeof(ZSTDv06_DCtx));\n    if (dctx==NULL) return NULL;\n    ZSTDv06_decompressBegin(dctx);\n    return dctx;\n}\n\nsize_t ZSTDv06_freeDCtx(ZSTDv06_DCtx* dctx)\n{\n    free(dctx);\n    return 0;   /* reserved as a potential error code in the future */\n}\n\nvoid ZSTDv06_copyDCtx(ZSTDv06_DCtx* dstDCtx, const ZSTDv06_DCtx* srcDCtx)\n{\n    memcpy(dstDCtx, srcDCtx,\n           sizeof(ZSTDv06_DCtx) - (ZSTDv06_BLOCKSIZE_MAX+WILDCOPY_OVERLENGTH + ZSTDv06_frameHeaderSize_max));  /* no need to copy workspace */\n}\n\n\n/*-*************************************************************\n*   Decompression section\n***************************************************************/\n\n/* Frame format description\n   Frame Header -  [ Block Header - Block ] - Frame End\n   1) Frame Header\n      - 4 bytes - Magic Number : ZSTDv06_MAGICNUMBER (defined within zstd_static.h)\n      - 1 byte  - Frame Descriptor\n   2) Block Header\n      - 3 bytes, starting with a 2-bits descriptor\n                 Uncompressed, Compressed, Frame End, unused\n   3) Block\n      See Block Format Description\n   4) Frame End\n      - 3 bytes, compatible with Block Header\n*/\n\n\n/* Frame descriptor\n\n   1 byte, using :\n   bit 0-3 : windowLog - ZSTDv06_WINDOWLOG_ABSOLUTEMIN   (see zstd_internal.h)\n   bit 4   : minmatch 4(0) or 3(1)\n   bit 5   : reserved (must be zero)\n   bit 6-7 : Frame content size : unknown, 1 byte, 2 bytes, 8 bytes\n\n   Optional : content size (0, 1, 2 or 8 bytes)\n   0 : unknown\n   1 : 0-255 bytes\n   2 : 256 - 65535+256\n   8 : up to 16 exa\n*/\n\n\n/* Compressed Block, format description\n\n   Block = Literal Section - Sequences Section\n   Prerequisite : size of (compressed) block, maximum size of regenerated data\n\n   1) Literal Section\n\n   1.1) Header : 1-5 bytes\n        flags: 2 bits\n            00 compressed by Huff0\n            01 unused\n            10 is Raw (uncompressed)\n            11 is Rle\n            Note : using 01 => Huff0 with precomputed table ?\n            Note : delta map ? => compressed ?\n\n   1.1.1) Huff0-compressed literal block : 3-5 bytes\n            srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream\n            srcSize < 1 KB => 3 bytes (2-2-10-10)\n            srcSize < 16KB => 4 bytes (2-2-14-14)\n            else           => 5 bytes (2-2-18-18)\n            big endian convention\n\n   1.1.2) Raw (uncompressed) literal block header : 1-3 bytes\n        size :  5 bits: (IS_RAW<<6) + (0<<4) + size\n               12 bits: (IS_RAW<<6) + (2<<4) + (size>>8)\n                        size&255\n               20 bits: (IS_RAW<<6) + (3<<4) + (size>>16)\n                        size>>8&255\n                        size&255\n\n   1.1.3) Rle (repeated single byte) literal block header : 1-3 bytes\n        size :  5 bits: (IS_RLE<<6) + (0<<4) + size\n               12 bits: (IS_RLE<<6) + (2<<4) + (size>>8)\n                        size&255\n               20 bits: (IS_RLE<<6) + (3<<4) + (size>>16)\n                        size>>8&255\n                        size&255\n\n   1.1.4) Huff0-compressed literal block, using precomputed CTables : 3-5 bytes\n            srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream\n            srcSize < 1 KB => 3 bytes (2-2-10-10)\n            srcSize < 16KB => 4 bytes (2-2-14-14)\n            else           => 5 bytes (2-2-18-18)\n            big endian convention\n\n        1- CTable available (stored into workspace ?)\n        2- Small input (fast heuristic ? Full comparison ? depend on clevel ?)\n\n\n   1.2) Literal block content\n\n   1.2.1) Huff0 block, using sizes from header\n        See Huff0 format\n\n   1.2.2) Huff0 block, using prepared table\n\n   1.2.3) Raw content\n\n   1.2.4) single byte\n\n\n   2) Sequences section\n      TO DO\n*/\n\n/** ZSTDv06_frameHeaderSize() :\n*   srcSize must be >= ZSTDv06_frameHeaderSize_min.\n*   @return : size of the Frame Header */\nstatic size_t ZSTDv06_frameHeaderSize(const void* src, size_t srcSize)\n{\n    if (srcSize < ZSTDv06_frameHeaderSize_min) return ERROR(srcSize_wrong);\n    { U32 const fcsId = (((const BYTE*)src)[4]) >> 6;\n      return ZSTDv06_frameHeaderSize_min + ZSTDv06_fcs_fieldSize[fcsId]; }\n}\n\n\n/** ZSTDv06_getFrameParams() :\n*   decode Frame Header, or provide expected `srcSize`.\n*   @return : 0, `fparamsPtr` is correctly filled,\n*            >0, `srcSize` is too small, result is expected `srcSize`,\n*             or an error code, which can be tested using ZSTDv06_isError() */\nsize_t ZSTDv06_getFrameParams(ZSTDv06_frameParams* fparamsPtr, const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n\n    if (srcSize < ZSTDv06_frameHeaderSize_min) return ZSTDv06_frameHeaderSize_min;\n    if (MEM_readLE32(src) != ZSTDv06_MAGICNUMBER) return ERROR(prefix_unknown);\n\n    /* ensure there is enough `srcSize` to fully read/decode frame header */\n    { size_t const fhsize = ZSTDv06_frameHeaderSize(src, srcSize);\n      if (srcSize < fhsize) return fhsize; }\n\n    memset(fparamsPtr, 0, sizeof(*fparamsPtr));\n    {   BYTE const frameDesc = ip[4];\n        fparamsPtr->windowLog = (frameDesc & 0xF) + ZSTDv06_WINDOWLOG_ABSOLUTEMIN;\n        if ((frameDesc & 0x20) != 0) return ERROR(frameParameter_unsupported);   /* reserved 1 bit */\n        switch(frameDesc >> 6)  /* fcsId */\n        {\n            default:   /* impossible */\n            case 0 : fparamsPtr->frameContentSize = 0; break;\n            case 1 : fparamsPtr->frameContentSize = ip[5]; break;\n            case 2 : fparamsPtr->frameContentSize = MEM_readLE16(ip+5)+256; break;\n            case 3 : fparamsPtr->frameContentSize = MEM_readLE64(ip+5); break;\n    }   }\n    return 0;\n}\n\n\n/** ZSTDv06_decodeFrameHeader() :\n*   `srcSize` must be the size provided by ZSTDv06_frameHeaderSize().\n*   @return : 0 if success, or an error code, which can be tested using ZSTDv06_isError() */\nstatic size_t ZSTDv06_decodeFrameHeader(ZSTDv06_DCtx* zc, const void* src, size_t srcSize)\n{\n    size_t const result = ZSTDv06_getFrameParams(&(zc->fParams), src, srcSize);\n    if ((MEM_32bits()) && (zc->fParams.windowLog > 25)) return ERROR(frameParameter_unsupported);\n    return result;\n}\n\n\ntypedef struct\n{\n    blockType_t blockType;\n    U32 origSize;\n} blockProperties_t;\n\n/*! ZSTDv06_getcBlockSize() :\n*   Provides the size of compressed block from block header `src` */\nstatic size_t ZSTDv06_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)\n{\n    const BYTE* const in = (const BYTE*)src;\n    U32 cSize;\n\n    if (srcSize < ZSTDv06_blockHeaderSize) return ERROR(srcSize_wrong);\n\n    bpPtr->blockType = (blockType_t)((*in) >> 6);\n    cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);\n    bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;\n\n    if (bpPtr->blockType == bt_end) return 0;\n    if (bpPtr->blockType == bt_rle) return 1;\n    return cSize;\n}\n\n\nstatic size_t ZSTDv06_copyRawBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    if (dst==NULL) return ERROR(dstSize_tooSmall);\n    if (srcSize > dstCapacity) return ERROR(dstSize_tooSmall);\n    memcpy(dst, src, srcSize);\n    return srcSize;\n}\n\n\n/*! ZSTDv06_decodeLiteralsBlock() :\n    @return : nb of bytes read from src (< srcSize ) */\nstatic size_t ZSTDv06_decodeLiteralsBlock(ZSTDv06_DCtx* dctx,\n                          const void* src, size_t srcSize)   /* note : srcSize < BLOCKSIZE */\n{\n    const BYTE* const istart = (const BYTE*) src;\n\n    /* any compressed block with literals segment must be at least this size */\n    if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);\n\n    switch(istart[0]>> 6)\n    {\n    case IS_HUF:\n        {   size_t litSize, litCSize, singleStream=0;\n            U32 lhSize = ((istart[0]) >> 4) & 3;\n            if (srcSize < 5) return ERROR(corruption_detected);   /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for lhSize, + cSize (+nbSeq) */\n            switch(lhSize)\n            {\n            case 0: case 1: default:   /* note : default is impossible, since lhSize into [0..3] */\n                /* 2 - 2 - 10 - 10 */\n                lhSize=3;\n                singleStream = istart[0] & 16;\n                litSize  = ((istart[0] & 15) << 6) + (istart[1] >> 2);\n                litCSize = ((istart[1] &  3) << 8) + istart[2];\n                break;\n            case 2:\n                /* 2 - 2 - 14 - 14 */\n                lhSize=4;\n                litSize  = ((istart[0] & 15) << 10) + (istart[1] << 2) + (istart[2] >> 6);\n                litCSize = ((istart[2] & 63) <<  8) + istart[3];\n                break;\n            case 3:\n                /* 2 - 2 - 18 - 18 */\n                lhSize=5;\n                litSize  = ((istart[0] & 15) << 14) + (istart[1] << 6) + (istart[2] >> 2);\n                litCSize = ((istart[2] &  3) << 16) + (istart[3] << 8) + istart[4];\n                break;\n            }\n            if (litSize > ZSTDv06_BLOCKSIZE_MAX) return ERROR(corruption_detected);\n            if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);\n\n            if (HUFv06_isError(singleStream ?\n                            HUFv06_decompress1X2(dctx->litBuffer, litSize, istart+lhSize, litCSize) :\n                            HUFv06_decompress   (dctx->litBuffer, litSize, istart+lhSize, litCSize) ))\n                return ERROR(corruption_detected);\n\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);\n            return litCSize + lhSize;\n        }\n    case IS_PCH:\n        {   size_t litSize, litCSize;\n            U32 lhSize = ((istart[0]) >> 4) & 3;\n            if (lhSize != 1)  /* only case supported for now : small litSize, single stream */\n                return ERROR(corruption_detected);\n            if (!dctx->flagRepeatTable)\n                return ERROR(dictionary_corrupted);\n\n            /* 2 - 2 - 10 - 10 */\n            lhSize=3;\n            litSize  = ((istart[0] & 15) << 6) + (istart[1] >> 2);\n            litCSize = ((istart[1] &  3) << 8) + istart[2];\n            if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);\n\n            {   size_t const errorCode = HUFv06_decompress1X4_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTableX4);\n                if (HUFv06_isError(errorCode)) return ERROR(corruption_detected);\n            }\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);\n            return litCSize + lhSize;\n        }\n    case IS_RAW:\n        {   size_t litSize;\n            U32 lhSize = ((istart[0]) >> 4) & 3;\n            switch(lhSize)\n            {\n            case 0: case 1: default:   /* note : default is impossible, since lhSize into [0..3] */\n                lhSize=1;\n                litSize = istart[0] & 31;\n                break;\n            case 2:\n                litSize = ((istart[0] & 15) << 8) + istart[1];\n                break;\n            case 3:\n                litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];\n                break;\n            }\n\n            if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) {  /* risk reading beyond src buffer with wildcopy */\n                if (litSize+lhSize > srcSize) return ERROR(corruption_detected);\n                memcpy(dctx->litBuffer, istart+lhSize, litSize);\n                dctx->litPtr = dctx->litBuffer;\n                dctx->litSize = litSize;\n                memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);\n                return lhSize+litSize;\n            }\n            /* direct reference into compressed stream */\n            dctx->litPtr = istart+lhSize;\n            dctx->litSize = litSize;\n            return lhSize+litSize;\n        }\n    case IS_RLE:\n        {   size_t litSize;\n            U32 lhSize = ((istart[0]) >> 4) & 3;\n            switch(lhSize)\n            {\n            case 0: case 1: default:   /* note : default is impossible, since lhSize into [0..3] */\n                lhSize = 1;\n                litSize = istart[0] & 31;\n                break;\n            case 2:\n                litSize = ((istart[0] & 15) << 8) + istart[1];\n                break;\n            case 3:\n                litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];\n                if (srcSize<4) return ERROR(corruption_detected);   /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */\n                break;\n            }\n            if (litSize > ZSTDv06_BLOCKSIZE_MAX) return ERROR(corruption_detected);\n            memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            return lhSize+1;\n        }\n    default:\n        return ERROR(corruption_detected);   /* impossible */\n    }\n}\n\n\n/*! ZSTDv06_buildSeqTable() :\n    @return : nb bytes read from src,\n              or an error code if it fails, testable with ZSTDv06_isError()\n*/\nstatic size_t ZSTDv06_buildSeqTable(FSEv06_DTable* DTable, U32 type, U32 max, U32 maxLog,\n                                 const void* src, size_t srcSize,\n                                 const S16* defaultNorm, U32 defaultLog, U32 flagRepeatTable)\n{\n    switch(type)\n    {\n    case FSEv06_ENCODING_RLE :\n        if (!srcSize) return ERROR(srcSize_wrong);\n        if ( (*(const BYTE*)src) > max) return ERROR(corruption_detected);\n        FSEv06_buildDTable_rle(DTable, *(const BYTE*)src);   /* if *src > max, data is corrupted */\n        return 1;\n    case FSEv06_ENCODING_RAW :\n        FSEv06_buildDTable(DTable, defaultNorm, max, defaultLog);\n        return 0;\n    case FSEv06_ENCODING_STATIC:\n        if (!flagRepeatTable) return ERROR(corruption_detected);\n        return 0;\n    default :   /* impossible */\n    case FSEv06_ENCODING_DYNAMIC :\n        {   U32 tableLog;\n            S16 norm[MaxSeq+1];\n            size_t const headerSize = FSEv06_readNCount(norm, &max, &tableLog, src, srcSize);\n            if (FSEv06_isError(headerSize)) return ERROR(corruption_detected);\n            if (tableLog > maxLog) return ERROR(corruption_detected);\n            FSEv06_buildDTable(DTable, norm, max, tableLog);\n            return headerSize;\n    }   }\n}\n\n\nstatic size_t ZSTDv06_decodeSeqHeaders(int* nbSeqPtr,\n                             FSEv06_DTable* DTableLL, FSEv06_DTable* DTableML, FSEv06_DTable* DTableOffb, U32 flagRepeatTable,\n                             const void* src, size_t srcSize)\n{\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* ip = istart;\n\n    /* check */\n    if (srcSize < MIN_SEQUENCES_SIZE) return ERROR(srcSize_wrong);\n\n    /* SeqHead */\n    {   int nbSeq = *ip++;\n        if (!nbSeq) { *nbSeqPtr=0; return 1; }\n        if (nbSeq > 0x7F) {\n            if (nbSeq == 0xFF) {\n                if (ip+2 > iend) return ERROR(srcSize_wrong);\n                nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;\n            } else {\n                if (ip >= iend) return ERROR(srcSize_wrong);\n                nbSeq = ((nbSeq-0x80)<<8) + *ip++;\n            }\n        }\n        *nbSeqPtr = nbSeq;\n    }\n\n    /* FSE table descriptors */\n    if (ip + 4 > iend) return ERROR(srcSize_wrong); /* min : header byte + all 3 are \"raw\", hence no header, but at least xxLog bits per type */\n    {   U32 const LLtype  = *ip >> 6;\n        U32 const Offtype = (*ip >> 4) & 3;\n        U32 const MLtype  = (*ip >> 2) & 3;\n        ip++;\n\n        /* Build DTables */\n        {   size_t const bhSize = ZSTDv06_buildSeqTable(DTableLL, LLtype, MaxLL, LLFSELog, ip, iend-ip, LL_defaultNorm, LL_defaultNormLog, flagRepeatTable);\n            if (ZSTDv06_isError(bhSize)) return ERROR(corruption_detected);\n            ip += bhSize;\n        }\n        {   size_t const bhSize = ZSTDv06_buildSeqTable(DTableOffb, Offtype, MaxOff, OffFSELog, ip, iend-ip, OF_defaultNorm, OF_defaultNormLog, flagRepeatTable);\n            if (ZSTDv06_isError(bhSize)) return ERROR(corruption_detected);\n            ip += bhSize;\n        }\n        {   size_t const bhSize = ZSTDv06_buildSeqTable(DTableML, MLtype, MaxML, MLFSELog, ip, iend-ip, ML_defaultNorm, ML_defaultNormLog, flagRepeatTable);\n            if (ZSTDv06_isError(bhSize)) return ERROR(corruption_detected);\n            ip += bhSize;\n    }   }\n\n    return ip-istart;\n}\n\n\ntypedef struct {\n    size_t litLength;\n    size_t matchLength;\n    size_t offset;\n} seq_t;\n\ntypedef struct {\n    BITv06_DStream_t DStream;\n    FSEv06_DState_t stateLL;\n    FSEv06_DState_t stateOffb;\n    FSEv06_DState_t stateML;\n    size_t prevOffset[ZSTDv06_REP_INIT];\n} seqState_t;\n\n\n\nstatic void ZSTDv06_decodeSequence(seq_t* seq, seqState_t* seqState)\n{\n    /* Literal length */\n    U32 const llCode = FSEv06_peekSymbol(&(seqState->stateLL));\n    U32 const mlCode = FSEv06_peekSymbol(&(seqState->stateML));\n    U32 const ofCode = FSEv06_peekSymbol(&(seqState->stateOffb));   /* <= maxOff, by table construction */\n\n    U32 const llBits = LL_bits[llCode];\n    U32 const mlBits = ML_bits[mlCode];\n    U32 const ofBits = ofCode;\n    U32 const totalBits = llBits+mlBits+ofBits;\n\n    static const U32 LL_base[MaxLL+1] = {\n                             0,  1,  2,  3,  4,  5,  6,  7,  8,  9,   10,    11,    12,    13,    14,     15,\n                            16, 18, 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,\n                            0x2000, 0x4000, 0x8000, 0x10000 };\n\n    static const U32 ML_base[MaxML+1] = {\n                             0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10,   11,    12,    13,    14,    15,\n                            16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,   27,    28,    29,    30,    31,\n                            32, 34, 36, 38, 40, 44, 48, 56, 64, 80, 96, 0x80, 0x100, 0x200, 0x400, 0x800,\n                            0x1000, 0x2000, 0x4000, 0x8000, 0x10000 };\n\n    static const U32 OF_base[MaxOff+1] = {\n                 0,        1,       3,       7,     0xF,     0x1F,     0x3F,     0x7F,\n                 0xFF,   0x1FF,   0x3FF,   0x7FF,   0xFFF,   0x1FFF,   0x3FFF,   0x7FFF,\n                 0xFFFF, 0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF,\n                 0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF, /*fake*/ 1, 1 };\n\n    /* sequence */\n    {   size_t offset;\n        if (!ofCode)\n            offset = 0;\n        else {\n            offset = OF_base[ofCode] + BITv06_readBits(&(seqState->DStream), ofBits);   /* <=  26 bits */\n            if (MEM_32bits()) BITv06_reloadDStream(&(seqState->DStream));\n        }\n\n        if (offset < ZSTDv06_REP_NUM) {\n            if (llCode == 0 && offset <= 1) offset = 1-offset;\n\n            if (offset != 0) {\n                size_t temp = seqState->prevOffset[offset];\n                if (offset != 1) {\n                    seqState->prevOffset[2] = seqState->prevOffset[1];\n                }\n                seqState->prevOffset[1] = seqState->prevOffset[0];\n                seqState->prevOffset[0] = offset = temp;\n\n            } else {\n                offset = seqState->prevOffset[0];\n            }\n        } else {\n            offset -= ZSTDv06_REP_MOVE;\n            seqState->prevOffset[2] = seqState->prevOffset[1];\n            seqState->prevOffset[1] = seqState->prevOffset[0];\n            seqState->prevOffset[0] = offset;\n        }\n        seq->offset = offset;\n    }\n\n    seq->matchLength = ML_base[mlCode] + MINMATCH + ((mlCode>31) ? BITv06_readBits(&(seqState->DStream), mlBits) : 0);   /* <=  16 bits */\n    if (MEM_32bits() && (mlBits+llBits>24)) BITv06_reloadDStream(&(seqState->DStream));\n\n    seq->litLength = LL_base[llCode] + ((llCode>15) ? BITv06_readBits(&(seqState->DStream), llBits) : 0);   /* <=  16 bits */\n    if (MEM_32bits() ||\n       (totalBits > 64 - 7 - (LLFSELog+MLFSELog+OffFSELog)) ) BITv06_reloadDStream(&(seqState->DStream));\n\n    /* ANS state update */\n    FSEv06_updateState(&(seqState->stateLL), &(seqState->DStream));   /* <=  9 bits */\n    FSEv06_updateState(&(seqState->stateML), &(seqState->DStream));   /* <=  9 bits */\n    if (MEM_32bits()) BITv06_reloadDStream(&(seqState->DStream));     /* <= 18 bits */\n    FSEv06_updateState(&(seqState->stateOffb), &(seqState->DStream)); /* <=  8 bits */\n}\n\n\nstatic size_t ZSTDv06_execSequence(BYTE* op,\n                                BYTE* const oend, seq_t sequence,\n                                const BYTE** litPtr, const BYTE* const litLimit,\n                                const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)\n{\n    BYTE* const oLitEnd = op + sequence.litLength;\n    size_t const sequenceLength = sequence.litLength + sequence.matchLength;\n    BYTE* const oMatchEnd = op + sequenceLength;   /* risk : address space overflow (32-bits) */\n    BYTE* const oend_8 = oend-8;\n    const BYTE* const iLitEnd = *litPtr + sequence.litLength;\n    const BYTE* match = oLitEnd - sequence.offset;\n\n    /* checks */\n    size_t const seqLength = sequence.litLength + sequence.matchLength;\n\n    if (seqLength > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);\n    if (sequence.litLength > (size_t)(litLimit - *litPtr)) return ERROR(corruption_detected);\n    /* Now we know there are no overflow in literal nor match lengths, can use pointer checks */\n    if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall);\n\n    if (oMatchEnd > oend) return ERROR(dstSize_tooSmall);   /* overwrite beyond dst buffer */\n    if (iLitEnd > litLimit) return ERROR(corruption_detected);   /* overRead beyond lit buffer */\n\n    /* copy Literals */\n    ZSTDv06_wildcopy(op, *litPtr, (ptrdiff_t)sequence.litLength);   /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */\n    op = oLitEnd;\n    *litPtr = iLitEnd;   /* update for next sequence */\n\n    /* copy Match */\n    if (sequence.offset > (size_t)(oLitEnd - base)) {\n        /* offset beyond prefix */\n        if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);\n        match = dictEnd - (base-match);\n        if (match + sequence.matchLength <= dictEnd) {\n            memmove(oLitEnd, match, sequence.matchLength);\n            return sequenceLength;\n        }\n        /* span extDict & currentPrefixSegment */\n        {   size_t const length1 = dictEnd - match;\n            memmove(oLitEnd, match, length1);\n            op = oLitEnd + length1;\n            sequence.matchLength -= length1;\n            match = base;\n            if (op > oend_8 || sequence.matchLength < MINMATCH) {\n              while (op < oMatchEnd) *op++ = *match++;\n              return sequenceLength;\n            }\n    }   }\n    /* Requirement: op <= oend_8 */\n\n    /* match within prefix */\n    if (sequence.offset < 8) {\n        /* close range match, overlap */\n        static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 };   /* added */\n        static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 };   /* subtracted */\n        int const sub2 = dec64table[sequence.offset];\n        op[0] = match[0];\n        op[1] = match[1];\n        op[2] = match[2];\n        op[3] = match[3];\n        match += dec32table[sequence.offset];\n        ZSTDv06_copy4(op+4, match);\n        match -= sub2;\n    } else {\n        ZSTDv06_copy8(op, match);\n    }\n    op += 8; match += 8;\n\n    if (oMatchEnd > oend-(16-MINMATCH)) {\n        if (op < oend_8) {\n            ZSTDv06_wildcopy(op, match, oend_8 - op);\n            match += oend_8 - op;\n            op = oend_8;\n        }\n        while (op < oMatchEnd) *op++ = *match++;\n    } else {\n        ZSTDv06_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8);   /* works even if matchLength < 8 */\n    }\n    return sequenceLength;\n}\n\n\nstatic size_t ZSTDv06_decompressSequences(\n                               ZSTDv06_DCtx* dctx,\n                               void* dst, size_t maxDstSize,\n                         const void* seqStart, size_t seqSize)\n{\n    const BYTE* ip = (const BYTE*)seqStart;\n    const BYTE* const iend = ip + seqSize;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = ostart + maxDstSize;\n    BYTE* op = ostart;\n    const BYTE* litPtr = dctx->litPtr;\n    const BYTE* const litEnd = litPtr + dctx->litSize;\n    FSEv06_DTable* DTableLL = dctx->LLTable;\n    FSEv06_DTable* DTableML = dctx->MLTable;\n    FSEv06_DTable* DTableOffb = dctx->OffTable;\n    const BYTE* const base = (const BYTE*) (dctx->base);\n    const BYTE* const vBase = (const BYTE*) (dctx->vBase);\n    const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);\n    int nbSeq;\n\n    /* Build Decoding Tables */\n    {   size_t const seqHSize = ZSTDv06_decodeSeqHeaders(&nbSeq, DTableLL, DTableML, DTableOffb, dctx->flagRepeatTable, ip, seqSize);\n        if (ZSTDv06_isError(seqHSize)) return seqHSize;\n        ip += seqHSize;\n        dctx->flagRepeatTable = 0;\n    }\n\n    /* Regen sequences */\n    if (nbSeq) {\n        seq_t sequence;\n        seqState_t seqState;\n\n        memset(&sequence, 0, sizeof(sequence));\n        sequence.offset = REPCODE_STARTVALUE;\n        { U32 i; for (i=0; i<ZSTDv06_REP_INIT; i++) seqState.prevOffset[i] = REPCODE_STARTVALUE; }\n        { size_t const errorCode = BITv06_initDStream(&(seqState.DStream), ip, iend-ip);\n          if (ERR_isError(errorCode)) return ERROR(corruption_detected); }\n        FSEv06_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);\n        FSEv06_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);\n        FSEv06_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);\n\n        for ( ; (BITv06_reloadDStream(&(seqState.DStream)) <= BITv06_DStream_completed) && nbSeq ; ) {\n            nbSeq--;\n            ZSTDv06_decodeSequence(&sequence, &seqState);\n\n#if 0  /* debug */\n            static BYTE* start = NULL;\n            if (start==NULL) start = op;\n            size_t pos = (size_t)(op-start);\n            if ((pos >= 5810037) && (pos < 5810400))\n                printf(\"Dpos %6u :%5u literals & match %3u bytes at distance %6u \\n\",\n                       pos, (U32)sequence.litLength, (U32)sequence.matchLength, (U32)sequence.offset);\n#endif\n\n            {   size_t const oneSeqSize = ZSTDv06_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);\n                if (ZSTDv06_isError(oneSeqSize)) return oneSeqSize;\n                op += oneSeqSize;\n        }   }\n\n        /* check if reached exact end */\n        if (nbSeq) return ERROR(corruption_detected);\n    }\n\n    /* last literal segment */\n    {   size_t const lastLLSize = litEnd - litPtr;\n        if (litPtr > litEnd) return ERROR(corruption_detected);   /* too many literals already used */\n        if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);\n        if (lastLLSize > 0) {\n            memcpy(op, litPtr, lastLLSize);\n            op += lastLLSize;\n        }\n    }\n\n    return op-ostart;\n}\n\n\nstatic void ZSTDv06_checkContinuity(ZSTDv06_DCtx* dctx, const void* dst)\n{\n    if (dst != dctx->previousDstEnd) {   /* not contiguous */\n        dctx->dictEnd = dctx->previousDstEnd;\n        dctx->vBase = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));\n        dctx->base = dst;\n        dctx->previousDstEnd = dst;\n    }\n}\n\n\nstatic size_t ZSTDv06_decompressBlock_internal(ZSTDv06_DCtx* dctx,\n                            void* dst, size_t dstCapacity,\n                      const void* src, size_t srcSize)\n{   /* blockType == blockCompressed */\n    const BYTE* ip = (const BYTE*)src;\n\n    if (srcSize >= ZSTDv06_BLOCKSIZE_MAX) return ERROR(srcSize_wrong);\n\n    /* Decode literals sub-block */\n    {   size_t const litCSize = ZSTDv06_decodeLiteralsBlock(dctx, src, srcSize);\n        if (ZSTDv06_isError(litCSize)) return litCSize;\n        ip += litCSize;\n        srcSize -= litCSize;\n    }\n    return ZSTDv06_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);\n}\n\n\nsize_t ZSTDv06_decompressBlock(ZSTDv06_DCtx* dctx,\n                            void* dst, size_t dstCapacity,\n                      const void* src, size_t srcSize)\n{\n    ZSTDv06_checkContinuity(dctx, dst);\n    return ZSTDv06_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);\n}\n\n\n/*! ZSTDv06_decompressFrame() :\n*   `dctx` must be properly initialized */\nstatic size_t ZSTDv06_decompressFrame(ZSTDv06_DCtx* dctx,\n                                 void* dst, size_t dstCapacity,\n                                 const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n    const BYTE* const iend = ip + srcSize;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + dstCapacity;\n    size_t remainingSize = srcSize;\n    blockProperties_t blockProperties = { bt_compressed, 0 };\n\n    /* check */\n    if (srcSize < ZSTDv06_frameHeaderSize_min+ZSTDv06_blockHeaderSize) return ERROR(srcSize_wrong);\n\n    /* Frame Header */\n    {   size_t const frameHeaderSize = ZSTDv06_frameHeaderSize(src, ZSTDv06_frameHeaderSize_min);\n        if (ZSTDv06_isError(frameHeaderSize)) return frameHeaderSize;\n        if (srcSize < frameHeaderSize+ZSTDv06_blockHeaderSize) return ERROR(srcSize_wrong);\n        if (ZSTDv06_decodeFrameHeader(dctx, src, frameHeaderSize)) return ERROR(corruption_detected);\n        ip += frameHeaderSize; remainingSize -= frameHeaderSize;\n    }\n\n    /* Loop on each block */\n    while (1) {\n        size_t decodedSize=0;\n        size_t const cBlockSize = ZSTDv06_getcBlockSize(ip, iend-ip, &blockProperties);\n        if (ZSTDv06_isError(cBlockSize)) return cBlockSize;\n\n        ip += ZSTDv06_blockHeaderSize;\n        remainingSize -= ZSTDv06_blockHeaderSize;\n        if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);\n\n        switch(blockProperties.blockType)\n        {\n        case bt_compressed:\n            decodedSize = ZSTDv06_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize);\n            break;\n        case bt_raw :\n            decodedSize = ZSTDv06_copyRawBlock(op, oend-op, ip, cBlockSize);\n            break;\n        case bt_rle :\n            return ERROR(GENERIC);   /* not yet supported */\n            break;\n        case bt_end :\n            /* end of frame */\n            if (remainingSize) return ERROR(srcSize_wrong);\n            break;\n        default:\n            return ERROR(GENERIC);   /* impossible */\n        }\n        if (cBlockSize == 0) break;   /* bt_end */\n\n        if (ZSTDv06_isError(decodedSize)) return decodedSize;\n        op += decodedSize;\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n    }\n\n    return op-ostart;\n}\n\n\nsize_t ZSTDv06_decompress_usingPreparedDCtx(ZSTDv06_DCtx* dctx, const ZSTDv06_DCtx* refDCtx,\n                                         void* dst, size_t dstCapacity,\n                                   const void* src, size_t srcSize)\n{\n    ZSTDv06_copyDCtx(dctx, refDCtx);\n    ZSTDv06_checkContinuity(dctx, dst);\n    return ZSTDv06_decompressFrame(dctx, dst, dstCapacity, src, srcSize);\n}\n\n\nsize_t ZSTDv06_decompress_usingDict(ZSTDv06_DCtx* dctx,\n                                 void* dst, size_t dstCapacity,\n                                 const void* src, size_t srcSize,\n                                 const void* dict, size_t dictSize)\n{\n    ZSTDv06_decompressBegin_usingDict(dctx, dict, dictSize);\n    ZSTDv06_checkContinuity(dctx, dst);\n    return ZSTDv06_decompressFrame(dctx, dst, dstCapacity, src, srcSize);\n}\n\n\nsize_t ZSTDv06_decompressDCtx(ZSTDv06_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    return ZSTDv06_decompress_usingDict(dctx, dst, dstCapacity, src, srcSize, NULL, 0);\n}\n\n\nsize_t ZSTDv06_decompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n#if defined(ZSTDv06_HEAPMODE) && (ZSTDv06_HEAPMODE==1)\n    size_t regenSize;\n    ZSTDv06_DCtx* dctx = ZSTDv06_createDCtx();\n    if (dctx==NULL) return ERROR(memory_allocation);\n    regenSize = ZSTDv06_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);\n    ZSTDv06_freeDCtx(dctx);\n    return regenSize;\n#else   /* stack mode */\n    ZSTDv06_DCtx dctx;\n    return ZSTDv06_decompressDCtx(&dctx, dst, dstCapacity, src, srcSize);\n#endif\n}\n\n/* ZSTD_errorFrameSizeInfoLegacy() :\n   assumes `cSize` and `dBound` are _not_ NULL */\nstatic void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)\n{\n    *cSize = ret;\n    *dBound = ZSTD_CONTENTSIZE_ERROR;\n}\n\nvoid ZSTDv06_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)\n{\n    const BYTE* ip = (const BYTE*)src;\n    size_t remainingSize = srcSize;\n    size_t nbBlocks = 0;\n    blockProperties_t blockProperties = { bt_compressed, 0 };\n\n    /* Frame Header */\n    {   size_t const frameHeaderSize = ZSTDv06_frameHeaderSize(src, srcSize);\n        if (ZSTDv06_isError(frameHeaderSize)) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, frameHeaderSize);\n            return;\n        }\n        if (MEM_readLE32(src) != ZSTDv06_MAGICNUMBER) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));\n            return;\n        }\n        if (srcSize < frameHeaderSize+ZSTDv06_blockHeaderSize) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n            return;\n        }\n        ip += frameHeaderSize; remainingSize -= frameHeaderSize;\n    }\n\n    /* Loop on each block */\n    while (1) {\n        size_t const cBlockSize = ZSTDv06_getcBlockSize(ip, remainingSize, &blockProperties);\n        if (ZSTDv06_isError(cBlockSize)) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);\n            return;\n        }\n\n        ip += ZSTDv06_blockHeaderSize;\n        remainingSize -= ZSTDv06_blockHeaderSize;\n        if (cBlockSize > remainingSize) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n            return;\n        }\n\n        if (cBlockSize == 0) break;   /* bt_end */\n\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n        nbBlocks++;\n    }\n\n    *cSize = ip - (const BYTE*)src;\n    *dBound = nbBlocks * ZSTDv06_BLOCKSIZE_MAX;\n}\n\n/*_******************************\n*  Streaming Decompression API\n********************************/\nsize_t ZSTDv06_nextSrcSizeToDecompress(ZSTDv06_DCtx* dctx)\n{\n    return dctx->expected;\n}\n\nsize_t ZSTDv06_decompressContinue(ZSTDv06_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    /* Sanity check */\n    if (srcSize != dctx->expected) return ERROR(srcSize_wrong);\n    if (dstCapacity) ZSTDv06_checkContinuity(dctx, dst);\n\n    /* Decompress : frame header; part 1 */\n    switch (dctx->stage)\n    {\n    case ZSTDds_getFrameHeaderSize :\n        if (srcSize != ZSTDv06_frameHeaderSize_min) return ERROR(srcSize_wrong);   /* impossible */\n        dctx->headerSize = ZSTDv06_frameHeaderSize(src, ZSTDv06_frameHeaderSize_min);\n        if (ZSTDv06_isError(dctx->headerSize)) return dctx->headerSize;\n        memcpy(dctx->headerBuffer, src, ZSTDv06_frameHeaderSize_min);\n        if (dctx->headerSize > ZSTDv06_frameHeaderSize_min) {\n            dctx->expected = dctx->headerSize - ZSTDv06_frameHeaderSize_min;\n            dctx->stage = ZSTDds_decodeFrameHeader;\n            return 0;\n        }\n        dctx->expected = 0;   /* not necessary to copy more */\n\t/* fall-through */\n    case ZSTDds_decodeFrameHeader:\n        {   size_t result;\n            memcpy(dctx->headerBuffer + ZSTDv06_frameHeaderSize_min, src, dctx->expected);\n            result = ZSTDv06_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize);\n            if (ZSTDv06_isError(result)) return result;\n            dctx->expected = ZSTDv06_blockHeaderSize;\n            dctx->stage = ZSTDds_decodeBlockHeader;\n            return 0;\n        }\n    case ZSTDds_decodeBlockHeader:\n        {   blockProperties_t bp;\n            size_t const cBlockSize = ZSTDv06_getcBlockSize(src, ZSTDv06_blockHeaderSize, &bp);\n            if (ZSTDv06_isError(cBlockSize)) return cBlockSize;\n            if (bp.blockType == bt_end) {\n                dctx->expected = 0;\n                dctx->stage = ZSTDds_getFrameHeaderSize;\n            } else {\n                dctx->expected = cBlockSize;\n                dctx->bType = bp.blockType;\n                dctx->stage = ZSTDds_decompressBlock;\n            }\n            return 0;\n        }\n    case ZSTDds_decompressBlock:\n        {   size_t rSize;\n            switch(dctx->bType)\n            {\n            case bt_compressed:\n                rSize = ZSTDv06_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);\n                break;\n            case bt_raw :\n                rSize = ZSTDv06_copyRawBlock(dst, dstCapacity, src, srcSize);\n                break;\n            case bt_rle :\n                return ERROR(GENERIC);   /* not yet handled */\n                break;\n            case bt_end :   /* should never happen (filtered at phase 1) */\n                rSize = 0;\n                break;\n            default:\n                return ERROR(GENERIC);   /* impossible */\n            }\n            dctx->stage = ZSTDds_decodeBlockHeader;\n            dctx->expected = ZSTDv06_blockHeaderSize;\n            if (ZSTDv06_isError(rSize)) return rSize;\n            dctx->previousDstEnd = (char*)dst + rSize;\n            return rSize;\n        }\n    default:\n        return ERROR(GENERIC);   /* impossible */\n    }\n}\n\n\nstatic void ZSTDv06_refDictContent(ZSTDv06_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    dctx->dictEnd = dctx->previousDstEnd;\n    dctx->vBase = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));\n    dctx->base = dict;\n    dctx->previousDstEnd = (const char*)dict + dictSize;\n}\n\nstatic size_t ZSTDv06_loadEntropy(ZSTDv06_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    size_t hSize, offcodeHeaderSize, matchlengthHeaderSize, litlengthHeaderSize;\n\n    hSize = HUFv06_readDTableX4(dctx->hufTableX4, dict, dictSize);\n    if (HUFv06_isError(hSize)) return ERROR(dictionary_corrupted);\n    dict = (const char*)dict + hSize;\n    dictSize -= hSize;\n\n    {   short offcodeNCount[MaxOff+1];\n        U32 offcodeMaxValue=MaxOff, offcodeLog;\n        offcodeHeaderSize = FSEv06_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dict, dictSize);\n        if (FSEv06_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);\n        if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted);\n        { size_t const errorCode = FSEv06_buildDTable(dctx->OffTable, offcodeNCount, offcodeMaxValue, offcodeLog);\n          if (FSEv06_isError(errorCode)) return ERROR(dictionary_corrupted); }\n        dict = (const char*)dict + offcodeHeaderSize;\n        dictSize -= offcodeHeaderSize;\n    }\n\n    {   short matchlengthNCount[MaxML+1];\n        unsigned matchlengthMaxValue = MaxML, matchlengthLog;\n        matchlengthHeaderSize = FSEv06_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dict, dictSize);\n        if (FSEv06_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);\n        if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);\n        { size_t const errorCode = FSEv06_buildDTable(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);\n          if (FSEv06_isError(errorCode)) return ERROR(dictionary_corrupted); }\n        dict = (const char*)dict + matchlengthHeaderSize;\n        dictSize -= matchlengthHeaderSize;\n    }\n\n    {   short litlengthNCount[MaxLL+1];\n        unsigned litlengthMaxValue = MaxLL, litlengthLog;\n        litlengthHeaderSize = FSEv06_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dict, dictSize);\n        if (FSEv06_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);\n        if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);\n        { size_t const errorCode = FSEv06_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog);\n          if (FSEv06_isError(errorCode)) return ERROR(dictionary_corrupted); }\n    }\n\n    dctx->flagRepeatTable = 1;\n    return hSize + offcodeHeaderSize + matchlengthHeaderSize + litlengthHeaderSize;\n}\n\nstatic size_t ZSTDv06_decompress_insertDictionary(ZSTDv06_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    size_t eSize;\n    U32 const magic = MEM_readLE32(dict);\n    if (magic != ZSTDv06_DICT_MAGIC) {\n        /* pure content mode */\n        ZSTDv06_refDictContent(dctx, dict, dictSize);\n        return 0;\n    }\n    /* load entropy tables */\n    dict = (const char*)dict + 4;\n    dictSize -= 4;\n    eSize = ZSTDv06_loadEntropy(dctx, dict, dictSize);\n    if (ZSTDv06_isError(eSize)) return ERROR(dictionary_corrupted);\n\n    /* reference dictionary content */\n    dict = (const char*)dict + eSize;\n    dictSize -= eSize;\n    ZSTDv06_refDictContent(dctx, dict, dictSize);\n\n    return 0;\n}\n\n\nsize_t ZSTDv06_decompressBegin_usingDict(ZSTDv06_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    { size_t const errorCode = ZSTDv06_decompressBegin(dctx);\n      if (ZSTDv06_isError(errorCode)) return errorCode; }\n\n    if (dict && dictSize) {\n        size_t const errorCode = ZSTDv06_decompress_insertDictionary(dctx, dict, dictSize);\n        if (ZSTDv06_isError(errorCode)) return ERROR(dictionary_corrupted);\n    }\n\n    return 0;\n}\n\n/*\n    Buffered version of Zstd compression library\n    Copyright (C) 2015-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd homepage : https://facebook.github.io/zstd/\n*/\n\n\n/*-***************************************************************************\n*  Streaming decompression howto\n*\n*  A ZBUFFv06_DCtx object is required to track streaming operations.\n*  Use ZBUFFv06_createDCtx() and ZBUFFv06_freeDCtx() to create/release resources.\n*  Use ZBUFFv06_decompressInit() to start a new decompression operation,\n*   or ZBUFFv06_decompressInitDictionary() if decompression requires a dictionary.\n*  Note that ZBUFFv06_DCtx objects can be re-init multiple times.\n*\n*  Use ZBUFFv06_decompressContinue() repetitively to consume your input.\n*  *srcSizePtr and *dstCapacityPtr can be any size.\n*  The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr.\n*  Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again.\n*  The content of @dst will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters, or change @dst.\n*  @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to help latency),\n*            or 0 when a frame is completely decoded,\n*            or an error code, which can be tested using ZBUFFv06_isError().\n*\n*  Hint : recommended buffer sizes (not compulsory) : ZBUFFv06_recommendedDInSize() and ZBUFFv06_recommendedDOutSize()\n*  output : ZBUFFv06_recommendedDOutSize==128 KB block size is the internal unit, it ensures it's always possible to write a full block when decoded.\n*  input  : ZBUFFv06_recommendedDInSize == 128KB + 3;\n*           just follow indications from ZBUFFv06_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .\n* *******************************************************************************/\n\ntypedef enum { ZBUFFds_init, ZBUFFds_loadHeader,\n               ZBUFFds_read, ZBUFFds_load, ZBUFFds_flush } ZBUFFv06_dStage;\n\n/* *** Resource management *** */\nstruct ZBUFFv06_DCtx_s {\n    ZSTDv06_DCtx* zd;\n    ZSTDv06_frameParams fParams;\n    ZBUFFv06_dStage stage;\n    char*  inBuff;\n    size_t inBuffSize;\n    size_t inPos;\n    char*  outBuff;\n    size_t outBuffSize;\n    size_t outStart;\n    size_t outEnd;\n    size_t blockSize;\n    BYTE headerBuffer[ZSTDv06_FRAMEHEADERSIZE_MAX];\n    size_t lhSize;\n};   /* typedef'd to ZBUFFv06_DCtx within \"zstd_buffered.h\" */\n\n\nZBUFFv06_DCtx* ZBUFFv06_createDCtx(void)\n{\n    ZBUFFv06_DCtx* zbd = (ZBUFFv06_DCtx*)malloc(sizeof(ZBUFFv06_DCtx));\n    if (zbd==NULL) return NULL;\n    memset(zbd, 0, sizeof(*zbd));\n    zbd->zd = ZSTDv06_createDCtx();\n    if (zbd->zd==NULL) {\n        ZBUFFv06_freeDCtx(zbd); /* avoid leaking the context */\n        return NULL;\n    }\n    zbd->stage = ZBUFFds_init;\n    return zbd;\n}\n\nsize_t ZBUFFv06_freeDCtx(ZBUFFv06_DCtx* zbd)\n{\n    if (zbd==NULL) return 0;   /* support free on null */\n    ZSTDv06_freeDCtx(zbd->zd);\n    free(zbd->inBuff);\n    free(zbd->outBuff);\n    free(zbd);\n    return 0;\n}\n\n\n/* *** Initialization *** */\n\nsize_t ZBUFFv06_decompressInitDictionary(ZBUFFv06_DCtx* zbd, const void* dict, size_t dictSize)\n{\n    zbd->stage = ZBUFFds_loadHeader;\n    zbd->lhSize = zbd->inPos = zbd->outStart = zbd->outEnd = 0;\n    return ZSTDv06_decompressBegin_usingDict(zbd->zd, dict, dictSize);\n}\n\nsize_t ZBUFFv06_decompressInit(ZBUFFv06_DCtx* zbd)\n{\n    return ZBUFFv06_decompressInitDictionary(zbd, NULL, 0);\n}\n\n\n\nMEM_STATIC size_t ZBUFFv06_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    size_t length = MIN(dstCapacity, srcSize);\n    if (length > 0) {\n        memcpy(dst, src, length);\n    }\n    return length;\n}\n\n\n/* *** Decompression *** */\n\nsize_t ZBUFFv06_decompressContinue(ZBUFFv06_DCtx* zbd,\n                                void* dst, size_t* dstCapacityPtr,\n                          const void* src, size_t* srcSizePtr)\n{\n    const char* const istart = (const char*)src;\n    const char* const iend = istart + *srcSizePtr;\n    const char* ip = istart;\n    char* const ostart = (char*)dst;\n    char* const oend = ostart + *dstCapacityPtr;\n    char* op = ostart;\n    U32 notDone = 1;\n\n    while (notDone) {\n        switch(zbd->stage)\n        {\n        case ZBUFFds_init :\n            return ERROR(init_missing);\n\n        case ZBUFFds_loadHeader :\n            {   size_t const hSize = ZSTDv06_getFrameParams(&(zbd->fParams), zbd->headerBuffer, zbd->lhSize);\n                if (hSize != 0) {\n                    size_t const toLoad = hSize - zbd->lhSize;   /* if hSize!=0, hSize > zbd->lhSize */\n                    if (ZSTDv06_isError(hSize)) return hSize;\n                    if (toLoad > (size_t)(iend-ip)) {   /* not enough input to load full header */\n                        if (ip != NULL)\n                            memcpy(zbd->headerBuffer + zbd->lhSize, ip, iend-ip);\n                        zbd->lhSize += iend-ip;\n                        *dstCapacityPtr = 0;\n                        return (hSize - zbd->lhSize) + ZSTDv06_blockHeaderSize;   /* remaining header bytes + next block header */\n                    }\n                    memcpy(zbd->headerBuffer + zbd->lhSize, ip, toLoad); zbd->lhSize = hSize; ip += toLoad;\n                    break;\n            }   }\n\n            /* Consume header */\n            {   size_t const h1Size = ZSTDv06_nextSrcSizeToDecompress(zbd->zd);  /* == ZSTDv06_frameHeaderSize_min */\n                size_t const h1Result = ZSTDv06_decompressContinue(zbd->zd, NULL, 0, zbd->headerBuffer, h1Size);\n                if (ZSTDv06_isError(h1Result)) return h1Result;\n                if (h1Size < zbd->lhSize) {   /* long header */\n                    size_t const h2Size = ZSTDv06_nextSrcSizeToDecompress(zbd->zd);\n                    size_t const h2Result = ZSTDv06_decompressContinue(zbd->zd, NULL, 0, zbd->headerBuffer+h1Size, h2Size);\n                    if (ZSTDv06_isError(h2Result)) return h2Result;\n            }   }\n\n            /* Frame header instruct buffer sizes */\n            {   size_t const blockSize = MIN(1 << zbd->fParams.windowLog, ZSTDv06_BLOCKSIZE_MAX);\n                zbd->blockSize = blockSize;\n                if (zbd->inBuffSize < blockSize) {\n                    free(zbd->inBuff);\n                    zbd->inBuffSize = blockSize;\n                    zbd->inBuff = (char*)malloc(blockSize);\n                    if (zbd->inBuff == NULL) return ERROR(memory_allocation);\n                }\n                {   size_t const neededOutSize = ((size_t)1 << zbd->fParams.windowLog) + blockSize + WILDCOPY_OVERLENGTH * 2;\n                    if (zbd->outBuffSize < neededOutSize) {\n                        free(zbd->outBuff);\n                        zbd->outBuffSize = neededOutSize;\n                        zbd->outBuff = (char*)malloc(neededOutSize);\n                        if (zbd->outBuff == NULL) return ERROR(memory_allocation);\n            }   }   }\n            zbd->stage = ZBUFFds_read;\n\t    /* fall-through */\n        case ZBUFFds_read:\n            {   size_t const neededInSize = ZSTDv06_nextSrcSizeToDecompress(zbd->zd);\n                if (neededInSize==0) {  /* end of frame */\n                    zbd->stage = ZBUFFds_init;\n                    notDone = 0;\n                    break;\n                }\n                if ((size_t)(iend-ip) >= neededInSize) {  /* decode directly from src */\n                    size_t const decodedSize = ZSTDv06_decompressContinue(zbd->zd,\n                        zbd->outBuff + zbd->outStart, zbd->outBuffSize - zbd->outStart,\n                        ip, neededInSize);\n                    if (ZSTDv06_isError(decodedSize)) return decodedSize;\n                    ip += neededInSize;\n                    if (!decodedSize) break;   /* this was just a header */\n                    zbd->outEnd = zbd->outStart +  decodedSize;\n                    zbd->stage = ZBUFFds_flush;\n                    break;\n                }\n                if (ip==iend) { notDone = 0; break; }   /* no more input */\n                zbd->stage = ZBUFFds_load;\n            }\n\t    /* fall-through */\n        case ZBUFFds_load:\n            {   size_t const neededInSize = ZSTDv06_nextSrcSizeToDecompress(zbd->zd);\n                size_t const toLoad = neededInSize - zbd->inPos;   /* should always be <= remaining space within inBuff */\n                size_t loadedSize;\n                if (toLoad > zbd->inBuffSize - zbd->inPos) return ERROR(corruption_detected);   /* should never happen */\n                loadedSize = ZBUFFv06_limitCopy(zbd->inBuff + zbd->inPos, toLoad, ip, iend-ip);\n                ip += loadedSize;\n                zbd->inPos += loadedSize;\n                if (loadedSize < toLoad) { notDone = 0; break; }   /* not enough input, wait for more */\n\n                /* decode loaded input */\n                {   size_t const decodedSize = ZSTDv06_decompressContinue(zbd->zd,\n                        zbd->outBuff + zbd->outStart, zbd->outBuffSize - zbd->outStart,\n                        zbd->inBuff, neededInSize);\n                    if (ZSTDv06_isError(decodedSize)) return decodedSize;\n                    zbd->inPos = 0;   /* input is consumed */\n                    if (!decodedSize) { zbd->stage = ZBUFFds_read; break; }   /* this was just a header */\n                    zbd->outEnd = zbd->outStart +  decodedSize;\n                    zbd->stage = ZBUFFds_flush;\n                    /* break; */ /* ZBUFFds_flush follows */\n                }\n\t    }\n\t    /* fall-through */\n        case ZBUFFds_flush:\n            {   size_t const toFlushSize = zbd->outEnd - zbd->outStart;\n                size_t const flushedSize = ZBUFFv06_limitCopy(op, oend-op, zbd->outBuff + zbd->outStart, toFlushSize);\n                op += flushedSize;\n                zbd->outStart += flushedSize;\n                if (flushedSize == toFlushSize) {\n                    zbd->stage = ZBUFFds_read;\n                    if (zbd->outStart + zbd->blockSize > zbd->outBuffSize)\n                        zbd->outStart = zbd->outEnd = 0;\n                    break;\n                }\n                /* cannot flush everything */\n                notDone = 0;\n                break;\n            }\n        default: return ERROR(GENERIC);   /* impossible */\n    }   }\n\n    /* result */\n    *srcSizePtr = ip-istart;\n    *dstCapacityPtr = op-ostart;\n    {   size_t nextSrcSizeHint = ZSTDv06_nextSrcSizeToDecompress(zbd->zd);\n        if (nextSrcSizeHint > ZSTDv06_blockHeaderSize) nextSrcSizeHint+= ZSTDv06_blockHeaderSize;   /* get following block header too */\n        nextSrcSizeHint -= zbd->inPos;   /* already loaded*/\n        return nextSrcSizeHint;\n    }\n}\n\n\n\n/* *************************************\n*  Tool functions\n***************************************/\nsize_t ZBUFFv06_recommendedDInSize(void)  { return ZSTDv06_BLOCKSIZE_MAX + ZSTDv06_blockHeaderSize /* block header size*/ ; }\nsize_t ZBUFFv06_recommendedDOutSize(void) { return ZSTDv06_BLOCKSIZE_MAX; }\n"
  },
  {
    "path": "lib/legacy/zstd_v06.h",
    "content": "/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTDv06_H\n#define ZSTDv06_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/*======  Dependency  ======*/\n#include <stddef.h>   /* size_t */\n\n\n/*======  Export for Windows  ======*/\n/*!\n*  ZSTDv06_DLL_EXPORT :\n*  Enable exporting of functions when building a Windows DLL\n*/\n#if defined(_WIN32) && defined(ZSTDv06_DLL_EXPORT) && (ZSTDv06_DLL_EXPORT==1)\n#  define ZSTDLIBv06_API __declspec(dllexport)\n#else\n#  define ZSTDLIBv06_API\n#endif\n\n\n/* *************************************\n*  Simple functions\n***************************************/\n/*! ZSTDv06_decompress() :\n    `compressedSize` : is the _exact_ size of the compressed blob, otherwise decompression will fail.\n    `dstCapacity` must be large enough, equal or larger than originalSize.\n    @return : the number of bytes decompressed into `dst` (<= `dstCapacity`),\n              or an errorCode if it fails (which can be tested using ZSTDv06_isError()) */\nZSTDLIBv06_API size_t ZSTDv06_decompress( void* dst, size_t dstCapacity,\n                                    const void* src, size_t compressedSize);\n\n/**\nZSTDv06_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.6.x format\n    srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'\n    cSize (output parameter)  : the number of bytes that would be read to decompress this frame\n                                or an error code if it fails (which can be tested using ZSTDv01_isError())\n    dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame\n                                or ZSTD_CONTENTSIZE_ERROR if an error occurs\n\n    note : assumes `cSize` and `dBound` are _not_ NULL.\n*/\nvoid ZSTDv06_findFrameSizeInfoLegacy(const void *src, size_t srcSize,\n                                     size_t* cSize, unsigned long long* dBound);\n\n/* *************************************\n*  Helper functions\n***************************************/\nZSTDLIBv06_API size_t      ZSTDv06_compressBound(size_t srcSize); /*!< maximum compressed size (worst case scenario) */\n\n/* Error Management */\nZSTDLIBv06_API unsigned    ZSTDv06_isError(size_t code);          /*!< tells if a `size_t` function result is an error code */\nZSTDLIBv06_API const char* ZSTDv06_getErrorName(size_t code);     /*!< provides readable string for an error code */\n\n\n/* *************************************\n*  Explicit memory management\n***************************************/\n/** Decompression context */\ntypedef struct ZSTDv06_DCtx_s ZSTDv06_DCtx;\nZSTDLIBv06_API ZSTDv06_DCtx* ZSTDv06_createDCtx(void);\nZSTDLIBv06_API size_t     ZSTDv06_freeDCtx(ZSTDv06_DCtx* dctx);      /*!< @return : errorCode */\n\n/** ZSTDv06_decompressDCtx() :\n*   Same as ZSTDv06_decompress(), but requires an already allocated ZSTDv06_DCtx (see ZSTDv06_createDCtx()) */\nZSTDLIBv06_API size_t ZSTDv06_decompressDCtx(ZSTDv06_DCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n\n/*-***********************\n*  Dictionary API\n*************************/\n/*! ZSTDv06_decompress_usingDict() :\n*   Decompression using a pre-defined Dictionary content (see dictBuilder).\n*   Dictionary must be identical to the one used during compression, otherwise regenerated data will be corrupted.\n*   Note : dict can be NULL, in which case, it's equivalent to ZSTDv06_decompressDCtx() */\nZSTDLIBv06_API size_t ZSTDv06_decompress_usingDict(ZSTDv06_DCtx* dctx,\n                                                   void* dst, size_t dstCapacity,\n                                             const void* src, size_t srcSize,\n                                             const void* dict,size_t dictSize);\n\n\n/*-************************\n*  Advanced Streaming API\n***************************/\nstruct ZSTDv06_frameParams_s { unsigned long long frameContentSize; unsigned windowLog; };\ntypedef struct ZSTDv06_frameParams_s ZSTDv06_frameParams;\n\nZSTDLIBv06_API size_t ZSTDv06_getFrameParams(ZSTDv06_frameParams* fparamsPtr, const void* src, size_t srcSize);   /**< doesn't consume input */\nZSTDLIBv06_API size_t ZSTDv06_decompressBegin_usingDict(ZSTDv06_DCtx* dctx, const void* dict, size_t dictSize);\nZSTDLIBv06_API void   ZSTDv06_copyDCtx(ZSTDv06_DCtx* dctx, const ZSTDv06_DCtx* preparedDCtx);\n\nZSTDLIBv06_API size_t ZSTDv06_nextSrcSizeToDecompress(ZSTDv06_DCtx* dctx);\nZSTDLIBv06_API size_t ZSTDv06_decompressContinue(ZSTDv06_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n\n\n/* *************************************\n*  ZBUFF API\n***************************************/\n\ntypedef struct ZBUFFv06_DCtx_s ZBUFFv06_DCtx;\nZSTDLIBv06_API ZBUFFv06_DCtx* ZBUFFv06_createDCtx(void);\nZSTDLIBv06_API size_t         ZBUFFv06_freeDCtx(ZBUFFv06_DCtx* dctx);\n\nZSTDLIBv06_API size_t ZBUFFv06_decompressInit(ZBUFFv06_DCtx* dctx);\nZSTDLIBv06_API size_t ZBUFFv06_decompressInitDictionary(ZBUFFv06_DCtx* dctx, const void* dict, size_t dictSize);\n\nZSTDLIBv06_API size_t ZBUFFv06_decompressContinue(ZBUFFv06_DCtx* dctx,\n                                                  void* dst, size_t* dstCapacityPtr,\n                                            const void* src, size_t* srcSizePtr);\n\n/*-***************************************************************************\n*  Streaming decompression howto\n*\n*  A ZBUFFv06_DCtx object is required to track streaming operations.\n*  Use ZBUFFv06_createDCtx() and ZBUFFv06_freeDCtx() to create/release resources.\n*  Use ZBUFFv06_decompressInit() to start a new decompression operation,\n*   or ZBUFFv06_decompressInitDictionary() if decompression requires a dictionary.\n*  Note that ZBUFFv06_DCtx objects can be re-init multiple times.\n*\n*  Use ZBUFFv06_decompressContinue() repetitively to consume your input.\n*  *srcSizePtr and *dstCapacityPtr can be any size.\n*  The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr.\n*  Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again.\n*  The content of `dst` will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters, or change `dst`.\n*  @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to help latency),\n*            or 0 when a frame is completely decoded,\n*            or an error code, which can be tested using ZBUFFv06_isError().\n*\n*  Hint : recommended buffer sizes (not compulsory) : ZBUFFv06_recommendedDInSize() and ZBUFFv06_recommendedDOutSize()\n*  output : ZBUFFv06_recommendedDOutSize== 128 KB block size is the internal unit, it ensures it's always possible to write a full block when decoded.\n*  input  : ZBUFFv06_recommendedDInSize == 128KB + 3;\n*           just follow indications from ZBUFFv06_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .\n* *******************************************************************************/\n\n\n/* *************************************\n*  Tool functions\n***************************************/\nZSTDLIBv06_API unsigned ZBUFFv06_isError(size_t errorCode);\nZSTDLIBv06_API const char* ZBUFFv06_getErrorName(size_t errorCode);\n\n/** Functions below provide recommended buffer sizes for Compression or Decompression operations.\n*   These sizes are just hints, they tend to offer better latency */\nZSTDLIBv06_API size_t ZBUFFv06_recommendedDInSize(void);\nZSTDLIBv06_API size_t ZBUFFv06_recommendedDOutSize(void);\n\n\n/*-*************************************\n*  Constants\n***************************************/\n#define ZSTDv06_MAGICNUMBER 0xFD2FB526   /* v0.6 */\n\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* ZSTDv06_BUFFERED_H */\n"
  },
  {
    "path": "lib/legacy/zstd_v07.c",
    "content": "/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/*- Dependencies -*/\n#include <stddef.h>     /* size_t, ptrdiff_t */\n#include <string.h>     /* memcpy */\n#include <stdlib.h>     /* malloc, free, qsort */\n\n#ifndef XXH_STATIC_LINKING_ONLY\n#  define XXH_STATIC_LINKING_ONLY    /* XXH64_state_t */\n#endif\n#include \"../common/xxhash.h\"                  /* XXH64_* */\n#include \"zstd_v07.h\"\n\n#define FSEv07_STATIC_LINKING_ONLY   /* FSEv07_MIN_TABLELOG */\n#define HUFv07_STATIC_LINKING_ONLY   /* HUFv07_TABLELOG_ABSOLUTEMAX */\n#define ZSTDv07_STATIC_LINKING_ONLY\n\n#include \"../common/compiler.h\"\n#include \"../common/error_private.h\"\n\n\n#ifdef ZSTDv07_STATIC_LINKING_ONLY\n\n/* ====================================================================================\n * The definitions in this section are considered experimental.\n * They should never be used with a dynamic library, as they may change in the future.\n * They are provided for advanced usages.\n * Use them only in association with static linking.\n * ==================================================================================== */\n\n/*--- Constants ---*/\n#define ZSTDv07_MAGIC_SKIPPABLE_START  0x184D2A50U\n\n#define ZSTDv07_WINDOWLOG_MAX_32  25\n#define ZSTDv07_WINDOWLOG_MAX_64  27\n#define ZSTDv07_WINDOWLOG_MAX    ((U32)(MEM_32bits() ? ZSTDv07_WINDOWLOG_MAX_32 : ZSTDv07_WINDOWLOG_MAX_64))\n#define ZSTDv07_WINDOWLOG_MIN     18\n#define ZSTDv07_CHAINLOG_MAX     (ZSTDv07_WINDOWLOG_MAX+1)\n#define ZSTDv07_CHAINLOG_MIN       4\n#define ZSTDv07_HASHLOG_MAX       ZSTDv07_WINDOWLOG_MAX\n#define ZSTDv07_HASHLOG_MIN       12\n#define ZSTDv07_HASHLOG3_MAX      17\n#define ZSTDv07_SEARCHLOG_MAX    (ZSTDv07_WINDOWLOG_MAX-1)\n#define ZSTDv07_SEARCHLOG_MIN      1\n#define ZSTDv07_SEARCHLENGTH_MAX   7\n#define ZSTDv07_SEARCHLENGTH_MIN   3\n#define ZSTDv07_TARGETLENGTH_MIN   4\n#define ZSTDv07_TARGETLENGTH_MAX 999\n\n#define ZSTDv07_FRAMEHEADERSIZE_MAX 18    /* for static allocation */\nstatic const size_t ZSTDv07_frameHeaderSize_min = 5;\nstatic const size_t ZSTDv07_frameHeaderSize_max = ZSTDv07_FRAMEHEADERSIZE_MAX;\nstatic const size_t ZSTDv07_skippableHeaderSize = 8;  /* magic number + skippable frame length */\n\n\n/* custom memory allocation functions */\ntypedef void* (*ZSTDv07_allocFunction) (void* opaque, size_t size);\ntypedef void  (*ZSTDv07_freeFunction) (void* opaque, void* address);\ntypedef struct { ZSTDv07_allocFunction customAlloc; ZSTDv07_freeFunction customFree; void* opaque; } ZSTDv07_customMem;\n\n\n/*--- Advanced Decompression functions ---*/\n\n/*! ZSTDv07_estimateDCtxSize() :\n *  Gives the potential amount of memory allocated to create a ZSTDv07_DCtx */\nZSTDLIBv07_API size_t ZSTDv07_estimateDCtxSize(void);\n\n/*! ZSTDv07_createDCtx_advanced() :\n *  Create a ZSTD decompression context using external alloc and free functions */\nZSTDLIBv07_API ZSTDv07_DCtx* ZSTDv07_createDCtx_advanced(ZSTDv07_customMem customMem);\n\n/*! ZSTDv07_sizeofDCtx() :\n *  Gives the amount of memory used by a given ZSTDv07_DCtx */\nZSTDLIBv07_API size_t ZSTDv07_sizeofDCtx(const ZSTDv07_DCtx* dctx);\n\n\n/* ******************************************************************\n*  Buffer-less streaming functions (synchronous mode)\n********************************************************************/\n\nZSTDLIBv07_API size_t ZSTDv07_decompressBegin(ZSTDv07_DCtx* dctx);\nZSTDLIBv07_API size_t ZSTDv07_decompressBegin_usingDict(ZSTDv07_DCtx* dctx, const void* dict, size_t dictSize);\nZSTDLIBv07_API void   ZSTDv07_copyDCtx(ZSTDv07_DCtx* dctx, const ZSTDv07_DCtx* preparedDCtx);\n\nZSTDLIBv07_API size_t ZSTDv07_nextSrcSizeToDecompress(ZSTDv07_DCtx* dctx);\nZSTDLIBv07_API size_t ZSTDv07_decompressContinue(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n/*\n  Buffer-less streaming decompression (synchronous mode)\n\n  A ZSTDv07_DCtx object is required to track streaming operations.\n  Use ZSTDv07_createDCtx() / ZSTDv07_freeDCtx() to manage it.\n  A ZSTDv07_DCtx object can be re-used multiple times.\n\n  First optional operation is to retrieve frame parameters, using ZSTDv07_getFrameParams(), which doesn't consume the input.\n  It can provide the minimum size of rolling buffer required to properly decompress data (`windowSize`),\n  and optionally the final size of uncompressed content.\n  (Note : content size is an optional info that may not be present. 0 means : content size unknown)\n  Frame parameters are extracted from the beginning of compressed frame.\n  The amount of data to read is variable, from ZSTDv07_frameHeaderSize_min to ZSTDv07_frameHeaderSize_max (so if `srcSize` >= ZSTDv07_frameHeaderSize_max, it will always work)\n  If `srcSize` is too small for operation to succeed, function will return the minimum size it requires to produce a result.\n  Result : 0 when successful, it means the ZSTDv07_frameParams structure has been filled.\n          >0 : means there is not enough data into `src`. Provides the expected size to successfully decode header.\n           errorCode, which can be tested using ZSTDv07_isError()\n\n  Start decompression, with ZSTDv07_decompressBegin() or ZSTDv07_decompressBegin_usingDict().\n  Alternatively, you can copy a prepared context, using ZSTDv07_copyDCtx().\n\n  Then use ZSTDv07_nextSrcSizeToDecompress() and ZSTDv07_decompressContinue() alternatively.\n  ZSTDv07_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTDv07_decompressContinue().\n  ZSTDv07_decompressContinue() requires this exact amount of bytes, or it will fail.\n\n  @result of ZSTDv07_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity).\n  It can be zero, which is not an error; it just means ZSTDv07_decompressContinue() has decoded some header.\n\n  ZSTDv07_decompressContinue() needs previous data blocks during decompression, up to `windowSize`.\n  They should preferably be located contiguously, prior to current block.\n  Alternatively, a round buffer of sufficient size is also possible. Sufficient size is determined by frame parameters.\n  ZSTDv07_decompressContinue() is very sensitive to contiguity,\n  if 2 blocks don't follow each other, make sure that either the compressor breaks contiguity at the same place,\n    or that previous contiguous segment is large enough to properly handle maximum back-reference.\n\n  A frame is fully decoded when ZSTDv07_nextSrcSizeToDecompress() returns zero.\n  Context can then be reset to start a new decompression.\n\n\n  == Special case : skippable frames ==\n\n  Skippable frames allow the integration of user-defined data into a flow of concatenated frames.\n  Skippable frames will be ignored (skipped) by a decompressor. The format of skippable frame is following:\n  a) Skippable frame ID - 4 Bytes, Little endian format, any value from 0x184D2A50 to 0x184D2A5F\n  b) Frame Size - 4 Bytes, Little endian format, unsigned 32-bits\n  c) Frame Content - any content (User Data) of length equal to Frame Size\n  For skippable frames ZSTDv07_decompressContinue() always returns 0.\n  For skippable frames ZSTDv07_getFrameParams() returns fparamsPtr->windowLog==0 what means that a frame is skippable.\n  It also returns Frame Size as fparamsPtr->frameContentSize.\n*/\n\n\n/* **************************************\n*  Block functions\n****************************************/\n/*! Block functions produce and decode raw zstd blocks, without frame metadata.\n    Frame metadata cost is typically ~18 bytes, which can be non-negligible for very small blocks (< 100 bytes).\n    User will have to take in charge required information to regenerate data, such as compressed and content sizes.\n\n    A few rules to respect :\n    - Compressing and decompressing require a context structure\n      + Use ZSTDv07_createCCtx() and ZSTDv07_createDCtx()\n    - It is necessary to init context before starting\n      + compression : ZSTDv07_compressBegin()\n      + decompression : ZSTDv07_decompressBegin()\n      + variants _usingDict() are also allowed\n      + copyCCtx() and copyDCtx() work too\n    - Block size is limited, it must be <= ZSTDv07_getBlockSizeMax()\n      + If you need to compress more, cut data into multiple blocks\n      + Consider using the regular ZSTDv07_compress() instead, as frame metadata costs become negligible when source size is large.\n    - When a block is considered not compressible enough, ZSTDv07_compressBlock() result will be zero.\n      In which case, nothing is produced into `dst`.\n      + User must test for such outcome and deal directly with uncompressed data\n      + ZSTDv07_decompressBlock() doesn't accept uncompressed data as input !!!\n      + In case of multiple successive blocks, decoder must be informed of uncompressed block existence to follow proper history.\n        Use ZSTDv07_insertBlock() in such a case.\n*/\n\n#define ZSTDv07_BLOCKSIZE_ABSOLUTEMAX (128 * 1024)   /* define, for static allocation */\nZSTDLIBv07_API size_t ZSTDv07_decompressBlock(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\nZSTDLIBv07_API size_t ZSTDv07_insertBlock(ZSTDv07_DCtx* dctx, const void* blockStart, size_t blockSize);  /**< insert block into `dctx` history. Useful for uncompressed blocks */\n\n\n#endif   /* ZSTDv07_STATIC_LINKING_ONLY */\n\n\n/* ******************************************************************\n   mem.h\n   low-level memory access routines\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef MEM_H_MODULE\n#define MEM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/*-****************************************\n*  Compiler specifics\n******************************************/\n#if defined(_MSC_VER)   /* Visual Studio */\n#   include <stdlib.h>  /* _byteswap_ulong */\n#   include <intrin.h>  /* _byteswap_* */\n#endif\n\n\n/*-**************************************************************\n*  Basic Types\n*****************************************************************/\n#if  !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )\n# if defined(_AIX)\n#  include <inttypes.h>\n# else\n#  include <stdint.h> /* intptr_t */\n# endif\n  typedef  uint8_t BYTE;\n  typedef uint16_t U16;\n  typedef  int16_t S16;\n  typedef uint32_t U32;\n  typedef  int32_t S32;\n  typedef uint64_t U64;\n  typedef  int64_t S64;\n#else\n  typedef unsigned char       BYTE;\n  typedef unsigned short      U16;\n  typedef   signed short      S16;\n  typedef unsigned int        U32;\n  typedef   signed int        S32;\n  typedef unsigned long long  U64;\n  typedef   signed long long  S64;\n#endif\n\n\n/*-**************************************************************\n*  Memory I/O\n*****************************************************************/\n\nMEM_STATIC unsigned MEM_32bits(void) { return sizeof(size_t)==4; }\nMEM_STATIC unsigned MEM_64bits(void) { return sizeof(size_t)==8; }\n\nMEM_STATIC unsigned MEM_isLittleEndian(void)\n{\n    const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */\n    return one.c[0];\n}\n\nMEM_STATIC U16 MEM_read16(const void* memPtr)\n{\n    U16 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U32 MEM_read32(const void* memPtr)\n{\n    U32 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U64 MEM_read64(const void* memPtr)\n{\n    U64 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value)\n{\n    memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC U32 MEM_swap32(U32 in)\n{\n#if defined(_MSC_VER)     /* Visual Studio */\n    return _byteswap_ulong(in);\n#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)\n    return __builtin_bswap32(in);\n#else\n    return  ((in << 24) & 0xff000000 ) |\n            ((in <<  8) & 0x00ff0000 ) |\n            ((in >>  8) & 0x0000ff00 ) |\n            ((in >> 24) & 0x000000ff );\n#endif\n}\n\nMEM_STATIC U64 MEM_swap64(U64 in)\n{\n#if defined(_MSC_VER)     /* Visual Studio */\n    return _byteswap_uint64(in);\n#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)\n    return __builtin_bswap64(in);\n#else\n    return  ((in << 56) & 0xff00000000000000ULL) |\n            ((in << 40) & 0x00ff000000000000ULL) |\n            ((in << 24) & 0x0000ff0000000000ULL) |\n            ((in << 8)  & 0x000000ff00000000ULL) |\n            ((in >> 8)  & 0x00000000ff000000ULL) |\n            ((in >> 24) & 0x0000000000ff0000ULL) |\n            ((in >> 40) & 0x000000000000ff00ULL) |\n            ((in >> 56) & 0x00000000000000ffULL);\n#endif\n}\n\n\n/*=== Little endian r/w ===*/\n\nMEM_STATIC U16 MEM_readLE16(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read16(memPtr);\n    else {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U16)(p[0] + (p[1]<<8));\n    }\n}\n\nMEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)\n{\n    if (MEM_isLittleEndian()) {\n        MEM_write16(memPtr, val);\n    } else {\n        BYTE* p = (BYTE*)memPtr;\n        p[0] = (BYTE)val;\n        p[1] = (BYTE)(val>>8);\n    }\n}\n\nMEM_STATIC U32 MEM_readLE32(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read32(memPtr);\n    else\n        return MEM_swap32(MEM_read32(memPtr));\n}\n\n\nMEM_STATIC U64 MEM_readLE64(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read64(memPtr);\n    else\n        return MEM_swap64(MEM_read64(memPtr));\n}\n\nMEM_STATIC size_t MEM_readLEST(const void* memPtr)\n{\n    if (MEM_32bits())\n        return (size_t)MEM_readLE32(memPtr);\n    else\n        return (size_t)MEM_readLE64(memPtr);\n}\n\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* MEM_H_MODULE */\n/* ******************************************************************\n   bitstream\n   Part of FSE library\n   header file (to include)\n   Copyright (C) 2013-2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n****************************************************************** */\n#ifndef BITSTREAM_H_MODULE\n#define BITSTREAM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/*\n*  This API consists of small unitary functions, which must be inlined for best performance.\n*  Since link-time-optimization is not available for all compilers,\n*  these functions are defined into a .h to be included.\n*/\n\n\n/*=========================================\n*  Target specific\n=========================================*/\n#if defined(__BMI__) && defined(__GNUC__)\n#  include <immintrin.h>   /* support for bextr (experimental) */\n#endif\n\n/*-********************************************\n*  bitStream decoding API (read backward)\n**********************************************/\ntypedef struct\n{\n    size_t   bitContainer;\n    unsigned bitsConsumed;\n    const char* ptr;\n    const char* start;\n} BITv07_DStream_t;\n\ntypedef enum { BITv07_DStream_unfinished = 0,\n               BITv07_DStream_endOfBuffer = 1,\n               BITv07_DStream_completed = 2,\n               BITv07_DStream_overflow = 3 } BITv07_DStream_status;  /* result of BITv07_reloadDStream() */\n               /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */\n\nMEM_STATIC size_t   BITv07_initDStream(BITv07_DStream_t* bitD, const void* srcBuffer, size_t srcSize);\nMEM_STATIC size_t   BITv07_readBits(BITv07_DStream_t* bitD, unsigned nbBits);\nMEM_STATIC BITv07_DStream_status BITv07_reloadDStream(BITv07_DStream_t* bitD);\nMEM_STATIC unsigned BITv07_endOfDStream(const BITv07_DStream_t* bitD);\n\n\n\n/*-****************************************\n*  unsafe API\n******************************************/\nMEM_STATIC size_t BITv07_readBitsFast(BITv07_DStream_t* bitD, unsigned nbBits);\n/* faster, but works only if nbBits >= 1 */\n\n\n\n/*-**************************************************************\n*  Internal functions\n****************************************************************/\nMEM_STATIC unsigned BITv07_highbit32 (U32 val)\n{\n#   if defined(_MSC_VER)   /* Visual */\n    unsigned long r;\n    return _BitScanReverse(&r, val) ? (unsigned)r : 0;\n#   elif defined(__GNUC__) && (__GNUC__ >= 3)   /* Use GCC Intrinsic */\n    return __builtin_clz (val) ^ 31;\n#   else   /* Software version */\n    static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };\n    U32 v = val;\n    v |= v >> 1;\n    v |= v >> 2;\n    v |= v >> 4;\n    v |= v >> 8;\n    v |= v >> 16;\n    return DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];\n#   endif\n}\n\n\n\n/*-********************************************************\n* bitStream decoding\n**********************************************************/\n/*! BITv07_initDStream() :\n*   Initialize a BITv07_DStream_t.\n*   `bitD` : a pointer to an already allocated BITv07_DStream_t structure.\n*   `srcSize` must be the *exact* size of the bitStream, in bytes.\n*   @return : size of stream (== srcSize) or an errorCode if a problem is detected\n*/\nMEM_STATIC size_t BITv07_initDStream(BITv07_DStream_t* bitD, const void* srcBuffer, size_t srcSize)\n{\n    if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }\n\n    if (srcSize >=  sizeof(bitD->bitContainer)) {  /* normal case */\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer);\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];\n          bitD->bitsConsumed = lastByte ? 8 - BITv07_highbit32(lastByte) : 0;\n          if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }\n    } else {\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = bitD->start;\n        bitD->bitContainer = *(const BYTE*)(bitD->start);\n        switch(srcSize)\n        {\n            case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);/* fall-through */\n            case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);/* fall-through */\n            case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);/* fall-through */\n            case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24; /* fall-through */\n            case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16; /* fall-through */\n            case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) <<  8; /* fall-through */\n            default: break;\n        }\n        { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];\n          bitD->bitsConsumed = lastByte ? 8 - BITv07_highbit32(lastByte) : 0;\n          if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }\n        bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8;\n    }\n\n    return srcSize;\n}\n\n\n MEM_STATIC size_t BITv07_lookBits(const BITv07_DStream_t* bitD, U32 nbBits)\n{\n    U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);\n}\n\n/*! BITv07_lookBitsFast() :\n*   unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BITv07_lookBitsFast(const BITv07_DStream_t* bitD, U32 nbBits)\n{\n    U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);\n}\n\nMEM_STATIC void BITv07_skipBits(BITv07_DStream_t* bitD, U32 nbBits)\n{\n    bitD->bitsConsumed += nbBits;\n}\n\nMEM_STATIC size_t BITv07_readBits(BITv07_DStream_t* bitD, U32 nbBits)\n{\n    size_t const value = BITv07_lookBits(bitD, nbBits);\n    BITv07_skipBits(bitD, nbBits);\n    return value;\n}\n\n/*! BITv07_readBitsFast() :\n*   unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BITv07_readBitsFast(BITv07_DStream_t* bitD, U32 nbBits)\n{\n    size_t const value = BITv07_lookBitsFast(bitD, nbBits);\n    BITv07_skipBits(bitD, nbBits);\n    return value;\n}\n\nMEM_STATIC BITv07_DStream_status BITv07_reloadDStream(BITv07_DStream_t* bitD)\n{\n    if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should not happen => corruption detected */\n        return BITv07_DStream_overflow;\n\n    if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {\n        bitD->ptr -= bitD->bitsConsumed >> 3;\n        bitD->bitsConsumed &= 7;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        return BITv07_DStream_unfinished;\n    }\n    if (bitD->ptr == bitD->start) {\n        if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BITv07_DStream_endOfBuffer;\n        return BITv07_DStream_completed;\n    }\n    {   U32 nbBytes = bitD->bitsConsumed >> 3;\n        BITv07_DStream_status result = BITv07_DStream_unfinished;\n        if (bitD->ptr - nbBytes < bitD->start) {\n            nbBytes = (U32)(bitD->ptr - bitD->start);  /* ptr > start */\n            result = BITv07_DStream_endOfBuffer;\n        }\n        bitD->ptr -= nbBytes;\n        bitD->bitsConsumed -= nbBytes*8;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);   /* reminder : srcSize > sizeof(bitD) */\n        return result;\n    }\n}\n\n/*! BITv07_endOfDStream() :\n*   @return Tells if DStream has exactly reached its end (all bits consumed).\n*/\nMEM_STATIC unsigned BITv07_endOfDStream(const BITv07_DStream_t* DStream)\n{\n    return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));\n}\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* BITSTREAM_H_MODULE */\n/* ******************************************************************\n   FSE : Finite State Entropy codec\n   Public Prototypes declaration\n   Copyright (C) 2013-2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n****************************************************************** */\n#ifndef FSEv07_H\n#define FSEv07_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n\n/*-****************************************\n*  FSE simple functions\n******************************************/\n\n/*! FSEv07_decompress():\n    Decompress FSE data from buffer 'cSrc', of size 'cSrcSize',\n    into already allocated destination buffer 'dst', of size 'dstCapacity'.\n    @return : size of regenerated data (<= maxDstSize),\n              or an error code, which can be tested using FSEv07_isError() .\n\n    ** Important ** : FSEv07_decompress() does not decompress non-compressible nor RLE data !!!\n    Why ? : making this distinction requires a header.\n    Header management is intentionally delegated to the user layer, which can better manage special cases.\n*/\nsize_t FSEv07_decompress(void* dst,  size_t dstCapacity,\n                const void* cSrc, size_t cSrcSize);\n\n\n/* Error Management */\nunsigned    FSEv07_isError(size_t code);        /* tells if a return value is an error code */\nconst char* FSEv07_getErrorName(size_t code);   /* provides error code string (useful for debugging) */\n\n\n/*-*****************************************\n*  FSE detailed API\n******************************************/\n/*!\nFSEv07_decompress() does the following:\n1. read normalized counters with readNCount()\n2. build decoding table 'DTable' from normalized counters\n3. decode the data stream using decoding table 'DTable'\n\nThe following API allows targeting specific sub-functions for advanced tasks.\nFor example, it's possible to compress several blocks using the same 'CTable',\nor to save and provide normalized distribution using external method.\n*/\n\n\n/* *** DECOMPRESSION *** */\n\n/*! FSEv07_readNCount():\n    Read compactly saved 'normalizedCounter' from 'rBuffer'.\n    @return : size read from 'rBuffer',\n              or an errorCode, which can be tested using FSEv07_isError().\n              maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */\nsize_t FSEv07_readNCount (short* normalizedCounter, unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, const void* rBuffer, size_t rBuffSize);\n\n/*! Constructor and Destructor of FSEv07_DTable.\n    Note that its size depends on 'tableLog' */\ntypedef unsigned FSEv07_DTable;   /* don't allocate that. It's just a way to be more restrictive than void* */\nFSEv07_DTable* FSEv07_createDTable(unsigned tableLog);\nvoid        FSEv07_freeDTable(FSEv07_DTable* dt);\n\n/*! FSEv07_buildDTable():\n    Builds 'dt', which must be already allocated, using FSEv07_createDTable().\n    return : 0, or an errorCode, which can be tested using FSEv07_isError() */\nsize_t FSEv07_buildDTable (FSEv07_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);\n\n/*! FSEv07_decompress_usingDTable():\n    Decompress compressed source `cSrc` of size `cSrcSize` using `dt`\n    into `dst` which must be already allocated.\n    @return : size of regenerated data (necessarily <= `dstCapacity`),\n              or an errorCode, which can be tested using FSEv07_isError() */\nsize_t FSEv07_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSEv07_DTable* dt);\n\n/*!\nTutorial :\n----------\n(Note : these functions only decompress FSE-compressed blocks.\n If block is uncompressed, use memcpy() instead\n If block is a single repeated byte, use memset() instead )\n\nThe first step is to obtain the normalized frequencies of symbols.\nThis can be performed by FSEv07_readNCount() if it was saved using FSEv07_writeNCount().\n'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short.\nIn practice, that means it's necessary to know 'maxSymbolValue' beforehand,\nor size the table to handle worst case situations (typically 256).\nFSEv07_readNCount() will provide 'tableLog' and 'maxSymbolValue'.\nThe result of FSEv07_readNCount() is the number of bytes read from 'rBuffer'.\nNote that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that.\nIf there is an error, the function will return an error code, which can be tested using FSEv07_isError().\n\nThe next step is to build the decompression tables 'FSEv07_DTable' from 'normalizedCounter'.\nThis is performed by the function FSEv07_buildDTable().\nThe space required by 'FSEv07_DTable' must be already allocated using FSEv07_createDTable().\nIf there is an error, the function will return an error code, which can be tested using FSEv07_isError().\n\n`FSEv07_DTable` can then be used to decompress `cSrc`, with FSEv07_decompress_usingDTable().\n`cSrcSize` must be strictly correct, otherwise decompression will fail.\nFSEv07_decompress_usingDTable() result will tell how many bytes were regenerated (<=`dstCapacity`).\nIf there is an error, the function will return an error code, which can be tested using FSEv07_isError(). (ex: dst buffer too small)\n*/\n\n\n#ifdef FSEv07_STATIC_LINKING_ONLY\n\n\n/* *****************************************\n*  Static allocation\n*******************************************/\n/* FSE buffer bounds */\n#define FSEv07_NCOUNTBOUND 512\n#define FSEv07_BLOCKBOUND(size) (size + (size>>7))\n\n/* It is possible to statically allocate FSE CTable/DTable as a table of unsigned using below macros */\n#define FSEv07_DTABLE_SIZE_U32(maxTableLog)                   (1 + (1<<maxTableLog))\n\n\n/* *****************************************\n*  FSE advanced API\n*******************************************/\nsize_t FSEv07_countFast(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize);\n/**< same as FSEv07_count(), but blindly trusts that all byte values within src are <= *maxSymbolValuePtr  */\n\nunsigned FSEv07_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus);\n/**< same as FSEv07_optimalTableLog(), which used `minus==2` */\n\nsize_t FSEv07_buildDTable_raw (FSEv07_DTable* dt, unsigned nbBits);\n/**< build a fake FSEv07_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */\n\nsize_t FSEv07_buildDTable_rle (FSEv07_DTable* dt, unsigned char symbolValue);\n/**< build a fake FSEv07_DTable, designed to always generate the same symbolValue */\n\n\n\n/* *****************************************\n*  FSE symbol decompression API\n*******************************************/\ntypedef struct\n{\n    size_t      state;\n    const void* table;   /* precise table may vary, depending on U16 */\n} FSEv07_DState_t;\n\n\nstatic void     FSEv07_initDState(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD, const FSEv07_DTable* dt);\n\nstatic unsigned char FSEv07_decodeSymbol(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD);\n\n\n\n/* *****************************************\n*  FSE unsafe API\n*******************************************/\nstatic unsigned char FSEv07_decodeSymbolFast(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD);\n/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */\n\n\n/* ======    Decompression    ====== */\n\ntypedef struct {\n    U16 tableLog;\n    U16 fastMode;\n} FSEv07_DTableHeader;   /* sizeof U32 */\n\ntypedef struct\n{\n    unsigned short newState;\n    unsigned char  symbol;\n    unsigned char  nbBits;\n} FSEv07_decode_t;   /* size == U32 */\n\nMEM_STATIC void FSEv07_initDState(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD, const FSEv07_DTable* dt)\n{\n    const void* ptr = dt;\n    const FSEv07_DTableHeader* const DTableH = (const FSEv07_DTableHeader*)ptr;\n    DStatePtr->state = BITv07_readBits(bitD, DTableH->tableLog);\n    BITv07_reloadDStream(bitD);\n    DStatePtr->table = dt + 1;\n}\n\nMEM_STATIC BYTE FSEv07_peekSymbol(const FSEv07_DState_t* DStatePtr)\n{\n    FSEv07_decode_t const DInfo = ((const FSEv07_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    return DInfo.symbol;\n}\n\nMEM_STATIC void FSEv07_updateState(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD)\n{\n    FSEv07_decode_t const DInfo = ((const FSEv07_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    U32 const nbBits = DInfo.nbBits;\n    size_t const lowBits = BITv07_readBits(bitD, nbBits);\n    DStatePtr->state = DInfo.newState + lowBits;\n}\n\nMEM_STATIC BYTE FSEv07_decodeSymbol(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD)\n{\n    FSEv07_decode_t const DInfo = ((const FSEv07_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    U32 const nbBits = DInfo.nbBits;\n    BYTE const symbol = DInfo.symbol;\n    size_t const lowBits = BITv07_readBits(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\n/*! FSEv07_decodeSymbolFast() :\n    unsafe, only works if no symbol has a probability > 50% */\nMEM_STATIC BYTE FSEv07_decodeSymbolFast(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD)\n{\n    FSEv07_decode_t const DInfo = ((const FSEv07_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    U32 const nbBits = DInfo.nbBits;\n    BYTE const symbol = DInfo.symbol;\n    size_t const lowBits = BITv07_readBitsFast(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\n\n\n#ifndef FSEv07_COMMONDEFS_ONLY\n\n/* **************************************************************\n*  Tuning parameters\n****************************************************************/\n/*!MEMORY_USAGE :\n*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n*  Increasing memory usage improves compression ratio\n*  Reduced memory usage can improve speed, due to cache effect\n*  Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */\n#define FSEv07_MAX_MEMORY_USAGE 14\n#define FSEv07_DEFAULT_MEMORY_USAGE 13\n\n/*!FSEv07_MAX_SYMBOL_VALUE :\n*  Maximum symbol value authorized.\n*  Required for proper stack allocation */\n#define FSEv07_MAX_SYMBOL_VALUE 255\n\n\n/* **************************************************************\n*  template functions type & suffix\n****************************************************************/\n#define FSEv07_FUNCTION_TYPE BYTE\n#define FSEv07_FUNCTION_EXTENSION\n#define FSEv07_DECODE_TYPE FSEv07_decode_t\n\n\n#endif   /* !FSEv07_COMMONDEFS_ONLY */\n\n\n/* ***************************************************************\n*  Constants\n*****************************************************************/\n#define FSEv07_MAX_TABLELOG  (FSEv07_MAX_MEMORY_USAGE-2)\n#define FSEv07_MAX_TABLESIZE (1U<<FSEv07_MAX_TABLELOG)\n#define FSEv07_MAXTABLESIZE_MASK (FSEv07_MAX_TABLESIZE-1)\n#define FSEv07_DEFAULT_TABLELOG (FSEv07_DEFAULT_MEMORY_USAGE-2)\n#define FSEv07_MIN_TABLELOG 5\n\n#define FSEv07_TABLELOG_ABSOLUTE_MAX 15\n#if FSEv07_MAX_TABLELOG > FSEv07_TABLELOG_ABSOLUTE_MAX\n#  error \"FSEv07_MAX_TABLELOG > FSEv07_TABLELOG_ABSOLUTE_MAX is not supported\"\n#endif\n\n#define FSEv07_TABLESTEP(tableSize) ((tableSize>>1) + (tableSize>>3) + 3)\n\n\n#endif /* FSEv07_STATIC_LINKING_ONLY */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* FSEv07_H */\n/* ******************************************************************\n   Huffman coder, part of New Generation Entropy library\n   header file\n   Copyright (C) 2013-2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n****************************************************************** */\n#ifndef HUFv07_H_298734234\n#define HUFv07_H_298734234\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n\n/* *** simple functions *** */\n/**\nHUFv07_decompress() :\n    Decompress HUF data from buffer 'cSrc', of size 'cSrcSize',\n    into already allocated buffer 'dst', of minimum size 'dstSize'.\n    `dstSize` : **must** be the ***exact*** size of original (uncompressed) data.\n    Note : in contrast with FSE, HUFv07_decompress can regenerate\n           RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data,\n           because it knows size to regenerate.\n    @return : size of regenerated data (== dstSize),\n              or an error code, which can be tested using HUFv07_isError()\n*/\nsize_t HUFv07_decompress(void* dst,  size_t dstSize,\n                const void* cSrc, size_t cSrcSize);\n\n\n/* ****************************************\n*  Tool functions\n******************************************/\n#define HUFv07_BLOCKSIZE_MAX (128 * 1024)\n\n/* Error Management */\nunsigned    HUFv07_isError(size_t code);        /**< tells if a return value is an error code */\nconst char* HUFv07_getErrorName(size_t code);   /**< provides error code string (useful for debugging) */\n\n\n/* *** Advanced function *** */\n\n\n#ifdef HUFv07_STATIC_LINKING_ONLY\n\n\n/* *** Constants *** */\n#define HUFv07_TABLELOG_ABSOLUTEMAX  16   /* absolute limit of HUFv07_MAX_TABLELOG. Beyond that value, code does not work */\n#define HUFv07_TABLELOG_MAX  12           /* max configured tableLog (for static allocation); can be modified up to HUFv07_ABSOLUTEMAX_TABLELOG */\n#define HUFv07_TABLELOG_DEFAULT  11       /* tableLog by default, when not specified */\n#define HUFv07_SYMBOLVALUE_MAX 255\n#if (HUFv07_TABLELOG_MAX > HUFv07_TABLELOG_ABSOLUTEMAX)\n#  error \"HUFv07_TABLELOG_MAX is too large !\"\n#endif\n\n\n/* ****************************************\n*  Static allocation\n******************************************/\n/* HUF buffer bounds */\n#define HUFv07_BLOCKBOUND(size) (size + (size>>8) + 8)   /* only true if incompressible pre-filtered with fast heuristic */\n\n/* static allocation of HUF's DTable */\ntypedef U32 HUFv07_DTable;\n#define HUFv07_DTABLE_SIZE(maxTableLog)   (1 + (1<<(maxTableLog)))\n#define HUFv07_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \\\n        HUFv07_DTable DTable[HUFv07_DTABLE_SIZE((maxTableLog)-1)] = { ((U32)((maxTableLog)-1)*0x1000001) }\n#define HUFv07_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \\\n        HUFv07_DTable DTable[HUFv07_DTABLE_SIZE(maxTableLog)] = { ((U32)(maxTableLog)*0x1000001) }\n\n\n/* ****************************************\n*  Advanced decompression functions\n******************************************/\nsize_t HUFv07_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< single-symbol decoder */\nsize_t HUFv07_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< double-symbols decoder */\n\nsize_t HUFv07_decompress4X_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< decodes RLE and uncompressed */\nsize_t HUFv07_decompress4X_hufOnly(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< considers RLE and uncompressed as errors */\nsize_t HUFv07_decompress4X2_DCtx(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< single-symbol decoder */\nsize_t HUFv07_decompress4X4_DCtx(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< double-symbols decoder */\n\nsize_t HUFv07_decompress1X_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);\nsize_t HUFv07_decompress1X2_DCtx(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< single-symbol decoder */\nsize_t HUFv07_decompress1X4_DCtx(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< double-symbols decoder */\n\n\n/* ****************************************\n*  HUF detailed API\n******************************************/\n/*!\nThe following API allows targeting specific sub-functions for advanced tasks.\nFor example, it's possible to compress several blocks using the same 'CTable',\nor to save and regenerate 'CTable' using external methods.\n*/\n/* FSEv07_count() : find it within \"fse.h\" */\n\n/*! HUFv07_readStats() :\n    Read compact Huffman tree, saved by HUFv07_writeCTable().\n    `huffWeight` is destination buffer.\n    @return : size read from `src` , or an error Code .\n    Note : Needed by HUFv07_readCTable() and HUFv07_readDTableXn() . */\nsize_t HUFv07_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                     U32* nbSymbolsPtr, U32* tableLogPtr,\n                     const void* src, size_t srcSize);\n\n\n/*\nHUFv07_decompress() does the following:\n1. select the decompression algorithm (X2, X4) based on pre-computed heuristics\n2. build Huffman table from save, using HUFv07_readDTableXn()\n3. decode 1 or 4 segments in parallel using HUFv07_decompressSXn_usingDTable\n*/\n\n/** HUFv07_selectDecoder() :\n*   Tells which decoder is likely to decode faster,\n*   based on a set of pre-determined metrics.\n*   @return : 0==HUFv07_decompress4X2, 1==HUFv07_decompress4X4 .\n*   Assumption : 0 < cSrcSize < dstSize <= 128 KB */\nU32 HUFv07_selectDecoder (size_t dstSize, size_t cSrcSize);\n\nsize_t HUFv07_readDTableX2 (HUFv07_DTable* DTable, const void* src, size_t srcSize);\nsize_t HUFv07_readDTableX4 (HUFv07_DTable* DTable, const void* src, size_t srcSize);\n\nsize_t HUFv07_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);\nsize_t HUFv07_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);\nsize_t HUFv07_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);\n\n\n/* single stream variants */\nsize_t HUFv07_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */\nsize_t HUFv07_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbol decoder */\n\nsize_t HUFv07_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);\nsize_t HUFv07_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);\nsize_t HUFv07_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);\n\n\n#endif /* HUFv07_STATIC_LINKING_ONLY */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif   /* HUFv07_H_298734234 */\n/*\n   Common functions of New Generation Entropy library\n   Copyright (C) 2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n*************************************************************************** */\n\n\n\n/*-****************************************\n*  FSE Error Management\n******************************************/\nunsigned FSEv07_isError(size_t code) { return ERR_isError(code); }\n\nconst char* FSEv07_getErrorName(size_t code) { return ERR_getErrorName(code); }\n\n\n/* **************************************************************\n*  HUF Error Management\n****************************************************************/\nunsigned HUFv07_isError(size_t code) { return ERR_isError(code); }\n\nconst char* HUFv07_getErrorName(size_t code) { return ERR_getErrorName(code); }\n\n\n/*-**************************************************************\n*  FSE NCount encoding-decoding\n****************************************************************/\nstatic short FSEv07_abs(short a) { return (short)(a<0 ? -a : a); }\n\nsize_t FSEv07_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n                 const void* headerBuffer, size_t hbSize)\n{\n    const BYTE* const istart = (const BYTE*) headerBuffer;\n    const BYTE* const iend = istart + hbSize;\n    const BYTE* ip = istart;\n    int nbBits;\n    int remaining;\n    int threshold;\n    U32 bitStream;\n    int bitCount;\n    unsigned charnum = 0;\n    int previous0 = 0;\n\n    if (hbSize < 4) return ERROR(srcSize_wrong);\n    bitStream = MEM_readLE32(ip);\n    nbBits = (bitStream & 0xF) + FSEv07_MIN_TABLELOG;   /* extract tableLog */\n    if (nbBits > FSEv07_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);\n    bitStream >>= 4;\n    bitCount = 4;\n    *tableLogPtr = nbBits;\n    remaining = (1<<nbBits)+1;\n    threshold = 1<<nbBits;\n    nbBits++;\n\n    while ((remaining>1) && (charnum<=*maxSVPtr)) {\n        if (previous0) {\n            unsigned n0 = charnum;\n            while ((bitStream & 0xFFFF) == 0xFFFF) {\n                n0+=24;\n                if (ip < iend-5) {\n                    ip+=2;\n                    bitStream = MEM_readLE32(ip) >> bitCount;\n                } else {\n                    bitStream >>= 16;\n                    bitCount+=16;\n            }   }\n            while ((bitStream & 3) == 3) {\n                n0+=3;\n                bitStream>>=2;\n                bitCount+=2;\n            }\n            n0 += bitStream & 3;\n            bitCount += 2;\n            if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);\n            while (charnum < n0) normalizedCounter[charnum++] = 0;\n            if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {\n                ip += bitCount>>3;\n                bitCount &= 7;\n                bitStream = MEM_readLE32(ip) >> bitCount;\n            }\n            else\n                bitStream >>= 2;\n        }\n        {   short const max = (short)((2*threshold-1)-remaining);\n            short count;\n\n            if ((bitStream & (threshold-1)) < (U32)max) {\n                count = (short)(bitStream & (threshold-1));\n                bitCount   += nbBits-1;\n            } else {\n                count = (short)(bitStream & (2*threshold-1));\n                if (count >= threshold) count -= max;\n                bitCount   += nbBits;\n            }\n\n            count--;   /* extra accuracy */\n            remaining -= FSEv07_abs(count);\n            normalizedCounter[charnum++] = count;\n            previous0 = !count;\n            while (remaining < threshold) {\n                nbBits--;\n                threshold >>= 1;\n            }\n\n            if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {\n                ip += bitCount>>3;\n                bitCount &= 7;\n            } else {\n                bitCount -= (int)(8 * (iend - 4 - ip));\n                ip = iend - 4;\n            }\n            bitStream = MEM_readLE32(ip) >> (bitCount & 31);\n    }   }   /* while ((remaining>1) && (charnum<=*maxSVPtr)) */\n    if (remaining != 1) return ERROR(GENERIC);\n    *maxSVPtr = charnum-1;\n\n    ip += (bitCount+7)>>3;\n    if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong);\n    return ip-istart;\n}\n\n\n/*! HUFv07_readStats() :\n    Read compact Huffman tree, saved by HUFv07_writeCTable().\n    `huffWeight` is destination buffer.\n    @return : size read from `src` , or an error Code .\n    Note : Needed by HUFv07_readCTable() and HUFv07_readDTableXn() .\n*/\nsize_t HUFv07_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                     U32* nbSymbolsPtr, U32* tableLogPtr,\n                     const void* src, size_t srcSize)\n{\n    U32 weightTotal;\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize;\n    size_t oSize;\n\n    if (!srcSize) return ERROR(srcSize_wrong);\n    iSize = ip[0];\n    /* memset(huffWeight, 0, hwSize); */   /* is not necessary, even though some analyzer complain ... */\n\n    if (iSize >= 128)  { /* special header */\n        if (iSize >= (242)) {  /* RLE */\n            static U32 l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };\n            oSize = l[iSize-242];\n            memset(huffWeight, 1, hwSize);\n            iSize = 0;\n        }\n        else {   /* Incompressible */\n            oSize = iSize - 127;\n            iSize = ((oSize+1)/2);\n            if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n            if (oSize >= hwSize) return ERROR(corruption_detected);\n            ip += 1;\n            {   U32 n;\n                for (n=0; n<oSize; n+=2) {\n                    huffWeight[n]   = ip[n/2] >> 4;\n                    huffWeight[n+1] = ip[n/2] & 15;\n    }   }   }   }\n    else  {   /* header compressed with FSE (normal case) */\n        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n        oSize = FSEv07_decompress(huffWeight, hwSize-1, ip+1, iSize);   /* max (hwSize-1) values decoded, as last one is implied */\n        if (FSEv07_isError(oSize)) return oSize;\n    }\n\n    /* collect weight stats */\n    memset(rankStats, 0, (HUFv07_TABLELOG_ABSOLUTEMAX + 1) * sizeof(U32));\n    weightTotal = 0;\n    {   U32 n; for (n=0; n<oSize; n++) {\n            if (huffWeight[n] >= HUFv07_TABLELOG_ABSOLUTEMAX) return ERROR(corruption_detected);\n            rankStats[huffWeight[n]]++;\n            weightTotal += (1 << huffWeight[n]) >> 1;\n    }   }\n    if (weightTotal == 0) return ERROR(corruption_detected);\n\n    /* get last non-null symbol weight (implied, total must be 2^n) */\n    {   U32 const tableLog = BITv07_highbit32(weightTotal) + 1;\n        if (tableLog > HUFv07_TABLELOG_ABSOLUTEMAX) return ERROR(corruption_detected);\n        *tableLogPtr = tableLog;\n        /* determine last weight */\n        {   U32 const total = 1 << tableLog;\n            U32 const rest = total - weightTotal;\n            U32 const verif = 1 << BITv07_highbit32(rest);\n            U32 const lastWeight = BITv07_highbit32(rest) + 1;\n            if (verif != rest) return ERROR(corruption_detected);    /* last value must be a clean power of 2 */\n            huffWeight[oSize] = (BYTE)lastWeight;\n            rankStats[lastWeight]++;\n    }   }\n\n    /* check tree construction validity */\n    if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected);   /* by construction : at least 2 elts of rank 1, must be even */\n\n    /* results */\n    *nbSymbolsPtr = (U32)(oSize+1);\n    return iSize+1;\n}\n/* ******************************************************************\n   FSE : Finite State Entropy decoder\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n\n/* **************************************************************\n*  Compiler specifics\n****************************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  define FORCE_INLINE static __forceinline\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4214)        /* disable: C4214: non-int bitfields */\n#else\n#  if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */\n#    ifdef __GNUC__\n#      define FORCE_INLINE static inline __attribute__((always_inline))\n#    else\n#      define FORCE_INLINE static inline\n#    endif\n#  else\n#    define FORCE_INLINE static\n#  endif /* __STDC_VERSION__ */\n#endif\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n#define FSEv07_isError ERR_isError\n#define FSEv07_STATIC_ASSERT(c) { enum { FSEv07_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n/* **************************************************************\n*  Complex types\n****************************************************************/\ntypedef U32 DTable_max_t[FSEv07_DTABLE_SIZE_U32(FSEv07_MAX_TABLELOG)];\n\n\n/* **************************************************************\n*  Templates\n****************************************************************/\n/*\n  designed to be included\n  for type-specific functions (template emulation in C)\n  Objective is to write these functions only once, for improved maintenance\n*/\n\n/* safety checks */\n#ifndef FSEv07_FUNCTION_EXTENSION\n#  error \"FSEv07_FUNCTION_EXTENSION must be defined\"\n#endif\n#ifndef FSEv07_FUNCTION_TYPE\n#  error \"FSEv07_FUNCTION_TYPE must be defined\"\n#endif\n\n/* Function names */\n#define FSEv07_CAT(X,Y) X##Y\n#define FSEv07_FUNCTION_NAME(X,Y) FSEv07_CAT(X,Y)\n#define FSEv07_TYPE_NAME(X,Y) FSEv07_CAT(X,Y)\n\n\n/* Function templates */\nFSEv07_DTable* FSEv07_createDTable (unsigned tableLog)\n{\n    if (tableLog > FSEv07_TABLELOG_ABSOLUTE_MAX) tableLog = FSEv07_TABLELOG_ABSOLUTE_MAX;\n    return (FSEv07_DTable*)malloc( FSEv07_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );\n}\n\nvoid FSEv07_freeDTable (FSEv07_DTable* dt)\n{\n    free(dt);\n}\n\nsize_t FSEv07_buildDTable(FSEv07_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)\n{\n    void* const tdPtr = dt+1;   /* because *dt is unsigned, 32-bits aligned on 32-bits */\n    FSEv07_DECODE_TYPE* const tableDecode = (FSEv07_DECODE_TYPE*) (tdPtr);\n    U16 symbolNext[FSEv07_MAX_SYMBOL_VALUE+1];\n\n    U32 const maxSV1 = maxSymbolValue + 1;\n    U32 const tableSize = 1 << tableLog;\n    U32 highThreshold = tableSize-1;\n\n    /* Sanity Checks */\n    if (maxSymbolValue > FSEv07_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);\n    if (tableLog > FSEv07_MAX_TABLELOG) return ERROR(tableLog_tooLarge);\n\n    /* Init, lay down lowprob symbols */\n    {   FSEv07_DTableHeader DTableH;\n        DTableH.tableLog = (U16)tableLog;\n        DTableH.fastMode = 1;\n        {   S16 const largeLimit= (S16)(1 << (tableLog-1));\n            U32 s;\n            for (s=0; s<maxSV1; s++) {\n                if (normalizedCounter[s]==-1) {\n                    tableDecode[highThreshold--].symbol = (FSEv07_FUNCTION_TYPE)s;\n                    symbolNext[s] = 1;\n                } else {\n                    if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;\n                    symbolNext[s] = normalizedCounter[s];\n        }   }   }\n        memcpy(dt, &DTableH, sizeof(DTableH));\n    }\n\n    /* Spread symbols */\n    {   U32 const tableMask = tableSize-1;\n        U32 const step = FSEv07_TABLESTEP(tableSize);\n        U32 s, position = 0;\n        for (s=0; s<maxSV1; s++) {\n            int i;\n            for (i=0; i<normalizedCounter[s]; i++) {\n                tableDecode[position].symbol = (FSEv07_FUNCTION_TYPE)s;\n                position = (position + step) & tableMask;\n                while (position > highThreshold) position = (position + step) & tableMask;   /* lowprob area */\n        }   }\n\n        if (position!=0) return ERROR(GENERIC);   /* position must reach all cells once, otherwise normalizedCounter is incorrect */\n    }\n\n    /* Build Decoding table */\n    {   U32 u;\n        for (u=0; u<tableSize; u++) {\n            FSEv07_FUNCTION_TYPE const symbol = (FSEv07_FUNCTION_TYPE)(tableDecode[u].symbol);\n            U16 nextState = symbolNext[symbol]++;\n            tableDecode[u].nbBits = (BYTE) (tableLog - BITv07_highbit32 ((U32)nextState) );\n            tableDecode[u].newState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);\n    }   }\n\n    return 0;\n}\n\n\n\n#ifndef FSEv07_COMMONDEFS_ONLY\n\n/*-*******************************************************\n*  Decompression (Byte symbols)\n*********************************************************/\nsize_t FSEv07_buildDTable_rle (FSEv07_DTable* dt, BYTE symbolValue)\n{\n    void* ptr = dt;\n    FSEv07_DTableHeader* const DTableH = (FSEv07_DTableHeader*)ptr;\n    void* dPtr = dt + 1;\n    FSEv07_decode_t* const cell = (FSEv07_decode_t*)dPtr;\n\n    DTableH->tableLog = 0;\n    DTableH->fastMode = 0;\n\n    cell->newState = 0;\n    cell->symbol = symbolValue;\n    cell->nbBits = 0;\n\n    return 0;\n}\n\n\nsize_t FSEv07_buildDTable_raw (FSEv07_DTable* dt, unsigned nbBits)\n{\n    void* ptr = dt;\n    FSEv07_DTableHeader* const DTableH = (FSEv07_DTableHeader*)ptr;\n    void* dPtr = dt + 1;\n    FSEv07_decode_t* const dinfo = (FSEv07_decode_t*)dPtr;\n    const unsigned tableSize = 1 << nbBits;\n    const unsigned tableMask = tableSize - 1;\n    const unsigned maxSV1 = tableMask+1;\n    unsigned s;\n\n    /* Sanity checks */\n    if (nbBits < 1) return ERROR(GENERIC);         /* min size */\n\n    /* Build Decoding Table */\n    DTableH->tableLog = (U16)nbBits;\n    DTableH->fastMode = 1;\n    for (s=0; s<maxSV1; s++) {\n        dinfo[s].newState = 0;\n        dinfo[s].symbol = (BYTE)s;\n        dinfo[s].nbBits = (BYTE)nbBits;\n    }\n\n    return 0;\n}\n\nFORCE_INLINE size_t FSEv07_decompress_usingDTable_generic(\n          void* dst, size_t maxDstSize,\n    const void* cSrc, size_t cSrcSize,\n    const FSEv07_DTable* dt, const unsigned fast)\n{\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* op = ostart;\n    BYTE* const omax = op + maxDstSize;\n    BYTE* const olimit = omax-3;\n\n    BITv07_DStream_t bitD;\n    FSEv07_DState_t state1;\n    FSEv07_DState_t state2;\n\n    /* Init */\n    { size_t const errorCode = BITv07_initDStream(&bitD, cSrc, cSrcSize);   /* replaced last arg by maxCompressed Size */\n      if (FSEv07_isError(errorCode)) return errorCode; }\n\n    FSEv07_initDState(&state1, &bitD, dt);\n    FSEv07_initDState(&state2, &bitD, dt);\n\n#define FSEv07_GETSYMBOL(statePtr) fast ? FSEv07_decodeSymbolFast(statePtr, &bitD) : FSEv07_decodeSymbol(statePtr, &bitD)\n\n    /* 4 symbols per loop */\n    for ( ; (BITv07_reloadDStream(&bitD)==BITv07_DStream_unfinished) && (op<olimit) ; op+=4) {\n        op[0] = FSEv07_GETSYMBOL(&state1);\n\n        if (FSEv07_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BITv07_reloadDStream(&bitD);\n\n        op[1] = FSEv07_GETSYMBOL(&state2);\n\n        if (FSEv07_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            { if (BITv07_reloadDStream(&bitD) > BITv07_DStream_unfinished) { op+=2; break; } }\n\n        op[2] = FSEv07_GETSYMBOL(&state1);\n\n        if (FSEv07_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BITv07_reloadDStream(&bitD);\n\n        op[3] = FSEv07_GETSYMBOL(&state2);\n    }\n\n    /* tail */\n    /* note : BITv07_reloadDStream(&bitD) >= FSEv07_DStream_partiallyFilled; Ends at exactly BITv07_DStream_completed */\n    while (1) {\n        if (op>(omax-2)) return ERROR(dstSize_tooSmall);\n\n        *op++ = FSEv07_GETSYMBOL(&state1);\n\n        if (BITv07_reloadDStream(&bitD)==BITv07_DStream_overflow) {\n            *op++ = FSEv07_GETSYMBOL(&state2);\n            break;\n        }\n\n        if (op>(omax-2)) return ERROR(dstSize_tooSmall);\n\n        *op++ = FSEv07_GETSYMBOL(&state2);\n\n        if (BITv07_reloadDStream(&bitD)==BITv07_DStream_overflow) {\n            *op++ = FSEv07_GETSYMBOL(&state1);\n            break;\n    }   }\n\n    return op-ostart;\n}\n\n\nsize_t FSEv07_decompress_usingDTable(void* dst, size_t originalSize,\n                            const void* cSrc, size_t cSrcSize,\n                            const FSEv07_DTable* dt)\n{\n    const void* ptr = dt;\n    const FSEv07_DTableHeader* DTableH = (const FSEv07_DTableHeader*)ptr;\n    const U32 fastMode = DTableH->fastMode;\n\n    /* select fast mode (static) */\n    if (fastMode) return FSEv07_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);\n    return FSEv07_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);\n}\n\n\nsize_t FSEv07_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)\n{\n    const BYTE* const istart = (const BYTE*)cSrc;\n    const BYTE* ip = istart;\n    short counting[FSEv07_MAX_SYMBOL_VALUE+1];\n    DTable_max_t dt;   /* Static analyzer seems unable to understand this table will be properly initialized later */\n    unsigned tableLog;\n    unsigned maxSymbolValue = FSEv07_MAX_SYMBOL_VALUE;\n\n    if (cSrcSize<2) return ERROR(srcSize_wrong);   /* too small input size */\n\n    /* normal FSE decoding mode */\n    {   size_t const NCountLength = FSEv07_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);\n        if (FSEv07_isError(NCountLength)) return NCountLength;\n        if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong);   /* too small input size */\n        ip += NCountLength;\n        cSrcSize -= NCountLength;\n    }\n\n    { size_t const errorCode = FSEv07_buildDTable (dt, counting, maxSymbolValue, tableLog);\n      if (FSEv07_isError(errorCode)) return errorCode; }\n\n    return FSEv07_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt);   /* always return, even if it is an error code */\n}\n\n\n\n#endif   /* FSEv07_COMMONDEFS_ONLY */\n\n/* ******************************************************************\n   Huffman decoder, part of New Generation Entropy library\n   Copyright (C) 2013-2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n/* **************************************************************\n*  Compiler specifics\n****************************************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n/* inline is defined */\n#elif defined(_MSC_VER)\n#  define inline __inline\n#else\n#  define inline /* disable inline */\n#endif\n\n\n#ifdef _MSC_VER    /* Visual Studio */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#endif\n\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n#define HUFv07_STATIC_ASSERT(c) { enum { HUFv07_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n/*-***************************/\n/*  generic DTableDesc       */\n/*-***************************/\n\ntypedef struct { BYTE maxTableLog; BYTE tableType; BYTE tableLog; BYTE reserved; } DTableDesc;\n\nstatic DTableDesc HUFv07_getDTableDesc(const HUFv07_DTable* table)\n{\n    DTableDesc dtd;\n    memcpy(&dtd, table, sizeof(dtd));\n    return dtd;\n}\n\n\n/*-***************************/\n/*  single-symbol decoding   */\n/*-***************************/\n\ntypedef struct { BYTE byte; BYTE nbBits; } HUFv07_DEltX2;   /* single-symbol decoding */\n\nsize_t HUFv07_readDTableX2 (HUFv07_DTable* DTable, const void* src, size_t srcSize)\n{\n    BYTE huffWeight[HUFv07_SYMBOLVALUE_MAX + 1];\n    U32 rankVal[HUFv07_TABLELOG_ABSOLUTEMAX + 1];   /* large enough for values from 0 to 16 */\n    U32 tableLog = 0;\n    U32 nbSymbols = 0;\n    size_t iSize;\n    void* const dtPtr = DTable + 1;\n    HUFv07_DEltX2* const dt = (HUFv07_DEltX2*)dtPtr;\n\n    HUFv07_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUFv07_DTable));\n    /* memset(huffWeight, 0, sizeof(huffWeight)); */   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUFv07_readStats(huffWeight, HUFv07_SYMBOLVALUE_MAX + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);\n    if (HUFv07_isError(iSize)) return iSize;\n\n    /* Table header */\n    {   DTableDesc dtd = HUFv07_getDTableDesc(DTable);\n        if (tableLog > (U32)(dtd.maxTableLog+1)) return ERROR(tableLog_tooLarge);   /* DTable too small, huffman tree cannot fit in */\n        dtd.tableType = 0;\n        dtd.tableLog = (BYTE)tableLog;\n        memcpy(DTable, &dtd, sizeof(dtd));\n    }\n\n    /* Prepare ranks */\n    {   U32 n, nextRankStart = 0;\n        for (n=1; n<tableLog+1; n++) {\n            U32 current = nextRankStart;\n            nextRankStart += (rankVal[n] << (n-1));\n            rankVal[n] = current;\n    }   }\n\n    /* fill DTable */\n    {   U32 n;\n        for (n=0; n<nbSymbols; n++) {\n            U32 const w = huffWeight[n];\n            U32 const length = (1 << w) >> 1;\n            U32 i;\n            HUFv07_DEltX2 D;\n            D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w);\n            for (i = rankVal[w]; i < rankVal[w] + length; i++)\n                dt[i] = D;\n            rankVal[w] += length;\n    }   }\n\n    return iSize;\n}\n\n\nstatic BYTE HUFv07_decodeSymbolX2(BITv07_DStream_t* Dstream, const HUFv07_DEltX2* dt, const U32 dtLog)\n{\n    size_t const val = BITv07_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */\n    BYTE const c = dt[val].byte;\n    BITv07_skipBits(Dstream, dt[val].nbBits);\n    return c;\n}\n\n#define HUFv07_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \\\n    *ptr++ = HUFv07_decodeSymbolX2(DStreamPtr, dt, dtLog)\n\n#define HUFv07_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUFv07_TABLELOG_MAX<=12)) \\\n        HUFv07_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\n#define HUFv07_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        HUFv07_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\nstatic inline size_t HUFv07_decodeStreamX2(BYTE* p, BITv07_DStream_t* const bitDPtr, BYTE* const pEnd, const HUFv07_DEltX2* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 4 symbols at a time */\n    while ((BITv07_reloadDStream(bitDPtr) == BITv07_DStream_unfinished) && (p <= pEnd-4)) {\n        HUFv07_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUFv07_DECODE_SYMBOLX2_1(p, bitDPtr);\n        HUFv07_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUFv07_DECODE_SYMBOLX2_0(p, bitDPtr);\n    }\n\n    /* closer to the end */\n    while ((BITv07_reloadDStream(bitDPtr) == BITv07_DStream_unfinished) && (p < pEnd))\n        HUFv07_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    /* no more data to retrieve from bitstream, hence no need to reload */\n    while (p < pEnd)\n        HUFv07_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    return pEnd-pStart;\n}\n\nstatic size_t HUFv07_decompress1X2_usingDTable_internal(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUFv07_DTable* DTable)\n{\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + dstSize;\n    const void* dtPtr = DTable + 1;\n    const HUFv07_DEltX2* const dt = (const HUFv07_DEltX2*)dtPtr;\n    BITv07_DStream_t bitD;\n    DTableDesc const dtd = HUFv07_getDTableDesc(DTable);\n    U32 const dtLog = dtd.tableLog;\n\n    { size_t const errorCode = BITv07_initDStream(&bitD, cSrc, cSrcSize);\n      if (HUFv07_isError(errorCode)) return errorCode; }\n\n    HUFv07_decodeStreamX2(op, &bitD, oend, dt, dtLog);\n\n    /* check */\n    if (!BITv07_endOfDStream(&bitD)) return ERROR(corruption_detected);\n\n    return dstSize;\n}\n\nsize_t HUFv07_decompress1X2_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUFv07_DTable* DTable)\n{\n    DTableDesc dtd = HUFv07_getDTableDesc(DTable);\n    if (dtd.tableType != 0) return ERROR(GENERIC);\n    return HUFv07_decompress1X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);\n}\n\nsize_t HUFv07_decompress1X2_DCtx (HUFv07_DTable* DCtx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t const hSize = HUFv07_readDTableX2 (DCtx, cSrc, cSrcSize);\n    if (HUFv07_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize; cSrcSize -= hSize;\n\n    return HUFv07_decompress1X2_usingDTable_internal (dst, dstSize, ip, cSrcSize, DCtx);\n}\n\nsize_t HUFv07_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv07_CREATE_STATIC_DTABLEX2(DTable, HUFv07_TABLELOG_MAX);\n    return HUFv07_decompress1X2_DCtx (DTable, dst, dstSize, cSrc, cSrcSize);\n}\n\n\nstatic size_t HUFv07_decompress4X2_usingDTable_internal(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUFv07_DTable* DTable)\n{\n    /* Check */\n    if (cSrcSize < 10) return ERROR(corruption_detected);  /* strict minimum : jump table + 1 byte per stream */\n\n    {   const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        const void* const dtPtr = DTable + 1;\n        const HUFv07_DEltX2* const dt = (const HUFv07_DEltX2*)dtPtr;\n\n        /* Init */\n        BITv07_DStream_t bitD1;\n        BITv07_DStream_t bitD2;\n        BITv07_DStream_t bitD3;\n        BITv07_DStream_t bitD4;\n        size_t const length1 = MEM_readLE16(istart);\n        size_t const length2 = MEM_readLE16(istart+2);\n        size_t const length3 = MEM_readLE16(istart+4);\n        size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n        DTableDesc const dtd = HUFv07_getDTableDesc(DTable);\n        U32 const dtLog = dtd.tableLog;\n\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        { size_t const errorCode = BITv07_initDStream(&bitD1, istart1, length1);\n          if (HUFv07_isError(errorCode)) return errorCode; }\n        { size_t const errorCode = BITv07_initDStream(&bitD2, istart2, length2);\n          if (HUFv07_isError(errorCode)) return errorCode; }\n        { size_t const errorCode = BITv07_initDStream(&bitD3, istart3, length3);\n          if (HUFv07_isError(errorCode)) return errorCode; }\n        { size_t const errorCode = BITv07_initDStream(&bitD4, istart4, length4);\n          if (HUFv07_isError(errorCode)) return errorCode; }\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BITv07_reloadDStream(&bitD1) | BITv07_reloadDStream(&bitD2) | BITv07_reloadDStream(&bitD3) | BITv07_reloadDStream(&bitD4);\n        for ( ; (endSignal==BITv07_DStream_unfinished) && (op4<(oend-7)) ; ) {\n            HUFv07_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUFv07_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUFv07_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUFv07_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUFv07_DECODE_SYMBOLX2_1(op1, &bitD1);\n            HUFv07_DECODE_SYMBOLX2_1(op2, &bitD2);\n            HUFv07_DECODE_SYMBOLX2_1(op3, &bitD3);\n            HUFv07_DECODE_SYMBOLX2_1(op4, &bitD4);\n            HUFv07_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUFv07_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUFv07_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUFv07_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUFv07_DECODE_SYMBOLX2_0(op1, &bitD1);\n            HUFv07_DECODE_SYMBOLX2_0(op2, &bitD2);\n            HUFv07_DECODE_SYMBOLX2_0(op3, &bitD3);\n            HUFv07_DECODE_SYMBOLX2_0(op4, &bitD4);\n            endSignal = BITv07_reloadDStream(&bitD1) | BITv07_reloadDStream(&bitD2) | BITv07_reloadDStream(&bitD3) | BITv07_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUFv07_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);\n        HUFv07_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);\n        HUFv07_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);\n        HUFv07_decodeStreamX2(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        endSignal = BITv07_endOfDStream(&bitD1) & BITv07_endOfDStream(&bitD2) & BITv07_endOfDStream(&bitD3) & BITv07_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nsize_t HUFv07_decompress4X2_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUFv07_DTable* DTable)\n{\n    DTableDesc dtd = HUFv07_getDTableDesc(DTable);\n    if (dtd.tableType != 0) return ERROR(GENERIC);\n    return HUFv07_decompress4X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);\n}\n\n\nsize_t HUFv07_decompress4X2_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t const hSize = HUFv07_readDTableX2 (dctx, cSrc, cSrcSize);\n    if (HUFv07_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize; cSrcSize -= hSize;\n\n    return HUFv07_decompress4X2_usingDTable_internal (dst, dstSize, ip, cSrcSize, dctx);\n}\n\nsize_t HUFv07_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv07_CREATE_STATIC_DTABLEX2(DTable, HUFv07_TABLELOG_MAX);\n    return HUFv07_decompress4X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);\n}\n\n\n/* *************************/\n/* double-symbols decoding */\n/* *************************/\ntypedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUFv07_DEltX4;  /* double-symbols decoding */\n\ntypedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;\n\nstatic void HUFv07_fillDTableX4Level2(HUFv07_DEltX4* DTable, U32 sizeLog, const U32 consumed,\n                           const U32* rankValOrigin, const int minWeight,\n                           const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,\n                           U32 nbBitsBaseline, U16 baseSeq)\n{\n    HUFv07_DEltX4 DElt;\n    U32 rankVal[HUFv07_TABLELOG_ABSOLUTEMAX + 1];\n\n    /* get pre-calculated rankVal */\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill skipped values */\n    if (minWeight>1) {\n        U32 i, skipSize = rankVal[minWeight];\n        MEM_writeLE16(&(DElt.sequence), baseSeq);\n        DElt.nbBits   = (BYTE)(consumed);\n        DElt.length   = 1;\n        for (i = 0; i < skipSize; i++)\n            DTable[i] = DElt;\n    }\n\n    /* fill DTable */\n    { U32 s; for (s=0; s<sortedListSize; s++) {   /* note : sortedSymbols already skipped */\n        const U32 symbol = sortedSymbols[s].symbol;\n        const U32 weight = sortedSymbols[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 length = 1 << (sizeLog-nbBits);\n        const U32 start = rankVal[weight];\n        U32 i = start;\n        const U32 end = start + length;\n\n        MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));\n        DElt.nbBits = (BYTE)(nbBits + consumed);\n        DElt.length = 2;\n        do { DTable[i++] = DElt; } while (i<end);   /* since length >= 1 */\n\n        rankVal[weight] += length;\n    }}\n}\n\ntypedef U32 rankVal_t[HUFv07_TABLELOG_ABSOLUTEMAX][HUFv07_TABLELOG_ABSOLUTEMAX + 1];\n\nstatic void HUFv07_fillDTableX4(HUFv07_DEltX4* DTable, const U32 targetLog,\n                           const sortedSymbol_t* sortedList, const U32 sortedListSize,\n                           const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,\n                           const U32 nbBitsBaseline)\n{\n    U32 rankVal[HUFv07_TABLELOG_ABSOLUTEMAX + 1];\n    const int scaleLog = nbBitsBaseline - targetLog;   /* note : targetLog >= srcLog, hence scaleLog <= 1 */\n    const U32 minBits  = nbBitsBaseline - maxWeight;\n    U32 s;\n\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill DTable */\n    for (s=0; s<sortedListSize; s++) {\n        const U16 symbol = sortedList[s].symbol;\n        const U32 weight = sortedList[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 start = rankVal[weight];\n        const U32 length = 1 << (targetLog-nbBits);\n\n        if (targetLog-nbBits >= minBits) {   /* enough room for a second symbol */\n            U32 sortedRank;\n            int minWeight = nbBits + scaleLog;\n            if (minWeight < 1) minWeight = 1;\n            sortedRank = rankStart[minWeight];\n            HUFv07_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits,\n                           rankValOrigin[nbBits], minWeight,\n                           sortedList+sortedRank, sortedListSize-sortedRank,\n                           nbBitsBaseline, symbol);\n        } else {\n            HUFv07_DEltX4 DElt;\n            MEM_writeLE16(&(DElt.sequence), symbol);\n            DElt.nbBits = (BYTE)(nbBits);\n            DElt.length = 1;\n            {   U32 u;\n                const U32 end = start + length;\n                for (u = start; u < end; u++) DTable[u] = DElt;\n        }   }\n        rankVal[weight] += length;\n    }\n}\n\nsize_t HUFv07_readDTableX4 (HUFv07_DTable* DTable, const void* src, size_t srcSize)\n{\n    BYTE weightList[HUFv07_SYMBOLVALUE_MAX + 1];\n    sortedSymbol_t sortedSymbol[HUFv07_SYMBOLVALUE_MAX + 1];\n    U32 rankStats[HUFv07_TABLELOG_ABSOLUTEMAX + 1] = { 0 };\n    U32 rankStart0[HUFv07_TABLELOG_ABSOLUTEMAX + 2] = { 0 };\n    U32* const rankStart = rankStart0+1;\n    rankVal_t rankVal;\n    U32 tableLog, maxW, sizeOfSort, nbSymbols;\n    DTableDesc dtd = HUFv07_getDTableDesc(DTable);\n    U32 const maxTableLog = dtd.maxTableLog;\n    size_t iSize;\n    void* dtPtr = DTable+1;   /* force compiler to avoid strict-aliasing */\n    HUFv07_DEltX4* const dt = (HUFv07_DEltX4*)dtPtr;\n\n    HUFv07_STATIC_ASSERT(sizeof(HUFv07_DEltX4) == sizeof(HUFv07_DTable));   /* if compilation fails here, assertion is false */\n    if (maxTableLog > HUFv07_TABLELOG_ABSOLUTEMAX) return ERROR(tableLog_tooLarge);\n    /* memset(weightList, 0, sizeof(weightList)); */   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUFv07_readStats(weightList, HUFv07_SYMBOLVALUE_MAX + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);\n    if (HUFv07_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > maxTableLog) return ERROR(tableLog_tooLarge);   /* DTable can't fit code depth */\n\n    /* find maxWeight */\n    for (maxW = tableLog; rankStats[maxW]==0; maxW--) {}  /* necessarily finds a solution before 0 */\n\n    /* Get start index of each weight */\n    {   U32 w, nextRankStart = 0;\n        for (w=1; w<maxW+1; w++) {\n            U32 current = nextRankStart;\n            nextRankStart += rankStats[w];\n            rankStart[w] = current;\n        }\n        rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/\n        sizeOfSort = nextRankStart;\n    }\n\n    /* sort symbols by weight */\n    {   U32 s;\n        for (s=0; s<nbSymbols; s++) {\n            U32 const w = weightList[s];\n            U32 const r = rankStart[w]++;\n            sortedSymbol[r].symbol = (BYTE)s;\n            sortedSymbol[r].weight = (BYTE)w;\n        }\n        rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */\n    }\n\n    /* Build rankVal */\n    {   U32* const rankVal0 = rankVal[0];\n        {   int const rescale = (maxTableLog-tableLog) - 1;   /* tableLog <= maxTableLog */\n            U32 nextRankVal = 0;\n            U32 w;\n            for (w=1; w<maxW+1; w++) {\n                U32 current = nextRankVal;\n                nextRankVal += rankStats[w] << (w+rescale);\n                rankVal0[w] = current;\n        }   }\n        {   U32 const minBits = tableLog+1 - maxW;\n            U32 consumed;\n            for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) {\n                U32* const rankValPtr = rankVal[consumed];\n                U32 w;\n                for (w = 1; w < maxW+1; w++) {\n                    rankValPtr[w] = rankVal0[w] >> consumed;\n    }   }   }   }\n\n    HUFv07_fillDTableX4(dt, maxTableLog,\n                   sortedSymbol, sizeOfSort,\n                   rankStart0, rankVal, maxW,\n                   tableLog+1);\n\n    dtd.tableLog = (BYTE)maxTableLog;\n    dtd.tableType = 1;\n    memcpy(DTable, &dtd, sizeof(dtd));\n    return iSize;\n}\n\n\nstatic U32 HUFv07_decodeSymbolX4(void* op, BITv07_DStream_t* DStream, const HUFv07_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BITv07_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 2);\n    BITv07_skipBits(DStream, dt[val].nbBits);\n    return dt[val].length;\n}\n\nstatic U32 HUFv07_decodeLastSymbolX4(void* op, BITv07_DStream_t* DStream, const HUFv07_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BITv07_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 1);\n    if (dt[val].length==1) BITv07_skipBits(DStream, dt[val].nbBits);\n    else {\n        if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {\n            BITv07_skipBits(DStream, dt[val].nbBits);\n            if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))\n                DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);   /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */\n    }   }\n    return 1;\n}\n\n\n#define HUFv07_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \\\n    ptr += HUFv07_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUFv07_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUFv07_TABLELOG_MAX<=12)) \\\n        ptr += HUFv07_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUFv07_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        ptr += HUFv07_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\nstatic inline size_t HUFv07_decodeStreamX4(BYTE* p, BITv07_DStream_t* bitDPtr, BYTE* const pEnd, const HUFv07_DEltX4* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 8 symbols at a time */\n    while ((BITv07_reloadDStream(bitDPtr) == BITv07_DStream_unfinished) && (p < pEnd-7)) {\n        HUFv07_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUFv07_DECODE_SYMBOLX4_1(p, bitDPtr);\n        HUFv07_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUFv07_DECODE_SYMBOLX4_0(p, bitDPtr);\n    }\n\n    /* closer to end : up to 2 symbols at a time */\n    while ((BITv07_reloadDStream(bitDPtr) == BITv07_DStream_unfinished) && (p <= pEnd-2))\n        HUFv07_DECODE_SYMBOLX4_0(p, bitDPtr);\n\n    while (p <= pEnd-2)\n        HUFv07_DECODE_SYMBOLX4_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */\n\n    if (p < pEnd)\n        p += HUFv07_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);\n\n    return p-pStart;\n}\n\n\nstatic size_t HUFv07_decompress1X4_usingDTable_internal(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUFv07_DTable* DTable)\n{\n    BITv07_DStream_t bitD;\n\n    /* Init */\n    {   size_t const errorCode = BITv07_initDStream(&bitD, cSrc, cSrcSize);\n        if (HUFv07_isError(errorCode)) return errorCode;\n    }\n\n    /* decode */\n    {   BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        const void* const dtPtr = DTable+1;   /* force compiler to not use strict-aliasing */\n        const HUFv07_DEltX4* const dt = (const HUFv07_DEltX4*)dtPtr;\n        DTableDesc const dtd = HUFv07_getDTableDesc(DTable);\n        HUFv07_decodeStreamX4(ostart, &bitD, oend, dt, dtd.tableLog);\n    }\n\n    /* check */\n    if (!BITv07_endOfDStream(&bitD)) return ERROR(corruption_detected);\n\n    /* decoded size */\n    return dstSize;\n}\n\nsize_t HUFv07_decompress1X4_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUFv07_DTable* DTable)\n{\n    DTableDesc dtd = HUFv07_getDTableDesc(DTable);\n    if (dtd.tableType != 1) return ERROR(GENERIC);\n    return HUFv07_decompress1X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);\n}\n\nsize_t HUFv07_decompress1X4_DCtx (HUFv07_DTable* DCtx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t const hSize = HUFv07_readDTableX4 (DCtx, cSrc, cSrcSize);\n    if (HUFv07_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize; cSrcSize -= hSize;\n\n    return HUFv07_decompress1X4_usingDTable_internal (dst, dstSize, ip, cSrcSize, DCtx);\n}\n\nsize_t HUFv07_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv07_CREATE_STATIC_DTABLEX4(DTable, HUFv07_TABLELOG_MAX);\n    return HUFv07_decompress1X4_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);\n}\n\nstatic size_t HUFv07_decompress4X4_usingDTable_internal(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUFv07_DTable* DTable)\n{\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n\n    {   const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        const void* const dtPtr = DTable+1;\n        const HUFv07_DEltX4* const dt = (const HUFv07_DEltX4*)dtPtr;\n\n        /* Init */\n        BITv07_DStream_t bitD1;\n        BITv07_DStream_t bitD2;\n        BITv07_DStream_t bitD3;\n        BITv07_DStream_t bitD4;\n        size_t const length1 = MEM_readLE16(istart);\n        size_t const length2 = MEM_readLE16(istart+2);\n        size_t const length3 = MEM_readLE16(istart+4);\n        size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        size_t const segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n        DTableDesc const dtd = HUFv07_getDTableDesc(DTable);\n        U32 const dtLog = dtd.tableLog;\n\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        { size_t const errorCode = BITv07_initDStream(&bitD1, istart1, length1);\n          if (HUFv07_isError(errorCode)) return errorCode; }\n        { size_t const errorCode = BITv07_initDStream(&bitD2, istart2, length2);\n          if (HUFv07_isError(errorCode)) return errorCode; }\n        { size_t const errorCode = BITv07_initDStream(&bitD3, istart3, length3);\n          if (HUFv07_isError(errorCode)) return errorCode; }\n        { size_t const errorCode = BITv07_initDStream(&bitD4, istart4, length4);\n          if (HUFv07_isError(errorCode)) return errorCode; }\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BITv07_reloadDStream(&bitD1) | BITv07_reloadDStream(&bitD2) | BITv07_reloadDStream(&bitD3) | BITv07_reloadDStream(&bitD4);\n        for ( ; (endSignal==BITv07_DStream_unfinished) && (op4<(oend-7)) ; ) {\n            HUFv07_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUFv07_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUFv07_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUFv07_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUFv07_DECODE_SYMBOLX4_1(op1, &bitD1);\n            HUFv07_DECODE_SYMBOLX4_1(op2, &bitD2);\n            HUFv07_DECODE_SYMBOLX4_1(op3, &bitD3);\n            HUFv07_DECODE_SYMBOLX4_1(op4, &bitD4);\n            HUFv07_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUFv07_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUFv07_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUFv07_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUFv07_DECODE_SYMBOLX4_0(op1, &bitD1);\n            HUFv07_DECODE_SYMBOLX4_0(op2, &bitD2);\n            HUFv07_DECODE_SYMBOLX4_0(op3, &bitD3);\n            HUFv07_DECODE_SYMBOLX4_0(op4, &bitD4);\n\n            endSignal = BITv07_reloadDStream(&bitD1) | BITv07_reloadDStream(&bitD2) | BITv07_reloadDStream(&bitD3) | BITv07_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUFv07_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);\n        HUFv07_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);\n        HUFv07_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);\n        HUFv07_decodeStreamX4(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        { U32 const endCheck = BITv07_endOfDStream(&bitD1) & BITv07_endOfDStream(&bitD2) & BITv07_endOfDStream(&bitD3) & BITv07_endOfDStream(&bitD4);\n          if (!endCheck) return ERROR(corruption_detected); }\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nsize_t HUFv07_decompress4X4_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUFv07_DTable* DTable)\n{\n    DTableDesc dtd = HUFv07_getDTableDesc(DTable);\n    if (dtd.tableType != 1) return ERROR(GENERIC);\n    return HUFv07_decompress4X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);\n}\n\n\nsize_t HUFv07_decompress4X4_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t hSize = HUFv07_readDTableX4 (dctx, cSrc, cSrcSize);\n    if (HUFv07_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize; cSrcSize -= hSize;\n\n    return HUFv07_decompress4X4_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx);\n}\n\nsize_t HUFv07_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv07_CREATE_STATIC_DTABLEX4(DTable, HUFv07_TABLELOG_MAX);\n    return HUFv07_decompress4X4_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);\n}\n\n\n/* ********************************/\n/* Generic decompression selector */\n/* ********************************/\n\nsize_t HUFv07_decompress1X_usingDTable(void* dst, size_t maxDstSize,\n                                    const void* cSrc, size_t cSrcSize,\n                                    const HUFv07_DTable* DTable)\n{\n    DTableDesc const dtd = HUFv07_getDTableDesc(DTable);\n    return dtd.tableType ? HUFv07_decompress1X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable) :\n                           HUFv07_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable);\n}\n\nsize_t HUFv07_decompress4X_usingDTable(void* dst, size_t maxDstSize,\n                                    const void* cSrc, size_t cSrcSize,\n                                    const HUFv07_DTable* DTable)\n{\n    DTableDesc const dtd = HUFv07_getDTableDesc(DTable);\n    return dtd.tableType ? HUFv07_decompress4X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable) :\n                           HUFv07_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable);\n}\n\n\ntypedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;\nstatic const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =\n{\n    /* single, double, quad */\n    {{0,0}, {1,1}, {2,2}},  /* Q==0 : impossible */\n    {{0,0}, {1,1}, {2,2}},  /* Q==1 : impossible */\n    {{  38,130}, {1313, 74}, {2151, 38}},   /* Q == 2 : 12-18% */\n    {{ 448,128}, {1353, 74}, {2238, 41}},   /* Q == 3 : 18-25% */\n    {{ 556,128}, {1353, 74}, {2238, 47}},   /* Q == 4 : 25-32% */\n    {{ 714,128}, {1418, 74}, {2436, 53}},   /* Q == 5 : 32-38% */\n    {{ 883,128}, {1437, 74}, {2464, 61}},   /* Q == 6 : 38-44% */\n    {{ 897,128}, {1515, 75}, {2622, 68}},   /* Q == 7 : 44-50% */\n    {{ 926,128}, {1613, 75}, {2730, 75}},   /* Q == 8 : 50-56% */\n    {{ 947,128}, {1729, 77}, {3359, 77}},   /* Q == 9 : 56-62% */\n    {{1107,128}, {2083, 81}, {4006, 84}},   /* Q ==10 : 62-69% */\n    {{1177,128}, {2379, 87}, {4785, 88}},   /* Q ==11 : 69-75% */\n    {{1242,128}, {2415, 93}, {5155, 84}},   /* Q ==12 : 75-81% */\n    {{1349,128}, {2644,106}, {5260,106}},   /* Q ==13 : 81-87% */\n    {{1455,128}, {2422,124}, {4174,124}},   /* Q ==14 : 87-93% */\n    {{ 722,128}, {1891,145}, {1936,146}},   /* Q ==15 : 93-99% */\n};\n\n/** HUFv07_selectDecoder() :\n*   Tells which decoder is likely to decode faster,\n*   based on a set of pre-determined metrics.\n*   @return : 0==HUFv07_decompress4X2, 1==HUFv07_decompress4X4 .\n*   Assumption : 0 < cSrcSize < dstSize <= 128 KB */\nU32 HUFv07_selectDecoder (size_t dstSize, size_t cSrcSize)\n{\n    /* decoder timing evaluation */\n    U32 const Q = (U32)(cSrcSize * 16 / dstSize);   /* Q < 16 since dstSize > cSrcSize */\n    U32 const D256 = (U32)(dstSize >> 8);\n    U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256);\n    U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256);\n    DTime1 += DTime1 >> 3;  /* advantage to algorithm using less memory, for cache eviction */\n\n    return DTime1 < DTime0;\n}\n\n\ntypedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);\n\nsize_t HUFv07_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    static const decompressionAlgo decompress[2] = { HUFv07_decompress4X2, HUFv07_decompress4X4 };\n\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */\n    if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */\n    if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */\n\n    {   U32 const algoNb = HUFv07_selectDecoder(dstSize, cSrcSize);\n        return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);\n    }\n\n    /* return HUFv07_decompress4X2(dst, dstSize, cSrc, cSrcSize); */   /* multi-streams single-symbol decoding */\n    /* return HUFv07_decompress4X4(dst, dstSize, cSrc, cSrcSize); */   /* multi-streams double-symbols decoding */\n}\n\nsize_t HUFv07_decompress4X_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */\n    if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */\n    if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */\n\n    {   U32 const algoNb = HUFv07_selectDecoder(dstSize, cSrcSize);\n        return algoNb ? HUFv07_decompress4X4_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :\n                        HUFv07_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;\n    }\n}\n\nsize_t HUFv07_decompress4X_hufOnly (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if ((cSrcSize >= dstSize) || (cSrcSize <= 1)) return ERROR(corruption_detected);   /* invalid */\n\n    {   U32 const algoNb = HUFv07_selectDecoder(dstSize, cSrcSize);\n        return algoNb ? HUFv07_decompress4X4_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :\n                        HUFv07_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;\n    }\n}\n\nsize_t HUFv07_decompress1X_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */\n    if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */\n    if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */\n\n    {   U32 const algoNb = HUFv07_selectDecoder(dstSize, cSrcSize);\n        return algoNb ? HUFv07_decompress1X4_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :\n                        HUFv07_decompress1X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;\n    }\n}\n/*\n    Common functions of Zstd compression library\n    Copyright (C) 2015-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd homepage : https://facebook.github.io/zstd/\n*/\n\n\n\n/*-****************************************\n*  ZSTD Error Management\n******************************************/\n/*! ZSTDv07_isError() :\n*   tells if a return value is an error code */\nunsigned ZSTDv07_isError(size_t code) { return ERR_isError(code); }\n\n/*! ZSTDv07_getErrorName() :\n*   provides error code string from function result (useful for debugging) */\nconst char* ZSTDv07_getErrorName(size_t code) { return ERR_getErrorName(code); }\n\n\n\n/* **************************************************************\n*  ZBUFF Error Management\n****************************************************************/\nunsigned ZBUFFv07_isError(size_t errorCode) { return ERR_isError(errorCode); }\n\nconst char* ZBUFFv07_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }\n\n\n\nstatic void* ZSTDv07_defaultAllocFunction(void* opaque, size_t size)\n{\n    void* address = malloc(size);\n    (void)opaque;\n    /* printf(\"alloc %p, %d opaque=%p \\n\", address, (int)size, opaque); */\n    return address;\n}\n\nstatic void ZSTDv07_defaultFreeFunction(void* opaque, void* address)\n{\n    (void)opaque;\n    /* if (address) printf(\"free %p opaque=%p \\n\", address, opaque); */\n    free(address);\n}\n/*\n    zstd_internal - common functions to include\n    Header File for include\n    Copyright (C) 2014-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd homepage : https://www.zstd.net\n*/\n#ifndef ZSTDv07_CCOMMON_H_MODULE\n#define ZSTDv07_CCOMMON_H_MODULE\n\n\n/*-*************************************\n*  Common macros\n***************************************/\n#define MIN(a,b) ((a)<(b) ? (a) : (b))\n#define MAX(a,b) ((a)>(b) ? (a) : (b))\n\n\n/*-*************************************\n*  Common constants\n***************************************/\n#define ZSTDv07_OPT_NUM    (1<<12)\n#define ZSTDv07_DICT_MAGIC  0xEC30A437   /* v0.7 */\n\n#define ZSTDv07_REP_NUM    3\n#define ZSTDv07_REP_INIT   ZSTDv07_REP_NUM\n#define ZSTDv07_REP_MOVE   (ZSTDv07_REP_NUM-1)\nstatic const U32 repStartValue[ZSTDv07_REP_NUM] = { 1, 4, 8 };\n\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\n#define BIT7 128\n#define BIT6  64\n#define BIT5  32\n#define BIT4  16\n#define BIT1   2\n#define BIT0   1\n\n#define ZSTDv07_WINDOWLOG_ABSOLUTEMIN 10\nstatic const size_t ZSTDv07_fcs_fieldSize[4] = { 0, 2, 4, 8 };\nstatic const size_t ZSTDv07_did_fieldSize[4] = { 0, 1, 2, 4 };\n\n#define ZSTDv07_BLOCKHEADERSIZE 3   /* C standard doesn't allow `static const` variable to be init using another `static const` variable */\nstatic const size_t ZSTDv07_blockHeaderSize = ZSTDv07_BLOCKHEADERSIZE;\ntypedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;\n\n#define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */\n#define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */)   /* for a non-null block */\n\n#define ZSTD_HUFFDTABLE_CAPACITY_LOG 12\ntypedef enum { lbt_huffman, lbt_repeat, lbt_raw, lbt_rle } litBlockType_t;\n\n#define LONGNBSEQ 0x7F00\n\n#define MINMATCH 3\n#define EQUAL_READ32 4\n\n#define Litbits  8\n#define MaxLit ((1<<Litbits) - 1)\n#define MaxML  52\n#define MaxLL  35\n#define MaxOff 28\n#define MaxSeq MAX(MaxLL, MaxML)   /* Assumption : MaxOff < MaxLL,MaxML */\n#define MLFSELog    9\n#define LLFSELog    9\n#define OffFSELog   8\n\n#define FSEv07_ENCODING_RAW     0\n#define FSEv07_ENCODING_RLE     1\n#define FSEv07_ENCODING_STATIC  2\n#define FSEv07_ENCODING_DYNAMIC 3\n\n#define ZSTD_CONTENTSIZE_ERROR   (0ULL - 2)\n\nstatic const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n                                      1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9,10,11,12,\n                                     13,14,15,16 };\nstatic const S16 LL_defaultNorm[MaxLL+1] = { 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,\n                                             2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1,\n                                            -1,-1,-1,-1 };\nstatic const U32 LL_defaultNormLog = 6;\n\nstatic const U32 ML_bits[MaxML+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n                                      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n                                      1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7, 8, 9,10,11,\n                                     12,13,14,15,16 };\nstatic const S16 ML_defaultNorm[MaxML+1] = { 1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,\n                                             1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n                                             1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,\n                                            -1,-1,-1,-1,-1 };\nstatic const U32 ML_defaultNormLog = 6;\n\nstatic const S16 OF_defaultNorm[MaxOff+1] = { 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,\n                                              1, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1 };\nstatic const U32 OF_defaultNormLog = 5;\n\n\n/*-*******************************************\n*  Shared functions to include for inlining\n*********************************************/\nstatic void ZSTDv07_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }\n#define COPY8(d,s) { ZSTDv07_copy8(d,s); d+=8; s+=8; }\n\n/*! ZSTDv07_wildcopy() :\n*   custom version of memcpy(), can copy up to 7 bytes too many (8 bytes if length==0) */\n#define WILDCOPY_OVERLENGTH 8\nMEM_STATIC void ZSTDv07_wildcopy(void* dst, const void* src, ptrdiff_t length)\n{\n    const BYTE* ip = (const BYTE*)src;\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + length;\n    do\n        COPY8(op, ip)\n    while (op < oend);\n}\n\n\n/*-*******************************************\n*  Private interfaces\n*********************************************/\ntypedef struct ZSTDv07_stats_s ZSTDv07_stats_t;\n\ntypedef struct {\n    U32 off;\n    U32 len;\n} ZSTDv07_match_t;\n\ntypedef struct {\n    U32 price;\n    U32 off;\n    U32 mlen;\n    U32 litlen;\n    U32 rep[ZSTDv07_REP_INIT];\n} ZSTDv07_optimal_t;\n\nstruct ZSTDv07_stats_s { U32 unused; };\n\ntypedef struct {\n    void* buffer;\n    U32*  offsetStart;\n    U32*  offset;\n    BYTE* offCodeStart;\n    BYTE* litStart;\n    BYTE* lit;\n    U16*  litLengthStart;\n    U16*  litLength;\n    BYTE* llCodeStart;\n    U16*  matchLengthStart;\n    U16*  matchLength;\n    BYTE* mlCodeStart;\n    U32   longLengthID;   /* 0 == no longLength; 1 == Lit.longLength; 2 == Match.longLength; */\n    U32   longLengthPos;\n    /* opt */\n    ZSTDv07_optimal_t* priceTable;\n    ZSTDv07_match_t* matchTable;\n    U32* matchLengthFreq;\n    U32* litLengthFreq;\n    U32* litFreq;\n    U32* offCodeFreq;\n    U32  matchLengthSum;\n    U32  matchSum;\n    U32  litLengthSum;\n    U32  litSum;\n    U32  offCodeSum;\n    U32  log2matchLengthSum;\n    U32  log2matchSum;\n    U32  log2litLengthSum;\n    U32  log2litSum;\n    U32  log2offCodeSum;\n    U32  factor;\n    U32  cachedPrice;\n    U32  cachedLitLength;\n    const BYTE* cachedLiterals;\n    ZSTDv07_stats_t stats;\n} SeqStore_t;\n\nvoid ZSTDv07_seqToCodes(const SeqStore_t* seqStorePtr, size_t const nbSeq);\n\n/* custom memory allocation functions */\nstatic const ZSTDv07_customMem defaultCustomMem = { ZSTDv07_defaultAllocFunction, ZSTDv07_defaultFreeFunction, NULL };\n\n#endif   /* ZSTDv07_CCOMMON_H_MODULE */\n/*\n    zstd - standard compression library\n    Copyright (C) 2014-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd homepage : https://facebook.github.io/zstd\n*/\n\n/* ***************************************************************\n*  Tuning parameters\n*****************************************************************/\n/*!\n * HEAPMODE :\n * Select how default decompression function ZSTDv07_decompress() will allocate memory,\n * in memory stack (0), or in memory heap (1, requires malloc())\n */\n#ifndef ZSTDv07_HEAPMODE\n#  define ZSTDv07_HEAPMODE 1\n#endif\n\n\n/*-*******************************************************\n*  Compiler specifics\n*********************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4324)        /* disable: C4324: padded structure */\n#  pragma warning(disable : 4100)        /* disable: C4100: unreferenced formal parameter */\n#endif\n\n\n/*-*************************************\n*  Macros\n***************************************/\n#define ZSTDv07_isError ERR_isError   /* for inlining */\n#define FSEv07_isError  ERR_isError\n#define HUFv07_isError  ERR_isError\n\n\n/*_*******************************************************\n*  Memory operations\n**********************************************************/\nstatic void ZSTDv07_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }\n\n\n/*-*************************************************************\n*   Context management\n***************************************************************/\ntypedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,\n               ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock,\n               ZSTDds_decodeSkippableHeader, ZSTDds_skipFrame } ZSTDv07_dStage;\n\nstruct ZSTDv07_DCtx_s\n{\n    FSEv07_DTable LLTable[FSEv07_DTABLE_SIZE_U32(LLFSELog)];\n    FSEv07_DTable OffTable[FSEv07_DTABLE_SIZE_U32(OffFSELog)];\n    FSEv07_DTable MLTable[FSEv07_DTABLE_SIZE_U32(MLFSELog)];\n    HUFv07_DTable hufTable[HUFv07_DTABLE_SIZE(ZSTD_HUFFDTABLE_CAPACITY_LOG)];  /* can accommodate HUFv07_decompress4X */\n    const void* previousDstEnd;\n    const void* base;\n    const void* vBase;\n    const void* dictEnd;\n    size_t expected;\n    U32 rep[3];\n    ZSTDv07_frameParams fParams;\n    blockType_t bType;   /* used in ZSTDv07_decompressContinue(), to transfer blockType between header decoding and block decoding stages */\n    ZSTDv07_dStage stage;\n    U32 litEntropy;\n    U32 fseEntropy;\n    XXH64_state_t xxhState;\n    size_t headerSize;\n    U32 dictID;\n    const BYTE* litPtr;\n    ZSTDv07_customMem customMem;\n    size_t litSize;\n    BYTE litBuffer[ZSTDv07_BLOCKSIZE_ABSOLUTEMAX + WILDCOPY_OVERLENGTH];\n    BYTE headerBuffer[ZSTDv07_FRAMEHEADERSIZE_MAX];\n};  /* typedef'd to ZSTDv07_DCtx within \"zstd_static.h\" */\n\nint ZSTDv07_isSkipFrame(ZSTDv07_DCtx* dctx);\n\nsize_t ZSTDv07_sizeofDCtx (const ZSTDv07_DCtx* dctx) { return sizeof(*dctx); }\n\nsize_t ZSTDv07_estimateDCtxSize(void) { return sizeof(ZSTDv07_DCtx); }\n\nsize_t ZSTDv07_decompressBegin(ZSTDv07_DCtx* dctx)\n{\n    dctx->expected = ZSTDv07_frameHeaderSize_min;\n    dctx->stage = ZSTDds_getFrameHeaderSize;\n    dctx->previousDstEnd = NULL;\n    dctx->base = NULL;\n    dctx->vBase = NULL;\n    dctx->dictEnd = NULL;\n    dctx->hufTable[0] = (HUFv07_DTable)((ZSTD_HUFFDTABLE_CAPACITY_LOG)*0x1000001);\n    dctx->litEntropy = dctx->fseEntropy = 0;\n    dctx->dictID = 0;\n    { int i; for (i=0; i<ZSTDv07_REP_NUM; i++) dctx->rep[i] = repStartValue[i]; }\n    return 0;\n}\n\nZSTDv07_DCtx* ZSTDv07_createDCtx_advanced(ZSTDv07_customMem customMem)\n{\n    ZSTDv07_DCtx* dctx;\n\n    if (!customMem.customAlloc && !customMem.customFree)\n        customMem = defaultCustomMem;\n\n    if (!customMem.customAlloc || !customMem.customFree)\n        return NULL;\n\n    dctx = (ZSTDv07_DCtx*) customMem.customAlloc(customMem.opaque, sizeof(ZSTDv07_DCtx));\n    if (!dctx) return NULL;\n    memcpy(&dctx->customMem, &customMem, sizeof(ZSTDv07_customMem));\n    ZSTDv07_decompressBegin(dctx);\n    return dctx;\n}\n\nZSTDv07_DCtx* ZSTDv07_createDCtx(void)\n{\n    return ZSTDv07_createDCtx_advanced(defaultCustomMem);\n}\n\nsize_t ZSTDv07_freeDCtx(ZSTDv07_DCtx* dctx)\n{\n    if (dctx==NULL) return 0;   /* support free on NULL */\n    dctx->customMem.customFree(dctx->customMem.opaque, dctx);\n    return 0;   /* reserved as a potential error code in the future */\n}\n\nvoid ZSTDv07_copyDCtx(ZSTDv07_DCtx* dstDCtx, const ZSTDv07_DCtx* srcDCtx)\n{\n    memcpy(dstDCtx, srcDCtx,\n           sizeof(ZSTDv07_DCtx) - (ZSTDv07_BLOCKSIZE_ABSOLUTEMAX+WILDCOPY_OVERLENGTH + ZSTDv07_frameHeaderSize_max));  /* no need to copy workspace */\n}\n\n\n/*-*************************************************************\n*   Decompression section\n***************************************************************/\n\n/* Frame format description\n   Frame Header -  [ Block Header - Block ] - Frame End\n   1) Frame Header\n      - 4 bytes - Magic Number : ZSTDv07_MAGICNUMBER (defined within zstd.h)\n      - 1 byte  - Frame Descriptor\n   2) Block Header\n      - 3 bytes, starting with a 2-bits descriptor\n                 Uncompressed, Compressed, Frame End, unused\n   3) Block\n      See Block Format Description\n   4) Frame End\n      - 3 bytes, compatible with Block Header\n*/\n\n\n/* Frame Header :\n\n   1 byte - FrameHeaderDescription :\n   bit 0-1 : dictID (0, 1, 2 or 4 bytes)\n   bit 2   : checksumFlag\n   bit 3   : reserved (must be zero)\n   bit 4   : reserved (unused, can be any value)\n   bit 5   : Single Segment (if 1, WindowLog byte is not present)\n   bit 6-7 : FrameContentFieldSize (0, 2, 4, or 8)\n             if (SkippedWindowLog && !FrameContentFieldsize) FrameContentFieldsize=1;\n\n   Optional : WindowLog (0 or 1 byte)\n   bit 0-2 : octal Fractional (1/8th)\n   bit 3-7 : Power of 2, with 0 = 1 KB (up to 2 TB)\n\n   Optional : dictID (0, 1, 2 or 4 bytes)\n   Automatic adaptation\n   0 : no dictID\n   1 : 1 - 255\n   2 : 256 - 65535\n   4 : all other values\n\n   Optional : content size (0, 1, 2, 4 or 8 bytes)\n   0 : unknown          (fcfs==0 and swl==0)\n   1 : 0-255 bytes      (fcfs==0 and swl==1)\n   2 : 256 - 65535+256  (fcfs==1)\n   4 : 0 - 4GB-1        (fcfs==2)\n   8 : 0 - 16EB-1       (fcfs==3)\n*/\n\n\n/* Compressed Block, format description\n\n   Block = Literal Section - Sequences Section\n   Prerequisite : size of (compressed) block, maximum size of regenerated data\n\n   1) Literal Section\n\n   1.1) Header : 1-5 bytes\n        flags: 2 bits\n            00 compressed by Huff0\n            01 unused\n            10 is Raw (uncompressed)\n            11 is Rle\n            Note : using 01 => Huff0 with precomputed table ?\n            Note : delta map ? => compressed ?\n\n   1.1.1) Huff0-compressed literal block : 3-5 bytes\n            srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream\n            srcSize < 1 KB => 3 bytes (2-2-10-10)\n            srcSize < 16KB => 4 bytes (2-2-14-14)\n            else           => 5 bytes (2-2-18-18)\n            big endian convention\n\n   1.1.2) Raw (uncompressed) literal block header : 1-3 bytes\n        size :  5 bits: (IS_RAW<<6) + (0<<4) + size\n               12 bits: (IS_RAW<<6) + (2<<4) + (size>>8)\n                        size&255\n               20 bits: (IS_RAW<<6) + (3<<4) + (size>>16)\n                        size>>8&255\n                        size&255\n\n   1.1.3) Rle (repeated single byte) literal block header : 1-3 bytes\n        size :  5 bits: (IS_RLE<<6) + (0<<4) + size\n               12 bits: (IS_RLE<<6) + (2<<4) + (size>>8)\n                        size&255\n               20 bits: (IS_RLE<<6) + (3<<4) + (size>>16)\n                        size>>8&255\n                        size&255\n\n   1.1.4) Huff0-compressed literal block, using precomputed CTables : 3-5 bytes\n            srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream\n            srcSize < 1 KB => 3 bytes (2-2-10-10)\n            srcSize < 16KB => 4 bytes (2-2-14-14)\n            else           => 5 bytes (2-2-18-18)\n            big endian convention\n\n        1- CTable available (stored into workspace ?)\n        2- Small input (fast heuristic ? Full comparison ? depend on clevel ?)\n\n\n   1.2) Literal block content\n\n   1.2.1) Huff0 block, using sizes from header\n        See Huff0 format\n\n   1.2.2) Huff0 block, using prepared table\n\n   1.2.3) Raw content\n\n   1.2.4) single byte\n\n\n   2) Sequences section\n      TO DO\n*/\n\n/** ZSTDv07_frameHeaderSize() :\n*   srcSize must be >= ZSTDv07_frameHeaderSize_min.\n*   @return : size of the Frame Header */\nstatic size_t ZSTDv07_frameHeaderSize(const void* src, size_t srcSize)\n{\n    if (srcSize < ZSTDv07_frameHeaderSize_min) return ERROR(srcSize_wrong);\n    {   BYTE const fhd = ((const BYTE*)src)[4];\n        U32 const dictID= fhd & 3;\n        U32 const directMode = (fhd >> 5) & 1;\n        U32 const fcsId = fhd >> 6;\n        return ZSTDv07_frameHeaderSize_min + !directMode + ZSTDv07_did_fieldSize[dictID] + ZSTDv07_fcs_fieldSize[fcsId]\n                + (directMode && !ZSTDv07_fcs_fieldSize[fcsId]);\n    }\n}\n\n\n/** ZSTDv07_getFrameParams() :\n*   decode Frame Header, or require larger `srcSize`.\n*   @return : 0, `fparamsPtr` is correctly filled,\n*            >0, `srcSize` is too small, result is expected `srcSize`,\n*             or an error code, which can be tested using ZSTDv07_isError() */\nsize_t ZSTDv07_getFrameParams(ZSTDv07_frameParams* fparamsPtr, const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n\n    if (srcSize < ZSTDv07_frameHeaderSize_min) return ZSTDv07_frameHeaderSize_min;\n    memset(fparamsPtr, 0, sizeof(*fparamsPtr));\n    if (MEM_readLE32(src) != ZSTDv07_MAGICNUMBER) {\n        if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTDv07_MAGIC_SKIPPABLE_START) {\n            if (srcSize < ZSTDv07_skippableHeaderSize) return ZSTDv07_skippableHeaderSize; /* magic number + skippable frame length */\n            fparamsPtr->frameContentSize = MEM_readLE32((const char *)src + 4);\n            fparamsPtr->windowSize = 0; /* windowSize==0 means a frame is skippable */\n            return 0;\n        }\n        return ERROR(prefix_unknown);\n    }\n\n    /* ensure there is enough `srcSize` to fully read/decode frame header */\n    { size_t const fhsize = ZSTDv07_frameHeaderSize(src, srcSize);\n      if (srcSize < fhsize) return fhsize; }\n\n    {   BYTE const fhdByte = ip[4];\n        size_t pos = 5;\n        U32 const dictIDSizeCode = fhdByte&3;\n        U32 const checksumFlag = (fhdByte>>2)&1;\n        U32 const directMode = (fhdByte>>5)&1;\n        U32 const fcsID = fhdByte>>6;\n        U32 const windowSizeMax = 1U << ZSTDv07_WINDOWLOG_MAX;\n        U32 windowSize = 0;\n        U32 dictID = 0;\n        U64 frameContentSize = 0;\n        if ((fhdByte & 0x08) != 0)   /* reserved bits, which must be zero */\n            return ERROR(frameParameter_unsupported);\n        if (!directMode) {\n            BYTE const wlByte = ip[pos++];\n            U32 const windowLog = (wlByte >> 3) + ZSTDv07_WINDOWLOG_ABSOLUTEMIN;\n            if (windowLog > ZSTDv07_WINDOWLOG_MAX)\n                return ERROR(frameParameter_unsupported);\n            windowSize = (1U << windowLog);\n            windowSize += (windowSize >> 3) * (wlByte&7);\n        }\n\n        switch(dictIDSizeCode)\n        {\n            default:   /* impossible */\n            case 0 : break;\n            case 1 : dictID = ip[pos]; pos++; break;\n            case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break;\n            case 3 : dictID = MEM_readLE32(ip+pos); pos+=4; break;\n        }\n        switch(fcsID)\n        {\n            default:   /* impossible */\n            case 0 : if (directMode) frameContentSize = ip[pos]; break;\n            case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break;\n            case 2 : frameContentSize = MEM_readLE32(ip+pos); break;\n            case 3 : frameContentSize = MEM_readLE64(ip+pos); break;\n        }\n        if (!windowSize) windowSize = (U32)frameContentSize;\n        if (windowSize > windowSizeMax)\n            return ERROR(frameParameter_unsupported);\n        fparamsPtr->frameContentSize = frameContentSize;\n        fparamsPtr->windowSize = windowSize;\n        fparamsPtr->dictID = dictID;\n        fparamsPtr->checksumFlag = checksumFlag;\n    }\n    return 0;\n}\n\n\n/** ZSTDv07_getDecompressedSize() :\n*   compatible with legacy mode\n*   @return : decompressed size if known, 0 otherwise\n              note : 0 can mean any of the following :\n                   - decompressed size is not provided within frame header\n                   - frame header unknown / not supported\n                   - frame header not completely provided (`srcSize` too small) */\nunsigned long long ZSTDv07_getDecompressedSize(const void* src, size_t srcSize)\n{\n    ZSTDv07_frameParams fparams;\n    size_t const frResult = ZSTDv07_getFrameParams(&fparams, src, srcSize);\n    if (frResult!=0) return 0;\n    return fparams.frameContentSize;\n}\n\n\n/** ZSTDv07_decodeFrameHeader() :\n*   `srcSize` must be the size provided by ZSTDv07_frameHeaderSize().\n*   @return : 0 if success, or an error code, which can be tested using ZSTDv07_isError() */\nstatic size_t ZSTDv07_decodeFrameHeader(ZSTDv07_DCtx* dctx, const void* src, size_t srcSize)\n{\n    size_t const result = ZSTDv07_getFrameParams(&(dctx->fParams), src, srcSize);\n    if (dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID)) return ERROR(dictionary_wrong);\n    if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0);\n    return result;\n}\n\n\ntypedef struct\n{\n    blockType_t blockType;\n    U32 origSize;\n} blockProperties_t;\n\n/*! ZSTDv07_getcBlockSize() :\n*   Provides the size of compressed block from block header `src` */\nstatic size_t ZSTDv07_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)\n{\n    const BYTE* const in = (const BYTE*)src;\n    U32 cSize;\n\n    if (srcSize < ZSTDv07_blockHeaderSize) return ERROR(srcSize_wrong);\n\n    bpPtr->blockType = (blockType_t)((*in) >> 6);\n    cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);\n    bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;\n\n    if (bpPtr->blockType == bt_end) return 0;\n    if (bpPtr->blockType == bt_rle) return 1;\n    return cSize;\n}\n\n\nstatic size_t ZSTDv07_copyRawBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    if (srcSize > dstCapacity) return ERROR(dstSize_tooSmall);\n    if (srcSize > 0) {\n        memcpy(dst, src, srcSize);\n    }\n    return srcSize;\n}\n\n\n/*! ZSTDv07_decodeLiteralsBlock() :\n    @return : nb of bytes read from src (< srcSize ) */\nstatic size_t ZSTDv07_decodeLiteralsBlock(ZSTDv07_DCtx* dctx,\n                          const void* src, size_t srcSize)   /* note : srcSize < BLOCKSIZE */\n{\n    const BYTE* const istart = (const BYTE*) src;\n\n    if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);\n\n    switch((litBlockType_t)(istart[0]>> 6))\n    {\n    case lbt_huffman:\n        {   size_t litSize, litCSize, singleStream=0;\n            U32 lhSize = (istart[0] >> 4) & 3;\n            if (srcSize < 5) return ERROR(corruption_detected);   /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for lhSize, + cSize (+nbSeq) */\n            switch(lhSize)\n            {\n            case 0: case 1: default:   /* note : default is impossible, since lhSize into [0..3] */\n                /* 2 - 2 - 10 - 10 */\n                lhSize=3;\n                singleStream = istart[0] & 16;\n                litSize  = ((istart[0] & 15) << 6) + (istart[1] >> 2);\n                litCSize = ((istart[1] &  3) << 8) + istart[2];\n                break;\n            case 2:\n                /* 2 - 2 - 14 - 14 */\n                lhSize=4;\n                litSize  = ((istart[0] & 15) << 10) + (istart[1] << 2) + (istart[2] >> 6);\n                litCSize = ((istart[2] & 63) <<  8) + istart[3];\n                break;\n            case 3:\n                /* 2 - 2 - 18 - 18 */\n                lhSize=5;\n                litSize  = ((istart[0] & 15) << 14) + (istart[1] << 6) + (istart[2] >> 2);\n                litCSize = ((istart[2] &  3) << 16) + (istart[3] << 8) + istart[4];\n                break;\n            }\n            if (litSize > ZSTDv07_BLOCKSIZE_ABSOLUTEMAX) return ERROR(corruption_detected);\n            if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);\n\n            if (HUFv07_isError(singleStream ?\n                            HUFv07_decompress1X2_DCtx(dctx->hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize) :\n                            HUFv07_decompress4X_hufOnly (dctx->hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize) ))\n                return ERROR(corruption_detected);\n\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            dctx->litEntropy = 1;\n            memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);\n            return litCSize + lhSize;\n        }\n    case lbt_repeat:\n        {   size_t litSize, litCSize;\n            U32 lhSize = ((istart[0]) >> 4) & 3;\n            if (lhSize != 1)  /* only case supported for now : small litSize, single stream */\n                return ERROR(corruption_detected);\n            if (dctx->litEntropy==0)\n                return ERROR(dictionary_corrupted);\n\n            /* 2 - 2 - 10 - 10 */\n            lhSize=3;\n            litSize  = ((istart[0] & 15) << 6) + (istart[1] >> 2);\n            litCSize = ((istart[1] &  3) << 8) + istart[2];\n            if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);\n\n            {   size_t const errorCode = HUFv07_decompress1X4_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTable);\n                if (HUFv07_isError(errorCode)) return ERROR(corruption_detected);\n            }\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);\n            return litCSize + lhSize;\n        }\n    case lbt_raw:\n        {   size_t litSize;\n            U32 lhSize = ((istart[0]) >> 4) & 3;\n            switch(lhSize)\n            {\n            case 0: case 1: default:   /* note : default is impossible, since lhSize into [0..3] */\n                lhSize=1;\n                litSize = istart[0] & 31;\n                break;\n            case 2:\n                litSize = ((istart[0] & 15) << 8) + istart[1];\n                break;\n            case 3:\n                litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];\n                break;\n            }\n\n            if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) {  /* risk reading beyond src buffer with wildcopy */\n                if (litSize+lhSize > srcSize) return ERROR(corruption_detected);\n                memcpy(dctx->litBuffer, istart+lhSize, litSize);\n                dctx->litPtr = dctx->litBuffer;\n                dctx->litSize = litSize;\n                memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);\n                return lhSize+litSize;\n            }\n            /* direct reference into compressed stream */\n            dctx->litPtr = istart+lhSize;\n            dctx->litSize = litSize;\n            return lhSize+litSize;\n        }\n    case lbt_rle:\n        {   size_t litSize;\n            U32 lhSize = ((istart[0]) >> 4) & 3;\n            switch(lhSize)\n            {\n            case 0: case 1: default:   /* note : default is impossible, since lhSize into [0..3] */\n                lhSize = 1;\n                litSize = istart[0] & 31;\n                break;\n            case 2:\n                litSize = ((istart[0] & 15) << 8) + istart[1];\n                break;\n            case 3:\n                litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];\n                if (srcSize<4) return ERROR(corruption_detected);   /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */\n                break;\n            }\n            if (litSize > ZSTDv07_BLOCKSIZE_ABSOLUTEMAX) return ERROR(corruption_detected);\n            memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            return lhSize+1;\n        }\n    default:\n        return ERROR(corruption_detected);   /* impossible */\n    }\n}\n\n\n/*! ZSTDv07_buildSeqTable() :\n    @return : nb bytes read from src,\n              or an error code if it fails, testable with ZSTDv07_isError()\n*/\nstatic size_t ZSTDv07_buildSeqTable(FSEv07_DTable* DTable, U32 type, U32 max, U32 maxLog,\n                                 const void* src, size_t srcSize,\n                                 const S16* defaultNorm, U32 defaultLog, U32 flagRepeatTable)\n{\n    switch(type)\n    {\n    case FSEv07_ENCODING_RLE :\n        if (!srcSize) return ERROR(srcSize_wrong);\n        if ( (*(const BYTE*)src) > max) return ERROR(corruption_detected);\n        FSEv07_buildDTable_rle(DTable, *(const BYTE*)src);   /* if *src > max, data is corrupted */\n        return 1;\n    case FSEv07_ENCODING_RAW :\n        FSEv07_buildDTable(DTable, defaultNorm, max, defaultLog);\n        return 0;\n    case FSEv07_ENCODING_STATIC:\n        if (!flagRepeatTable) return ERROR(corruption_detected);\n        return 0;\n    default :   /* impossible */\n    case FSEv07_ENCODING_DYNAMIC :\n        {   U32 tableLog;\n            S16 norm[MaxSeq+1];\n            size_t const headerSize = FSEv07_readNCount(norm, &max, &tableLog, src, srcSize);\n            if (FSEv07_isError(headerSize)) return ERROR(corruption_detected);\n            if (tableLog > maxLog) return ERROR(corruption_detected);\n            FSEv07_buildDTable(DTable, norm, max, tableLog);\n            return headerSize;\n    }   }\n}\n\n\nstatic size_t ZSTDv07_decodeSeqHeaders(int* nbSeqPtr,\n                             FSEv07_DTable* DTableLL, FSEv07_DTable* DTableML, FSEv07_DTable* DTableOffb, U32 flagRepeatTable,\n                             const void* src, size_t srcSize)\n{\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* ip = istart;\n\n    /* check */\n    if (srcSize < MIN_SEQUENCES_SIZE) return ERROR(srcSize_wrong);\n\n    /* SeqHead */\n    {   int nbSeq = *ip++;\n        if (!nbSeq) { *nbSeqPtr=0; return 1; }\n        if (nbSeq > 0x7F) {\n            if (nbSeq == 0xFF) {\n                if (ip+2 > iend) return ERROR(srcSize_wrong);\n                nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;\n            } else {\n                if (ip >= iend) return ERROR(srcSize_wrong);\n                nbSeq = ((nbSeq-0x80)<<8) + *ip++;\n            }\n        }\n        *nbSeqPtr = nbSeq;\n    }\n\n    /* FSE table descriptors */\n    if (ip + 4 > iend) return ERROR(srcSize_wrong); /* min : header byte + all 3 are \"raw\", hence no header, but at least xxLog bits per type */\n    {   U32 const LLtype  = *ip >> 6;\n        U32 const OFtype = (*ip >> 4) & 3;\n        U32 const MLtype  = (*ip >> 2) & 3;\n        ip++;\n\n        /* Build DTables */\n        {   size_t const llhSize = ZSTDv07_buildSeqTable(DTableLL, LLtype, MaxLL, LLFSELog, ip, iend-ip, LL_defaultNorm, LL_defaultNormLog, flagRepeatTable);\n            if (ZSTDv07_isError(llhSize)) return ERROR(corruption_detected);\n            ip += llhSize;\n        }\n        {   size_t const ofhSize = ZSTDv07_buildSeqTable(DTableOffb, OFtype, MaxOff, OffFSELog, ip, iend-ip, OF_defaultNorm, OF_defaultNormLog, flagRepeatTable);\n            if (ZSTDv07_isError(ofhSize)) return ERROR(corruption_detected);\n            ip += ofhSize;\n        }\n        {   size_t const mlhSize = ZSTDv07_buildSeqTable(DTableML, MLtype, MaxML, MLFSELog, ip, iend-ip, ML_defaultNorm, ML_defaultNormLog, flagRepeatTable);\n            if (ZSTDv07_isError(mlhSize)) return ERROR(corruption_detected);\n            ip += mlhSize;\n    }   }\n\n    return ip-istart;\n}\n\n\ntypedef struct {\n    size_t litLength;\n    size_t matchLength;\n    size_t offset;\n} seq_t;\n\ntypedef struct {\n    BITv07_DStream_t DStream;\n    FSEv07_DState_t stateLL;\n    FSEv07_DState_t stateOffb;\n    FSEv07_DState_t stateML;\n    size_t prevOffset[ZSTDv07_REP_INIT];\n} seqState_t;\n\n\nstatic seq_t ZSTDv07_decodeSequence(seqState_t* seqState)\n{\n    seq_t seq;\n\n    U32 const llCode = FSEv07_peekSymbol(&(seqState->stateLL));\n    U32 const mlCode = FSEv07_peekSymbol(&(seqState->stateML));\n    U32 const ofCode = FSEv07_peekSymbol(&(seqState->stateOffb));   /* <= maxOff, by table construction */\n\n    U32 const llBits = LL_bits[llCode];\n    U32 const mlBits = ML_bits[mlCode];\n    U32 const ofBits = ofCode;\n    U32 const totalBits = llBits+mlBits+ofBits;\n\n    static const U32 LL_base[MaxLL+1] = {\n                             0,  1,  2,  3,  4,  5,  6,  7,  8,  9,   10,    11,    12,    13,    14,     15,\n                            16, 18, 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,\n                            0x2000, 0x4000, 0x8000, 0x10000 };\n\n    static const U32 ML_base[MaxML+1] = {\n                             3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13,   14,    15,    16,    17,    18,\n                            19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,   30,    31,    32,    33,    34,\n                            35, 37, 39, 41, 43, 47, 51, 59, 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,\n                            0x1003, 0x2003, 0x4003, 0x8003, 0x10003 };\n\n    static const U32 OF_base[MaxOff+1] = {\n                 0,        1,       1,       5,     0xD,     0x1D,     0x3D,     0x7D,\n                 0xFD,   0x1FD,   0x3FD,   0x7FD,   0xFFD,   0x1FFD,   0x3FFD,   0x7FFD,\n                 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,\n                 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD };\n\n    /* sequence */\n    {   size_t offset;\n        if (!ofCode)\n            offset = 0;\n        else {\n            offset = OF_base[ofCode] + BITv07_readBits(&(seqState->DStream), ofBits);   /* <=  (ZSTDv07_WINDOWLOG_MAX-1) bits */\n            if (MEM_32bits()) BITv07_reloadDStream(&(seqState->DStream));\n        }\n\n        if (ofCode <= 1) {\n            if ((llCode == 0) & (offset <= 1)) offset = 1-offset;\n            if (offset) {\n                size_t const temp = seqState->prevOffset[offset];\n                if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1];\n                seqState->prevOffset[1] = seqState->prevOffset[0];\n                seqState->prevOffset[0] = offset = temp;\n            } else {\n                offset = seqState->prevOffset[0];\n            }\n        } else {\n            seqState->prevOffset[2] = seqState->prevOffset[1];\n            seqState->prevOffset[1] = seqState->prevOffset[0];\n            seqState->prevOffset[0] = offset;\n        }\n        seq.offset = offset;\n    }\n\n    seq.matchLength = ML_base[mlCode] + ((mlCode>31) ? BITv07_readBits(&(seqState->DStream), mlBits) : 0);   /* <=  16 bits */\n    if (MEM_32bits() && (mlBits+llBits>24)) BITv07_reloadDStream(&(seqState->DStream));\n\n    seq.litLength = LL_base[llCode] + ((llCode>15) ? BITv07_readBits(&(seqState->DStream), llBits) : 0);   /* <=  16 bits */\n    if (MEM_32bits() ||\n       (totalBits > 64 - 7 - (LLFSELog+MLFSELog+OffFSELog)) ) BITv07_reloadDStream(&(seqState->DStream));\n\n    /* ANS state update */\n    FSEv07_updateState(&(seqState->stateLL), &(seqState->DStream));   /* <=  9 bits */\n    FSEv07_updateState(&(seqState->stateML), &(seqState->DStream));   /* <=  9 bits */\n    if (MEM_32bits()) BITv07_reloadDStream(&(seqState->DStream));     /* <= 18 bits */\n    FSEv07_updateState(&(seqState->stateOffb), &(seqState->DStream)); /* <=  8 bits */\n\n    return seq;\n}\n\n\nstatic\nsize_t ZSTDv07_execSequence(BYTE* op,\n                                BYTE* const oend, seq_t sequence,\n                                const BYTE** litPtr, const BYTE* const litLimit,\n                                const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)\n{\n    BYTE* const oLitEnd = op + sequence.litLength;\n    size_t const sequenceLength = sequence.litLength + sequence.matchLength;\n    BYTE* const oMatchEnd = op + sequenceLength;   /* risk : address space overflow (32-bits) */\n    BYTE* const oend_w = oend-WILDCOPY_OVERLENGTH;\n    const BYTE* const iLitEnd = *litPtr + sequence.litLength;\n    const BYTE* match = oLitEnd - sequence.offset;\n\n    /* check */\n    assert(oend >= op);\n    if (sequence.litLength + WILDCOPY_OVERLENGTH > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);\n    if (sequenceLength > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);\n    assert(litLimit >= *litPtr);\n    if (sequence.litLength > (size_t)(litLimit - *litPtr)) return ERROR(corruption_detected);;\n\n    /* copy Literals */\n    ZSTDv07_wildcopy(op, *litPtr, (ptrdiff_t)sequence.litLength);   /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */\n    op = oLitEnd;\n    *litPtr = iLitEnd;   /* update for next sequence */\n\n    /* copy Match */\n    if (sequence.offset > (size_t)(oLitEnd - base)) {\n        /* offset beyond prefix */\n        if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);\n        match = dictEnd - (base-match);\n        if (match + sequence.matchLength <= dictEnd) {\n            memmove(oLitEnd, match, sequence.matchLength);\n            return sequenceLength;\n        }\n        /* span extDict & currentPrefixSegment */\n        {   size_t const length1 = (size_t)(dictEnd - match);\n            memmove(oLitEnd, match, length1);\n            op = oLitEnd + length1;\n            sequence.matchLength -= length1;\n            match = base;\n            if (op > oend_w || sequence.matchLength < MINMATCH) {\n              while (op < oMatchEnd) *op++ = *match++;\n              return sequenceLength;\n            }\n    }   }\n    /* Requirement: op <= oend_w */\n\n    /* match within prefix */\n    if (sequence.offset < 8) {\n        /* close range match, overlap */\n        static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 };   /* added */\n        static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 };   /* subtracted */\n        int const sub2 = dec64table[sequence.offset];\n        op[0] = match[0];\n        op[1] = match[1];\n        op[2] = match[2];\n        op[3] = match[3];\n        match += dec32table[sequence.offset];\n        ZSTDv07_copy4(op+4, match);\n        match -= sub2;\n    } else {\n        ZSTDv07_copy8(op, match);\n    }\n    op += 8; match += 8;\n\n    if (oMatchEnd > oend-(16-MINMATCH)) {\n        if (op < oend_w) {\n            ZSTDv07_wildcopy(op, match, oend_w - op);\n            match += oend_w - op;\n            op = oend_w;\n        }\n        while (op < oMatchEnd) *op++ = *match++;\n    } else {\n        ZSTDv07_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8);   /* works even if matchLength < 8 */\n    }\n    return sequenceLength;\n}\n\n\nstatic size_t ZSTDv07_decompressSequences(\n                               ZSTDv07_DCtx* dctx,\n                               void* dst, size_t maxDstSize,\n                         const void* seqStart, size_t seqSize)\n{\n    const BYTE* ip = (const BYTE*)seqStart;\n    const BYTE* const iend = ip + seqSize;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = ostart + maxDstSize;\n    BYTE* op = ostart;\n    const BYTE* litPtr = dctx->litPtr;\n    const BYTE* const litEnd = litPtr + dctx->litSize;\n    FSEv07_DTable* DTableLL = dctx->LLTable;\n    FSEv07_DTable* DTableML = dctx->MLTable;\n    FSEv07_DTable* DTableOffb = dctx->OffTable;\n    const BYTE* const base = (const BYTE*) (dctx->base);\n    const BYTE* const vBase = (const BYTE*) (dctx->vBase);\n    const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);\n    int nbSeq;\n\n    /* Build Decoding Tables */\n    {   size_t const seqHSize = ZSTDv07_decodeSeqHeaders(&nbSeq, DTableLL, DTableML, DTableOffb, dctx->fseEntropy, ip, seqSize);\n        if (ZSTDv07_isError(seqHSize)) return seqHSize;\n        ip += seqHSize;\n    }\n\n    /* Regen sequences */\n    if (nbSeq) {\n        seqState_t seqState;\n        dctx->fseEntropy = 1;\n        { U32 i; for (i=0; i<ZSTDv07_REP_INIT; i++) seqState.prevOffset[i] = dctx->rep[i]; }\n        { size_t const errorCode = BITv07_initDStream(&(seqState.DStream), ip, iend-ip);\n          if (ERR_isError(errorCode)) return ERROR(corruption_detected); }\n        FSEv07_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);\n        FSEv07_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);\n        FSEv07_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);\n\n        for ( ; (BITv07_reloadDStream(&(seqState.DStream)) <= BITv07_DStream_completed) && nbSeq ; ) {\n            nbSeq--;\n            {   seq_t const sequence = ZSTDv07_decodeSequence(&seqState);\n                size_t const oneSeqSize = ZSTDv07_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);\n                if (ZSTDv07_isError(oneSeqSize)) return oneSeqSize;\n                op += oneSeqSize;\n        }   }\n\n        /* check if reached exact end */\n        if (nbSeq) return ERROR(corruption_detected);\n        /* save reps for next block */\n        { U32 i; for (i=0; i<ZSTDv07_REP_INIT; i++) dctx->rep[i] = (U32)(seqState.prevOffset[i]); }\n    }\n\n    /* last literal segment */\n    {   size_t const lastLLSize = litEnd - litPtr;\n        /* if (litPtr > litEnd) return ERROR(corruption_detected); */   /* too many literals already used */\n        if (lastLLSize > (size_t)(oend-op)) return ERROR(dstSize_tooSmall);\n        if (lastLLSize > 0) {\n            memcpy(op, litPtr, lastLLSize);\n            op += lastLLSize;\n        }\n    }\n\n    return op-ostart;\n}\n\n\nstatic void ZSTDv07_checkContinuity(ZSTDv07_DCtx* dctx, const void* dst)\n{\n    if (dst != dctx->previousDstEnd) {   /* not contiguous */\n        dctx->dictEnd = dctx->previousDstEnd;\n        dctx->vBase = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));\n        dctx->base = dst;\n        dctx->previousDstEnd = dst;\n    }\n}\n\n\nstatic size_t ZSTDv07_decompressBlock_internal(ZSTDv07_DCtx* dctx,\n                            void* dst, size_t dstCapacity,\n                      const void* src, size_t srcSize)\n{   /* blockType == blockCompressed */\n    const BYTE* ip = (const BYTE*)src;\n\n    if (srcSize >= ZSTDv07_BLOCKSIZE_ABSOLUTEMAX) return ERROR(srcSize_wrong);\n\n    /* Decode literals sub-block */\n    {   size_t const litCSize = ZSTDv07_decodeLiteralsBlock(dctx, src, srcSize);\n        if (ZSTDv07_isError(litCSize)) return litCSize;\n        ip += litCSize;\n        srcSize -= litCSize;\n    }\n    return ZSTDv07_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);\n}\n\n\nsize_t ZSTDv07_decompressBlock(ZSTDv07_DCtx* dctx,\n                            void* dst, size_t dstCapacity,\n                      const void* src, size_t srcSize)\n{\n    size_t dSize;\n    ZSTDv07_checkContinuity(dctx, dst);\n    dSize = ZSTDv07_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);\n    dctx->previousDstEnd = (char*)dst + dSize;\n    return dSize;\n}\n\n\n/** ZSTDv07_insertBlock() :\n    insert `src` block into `dctx` history. Useful to track uncompressed blocks. */\nZSTDLIBv07_API size_t ZSTDv07_insertBlock(ZSTDv07_DCtx* dctx, const void* blockStart, size_t blockSize)\n{\n    ZSTDv07_checkContinuity(dctx, blockStart);\n    dctx->previousDstEnd = (const char*)blockStart + blockSize;\n    return blockSize;\n}\n\n\nstatic size_t ZSTDv07_generateNxBytes(void* dst, size_t dstCapacity, BYTE byte, size_t length)\n{\n    if (length > dstCapacity) return ERROR(dstSize_tooSmall);\n    if (length > 0) {\n        memset(dst, byte, length);\n    }\n    return length;\n}\n\n\n/*! ZSTDv07_decompressFrame() :\n*   `dctx` must be properly initialized */\nstatic size_t ZSTDv07_decompressFrame(ZSTDv07_DCtx* dctx,\n                                 void* dst, size_t dstCapacity,\n                                 const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n    const BYTE* const iend = ip + srcSize;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = ostart + dstCapacity;\n    BYTE* op = ostart;\n    size_t remainingSize = srcSize;\n\n    /* check */\n    if (srcSize < ZSTDv07_frameHeaderSize_min+ZSTDv07_blockHeaderSize) return ERROR(srcSize_wrong);\n\n    /* Frame Header */\n    {   size_t const frameHeaderSize = ZSTDv07_frameHeaderSize(src, ZSTDv07_frameHeaderSize_min);\n        if (ZSTDv07_isError(frameHeaderSize)) return frameHeaderSize;\n        if (srcSize < frameHeaderSize+ZSTDv07_blockHeaderSize) return ERROR(srcSize_wrong);\n        if (ZSTDv07_decodeFrameHeader(dctx, src, frameHeaderSize)) return ERROR(corruption_detected);\n        ip += frameHeaderSize; remainingSize -= frameHeaderSize;\n    }\n\n    /* Loop on each block */\n    while (1) {\n        size_t decodedSize;\n        blockProperties_t blockProperties;\n        size_t const cBlockSize = ZSTDv07_getcBlockSize(ip, iend-ip, &blockProperties);\n        if (ZSTDv07_isError(cBlockSize)) return cBlockSize;\n\n        ip += ZSTDv07_blockHeaderSize;\n        remainingSize -= ZSTDv07_blockHeaderSize;\n        if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);\n\n        switch(blockProperties.blockType)\n        {\n        case bt_compressed:\n            decodedSize = ZSTDv07_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize);\n            break;\n        case bt_raw :\n            decodedSize = ZSTDv07_copyRawBlock(op, oend-op, ip, cBlockSize);\n            break;\n        case bt_rle :\n            decodedSize = ZSTDv07_generateNxBytes(op, oend-op, *ip, blockProperties.origSize);\n            break;\n        case bt_end :\n            /* end of frame */\n            if (remainingSize) return ERROR(srcSize_wrong);\n            decodedSize = 0;\n            break;\n        default:\n            return ERROR(GENERIC);   /* impossible */\n        }\n        if (blockProperties.blockType == bt_end) break;   /* bt_end */\n\n        if (ZSTDv07_isError(decodedSize)) return decodedSize;\n        if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, op, decodedSize);\n        op += decodedSize;\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n    }\n\n    return op-ostart;\n}\n\n\n/*! ZSTDv07_decompress_usingPreparedDCtx() :\n*   Same as ZSTDv07_decompress_usingDict, but using a reference context `preparedDCtx`, where dictionary has been loaded.\n*   It avoids reloading the dictionary each time.\n*   `preparedDCtx` must have been properly initialized using ZSTDv07_decompressBegin_usingDict().\n*   Requires 2 contexts : 1 for reference (preparedDCtx), which will not be modified, and 1 to run the decompression operation (dctx) */\nstatic size_t ZSTDv07_decompress_usingPreparedDCtx(ZSTDv07_DCtx* dctx, const ZSTDv07_DCtx* refDCtx,\n                                         void* dst, size_t dstCapacity,\n                                   const void* src, size_t srcSize)\n{\n    ZSTDv07_copyDCtx(dctx, refDCtx);\n    ZSTDv07_checkContinuity(dctx, dst);\n    return ZSTDv07_decompressFrame(dctx, dst, dstCapacity, src, srcSize);\n}\n\n\nsize_t ZSTDv07_decompress_usingDict(ZSTDv07_DCtx* dctx,\n                                 void* dst, size_t dstCapacity,\n                                 const void* src, size_t srcSize,\n                                 const void* dict, size_t dictSize)\n{\n    ZSTDv07_decompressBegin_usingDict(dctx, dict, dictSize);\n    ZSTDv07_checkContinuity(dctx, dst);\n    return ZSTDv07_decompressFrame(dctx, dst, dstCapacity, src, srcSize);\n}\n\n\nsize_t ZSTDv07_decompressDCtx(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    return ZSTDv07_decompress_usingDict(dctx, dst, dstCapacity, src, srcSize, NULL, 0);\n}\n\n\nsize_t ZSTDv07_decompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n#if defined(ZSTDv07_HEAPMODE) && (ZSTDv07_HEAPMODE==1)\n    size_t regenSize;\n    ZSTDv07_DCtx* const dctx = ZSTDv07_createDCtx();\n    if (dctx==NULL) return ERROR(memory_allocation);\n    regenSize = ZSTDv07_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);\n    ZSTDv07_freeDCtx(dctx);\n    return regenSize;\n#else   /* stack mode */\n    ZSTDv07_DCtx dctx;\n    return ZSTDv07_decompressDCtx(&dctx, dst, dstCapacity, src, srcSize);\n#endif\n}\n\n/* ZSTD_errorFrameSizeInfoLegacy() :\n   assumes `cSize` and `dBound` are _not_ NULL */\nstatic void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)\n{\n    *cSize = ret;\n    *dBound = ZSTD_CONTENTSIZE_ERROR;\n}\n\nvoid ZSTDv07_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)\n{\n    const BYTE* ip = (const BYTE*)src;\n    size_t remainingSize = srcSize;\n    size_t nbBlocks = 0;\n\n    /* check */\n    if (srcSize < ZSTDv07_frameHeaderSize_min+ZSTDv07_blockHeaderSize) {\n        ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n        return;\n    }\n\n    /* Frame Header */\n    {   size_t const frameHeaderSize = ZSTDv07_frameHeaderSize(src, srcSize);\n        if (ZSTDv07_isError(frameHeaderSize)) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, frameHeaderSize);\n            return;\n        }\n        if (MEM_readLE32(src) != ZSTDv07_MAGICNUMBER) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));\n            return;\n        }\n        if (srcSize < frameHeaderSize+ZSTDv07_blockHeaderSize) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n            return;\n        }\n        ip += frameHeaderSize; remainingSize -= frameHeaderSize;\n    }\n\n    /* Loop on each block */\n    while (1) {\n        blockProperties_t blockProperties;\n        size_t const cBlockSize = ZSTDv07_getcBlockSize(ip, remainingSize, &blockProperties);\n        if (ZSTDv07_isError(cBlockSize)) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);\n            return;\n        }\n\n        ip += ZSTDv07_blockHeaderSize;\n        remainingSize -= ZSTDv07_blockHeaderSize;\n\n        if (blockProperties.blockType == bt_end) break;\n\n        if (cBlockSize > remainingSize) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n            return;\n        }\n\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n        nbBlocks++;\n    }\n\n    *cSize = ip - (const BYTE*)src;\n    *dBound = nbBlocks * ZSTDv07_BLOCKSIZE_ABSOLUTEMAX;\n}\n\n/*_******************************\n*  Streaming Decompression API\n********************************/\nsize_t ZSTDv07_nextSrcSizeToDecompress(ZSTDv07_DCtx* dctx)\n{\n    return dctx->expected;\n}\n\nint ZSTDv07_isSkipFrame(ZSTDv07_DCtx* dctx)\n{\n    return dctx->stage == ZSTDds_skipFrame;\n}\n\n/** ZSTDv07_decompressContinue() :\n*   @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity)\n*             or an error code, which can be tested using ZSTDv07_isError() */\nsize_t ZSTDv07_decompressContinue(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    /* Sanity check */\n    if (srcSize != dctx->expected) return ERROR(srcSize_wrong);\n    if (dstCapacity) ZSTDv07_checkContinuity(dctx, dst);\n\n    switch (dctx->stage)\n    {\n    case ZSTDds_getFrameHeaderSize :\n        if (srcSize != ZSTDv07_frameHeaderSize_min) return ERROR(srcSize_wrong);   /* impossible */\n        if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTDv07_MAGIC_SKIPPABLE_START) {\n            memcpy(dctx->headerBuffer, src, ZSTDv07_frameHeaderSize_min);\n            dctx->expected = ZSTDv07_skippableHeaderSize - ZSTDv07_frameHeaderSize_min; /* magic number + skippable frame length */\n            dctx->stage = ZSTDds_decodeSkippableHeader;\n            return 0;\n        }\n        dctx->headerSize = ZSTDv07_frameHeaderSize(src, ZSTDv07_frameHeaderSize_min);\n        if (ZSTDv07_isError(dctx->headerSize)) return dctx->headerSize;\n        memcpy(dctx->headerBuffer, src, ZSTDv07_frameHeaderSize_min);\n        if (dctx->headerSize > ZSTDv07_frameHeaderSize_min) {\n            dctx->expected = dctx->headerSize - ZSTDv07_frameHeaderSize_min;\n            dctx->stage = ZSTDds_decodeFrameHeader;\n            return 0;\n        }\n        dctx->expected = 0;   /* not necessary to copy more */\n\t/* fall-through */\n    case ZSTDds_decodeFrameHeader:\n        {   size_t result;\n            memcpy(dctx->headerBuffer + ZSTDv07_frameHeaderSize_min, src, dctx->expected);\n            result = ZSTDv07_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize);\n            if (ZSTDv07_isError(result)) return result;\n            dctx->expected = ZSTDv07_blockHeaderSize;\n            dctx->stage = ZSTDds_decodeBlockHeader;\n            return 0;\n        }\n    case ZSTDds_decodeBlockHeader:\n        {   blockProperties_t bp;\n            size_t const cBlockSize = ZSTDv07_getcBlockSize(src, ZSTDv07_blockHeaderSize, &bp);\n            if (ZSTDv07_isError(cBlockSize)) return cBlockSize;\n            if (bp.blockType == bt_end) {\n                if (dctx->fParams.checksumFlag) {\n                    U64 const h64 = XXH64_digest(&dctx->xxhState);\n                    U32 const h32 = (U32)(h64>>11) & ((1<<22)-1);\n                    const BYTE* const ip = (const BYTE*)src;\n                    U32 const check32 = ip[2] + (ip[1] << 8) + ((ip[0] & 0x3F) << 16);\n                    if (check32 != h32) return ERROR(checksum_wrong);\n                }\n                dctx->expected = 0;\n                dctx->stage = ZSTDds_getFrameHeaderSize;\n            } else {\n                dctx->expected = cBlockSize;\n                dctx->bType = bp.blockType;\n                dctx->stage = ZSTDds_decompressBlock;\n            }\n            return 0;\n        }\n    case ZSTDds_decompressBlock:\n        {   size_t rSize;\n            switch(dctx->bType)\n            {\n            case bt_compressed:\n                rSize = ZSTDv07_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);\n                break;\n            case bt_raw :\n                rSize = ZSTDv07_copyRawBlock(dst, dstCapacity, src, srcSize);\n                break;\n            case bt_rle :\n                return ERROR(GENERIC);   /* not yet handled */\n                break;\n            case bt_end :   /* should never happen (filtered at phase 1) */\n                rSize = 0;\n                break;\n            default:\n                return ERROR(GENERIC);   /* impossible */\n            }\n            dctx->stage = ZSTDds_decodeBlockHeader;\n            dctx->expected = ZSTDv07_blockHeaderSize;\n            if (ZSTDv07_isError(rSize)) return rSize;\n            dctx->previousDstEnd = (char*)dst + rSize;\n            if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize);\n            return rSize;\n        }\n    case ZSTDds_decodeSkippableHeader:\n        {   memcpy(dctx->headerBuffer + ZSTDv07_frameHeaderSize_min, src, dctx->expected);\n            dctx->expected = MEM_readLE32(dctx->headerBuffer + 4);\n            dctx->stage = ZSTDds_skipFrame;\n            return 0;\n        }\n    case ZSTDds_skipFrame:\n        {   dctx->expected = 0;\n            dctx->stage = ZSTDds_getFrameHeaderSize;\n            return 0;\n        }\n    default:\n        return ERROR(GENERIC);   /* impossible */\n    }\n}\n\n\nstatic size_t ZSTDv07_refDictContent(ZSTDv07_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    dctx->dictEnd = dctx->previousDstEnd;\n    dctx->vBase = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));\n    dctx->base = dict;\n    dctx->previousDstEnd = (const char*)dict + dictSize;\n    return 0;\n}\n\nstatic size_t ZSTDv07_loadEntropy(ZSTDv07_DCtx* dctx, const void* const dict, size_t const dictSize)\n{\n    const BYTE* dictPtr = (const BYTE*)dict;\n    const BYTE* const dictEnd = dictPtr + dictSize;\n\n    {   size_t const hSize = HUFv07_readDTableX4(dctx->hufTable, dict, dictSize);\n        if (HUFv07_isError(hSize)) return ERROR(dictionary_corrupted);\n        dictPtr += hSize;\n    }\n\n    {   short offcodeNCount[MaxOff+1];\n        U32 offcodeMaxValue=MaxOff, offcodeLog;\n        size_t const offcodeHeaderSize = FSEv07_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);\n        if (FSEv07_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);\n        if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted);\n        { size_t const errorCode = FSEv07_buildDTable(dctx->OffTable, offcodeNCount, offcodeMaxValue, offcodeLog);\n          if (FSEv07_isError(errorCode)) return ERROR(dictionary_corrupted); }\n        dictPtr += offcodeHeaderSize;\n    }\n\n    {   short matchlengthNCount[MaxML+1];\n        unsigned matchlengthMaxValue = MaxML, matchlengthLog;\n        size_t const matchlengthHeaderSize = FSEv07_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);\n        if (FSEv07_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);\n        if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);\n        { size_t const errorCode = FSEv07_buildDTable(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);\n          if (FSEv07_isError(errorCode)) return ERROR(dictionary_corrupted); }\n        dictPtr += matchlengthHeaderSize;\n    }\n\n    {   short litlengthNCount[MaxLL+1];\n        unsigned litlengthMaxValue = MaxLL, litlengthLog;\n        size_t const litlengthHeaderSize = FSEv07_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);\n        if (FSEv07_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);\n        if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);\n        { size_t const errorCode = FSEv07_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog);\n          if (FSEv07_isError(errorCode)) return ERROR(dictionary_corrupted); }\n        dictPtr += litlengthHeaderSize;\n    }\n\n    if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);\n    dctx->rep[0] = MEM_readLE32(dictPtr+0); if (dctx->rep[0] == 0 || dctx->rep[0] >= dictSize) return ERROR(dictionary_corrupted);\n    dctx->rep[1] = MEM_readLE32(dictPtr+4); if (dctx->rep[1] == 0 || dctx->rep[1] >= dictSize) return ERROR(dictionary_corrupted);\n    dctx->rep[2] = MEM_readLE32(dictPtr+8); if (dctx->rep[2] == 0 || dctx->rep[2] >= dictSize) return ERROR(dictionary_corrupted);\n    dictPtr += 12;\n\n    dctx->litEntropy = dctx->fseEntropy = 1;\n    return dictPtr - (const BYTE*)dict;\n}\n\nstatic size_t ZSTDv07_decompress_insertDictionary(ZSTDv07_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    if (dictSize < 8) return ZSTDv07_refDictContent(dctx, dict, dictSize);\n    {   U32 const magic = MEM_readLE32(dict);\n        if (magic != ZSTDv07_DICT_MAGIC) {\n            return ZSTDv07_refDictContent(dctx, dict, dictSize);   /* pure content mode */\n    }   }\n    dctx->dictID = MEM_readLE32((const char*)dict + 4);\n\n    /* load entropy tables */\n    dict = (const char*)dict + 8;\n    dictSize -= 8;\n    {   size_t const eSize = ZSTDv07_loadEntropy(dctx, dict, dictSize);\n        if (ZSTDv07_isError(eSize)) return ERROR(dictionary_corrupted);\n        dict = (const char*)dict + eSize;\n        dictSize -= eSize;\n    }\n\n    /* reference dictionary content */\n    return ZSTDv07_refDictContent(dctx, dict, dictSize);\n}\n\n\nsize_t ZSTDv07_decompressBegin_usingDict(ZSTDv07_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    { size_t const errorCode = ZSTDv07_decompressBegin(dctx);\n      if (ZSTDv07_isError(errorCode)) return errorCode; }\n\n    if (dict && dictSize) {\n        size_t const errorCode = ZSTDv07_decompress_insertDictionary(dctx, dict, dictSize);\n        if (ZSTDv07_isError(errorCode)) return ERROR(dictionary_corrupted);\n    }\n\n    return 0;\n}\n\n\nstruct ZSTDv07_DDict_s {\n    void* dict;\n    size_t dictSize;\n    ZSTDv07_DCtx* refContext;\n};  /* typedef'd tp ZSTDv07_CDict within zstd.h */\n\nstatic ZSTDv07_DDict* ZSTDv07_createDDict_advanced(const void* dict, size_t dictSize, ZSTDv07_customMem customMem)\n{\n    if (!customMem.customAlloc && !customMem.customFree)\n        customMem = defaultCustomMem;\n\n    if (!customMem.customAlloc || !customMem.customFree)\n        return NULL;\n\n    {   ZSTDv07_DDict* const ddict = (ZSTDv07_DDict*) customMem.customAlloc(customMem.opaque, sizeof(*ddict));\n        void* const dictContent = customMem.customAlloc(customMem.opaque, dictSize);\n        ZSTDv07_DCtx* const dctx = ZSTDv07_createDCtx_advanced(customMem);\n\n        if (!dictContent || !ddict || !dctx) {\n            customMem.customFree(customMem.opaque, dictContent);\n            customMem.customFree(customMem.opaque, ddict);\n            customMem.customFree(customMem.opaque, dctx);\n            return NULL;\n        }\n\n        memcpy(dictContent, dict, dictSize);\n        {   size_t const errorCode = ZSTDv07_decompressBegin_usingDict(dctx, dictContent, dictSize);\n            if (ZSTDv07_isError(errorCode)) {\n                customMem.customFree(customMem.opaque, dictContent);\n                customMem.customFree(customMem.opaque, ddict);\n                customMem.customFree(customMem.opaque, dctx);\n                return NULL;\n        }   }\n\n        ddict->dict = dictContent;\n        ddict->dictSize = dictSize;\n        ddict->refContext = dctx;\n        return ddict;\n    }\n}\n\n/*! ZSTDv07_createDDict() :\n*   Create a digested dictionary, ready to start decompression without startup delay.\n*   `dict` can be released after `ZSTDv07_DDict` creation */\nZSTDv07_DDict* ZSTDv07_createDDict(const void* dict, size_t dictSize)\n{\n    ZSTDv07_customMem const allocator = { NULL, NULL, NULL };\n    return ZSTDv07_createDDict_advanced(dict, dictSize, allocator);\n}\n\nsize_t ZSTDv07_freeDDict(ZSTDv07_DDict* ddict)\n{\n    ZSTDv07_freeFunction const cFree = ddict->refContext->customMem.customFree;\n    void* const opaque = ddict->refContext->customMem.opaque;\n    ZSTDv07_freeDCtx(ddict->refContext);\n    cFree(opaque, ddict->dict);\n    cFree(opaque, ddict);\n    return 0;\n}\n\n/*! ZSTDv07_decompress_usingDDict() :\n*   Decompression using a pre-digested Dictionary\n*   Use dictionary without significant overhead. */\nZSTDLIBv07_API size_t ZSTDv07_decompress_usingDDict(ZSTDv07_DCtx* dctx,\n                                           void* dst, size_t dstCapacity,\n                                     const void* src, size_t srcSize,\n                                     const ZSTDv07_DDict* ddict)\n{\n    return ZSTDv07_decompress_usingPreparedDCtx(dctx, ddict->refContext,\n                                           dst, dstCapacity,\n                                           src, srcSize);\n}\n/*\n    Buffered version of Zstd compression library\n    Copyright (C) 2015-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd homepage : https://facebook.github.io/zstd/\n*/\n\n\n\n/*-***************************************************************************\n*  Streaming decompression howto\n*\n*  A ZBUFFv07_DCtx object is required to track streaming operations.\n*  Use ZBUFFv07_createDCtx() and ZBUFFv07_freeDCtx() to create/release resources.\n*  Use ZBUFFv07_decompressInit() to start a new decompression operation,\n*   or ZBUFFv07_decompressInitDictionary() if decompression requires a dictionary.\n*  Note that ZBUFFv07_DCtx objects can be re-init multiple times.\n*\n*  Use ZBUFFv07_decompressContinue() repetitively to consume your input.\n*  *srcSizePtr and *dstCapacityPtr can be any size.\n*  The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr.\n*  Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again.\n*  The content of @dst will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters, or change @dst.\n*  @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to help latency),\n*            or 0 when a frame is completely decoded,\n*            or an error code, which can be tested using ZBUFFv07_isError().\n*\n*  Hint : recommended buffer sizes (not compulsory) : ZBUFFv07_recommendedDInSize() and ZBUFFv07_recommendedDOutSize()\n*  output : ZBUFFv07_recommendedDOutSize==128 KB block size is the internal unit, it ensures it's always possible to write a full block when decoded.\n*  input  : ZBUFFv07_recommendedDInSize == 128KB + 3;\n*           just follow indications from ZBUFFv07_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .\n* *******************************************************************************/\n\ntypedef enum { ZBUFFds_init, ZBUFFds_loadHeader,\n               ZBUFFds_read, ZBUFFds_load, ZBUFFds_flush } ZBUFFv07_dStage;\n\n/* *** Resource management *** */\nstruct ZBUFFv07_DCtx_s {\n    ZSTDv07_DCtx* zd;\n    ZSTDv07_frameParams fParams;\n    ZBUFFv07_dStage stage;\n    char*  inBuff;\n    size_t inBuffSize;\n    size_t inPos;\n    char*  outBuff;\n    size_t outBuffSize;\n    size_t outStart;\n    size_t outEnd;\n    size_t blockSize;\n    BYTE headerBuffer[ZSTDv07_FRAMEHEADERSIZE_MAX];\n    size_t lhSize;\n    ZSTDv07_customMem customMem;\n};   /* typedef'd to ZBUFFv07_DCtx within \"zstd_buffered.h\" */\n\nZSTDLIBv07_API ZBUFFv07_DCtx* ZBUFFv07_createDCtx_advanced(ZSTDv07_customMem customMem);\n\nZBUFFv07_DCtx* ZBUFFv07_createDCtx(void)\n{\n    return ZBUFFv07_createDCtx_advanced(defaultCustomMem);\n}\n\nZBUFFv07_DCtx* ZBUFFv07_createDCtx_advanced(ZSTDv07_customMem customMem)\n{\n    ZBUFFv07_DCtx* zbd;\n\n    if (!customMem.customAlloc && !customMem.customFree)\n        customMem = defaultCustomMem;\n\n    if (!customMem.customAlloc || !customMem.customFree)\n        return NULL;\n\n    zbd = (ZBUFFv07_DCtx*)customMem.customAlloc(customMem.opaque, sizeof(ZBUFFv07_DCtx));\n    if (zbd==NULL) return NULL;\n    memset(zbd, 0, sizeof(ZBUFFv07_DCtx));\n    memcpy(&zbd->customMem, &customMem, sizeof(ZSTDv07_customMem));\n    zbd->zd = ZSTDv07_createDCtx_advanced(customMem);\n    if (zbd->zd == NULL) { ZBUFFv07_freeDCtx(zbd); return NULL; }\n    zbd->stage = ZBUFFds_init;\n    return zbd;\n}\n\nsize_t ZBUFFv07_freeDCtx(ZBUFFv07_DCtx* zbd)\n{\n    if (zbd==NULL) return 0;   /* support free on null */\n    ZSTDv07_freeDCtx(zbd->zd);\n    if (zbd->inBuff) zbd->customMem.customFree(zbd->customMem.opaque, zbd->inBuff);\n    if (zbd->outBuff) zbd->customMem.customFree(zbd->customMem.opaque, zbd->outBuff);\n    zbd->customMem.customFree(zbd->customMem.opaque, zbd);\n    return 0;\n}\n\n\n/* *** Initialization *** */\n\nsize_t ZBUFFv07_decompressInitDictionary(ZBUFFv07_DCtx* zbd, const void* dict, size_t dictSize)\n{\n    zbd->stage = ZBUFFds_loadHeader;\n    zbd->lhSize = zbd->inPos = zbd->outStart = zbd->outEnd = 0;\n    return ZSTDv07_decompressBegin_usingDict(zbd->zd, dict, dictSize);\n}\n\nsize_t ZBUFFv07_decompressInit(ZBUFFv07_DCtx* zbd)\n{\n    return ZBUFFv07_decompressInitDictionary(zbd, NULL, 0);\n}\n\n\n/* internal util function */\nMEM_STATIC size_t ZBUFFv07_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    size_t const length = MIN(dstCapacity, srcSize);\n    if (length > 0) {\n        memcpy(dst, src, length);\n    }\n    return length;\n}\n\n\n/* *** Decompression *** */\n\nsize_t ZBUFFv07_decompressContinue(ZBUFFv07_DCtx* zbd,\n                                void* dst, size_t* dstCapacityPtr,\n                          const void* src, size_t* srcSizePtr)\n{\n    const char* const istart = (const char*)src;\n    const char* const iend = istart + *srcSizePtr;\n    const char* ip = istart;\n    char* const ostart = (char*)dst;\n    char* const oend = ostart + *dstCapacityPtr;\n    char* op = ostart;\n    U32 notDone = 1;\n\n    while (notDone) {\n        switch(zbd->stage)\n        {\n        case ZBUFFds_init :\n            return ERROR(init_missing);\n\n        case ZBUFFds_loadHeader :\n            {   size_t const hSize = ZSTDv07_getFrameParams(&(zbd->fParams), zbd->headerBuffer, zbd->lhSize);\n                if (ZSTDv07_isError(hSize)) return hSize;\n                if (hSize != 0) {\n                    size_t const toLoad = hSize - zbd->lhSize;   /* if hSize!=0, hSize > zbd->lhSize */\n                    if (toLoad > (size_t)(iend-ip)) {   /* not enough input to load full header */\n                        if (ip != NULL)\n                            memcpy(zbd->headerBuffer + zbd->lhSize, ip, iend-ip);\n                        zbd->lhSize += iend-ip;\n                        *dstCapacityPtr = 0;\n                        return (hSize - zbd->lhSize) + ZSTDv07_blockHeaderSize;   /* remaining header bytes + next block header */\n                    }\n                    memcpy(zbd->headerBuffer + zbd->lhSize, ip, toLoad); zbd->lhSize = hSize; ip += toLoad;\n                    break;\n            }   }\n\n            /* Consume header */\n            {   size_t const h1Size = ZSTDv07_nextSrcSizeToDecompress(zbd->zd);  /* == ZSTDv07_frameHeaderSize_min */\n                size_t const h1Result = ZSTDv07_decompressContinue(zbd->zd, NULL, 0, zbd->headerBuffer, h1Size);\n                if (ZSTDv07_isError(h1Result)) return h1Result;\n                if (h1Size < zbd->lhSize) {   /* long header */\n                    size_t const h2Size = ZSTDv07_nextSrcSizeToDecompress(zbd->zd);\n                    size_t const h2Result = ZSTDv07_decompressContinue(zbd->zd, NULL, 0, zbd->headerBuffer+h1Size, h2Size);\n                    if (ZSTDv07_isError(h2Result)) return h2Result;\n            }   }\n\n            zbd->fParams.windowSize = MAX(zbd->fParams.windowSize, 1U << ZSTDv07_WINDOWLOG_ABSOLUTEMIN);\n\n            /* Frame header instruct buffer sizes */\n            {   size_t const blockSize = MIN(zbd->fParams.windowSize, ZSTDv07_BLOCKSIZE_ABSOLUTEMAX);\n                zbd->blockSize = blockSize;\n                if (zbd->inBuffSize < blockSize) {\n                    zbd->customMem.customFree(zbd->customMem.opaque, zbd->inBuff);\n                    zbd->inBuffSize = blockSize;\n                    zbd->inBuff = (char*)zbd->customMem.customAlloc(zbd->customMem.opaque, blockSize);\n                    if (zbd->inBuff == NULL) return ERROR(memory_allocation);\n                }\n                {   size_t const neededOutSize = zbd->fParams.windowSize + blockSize + WILDCOPY_OVERLENGTH * 2;\n                    if (zbd->outBuffSize < neededOutSize) {\n                        zbd->customMem.customFree(zbd->customMem.opaque, zbd->outBuff);\n                        zbd->outBuffSize = neededOutSize;\n                        zbd->outBuff = (char*)zbd->customMem.customAlloc(zbd->customMem.opaque, neededOutSize);\n                        if (zbd->outBuff == NULL) return ERROR(memory_allocation);\n            }   }   }\n            zbd->stage = ZBUFFds_read;\n            /* pass-through */\n\t    /* fall-through */\n        case ZBUFFds_read:\n            {   size_t const neededInSize = ZSTDv07_nextSrcSizeToDecompress(zbd->zd);\n                if (neededInSize==0) {  /* end of frame */\n                    zbd->stage = ZBUFFds_init;\n                    notDone = 0;\n                    break;\n                }\n                if ((size_t)(iend-ip) >= neededInSize) {  /* decode directly from src */\n                    const int isSkipFrame = ZSTDv07_isSkipFrame(zbd->zd);\n                    size_t const decodedSize = ZSTDv07_decompressContinue(zbd->zd,\n                        zbd->outBuff + zbd->outStart, (isSkipFrame ? 0 : zbd->outBuffSize - zbd->outStart),\n                        ip, neededInSize);\n                    if (ZSTDv07_isError(decodedSize)) return decodedSize;\n                    ip += neededInSize;\n                    if (!decodedSize && !isSkipFrame) break;   /* this was just a header */\n                    zbd->outEnd = zbd->outStart +  decodedSize;\n                    zbd->stage = ZBUFFds_flush;\n                    break;\n                }\n                if (ip==iend) { notDone = 0; break; }   /* no more input */\n                zbd->stage = ZBUFFds_load;\n            }\n\t    /* fall-through */\n        case ZBUFFds_load:\n            {   size_t const neededInSize = ZSTDv07_nextSrcSizeToDecompress(zbd->zd);\n                size_t const toLoad = neededInSize - zbd->inPos;   /* should always be <= remaining space within inBuff */\n                size_t loadedSize;\n                if (toLoad > zbd->inBuffSize - zbd->inPos) return ERROR(corruption_detected);   /* should never happen */\n                loadedSize = ZBUFFv07_limitCopy(zbd->inBuff + zbd->inPos, toLoad, ip, iend-ip);\n                ip += loadedSize;\n                zbd->inPos += loadedSize;\n                if (loadedSize < toLoad) { notDone = 0; break; }   /* not enough input, wait for more */\n\n                /* decode loaded input */\n                {  const int isSkipFrame = ZSTDv07_isSkipFrame(zbd->zd);\n                   size_t const decodedSize = ZSTDv07_decompressContinue(zbd->zd,\n                        zbd->outBuff + zbd->outStart, zbd->outBuffSize - zbd->outStart,\n                        zbd->inBuff, neededInSize);\n                    if (ZSTDv07_isError(decodedSize)) return decodedSize;\n                    zbd->inPos = 0;   /* input is consumed */\n                    if (!decodedSize && !isSkipFrame) { zbd->stage = ZBUFFds_read; break; }   /* this was just a header */\n                    zbd->outEnd = zbd->outStart +  decodedSize;\n                    zbd->stage = ZBUFFds_flush;\n                    /* break; */\n                    /* pass-through */\n                }\n\t    }\n\t    /* fall-through */\n        case ZBUFFds_flush:\n            {   size_t const toFlushSize = zbd->outEnd - zbd->outStart;\n                size_t const flushedSize = ZBUFFv07_limitCopy(op, oend-op, zbd->outBuff + zbd->outStart, toFlushSize);\n                op += flushedSize;\n                zbd->outStart += flushedSize;\n                if (flushedSize == toFlushSize) {\n                    zbd->stage = ZBUFFds_read;\n                    if (zbd->outStart + zbd->blockSize > zbd->outBuffSize)\n                        zbd->outStart = zbd->outEnd = 0;\n                    break;\n                }\n                /* cannot flush everything */\n                notDone = 0;\n                break;\n            }\n        default: return ERROR(GENERIC);   /* impossible */\n    }   }\n\n    /* result */\n    *srcSizePtr = ip-istart;\n    *dstCapacityPtr = op-ostart;\n    {   size_t nextSrcSizeHint = ZSTDv07_nextSrcSizeToDecompress(zbd->zd);\n        nextSrcSizeHint -= zbd->inPos;   /* already loaded*/\n        return nextSrcSizeHint;\n    }\n}\n\n\n\n/* *************************************\n*  Tool functions\n***************************************/\nsize_t ZBUFFv07_recommendedDInSize(void)  { return ZSTDv07_BLOCKSIZE_ABSOLUTEMAX + ZSTDv07_blockHeaderSize /* block header size*/ ; }\nsize_t ZBUFFv07_recommendedDOutSize(void) { return ZSTDv07_BLOCKSIZE_ABSOLUTEMAX; }\n"
  },
  {
    "path": "lib/legacy/zstd_v07.h",
    "content": "/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTDv07_H_235446\n#define ZSTDv07_H_235446\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/*======  Dependency  ======*/\n#include <stddef.h>   /* size_t */\n\n\n/*======  Export for Windows  ======*/\n/*!\n*  ZSTDv07_DLL_EXPORT :\n*  Enable exporting of functions when building a Windows DLL\n*/\n#if defined(_WIN32) && defined(ZSTDv07_DLL_EXPORT) && (ZSTDv07_DLL_EXPORT==1)\n#  define ZSTDLIBv07_API __declspec(dllexport)\n#else\n#  define ZSTDLIBv07_API\n#endif\n\n\n/* *************************************\n*  Simple API\n***************************************/\n/*! ZSTDv07_getDecompressedSize() :\n*   @return : decompressed size if known, 0 otherwise.\n       note 1 : if `0`, follow up with ZSTDv07_getFrameParams() to know precise failure cause.\n       note 2 : decompressed size could be wrong or intentionally modified !\n                always ensure results fit within application's authorized limits */\nunsigned long long ZSTDv07_getDecompressedSize(const void* src, size_t srcSize);\n\n/*! ZSTDv07_decompress() :\n    `compressedSize` : must be _exact_ size of compressed input, otherwise decompression will fail.\n    `dstCapacity` must be equal or larger than originalSize.\n    @return : the number of bytes decompressed into `dst` (<= `dstCapacity`),\n              or an errorCode if it fails (which can be tested using ZSTDv07_isError()) */\nZSTDLIBv07_API size_t ZSTDv07_decompress( void* dst, size_t dstCapacity,\n                                    const void* src, size_t compressedSize);\n\n/**\nZSTDv07_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.7.x format\n    srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'\n    cSize (output parameter)  : the number of bytes that would be read to decompress this frame\n                                or an error code if it fails (which can be tested using ZSTDv01_isError())\n    dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame\n                                or ZSTD_CONTENTSIZE_ERROR if an error occurs\n\n    note : assumes `cSize` and `dBound` are _not_ NULL.\n*/\nvoid ZSTDv07_findFrameSizeInfoLegacy(const void *src, size_t srcSize,\n                                     size_t* cSize, unsigned long long* dBound);\n\n/*======  Helper functions  ======*/\nZSTDLIBv07_API unsigned    ZSTDv07_isError(size_t code);          /*!< tells if a `size_t` function result is an error code */\nZSTDLIBv07_API const char* ZSTDv07_getErrorName(size_t code);     /*!< provides readable string from an error code */\n\n\n/*-*************************************\n*  Explicit memory management\n***************************************/\n/** Decompression context */\ntypedef struct ZSTDv07_DCtx_s ZSTDv07_DCtx;\nZSTDLIBv07_API ZSTDv07_DCtx* ZSTDv07_createDCtx(void);\nZSTDLIBv07_API size_t     ZSTDv07_freeDCtx(ZSTDv07_DCtx* dctx);      /*!< @return : errorCode */\n\n/** ZSTDv07_decompressDCtx() :\n*   Same as ZSTDv07_decompress(), requires an allocated ZSTDv07_DCtx (see ZSTDv07_createDCtx()) */\nZSTDLIBv07_API size_t ZSTDv07_decompressDCtx(ZSTDv07_DCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n\n/*-************************\n*  Simple dictionary API\n***************************/\n/*! ZSTDv07_decompress_usingDict() :\n*   Decompression using a pre-defined Dictionary content (see dictBuilder).\n*   Dictionary must be identical to the one used during compression.\n*   Note : This function load the dictionary, resulting in a significant startup time */\nZSTDLIBv07_API size_t ZSTDv07_decompress_usingDict(ZSTDv07_DCtx* dctx,\n                                                   void* dst, size_t dstCapacity,\n                                             const void* src, size_t srcSize,\n                                             const void* dict,size_t dictSize);\n\n\n/*-**************************\n*  Advanced Dictionary API\n****************************/\n/*! ZSTDv07_createDDict() :\n*   Create a digested dictionary, ready to start decompression operation without startup delay.\n*   `dict` can be released after creation */\ntypedef struct ZSTDv07_DDict_s ZSTDv07_DDict;\nZSTDLIBv07_API ZSTDv07_DDict* ZSTDv07_createDDict(const void* dict, size_t dictSize);\nZSTDLIBv07_API size_t      ZSTDv07_freeDDict(ZSTDv07_DDict* ddict);\n\n/*! ZSTDv07_decompress_usingDDict() :\n*   Decompression using a pre-digested Dictionary\n*   Faster startup than ZSTDv07_decompress_usingDict(), recommended when same dictionary is used multiple times. */\nZSTDLIBv07_API size_t ZSTDv07_decompress_usingDDict(ZSTDv07_DCtx* dctx,\n                                                    void* dst, size_t dstCapacity,\n                                              const void* src, size_t srcSize,\n                                              const ZSTDv07_DDict* ddict);\n\ntypedef struct {\n    unsigned long long frameContentSize;\n    unsigned windowSize;\n    unsigned dictID;\n    unsigned checksumFlag;\n} ZSTDv07_frameParams;\n\nZSTDLIBv07_API size_t ZSTDv07_getFrameParams(ZSTDv07_frameParams* fparamsPtr, const void* src, size_t srcSize);   /**< doesn't consume input */\n\n\n\n\n/* *************************************\n*  Streaming functions\n***************************************/\ntypedef struct ZBUFFv07_DCtx_s ZBUFFv07_DCtx;\nZSTDLIBv07_API ZBUFFv07_DCtx* ZBUFFv07_createDCtx(void);\nZSTDLIBv07_API size_t      ZBUFFv07_freeDCtx(ZBUFFv07_DCtx* dctx);\n\nZSTDLIBv07_API size_t ZBUFFv07_decompressInit(ZBUFFv07_DCtx* dctx);\nZSTDLIBv07_API size_t ZBUFFv07_decompressInitDictionary(ZBUFFv07_DCtx* dctx, const void* dict, size_t dictSize);\n\nZSTDLIBv07_API size_t ZBUFFv07_decompressContinue(ZBUFFv07_DCtx* dctx,\n                                            void* dst, size_t* dstCapacityPtr,\n                                      const void* src, size_t* srcSizePtr);\n\n/*-***************************************************************************\n*  Streaming decompression howto\n*\n*  A ZBUFFv07_DCtx object is required to track streaming operations.\n*  Use ZBUFFv07_createDCtx() and ZBUFFv07_freeDCtx() to create/release resources.\n*  Use ZBUFFv07_decompressInit() to start a new decompression operation,\n*   or ZBUFFv07_decompressInitDictionary() if decompression requires a dictionary.\n*  Note that ZBUFFv07_DCtx objects can be re-init multiple times.\n*\n*  Use ZBUFFv07_decompressContinue() repetitively to consume your input.\n*  *srcSizePtr and *dstCapacityPtr can be any size.\n*  The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr.\n*  Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again.\n*  The content of `dst` will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters, or change `dst`.\n*  @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to help latency),\n*            or 0 when a frame is completely decoded,\n*            or an error code, which can be tested using ZBUFFv07_isError().\n*\n*  Hint : recommended buffer sizes (not compulsory) : ZBUFFv07_recommendedDInSize() and ZBUFFv07_recommendedDOutSize()\n*  output : ZBUFFv07_recommendedDOutSize== 128 KB block size is the internal unit, it ensures it's always possible to write a full block when decoded.\n*  input  : ZBUFFv07_recommendedDInSize == 128KB + 3;\n*           just follow indications from ZBUFFv07_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .\n* *******************************************************************************/\n\n\n/* *************************************\n*  Tool functions\n***************************************/\nZSTDLIBv07_API unsigned ZBUFFv07_isError(size_t errorCode);\nZSTDLIBv07_API const char* ZBUFFv07_getErrorName(size_t errorCode);\n\n/** Functions below provide recommended buffer sizes for Compression or Decompression operations.\n*   These sizes are just hints, they tend to offer better latency */\nZSTDLIBv07_API size_t ZBUFFv07_recommendedDInSize(void);\nZSTDLIBv07_API size_t ZBUFFv07_recommendedDOutSize(void);\n\n\n/*-*************************************\n*  Constants\n***************************************/\n#define ZSTDv07_MAGICNUMBER            0xFD2FB527   /* v0.7 */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* ZSTDv07_H_235446 */\n"
  },
  {
    "path": "lib/libzstd.mk",
    "content": "# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ################################################################\n\n# This included Makefile provides the following variables :\n# LIB_SRCDIR, LIB_BINDIR\n\n# Ensure the file is not included twice\n# Note : must be included after setting the default target\nifndef LIBZSTD_MK_INCLUDED\nLIBZSTD_MK_INCLUDED := 1\n\n##################################################################\n# Input Variables\n##################################################################\n\n# By default, library's directory is same as this included makefile\nLIB_SRCDIR ?= $(dir $(realpath $(lastword $(MAKEFILE_LIST))))\nLIB_BINDIR ?= $(LIB_SRCDIR)\n\n# ZSTD_LIB_MINIFY is a helper variable that\n# configures a bunch of other variables to space-optimized defaults.\nZSTD_LIB_MINIFY ?= 0\n\n# Legacy support disabled by default\nZSTD_LEGACY_SUPPORT ?= 0\nZSTD_LEGACY_MULTITHREADED_API ?= 0\n\n# Build size optimizations\nifneq ($(ZSTD_LIB_MINIFY), 0)\n  HUF_FORCE_DECOMPRESS_X1 ?= 1\n  HUF_FORCE_DECOMPRESS_X2 ?= 0\n  ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT ?= 1\n  ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG ?= 0\n  ZSTD_NO_INLINE ?= 1\n  ZSTD_STRIP_ERROR_STRINGS ?= 1\nelse\n  HUF_FORCE_DECOMPRESS_X1 ?= 0\n  HUF_FORCE_DECOMPRESS_X2 ?= 0\n  ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT ?= 0\n  ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG ?= 0\n  ZSTD_NO_INLINE ?= 0\n  ZSTD_STRIP_ERROR_STRINGS ?= 0\nendif\n\n# Assembly support\nZSTD_NO_ASM ?= 0\n\nZSTD_LIB_EXCLUDE_COMPRESSORS_DFAST_AND_UP ?= 0\nZSTD_LIB_EXCLUDE_COMPRESSORS_GREEDY_AND_UP ?= 0\n\n##################################################################\n# libzstd helpers\n##################################################################\n\nVOID ?= /dev/null\n\n# Make 4.3 doesn't support '\\#' anymore (https://lwn.net/Articles/810071/)\nNUM_SYMBOL := \\#\n\n# define silent mode as default (verbose mode with V=1 or VERBOSE=1)\n# Note : must be defined _after_ the default target\n$(V)$(VERBOSE).SILENT:\n\n# When cross-compiling from linux to windows,\n# one might need to specify TARGET_SYSTEM as \"Windows.\"\n# Building from Fedora fails without it.\n# (but Ubuntu and Debian don't need to set anything)\nTARGET_SYSTEM ?= $(OS)\n\n# Version numbers\nLIBVER_SRC := $(LIB_SRCDIR)/zstd.h\nLIBVER_MAJOR_SCRIPT:=`sed -n '/define ZSTD_VERSION_MAJOR/s/.*[[:blank:]]\\([0-9][0-9]*\\).*/\\1/p' < $(LIBVER_SRC)`\nLIBVER_MINOR_SCRIPT:=`sed -n '/define ZSTD_VERSION_MINOR/s/.*[[:blank:]]\\([0-9][0-9]*\\).*/\\1/p' < $(LIBVER_SRC)`\nLIBVER_PATCH_SCRIPT:=`sed -n '/define ZSTD_VERSION_RELEASE/s/.*[[:blank:]]\\([0-9][0-9]*\\).*/\\1/p' < $(LIBVER_SRC)`\nLIBVER_SCRIPT:= $(LIBVER_MAJOR_SCRIPT).$(LIBVER_MINOR_SCRIPT).$(LIBVER_PATCH_SCRIPT)\nLIBVER_MAJOR := $(shell echo $(LIBVER_MAJOR_SCRIPT))\nLIBVER_MINOR := $(shell echo $(LIBVER_MINOR_SCRIPT))\nLIBVER_PATCH := $(shell echo $(LIBVER_PATCH_SCRIPT))\nLIBVER := $(shell echo $(LIBVER_SCRIPT))\nCCVER := $(shell $(CC) --version)\nZSTD_VERSION?= $(LIBVER)\n\nifneq ($(ZSTD_LIB_MINIFY), 0)\n  HAVE_CC_OZ ?= $(shell echo \"\" | $(CC) -Oz -x c -c - -o /dev/null 2> /dev/null && echo 1 || echo 0)\nifneq ($(HAVE_CC_OZ), 0)\n    # Some compilers (clang) support an even more space-optimized setting.\n    CFLAGS += -Oz\nelse\n    CFLAGS += -Os\nendif\n  CFLAGS += -fno-stack-protector -fomit-frame-pointer -fno-ident \\\n            -DDYNAMIC_BMI2=0 -DNDEBUG\nelse\n  CFLAGS ?= -O3\nendif\n\nDEBUGLEVEL ?= 0\nCPPFLAGS += -DXXH_NAMESPACE=ZSTD_ -DDEBUGLEVEL=$(DEBUGLEVEL)\nifeq ($(TARGET_SYSTEM),Windows_NT)   # MinGW assumed\n  CPPFLAGS += -D__USE_MINGW_ANSI_STDIO   # compatibility with %zu formatting\nendif\nDEBUGFLAGS= -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \\\n            -Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \\\n            -Wstrict-prototypes -Wundef -Wpointer-arith \\\n            -Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \\\n            -Wredundant-decls -Wmissing-prototypes -Wc++-compat\nCFLAGS   += $(DEBUGFLAGS) $(MOREFLAGS)\nASFLAGS  += $(DEBUGFLAGS) $(MOREFLAGS) $(CFLAGS)\nLDFLAGS  += $(MOREFLAGS)\nFLAGS     = $(CPPFLAGS) $(CFLAGS) $(ASFLAGS) $(LDFLAGS)\n\nifndef ALREADY_APPENDED_NOEXECSTACK\nexport ALREADY_APPENDED_NOEXECSTACK := 1\nifeq ($(shell echo \"int main(int argc, char* argv[]) { (void)argc; (void)argv; return 0; }\" | $(CC) $(FLAGS) -z noexecstack -x c -Werror - -o $(VOID) 2>$(VOID) && echo 1 || echo 0),1)\nLDFLAGS += -z noexecstack\nendif\nifeq ($(shell echo | $(CC) $(FLAGS) -Wa,--noexecstack -x assembler -Werror -c - -o $(VOID) 2>$(VOID) && echo 1 || echo 0),1)\nCFLAGS  += -Wa,--noexecstack\n# CFLAGS are also added to ASFLAGS\nelse ifeq ($(shell echo | $(CC) $(FLAGS) -Qunused-arguments -Wa,--noexecstack -x assembler -Werror -c - -o $(VOID) 2>$(VOID) && echo 1 || echo 0),1)\n# See e.g.: https://github.com/android/ndk/issues/171\nCFLAGS  += -Qunused-arguments -Wa,--noexecstack\n# CFLAGS are also added to ASFLAGS\nendif\nendif\n\nifeq ($(shell echo \"int main(int argc, char* argv[]) { (void)argc; (void)argv; return 0; }\" | $(CC) $(FLAGS) -z cet-report=error -x c -Werror - -o $(VOID) 2>$(VOID) && echo 1 || echo 0),1)\nLDFLAGS += -z cet-report=error\nendif\n\nHAVE_COLORNEVER = $(shell echo a | grep --color=never a > /dev/null 2> /dev/null && echo 1 || echo 0)\nGREP_OPTIONS ?=\nifeq ($(HAVE_COLORNEVER), 1)\n  GREP_OPTIONS += --color=never\nendif\nGREP = grep $(GREP_OPTIONS)\n\nZSTD_COMMON_FILES := $(sort $(wildcard $(LIB_SRCDIR)/common/*.c))\nZSTD_COMPRESS_FILES := $(sort $(wildcard $(LIB_SRCDIR)/compress/*.c))\nZSTD_DECOMPRESS_FILES := $(sort $(wildcard $(LIB_SRCDIR)/decompress/*.c))\nZSTD_DICTBUILDER_FILES := $(sort $(wildcard $(LIB_SRCDIR)/dictBuilder/*.c))\nZSTD_DEPRECATED_FILES := $(sort $(wildcard $(LIB_SRCDIR)/deprecated/*.c))\nZSTD_LEGACY_FILES :=\n\nZSTD_DECOMPRESS_AMD64_ASM_FILES := $(sort $(wildcard $(LIB_SRCDIR)/decompress/*_amd64.S))\n\nifneq ($(ZSTD_NO_ASM), 0)\n  CPPFLAGS += -DZSTD_DISABLE_ASM\nelse\n  # Unconditionally add the ASM files they are disabled by\n  # macros in the .S file.\n  ZSTD_DECOMPRESS_FILES += $(ZSTD_DECOMPRESS_AMD64_ASM_FILES)\nendif\n\nifneq ($(HUF_FORCE_DECOMPRESS_X1), 0)\n  CFLAGS += -DHUF_FORCE_DECOMPRESS_X1\nendif\n\nifneq ($(HUF_FORCE_DECOMPRESS_X2), 0)\n  CFLAGS += -DHUF_FORCE_DECOMPRESS_X2\nendif\n\nifneq ($(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT), 0)\n  CFLAGS += -DZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT\nendif\n\nifneq ($(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG), 0)\n  CFLAGS += -DZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG\nendif\n\nifneq ($(ZSTD_NO_INLINE), 0)\n  CFLAGS += -DZSTD_NO_INLINE\nendif\n\nifneq ($(ZSTD_STRIP_ERROR_STRINGS), 0)\n  CFLAGS += -DZSTD_STRIP_ERROR_STRINGS\nendif\n\nifneq ($(ZSTD_LEGACY_MULTITHREADED_API), 0)\n  CFLAGS += -DZSTD_LEGACY_MULTITHREADED_API\nendif\n\nifneq ($(ZSTD_LIB_EXCLUDE_COMPRESSORS_DFAST_AND_UP), 0)\n  CFLAGS += -DZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR -DZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR -DZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR -DZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR -DZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR -DZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR\nelse\nifneq ($(ZSTD_LIB_EXCLUDE_COMPRESSORS_GREEDY_AND_UP), 0)\n  CFLAGS += -DZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR -DZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR -DZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR -DZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR -DZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR\nendif\nendif\n\nifneq ($(ZSTD_LEGACY_SUPPORT), 0)\nifeq ($(shell test $(ZSTD_LEGACY_SUPPORT) -lt 8; echo $$?), 0)\n  ZSTD_LEGACY_FILES += $(shell ls $(LIB_SRCDIR)/legacy/*.c | $(GREP) 'v0[$(ZSTD_LEGACY_SUPPORT)-7]')\nendif\nendif\nCPPFLAGS  += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT)\n\n# Include install_oses.mk from the same directory\ninclude $(dir $(lastword $(MAKEFILE_LIST)))/install_oses.mk\nLN ?= ln\nCP ?= cp -f\n\nifndef BUILD_DIR\nifeq ($(UNAME), Darwin)\n  ifeq ($(shell md5 < /dev/null > /dev/null; echo $$?), 0)\n    HASH ?= md5\n  endif\nelse ifeq ($(UNAME), NetBSD)\n  HASH ?= md5 -n\nelse ifeq ($(UNAME), OpenBSD)\n  HASH ?= md5\nendif\nHASH ?= md5sum\n\nHASH_DIR = conf_$(shell echo $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(ZSTD_FILES) | $(HASH) | cut -f 1 -d \" \" )\nHAVE_HASH :=$(shell echo 1 | $(HASH) > /dev/null && echo 1 || echo 0)\nifeq ($(HAVE_HASH),0)\n  $(info warning : could not find HASH ($(HASH)), needed to differentiate builds using different flags)\n  BUILD_DIR := obj/generic_noconf\nendif\nendif # BUILD_DIR\n\nZSTD_SUBDIR := $(LIB_SRCDIR)/common $(LIB_SRCDIR)/compress $(LIB_SRCDIR)/decompress $(LIB_SRCDIR)/dictBuilder $(LIB_SRCDIR)/legacy $(LIB_SRCDIR)/deprecated\nvpath %.c $(ZSTD_SUBDIR)\nvpath %.S $(ZSTD_SUBDIR)\n\nendif # LIBZSTD_MK_INCLUDED\n"
  },
  {
    "path": "lib/libzstd.pc.in",
    "content": "#   ZSTD - standard compression algorithm\n#   Copyright (c) Meta Platforms, Inc. and affiliates.\n#   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\nprefix=@PREFIX@\nexec_prefix=@EXEC_PREFIX@\nincludedir=@INCLUDEDIR@\nlibdir=@LIBDIR@\n\nName: zstd\nDescription: fast lossless compression algorithm library\nURL: https://facebook.github.io/zstd/\nVersion: @VERSION@\nLibs: -L${libdir} -lzstd @LIBS_MT@\nLibs.private: @LIBS_PRIVATE@\nCflags: -I${includedir} @LIBS_MT@\nLicense: BSD-3-Clause OR GPL-2.0-only\n"
  },
  {
    "path": "lib/module.modulemap",
    "content": "module libzstd [extern_c] {\n    header \"zstd.h\"\n    export *\n\n    module dictbuilder [extern_c] {\n        header \"zdict.h\"\n        export *\n    }\n\n    module errors [extern_c] {\n        header \"zstd_errors.h\"\n        export *\n    }\n}\n"
  },
  {
    "path": "lib/zdict.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_ZDICT_H\n#define ZSTD_ZDICT_H\n\n\n/*======  Dependencies  ======*/\n#include <stddef.h>  /* size_t */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* =====   ZDICTLIB_API : control library symbols visibility   ===== */\n#ifndef ZDICTLIB_VISIBLE\n   /* Backwards compatibility with old macro name */\n#  ifdef ZDICTLIB_VISIBILITY\n#    define ZDICTLIB_VISIBLE ZDICTLIB_VISIBILITY\n#  elif defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)\n#    define ZDICTLIB_VISIBLE __attribute__ ((visibility (\"default\")))\n#  else\n#    define ZDICTLIB_VISIBLE\n#  endif\n#endif\n\n#ifndef ZDICTLIB_HIDDEN\n#  if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)\n#    define ZDICTLIB_HIDDEN __attribute__ ((visibility (\"hidden\")))\n#  else\n#    define ZDICTLIB_HIDDEN\n#  endif\n#endif\n\n#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)\n#  define ZDICTLIB_API __declspec(dllexport) ZDICTLIB_VISIBLE\n#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)\n#  define ZDICTLIB_API __declspec(dllimport) ZDICTLIB_VISIBLE /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/\n#else\n#  define ZDICTLIB_API ZDICTLIB_VISIBLE\n#endif\n\n/*******************************************************************************\n * Zstd dictionary builder\n *\n * FAQ\n * ===\n * Why should I use a dictionary?\n * ------------------------------\n *\n * Zstd can use dictionaries to improve compression ratio of small data.\n * Traditionally small files don't compress well because there is very little\n * repetition in a single sample, since it is small. But, if you are compressing\n * many similar files, like a bunch of JSON records that share the same\n * structure, you can train a dictionary on ahead of time on some samples of\n * these files. Then, zstd can use the dictionary to find repetitions that are\n * present across samples. This can vastly improve compression ratio.\n *\n * When is a dictionary useful?\n * ----------------------------\n *\n * Dictionaries are useful when compressing many small files that are similar.\n * The larger a file is, the less benefit a dictionary will have. Generally,\n * we don't expect dictionary compression to be effective past 100KB. And the\n * smaller a file is, the more we would expect the dictionary to help.\n *\n * How do I use a dictionary?\n * --------------------------\n *\n * Simply pass the dictionary to the zstd compressor with\n * `ZSTD_CCtx_loadDictionary()`. The same dictionary must then be passed to\n * the decompressor, using `ZSTD_DCtx_loadDictionary()`. There are other\n * more advanced functions that allow selecting some options, see zstd.h for\n * complete documentation.\n *\n * What is a zstd dictionary?\n * --------------------------\n *\n * A zstd dictionary has two pieces: Its header, and its content. The header\n * contains a magic number, the dictionary ID, and entropy tables. These\n * entropy tables allow zstd to save on header costs in the compressed file,\n * which really matters for small data. The content is just bytes, which are\n * repeated content that is common across many samples.\n *\n * What is a raw content dictionary?\n * ---------------------------------\n *\n * A raw content dictionary is just bytes. It doesn't have a zstd dictionary\n * header, a dictionary ID, or entropy tables. Any buffer is a valid raw\n * content dictionary.\n *\n * How do I train a dictionary?\n * ----------------------------\n *\n * Gather samples from your use case. These samples should be similar to each\n * other. If you have several use cases, you could try to train one dictionary\n * per use case.\n *\n * Pass those samples to `ZDICT_trainFromBuffer()` and that will train your\n * dictionary. There are a few advanced versions of this function, but this\n * is a great starting point. If you want to further tune your dictionary\n * you could try `ZDICT_optimizeTrainFromBuffer_cover()`. If that is too slow\n * you can try `ZDICT_optimizeTrainFromBuffer_fastCover()`.\n *\n * If the dictionary training function fails, that is likely because you\n * either passed too few samples, or a dictionary would not be effective\n * for your data. Look at the messages that the dictionary trainer printed,\n * if it doesn't say too few samples, then a dictionary would not be effective.\n *\n * How large should my dictionary be?\n * ----------------------------------\n *\n * A reasonable dictionary size, the `dictBufferCapacity`, is about 100KB.\n * The zstd CLI defaults to a 110KB dictionary. You likely don't need a\n * dictionary larger than that. But, most use cases can get away with a\n * smaller dictionary. The advanced dictionary builders can automatically\n * shrink the dictionary for you, and select the smallest size that doesn't\n * hurt compression ratio too much. See the `shrinkDict` parameter.\n * A smaller dictionary can save memory, and potentially speed up\n * compression.\n *\n * How many samples should I provide to the dictionary builder?\n * ------------------------------------------------------------\n *\n * We generally recommend passing ~100x the size of the dictionary\n * in samples. A few thousand should suffice. Having too few samples\n * can hurt the dictionaries effectiveness. Having more samples will\n * only improve the dictionaries effectiveness. But having too many\n * samples can slow down the dictionary builder.\n *\n * How do I determine if a dictionary will be effective?\n * -----------------------------------------------------\n *\n * Simply train a dictionary and try it out. You can use zstd's built in\n * benchmarking tool to test the dictionary effectiveness.\n *\n *   # Benchmark levels 1-3 without a dictionary\n *   zstd -b1e3 -r /path/to/my/files\n *   # Benchmark levels 1-3 with a dictionary\n *   zstd -b1e3 -r /path/to/my/files -D /path/to/my/dictionary\n *\n * When should I retrain a dictionary?\n * -----------------------------------\n *\n * You should retrain a dictionary when its effectiveness drops. Dictionary\n * effectiveness drops as the data you are compressing changes. Generally, we do\n * expect dictionaries to \"decay\" over time, as your data changes, but the rate\n * at which they decay depends on your use case. Internally, we regularly\n * retrain dictionaries, and if the new dictionary performs significantly\n * better than the old dictionary, we will ship the new dictionary.\n *\n * I have a raw content dictionary, how do I turn it into a zstd dictionary?\n * -------------------------------------------------------------------------\n *\n * If you have a raw content dictionary, e.g. by manually constructing it, or\n * using a third-party dictionary builder, you can turn it into a zstd\n * dictionary by using `ZDICT_finalizeDictionary()`. You'll also have to\n * provide some samples of the data. It will add the zstd header to the\n * raw content, which contains a dictionary ID and entropy tables, which\n * will improve compression ratio, and allow zstd to write the dictionary ID\n * into the frame, if you so choose.\n *\n * Do I have to use zstd's dictionary builder?\n * -------------------------------------------\n *\n * No! You can construct dictionary content however you please, it is just\n * bytes. It will always be valid as a raw content dictionary. If you want\n * a zstd dictionary, which can improve compression ratio, use\n * `ZDICT_finalizeDictionary()`.\n *\n * What is the attack surface of a zstd dictionary?\n * ------------------------------------------------\n *\n * Zstd is heavily fuzz tested, including loading fuzzed dictionaries, so\n * zstd should never crash, or access out-of-bounds memory no matter what\n * the dictionary is. However, if an attacker can control the dictionary\n * during decompression, they can cause zstd to generate arbitrary bytes,\n * just like if they controlled the compressed data.\n *\n ******************************************************************************/\n\n\n/*! ZDICT_trainFromBuffer():\n *  Train a dictionary from an array of samples.\n *  Redirect towards ZDICT_optimizeTrainFromBuffer_fastCover() single-threaded, with d=8, steps=4,\n *  f=20, and accel=1.\n *  Samples must be stored concatenated in a single flat buffer `samplesBuffer`,\n *  supplied with an array of sizes `samplesSizes`, providing the size of each sample, in order.\n *  The resulting dictionary will be saved into `dictBuffer`.\n * @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)\n *          or an error code, which can be tested with ZDICT_isError().\n *  Note:  Dictionary training will fail if there are not enough samples to construct a\n *         dictionary, or if most of the samples are too small (< 8 bytes being the lower limit).\n *         If dictionary training fails, you should use zstd without a dictionary, as the dictionary\n *         would've been ineffective anyways. If you believe your samples would benefit from a dictionary\n *         please open an issue with details, and we can look into it.\n *  Note: ZDICT_trainFromBuffer()'s memory usage is about 6 MB.\n *  Tips: In general, a reasonable dictionary has a size of ~ 100 KB.\n *        It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`.\n *        In general, it's recommended to provide a few thousands samples, though this can vary a lot.\n *        It's recommended that total size of all samples be about ~x100 times the target size of dictionary.\n */\nZDICTLIB_API size_t ZDICT_trainFromBuffer(void* dictBuffer, size_t dictBufferCapacity,\n                                    const void* samplesBuffer,\n                                    const size_t* samplesSizes, unsigned nbSamples);\n\ntypedef struct {\n    int      compressionLevel;   /**< optimize for a specific zstd compression level; 0 means default */\n    unsigned notificationLevel;  /**< Write log to stderr; 0 = none (default); 1 = errors; 2 = progression; 3 = details; 4 = debug; */\n    unsigned dictID;             /**< force dictID value; 0 means auto mode (32-bits random value)\n                                  *   NOTE: The zstd format reserves some dictionary IDs for future use.\n                                  *         You may use them in private settings, but be warned that they\n                                  *         may be used by zstd in a public dictionary registry in the future.\n                                  *         These dictionary IDs are:\n                                  *           - low range  : <= 32767\n                                  *           - high range : >= (2^31)\n                                  */\n} ZDICT_params_t;\n\n/*! ZDICT_finalizeDictionary():\n * Given a custom content as a basis for dictionary, and a set of samples,\n * finalize dictionary by adding headers and statistics according to the zstd\n * dictionary format.\n *\n * Samples must be stored concatenated in a flat buffer `samplesBuffer`,\n * supplied with an array of sizes `samplesSizes`, providing the size of each\n * sample in order. The samples are used to construct the statistics, so they\n * should be representative of what you will compress with this dictionary.\n *\n * The compression level can be set in `parameters`. You should pass the\n * compression level you expect to use in production. The statistics for each\n * compression level differ, so tuning the dictionary for the compression level\n * can help quite a bit.\n *\n * You can set an explicit dictionary ID in `parameters`, or allow us to pick\n * a random dictionary ID for you, but we can't guarantee no collisions.\n *\n * The dstDictBuffer and the dictContent may overlap, and the content will be\n * appended to the end of the header. If the header + the content doesn't fit in\n * maxDictSize the beginning of the content is truncated to make room, since it\n * is presumed that the most profitable content is at the end of the dictionary,\n * since that is the cheapest to reference.\n *\n * `maxDictSize` must be >= max(dictContentSize, ZDICT_DICTSIZE_MIN).\n *\n * @return: size of dictionary stored into `dstDictBuffer` (<= `maxDictSize`),\n *          or an error code, which can be tested by ZDICT_isError().\n * Note: ZDICT_finalizeDictionary() will push notifications into stderr if\n *       instructed to, using notificationLevel>0.\n * NOTE: This function currently may fail in several edge cases including:\n *         * Not enough samples\n *         * Samples are uncompressible\n *         * Samples are all exactly the same\n */\nZDICTLIB_API size_t ZDICT_finalizeDictionary(void* dstDictBuffer, size_t maxDictSize,\n                                const void* dictContent, size_t dictContentSize,\n                                const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,\n                                ZDICT_params_t parameters);\n\n\n/*======   Helper functions   ======*/\nZDICTLIB_API unsigned ZDICT_getDictID(const void* dictBuffer, size_t dictSize);  /**< extracts dictID; @return zero if error (not a valid dictionary) */\nZDICTLIB_API size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize);  /* returns dict header size; returns a ZSTD error code on failure */\nZDICTLIB_API unsigned ZDICT_isError(size_t errorCode);\nZDICTLIB_API const char* ZDICT_getErrorName(size_t errorCode);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif   /* ZSTD_ZDICT_H */\n\n#if defined(ZDICT_STATIC_LINKING_ONLY) && !defined(ZSTD_ZDICT_H_STATIC)\n#define ZSTD_ZDICT_H_STATIC\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* This can be overridden externally to hide static symbols. */\n#ifndef ZDICTLIB_STATIC_API\n#  if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)\n#    define ZDICTLIB_STATIC_API __declspec(dllexport) ZDICTLIB_VISIBLE\n#  elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)\n#    define ZDICTLIB_STATIC_API __declspec(dllimport) ZDICTLIB_VISIBLE\n#  else\n#    define ZDICTLIB_STATIC_API ZDICTLIB_VISIBLE\n#  endif\n#endif\n\n/* ====================================================================================\n * The definitions in this section are considered experimental.\n * They should never be used with a dynamic library, as they may change in the future.\n * They are provided for advanced usages.\n * Use them only in association with static linking.\n * ==================================================================================== */\n\n#define ZDICT_DICTSIZE_MIN    256\n/* Deprecated: Remove in v1.6.0 */\n#define ZDICT_CONTENTSIZE_MIN 128\n\n/*! ZDICT_cover_params_t:\n *  k and d are the only required parameters.\n *  For others, value 0 means default.\n */\ntypedef struct {\n    unsigned k;                  /* Segment size : constraint: 0 < k : Reasonable range [16, 2048+] */\n    unsigned d;                  /* dmer size : constraint: 0 < d <= k : Reasonable range [6, 16] */\n    unsigned steps;              /* Number of steps : Only used for optimization : 0 means default (40) : Higher means more parameters checked */\n    unsigned nbThreads;          /* Number of threads : constraint: 0 < nbThreads : 1 means single-threaded : Only used for optimization : Ignored if ZSTD_MULTITHREAD is not defined */\n    double splitPoint;           /* Percentage of samples used for training: Only used for optimization : the first nbSamples * splitPoint samples will be used to training, the last nbSamples * (1 - splitPoint) samples will be used for testing, 0 means default (1.0), 1.0 when all samples are used for both training and testing */\n    unsigned shrinkDict;         /* Train dictionaries to shrink in size starting from the minimum size and selects the smallest dictionary that is shrinkDictMaxRegression% worse than the largest dictionary. 0 means no shrinking and 1 means shrinking  */\n    unsigned shrinkDictMaxRegression; /* Sets shrinkDictMaxRegression so that a smaller dictionary can be at worse shrinkDictMaxRegression% worse than the max dict size dictionary. */\n    ZDICT_params_t zParams;\n} ZDICT_cover_params_t;\n\ntypedef struct {\n    unsigned k;                  /* Segment size : constraint: 0 < k : Reasonable range [16, 2048+] */\n    unsigned d;                  /* dmer size : constraint: 0 < d <= k : Reasonable range [6, 16] */\n    unsigned f;                  /* log of size of frequency array : constraint: 0 < f <= 31 : 1 means default(20)*/\n    unsigned steps;              /* Number of steps : Only used for optimization : 0 means default (40) : Higher means more parameters checked */\n    unsigned nbThreads;          /* Number of threads : constraint: 0 < nbThreads : 1 means single-threaded : Only used for optimization : Ignored if ZSTD_MULTITHREAD is not defined */\n    double splitPoint;           /* Percentage of samples used for training: Only used for optimization : the first nbSamples * splitPoint samples will be used to training, the last nbSamples * (1 - splitPoint) samples will be used for testing, 0 means default (0.75), 1.0 when all samples are used for both training and testing */\n    unsigned accel;              /* Acceleration level: constraint: 0 < accel <= 10, higher means faster and less accurate, 0 means default(1) */\n    unsigned shrinkDict;         /* Train dictionaries to shrink in size starting from the minimum size and selects the smallest dictionary that is shrinkDictMaxRegression% worse than the largest dictionary. 0 means no shrinking and 1 means shrinking  */\n    unsigned shrinkDictMaxRegression; /* Sets shrinkDictMaxRegression so that a smaller dictionary can be at worse shrinkDictMaxRegression% worse than the max dict size dictionary. */\n\n    ZDICT_params_t zParams;\n} ZDICT_fastCover_params_t;\n\n/*! ZDICT_trainFromBuffer_cover():\n *  Train a dictionary from an array of samples using the COVER algorithm.\n *  Samples must be stored concatenated in a single flat buffer `samplesBuffer`,\n *  supplied with an array of sizes `samplesSizes`, providing the size of each sample, in order.\n *  The resulting dictionary will be saved into `dictBuffer`.\n * @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)\n *          or an error code, which can be tested with ZDICT_isError().\n *          See ZDICT_trainFromBuffer() for details on failure modes.\n *  Note: ZDICT_trainFromBuffer_cover() requires about 9 bytes of memory for each input byte.\n *  Tips: In general, a reasonable dictionary has a size of ~ 100 KB.\n *        It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`.\n *        In general, it's recommended to provide a few thousands samples, though this can vary a lot.\n *        It's recommended that total size of all samples be about ~x100 times the target size of dictionary.\n */\nZDICTLIB_STATIC_API size_t ZDICT_trainFromBuffer_cover(\n          void *dictBuffer, size_t dictBufferCapacity,\n    const void *samplesBuffer, const size_t *samplesSizes, unsigned nbSamples,\n          ZDICT_cover_params_t parameters);\n\n/*! ZDICT_optimizeTrainFromBuffer_cover():\n * The same requirements as above hold for all the parameters except `parameters`.\n * This function tries many parameter combinations and picks the best parameters.\n * `*parameters` is filled with the best parameters found,\n * dictionary constructed with those parameters is stored in `dictBuffer`.\n *\n * All of the parameters d, k, steps are optional.\n * If d is non-zero then we don't check multiple values of d, otherwise we check d = {6, 8}.\n * if steps is zero it defaults to its default value.\n * If k is non-zero then we don't check multiple values of k, otherwise we check steps values in [50, 2000].\n *\n * @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)\n *          or an error code, which can be tested with ZDICT_isError().\n *          On success `*parameters` contains the parameters selected.\n *          See ZDICT_trainFromBuffer() for details on failure modes.\n * Note: ZDICT_optimizeTrainFromBuffer_cover() requires about 8 bytes of memory for each input byte and additionally another 5 bytes of memory for each byte of memory for each thread.\n */\nZDICTLIB_STATIC_API size_t ZDICT_optimizeTrainFromBuffer_cover(\n          void* dictBuffer, size_t dictBufferCapacity,\n    const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,\n          ZDICT_cover_params_t* parameters);\n\n/*! ZDICT_trainFromBuffer_fastCover():\n *  Train a dictionary from an array of samples using a modified version of COVER algorithm.\n *  Samples must be stored concatenated in a single flat buffer `samplesBuffer`,\n *  supplied with an array of sizes `samplesSizes`, providing the size of each sample, in order.\n *  d and k are required.\n *  All other parameters are optional, will use default values if not provided\n *  The resulting dictionary will be saved into `dictBuffer`.\n * @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)\n *          or an error code, which can be tested with ZDICT_isError().\n *          See ZDICT_trainFromBuffer() for details on failure modes.\n *  Note: ZDICT_trainFromBuffer_fastCover() requires 6 * 2^f bytes of memory.\n *  Tips: In general, a reasonable dictionary has a size of ~ 100 KB.\n *        It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`.\n *        In general, it's recommended to provide a few thousands samples, though this can vary a lot.\n *        It's recommended that total size of all samples be about ~x100 times the target size of dictionary.\n */\nZDICTLIB_STATIC_API size_t ZDICT_trainFromBuffer_fastCover(void *dictBuffer,\n                    size_t dictBufferCapacity, const void *samplesBuffer,\n                    const size_t *samplesSizes, unsigned nbSamples,\n                    ZDICT_fastCover_params_t parameters);\n\n/*! ZDICT_optimizeTrainFromBuffer_fastCover():\n * The same requirements as above hold for all the parameters except `parameters`.\n * This function tries many parameter combinations (specifically, k and d combinations)\n * and picks the best parameters. `*parameters` is filled with the best parameters found,\n * dictionary constructed with those parameters is stored in `dictBuffer`.\n * All of the parameters d, k, steps, f, and accel are optional.\n * If d is non-zero then we don't check multiple values of d, otherwise we check d = {6, 8}.\n * if steps is zero it defaults to its default value.\n * If k is non-zero then we don't check multiple values of k, otherwise we check steps values in [50, 2000].\n * If f is zero, default value of 20 is used.\n * If accel is zero, default value of 1 is used.\n *\n * @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)\n *          or an error code, which can be tested with ZDICT_isError().\n *          On success `*parameters` contains the parameters selected.\n *          See ZDICT_trainFromBuffer() for details on failure modes.\n * Note: ZDICT_optimizeTrainFromBuffer_fastCover() requires about 6 * 2^f bytes of memory for each thread.\n */\nZDICTLIB_STATIC_API size_t ZDICT_optimizeTrainFromBuffer_fastCover(void* dictBuffer,\n                    size_t dictBufferCapacity, const void* samplesBuffer,\n                    const size_t* samplesSizes, unsigned nbSamples,\n                    ZDICT_fastCover_params_t* parameters);\n\ntypedef struct {\n    unsigned selectivityLevel;   /* 0 means default; larger => select more => larger dictionary */\n    ZDICT_params_t zParams;\n} ZDICT_legacy_params_t;\n\n/*! ZDICT_trainFromBuffer_legacy():\n *  Train a dictionary from an array of samples.\n *  Samples must be stored concatenated in a single flat buffer `samplesBuffer`,\n *  supplied with an array of sizes `samplesSizes`, providing the size of each sample, in order.\n *  The resulting dictionary will be saved into `dictBuffer`.\n * `parameters` is optional and can be provided with values set to 0 to mean \"default\".\n * @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)\n *          or an error code, which can be tested with ZDICT_isError().\n *          See ZDICT_trainFromBuffer() for details on failure modes.\n *  Tips: In general, a reasonable dictionary has a size of ~ 100 KB.\n *        It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`.\n *        In general, it's recommended to provide a few thousands samples, though this can vary a lot.\n *        It's recommended that total size of all samples be about ~x100 times the target size of dictionary.\n *  Note: ZDICT_trainFromBuffer_legacy() will send notifications into stderr if instructed to, using notificationLevel>0.\n */\nZDICTLIB_STATIC_API size_t ZDICT_trainFromBuffer_legacy(\n    void* dictBuffer, size_t dictBufferCapacity,\n    const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,\n    ZDICT_legacy_params_t parameters);\n\n\n/* Deprecation warnings */\n/* It is generally possible to disable deprecation warnings from compiler,\n   for example with -Wno-deprecated-declarations for gcc\n   or _CRT_SECURE_NO_WARNINGS in Visual.\n   Otherwise, it's also possible to manually define ZDICT_DISABLE_DEPRECATE_WARNINGS */\n#ifdef ZDICT_DISABLE_DEPRECATE_WARNINGS\n#  define ZDICT_DEPRECATED(message) /* disable deprecation warnings */\n#else\n#  define ZDICT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)\n#  if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */\n#    define ZDICT_DEPRECATED(message) [[deprecated(message)]]\n#  elif defined(__clang__) || (ZDICT_GCC_VERSION >= 405)\n#    define ZDICT_DEPRECATED(message) __attribute__((deprecated(message)))\n#  elif (ZDICT_GCC_VERSION >= 301)\n#    define ZDICT_DEPRECATED(message) __attribute__((deprecated))\n#  elif defined(_MSC_VER)\n#    define ZDICT_DEPRECATED(message) __declspec(deprecated(message))\n#  else\n#    pragma message(\"WARNING: You need to implement ZDICT_DEPRECATED for this compiler\")\n#    define ZDICT_DEPRECATED(message)\n#  endif\n#endif /* ZDICT_DISABLE_DEPRECATE_WARNINGS */\n\nZDICT_DEPRECATED(\"use ZDICT_finalizeDictionary() instead\")\nZDICTLIB_STATIC_API\nsize_t ZDICT_addEntropyTablesFromBuffer(void* dictBuffer, size_t dictContentSize, size_t dictBufferCapacity,\n                                  const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif   /* ZSTD_ZDICT_H_STATIC */\n"
  },
  {
    "path": "lib/zstd.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_H_235446\n#define ZSTD_H_235446\n\n\n/* ======   Dependencies   ======*/\n#include <stddef.h>   /* size_t */\n\n#include \"zstd_errors.h\" /* list of errors */\n#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY)\n#include <limits.h>   /* INT_MAX */\n#endif /* ZSTD_STATIC_LINKING_ONLY */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* =====   ZSTDLIB_API : control library symbols visibility   ===== */\n#ifndef ZSTDLIB_VISIBLE\n   /* Backwards compatibility with old macro name */\n#  ifdef ZSTDLIB_VISIBILITY\n#    define ZSTDLIB_VISIBLE ZSTDLIB_VISIBILITY\n#  elif defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)\n#    define ZSTDLIB_VISIBLE __attribute__ ((visibility (\"default\")))\n#  else\n#    define ZSTDLIB_VISIBLE\n#  endif\n#endif\n\n#ifndef ZSTDLIB_HIDDEN\n#  if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)\n#    define ZSTDLIB_HIDDEN __attribute__ ((visibility (\"hidden\")))\n#  else\n#    define ZSTDLIB_HIDDEN\n#  endif\n#endif\n\n#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)\n#  define ZSTDLIB_API __declspec(dllexport) ZSTDLIB_VISIBLE\n#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)\n#  define ZSTDLIB_API __declspec(dllimport) ZSTDLIB_VISIBLE /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/\n#else\n#  define ZSTDLIB_API ZSTDLIB_VISIBLE\n#endif\n\n/* Deprecation warnings :\n * Should these warnings be a problem, it is generally possible to disable them,\n * typically with -Wno-deprecated-declarations for gcc or _CRT_SECURE_NO_WARNINGS in Visual.\n * Otherwise, it's also possible to define ZSTD_DISABLE_DEPRECATE_WARNINGS.\n */\n#ifdef ZSTD_DISABLE_DEPRECATE_WARNINGS\n#  define ZSTD_DEPRECATED(message) /* disable deprecation warnings */\n#else\n#  if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */\n#    define ZSTD_DEPRECATED(message) [[deprecated(message)]]\n#  elif (defined(GNUC) && (GNUC > 4 || (GNUC == 4 && GNUC_MINOR >= 5))) || defined(__clang__) || defined(__IAR_SYSTEMS_ICC__)\n#    define ZSTD_DEPRECATED(message) __attribute__((deprecated(message)))\n#  elif defined(__GNUC__) && (__GNUC__ >= 3)\n#    define ZSTD_DEPRECATED(message) __attribute__((deprecated))\n#  elif defined(_MSC_VER)\n#    define ZSTD_DEPRECATED(message) __declspec(deprecated(message))\n#  else\n#    pragma message(\"WARNING: You need to implement ZSTD_DEPRECATED for this compiler\")\n#    define ZSTD_DEPRECATED(message)\n#  endif\n#endif /* ZSTD_DISABLE_DEPRECATE_WARNINGS */\n\n\n/*******************************************************************************\n  Introduction\n\n  zstd, short for Zstandard, is a fast lossless compression algorithm, targeting\n  real-time compression scenarios at zlib-level and better compression ratios.\n  The zstd compression library provides in-memory compression and decompression\n  functions.\n\n  The library supports regular compression levels from 1 up to ZSTD_maxCLevel(),\n  which is currently 22. Levels >= 20, labeled `--ultra`, should be used with\n  caution, as they require more memory. The library also offers negative\n  compression levels, which extend the range of speed vs. ratio preferences.\n  The lower the level, the faster the speed (at the cost of compression).\n\n  Compression can be done in:\n    - a single step (described as Simple API)\n    - a single step, reusing a context (described as Explicit context)\n    - unbounded multiple steps (described as Streaming compression)\n\n  The compression ratio achievable on small data can be highly improved using\n  a dictionary. Dictionary compression can be performed in:\n    - a single step (described as Simple dictionary API)\n    - a single step, reusing a dictionary (described as Bulk-processing\n      dictionary API)\n\n  Advanced experimental functions can be accessed using\n  `#define ZSTD_STATIC_LINKING_ONLY` before including zstd.h.\n\n  Advanced experimental APIs should never be used with a dynamically-linked\n  library. They are not \"stable\"; their definitions or signatures may change in\n  the future. Only static linking is allowed.\n*******************************************************************************/\n\n/*------   Version   ------*/\n#define ZSTD_VERSION_MAJOR    1\n#define ZSTD_VERSION_MINOR    6\n#define ZSTD_VERSION_RELEASE  0\n#define ZSTD_VERSION_NUMBER  (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)\n\n/*! ZSTD_versionNumber() :\n *  Return runtime library version, the value is (MAJOR*100*100 + MINOR*100 + RELEASE). */\nZSTDLIB_API unsigned ZSTD_versionNumber(void);\n\n#define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE\n#define ZSTD_QUOTE(str) #str\n#define ZSTD_EXPAND_AND_QUOTE(str) ZSTD_QUOTE(str)\n#define ZSTD_VERSION_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_LIB_VERSION)\n\n/*! ZSTD_versionString() :\n *  Return runtime library version, like \"1.4.5\". Requires v1.3.0+. */\nZSTDLIB_API const char* ZSTD_versionString(void);\n\n/* *************************************\n *  Default constant\n ***************************************/\n#ifndef ZSTD_CLEVEL_DEFAULT\n#  define ZSTD_CLEVEL_DEFAULT 3\n#endif\n\n/* *************************************\n *  Constants\n ***************************************/\n\n/* All magic numbers are supposed read/written to/from files/memory using little-endian convention */\n#define ZSTD_MAGICNUMBER            0xFD2FB528    /* valid since v0.8.0 */\n#define ZSTD_MAGIC_DICTIONARY       0xEC30A437    /* valid since v0.7.0 */\n#define ZSTD_MAGIC_SKIPPABLE_START  0x184D2A50    /* all 16 values, from 0x184D2A50 to 0x184D2A5F, signal the beginning of a skippable frame */\n#define ZSTD_MAGIC_SKIPPABLE_MASK   0xFFFFFFF0\n\n#define ZSTD_BLOCKSIZELOG_MAX  17\n#define ZSTD_BLOCKSIZE_MAX     (1<<ZSTD_BLOCKSIZELOG_MAX)\n\n\n/***************************************\n*  Simple Core API\n***************************************/\n/*! ZSTD_compress() :\n *  Compresses `src` content as a single zstd compressed frame into already allocated `dst`.\n *  NOTE: Providing `dstCapacity >= ZSTD_compressBound(srcSize)` guarantees that zstd will have\n *        enough space to successfully compress the data.\n *  @return : compressed size written into `dst` (<= `dstCapacity),\n *            or an error code if it fails (which can be tested using ZSTD_isError()). */\nZSTDLIB_API size_t ZSTD_compress( void* dst, size_t dstCapacity,\n                            const void* src, size_t srcSize,\n                                  int compressionLevel);\n\n/*! ZSTD_decompress() :\n * `compressedSize` : must be the _exact_ size of some number of compressed and/or skippable frames.\n *  Multiple compressed frames can be decompressed at once with this method.\n *  The result will be the concatenation of all decompressed frames, back to back.\n * `dstCapacity` is an upper bound of originalSize to regenerate.\n *  First frame's decompressed size can be extracted using ZSTD_getFrameContentSize().\n *  If maximum upper bound isn't known, prefer using streaming mode to decompress data.\n * @return : the number of bytes decompressed into `dst` (<= `dstCapacity`),\n *           or an errorCode if it fails (which can be tested using ZSTD_isError()). */\nZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity,\n                              const void* src, size_t compressedSize);\n\n\n/*======  Decompression helper functions  ======*/\n\n/*! @brief Returns the decompressed content size stored in a ZSTD frame header.\n *\n *  @since v1.3.0\n *\n *  @param src Pointer to the beginning of a ZSTD encoded frame.\n *  @param srcSize Size of the buffer pointed to by @p src. It must be at least as large as the frame header.\n *                 Any value greater than or equal to `ZSTD_frameHeaderSize_max` is sufficient.\n *  @return The decompressed size in bytes when the value is available in the frame header.\n *  @retval ZSTD_CONTENTSIZE_UNKNOWN The frame does not encode a decompressed size (typical for streaming).\n *  @retval ZSTD_CONTENTSIZE_ERROR An error occurred (e.g. invalid magic number, @p srcSize too small).\n *\n *  @note The return value is not compatible with `ZSTD_isError()`.\n *  @note A return value of 0 denotes a valid but empty frame. Skippable frames also report 0.\n *  @note The decompressed size field is optional. When it is absent (the function returns @c ZSTD_CONTENTSIZE_UNKNOWN),\n *        the caller must rely on streaming decompression or an application-specific upper bound. `ZSTD_decompress()`\n *        only requires an upper bound, so applications may enforce their own block limits (for example 16 KB).\n *  @note The decompressed size is guaranteed to be present when compression was performed with single-pass APIs such as\n *        `ZSTD_compress()`, `ZSTD_compressCCtx()`, `ZSTD_compress_usingDict()`, or `ZSTD_compress_usingCDict()`.\n *  @note The decompressed size is a 64-bit value and may exceed the addressable space of the system. Use streaming\n *        decompression when the value is too large to materialize in contiguous memory.\n *  @warning When processing untrusted input, validate the returned size against the application's limits; attackers may\n *           forge an arbitrarily large value.\n *  @note This function replaces `ZSTD_getDecompressedSize()`.\n */\n#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1)\n#define ZSTD_CONTENTSIZE_ERROR   (0ULL - 2)\nZSTDLIB_API unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize);\n\n/*! ZSTD_getDecompressedSize() (obsolete):\n *  This function is now obsolete, in favor of ZSTD_getFrameContentSize().\n *  Both functions work the same way, but ZSTD_getDecompressedSize() blends\n *  \"empty\", \"unknown\" and \"error\" results to the same return value (0),\n *  while ZSTD_getFrameContentSize() gives them separate return values.\n * @return : decompressed size of `src` frame content _if known and not empty_, 0 otherwise. */\nZSTD_DEPRECATED(\"Replaced by ZSTD_getFrameContentSize\")\nZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize);\n\n/*! ZSTD_findFrameCompressedSize() : Requires v1.4.0+\n * `src` should point to the start of a ZSTD frame or skippable frame.\n * `srcSize` must be >= first frame size\n * @return : the compressed size of the first frame starting at `src`,\n *           suitable to pass as `srcSize` to `ZSTD_decompress` or similar,\n *           or an error code if input is invalid\n *  Note 1: this method is called _find*() because it's not enough to read the header,\n *          it may have to scan through the frame's content, to reach its end.\n *  Note 2: this method also works with Skippable Frames. In which case,\n *          it returns the size of the complete skippable frame,\n *          which is always equal to its content size + 8 bytes for headers. */\nZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize);\n\n\n/*======  Compression helper functions  ======*/\n\n/*! ZSTD_compressBound() :\n * maximum compressed size in worst case single-pass scenario.\n * When invoking `ZSTD_compress()`, or any other one-pass compression function,\n * it's recommended to provide @dstCapacity >= ZSTD_compressBound(srcSize)\n * as it eliminates one potential failure scenario,\n * aka not enough room in dst buffer to write the compressed frame.\n * Note : ZSTD_compressBound() itself can fail, if @srcSize >= ZSTD_MAX_INPUT_SIZE .\n *        In which case, ZSTD_compressBound() will return an error code\n *        which can be tested using ZSTD_isError().\n *\n * ZSTD_COMPRESSBOUND() :\n * same as ZSTD_compressBound(), but as a macro.\n * It can be used to produce constants, which can be useful for static allocation,\n * for example to size a static array on stack.\n * Will produce constant value 0 if srcSize is too large.\n */\n#define ZSTD_MAX_INPUT_SIZE ((sizeof(size_t)==8) ? 0xFF00FF00FF00FF00ULL : 0xFF00FF00U)\n#define ZSTD_COMPRESSBOUND(srcSize)   (((size_t)(srcSize) >= ZSTD_MAX_INPUT_SIZE) ? 0 : (srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) /* margin, from 64 to 0 */ : 0))  /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */\nZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */\n\n\n/*======  Error helper functions  ======*/\n/* ZSTD_isError() :\n * Most ZSTD_* functions returning a size_t value can be tested for error,\n * using ZSTD_isError().\n * @return 1 if error, 0 otherwise\n */\nZSTDLIB_API unsigned     ZSTD_isError(size_t result);      /*!< tells if a `size_t` function result is an error code */\nZSTDLIB_API ZSTD_ErrorCode ZSTD_getErrorCode(size_t functionResult); /* convert a result into an error code, which can be compared to error enum list */\nZSTDLIB_API const char*  ZSTD_getErrorName(size_t result); /*!< provides readable string from a function result */\nZSTDLIB_API int          ZSTD_minCLevel(void);             /*!< minimum negative compression level allowed, requires v1.4.0+ */\nZSTDLIB_API int          ZSTD_maxCLevel(void);             /*!< maximum compression level available */\nZSTDLIB_API int          ZSTD_defaultCLevel(void);         /*!< default compression level, specified by ZSTD_CLEVEL_DEFAULT, requires v1.5.0+ */\n\n\n/***************************************\n*  Explicit context\n***************************************/\n/*= Compression context\n *  When compressing many times,\n *  it is recommended to allocate a compression context just once,\n *  and reuse it for each successive compression operation.\n *  This will make the workload easier for system's memory.\n *  Note : re-using context is just a speed / resource optimization.\n *         It doesn't change the compression ratio, which remains identical.\n *  Note 2: For parallel execution in multi-threaded environments,\n *         use one different context per thread .\n */\ntypedef struct ZSTD_CCtx_s ZSTD_CCtx;\nZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx(void);\nZSTDLIB_API size_t     ZSTD_freeCCtx(ZSTD_CCtx* cctx);  /* compatible with NULL pointer */\n\n/*! ZSTD_compressCCtx() :\n *  Same as ZSTD_compress(), using an explicit ZSTD_CCtx.\n *  Important : in order to mirror `ZSTD_compress()` behavior,\n *  this function compresses at the requested compression level,\n *  __ignoring any other advanced parameter__ .\n *  If any advanced parameter was set using the advanced API,\n *  they will all be reset. Only @compressionLevel remains.\n */\nZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx,\n                                     void* dst, size_t dstCapacity,\n                               const void* src, size_t srcSize,\n                                     int compressionLevel);\n\n/*= Decompression context\n *  When decompressing many times,\n *  it is recommended to allocate a context only once,\n *  and reuse it for each successive compression operation.\n *  This will make workload friendlier for system's memory.\n *  Use one context per thread for parallel execution. */\ntypedef struct ZSTD_DCtx_s ZSTD_DCtx;\nZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx(void);\nZSTDLIB_API size_t     ZSTD_freeDCtx(ZSTD_DCtx* dctx);  /* accept NULL pointer */\n\n/*! ZSTD_decompressDCtx() :\n *  Same as ZSTD_decompress(),\n *  requires an allocated ZSTD_DCtx.\n *  Compatible with sticky parameters (see below).\n */\nZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx,\n                                       void* dst, size_t dstCapacity,\n                                 const void* src, size_t srcSize);\n\n\n/*********************************************\n*  Advanced compression API (Requires v1.4.0+)\n**********************************************/\n\n/* API design :\n *   Parameters are pushed one by one into an existing context,\n *   using ZSTD_CCtx_set*() functions.\n *   Pushed parameters are sticky : they are valid for next compressed frame, and any subsequent frame.\n *   \"sticky\" parameters are applicable to `ZSTD_compress2()` and `ZSTD_compressStream*()` !\n *   __They do not apply to one-shot variants such as ZSTD_compressCCtx()__ .\n *\n *   It's possible to reset all parameters to \"default\" using ZSTD_CCtx_reset().\n *\n *   This API supersedes all other \"advanced\" API entry points in the experimental section.\n *   In the future, we expect to remove API entry points from experimental which are redundant with this API.\n */\n\n\n/* Compression strategies, listed from fastest to strongest */\ntypedef enum { ZSTD_fast=1,\n               ZSTD_dfast=2,\n               ZSTD_greedy=3,\n               ZSTD_lazy=4,\n               ZSTD_lazy2=5,\n               ZSTD_btlazy2=6,\n               ZSTD_btopt=7,\n               ZSTD_btultra=8,\n               ZSTD_btultra2=9\n               /* note : new strategies _might_ be added in the future.\n                         Only the order (from fast to strong) is guaranteed */\n} ZSTD_strategy;\n\ntypedef enum {\n\n    /* compression parameters\n     * Note: When compressing with a ZSTD_CDict these parameters are superseded\n     * by the parameters used to construct the ZSTD_CDict.\n     * See ZSTD_CCtx_refCDict() for more info (superseded-by-cdict). */\n    ZSTD_c_compressionLevel=100, /* Set compression parameters according to pre-defined cLevel table.\n                              * Note that exact compression parameters are dynamically determined,\n                              * depending on both compression level and srcSize (when known).\n                              * Default level is ZSTD_CLEVEL_DEFAULT==3.\n                              * Special: value 0 means default, which is controlled by ZSTD_CLEVEL_DEFAULT.\n                              * Note 1 : it's possible to pass a negative compression level.\n                              * Note 2 : setting a level does not automatically set all other compression parameters\n                              *   to default. Setting this will however eventually dynamically impact the compression\n                              *   parameters which have not been manually set. The manually set\n                              *   ones will 'stick'. */\n    /* Advanced compression parameters :\n     * It's possible to pin down compression parameters to some specific values.\n     * In which case, these values are no longer dynamically selected by the compressor */\n    ZSTD_c_windowLog=101,    /* Maximum allowed back-reference distance, expressed as power of 2.\n                              * This will set a memory budget for streaming decompression,\n                              * with larger values requiring more memory\n                              * and typically compressing more.\n                              * Must be clamped between ZSTD_WINDOWLOG_MIN and ZSTD_WINDOWLOG_MAX.\n                              * Special: value 0 means \"use default windowLog\".\n                              * Note: Using a windowLog greater than ZSTD_WINDOWLOG_LIMIT_DEFAULT\n                              *       requires explicitly allowing such size at streaming decompression stage. */\n    ZSTD_c_hashLog=102,      /* Size of the initial probe table, as a power of 2.\n                              * Resulting memory usage is (1 << (hashLog+2)).\n                              * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX.\n                              * Larger tables improve compression ratio of strategies <= dFast,\n                              * and improve speed of strategies > dFast.\n                              * Special: value 0 means \"use default hashLog\". */\n    ZSTD_c_chainLog=103,     /* Size of the multi-probe search table, as a power of 2.\n                              * Resulting memory usage is (1 << (chainLog+2)).\n                              * Must be clamped between ZSTD_CHAINLOG_MIN and ZSTD_CHAINLOG_MAX.\n                              * Larger tables result in better and slower compression.\n                              * This parameter is useless for \"fast\" strategy.\n                              * It's still useful when using \"dfast\" strategy,\n                              * in which case it defines a secondary probe table.\n                              * Special: value 0 means \"use default chainLog\". */\n    ZSTD_c_searchLog=104,    /* Number of search attempts, as a power of 2.\n                              * More attempts result in better and slower compression.\n                              * This parameter is useless for \"fast\" and \"dFast\" strategies.\n                              * Special: value 0 means \"use default searchLog\". */\n    ZSTD_c_minMatch=105,     /* Minimum size of searched matches.\n                              * Note that Zstandard can still find matches of smaller size,\n                              * it just tweaks its search algorithm to look for this size and larger.\n                              * Larger values increase compression and decompression speed, but decrease ratio.\n                              * Must be clamped between ZSTD_MINMATCH_MIN and ZSTD_MINMATCH_MAX.\n                              * Note that currently, for all strategies < btopt, effective minimum is 4.\n                              *                    , for all strategies > fast, effective maximum is 6.\n                              * Special: value 0 means \"use default minMatchLength\". */\n    ZSTD_c_targetLength=106, /* Impact of this field depends on strategy.\n                              * For strategies btopt, btultra & btultra2:\n                              *     Length of Match considered \"good enough\" to stop search.\n                              *     Larger values make compression stronger, and slower.\n                              * For strategy fast:\n                              *     Distance between match sampling.\n                              *     Larger values make compression faster, and weaker.\n                              * Special: value 0 means \"use default targetLength\". */\n    ZSTD_c_strategy=107,     /* See ZSTD_strategy enum definition.\n                              * The higher the value of selected strategy, the more complex it is,\n                              * resulting in stronger and slower compression.\n                              * Special: value 0 means \"use default strategy\". */\n\n    ZSTD_c_targetCBlockSize=130, /* v1.5.6+\n                                  * Attempts to fit compressed block size into approximately targetCBlockSize.\n                                  * Bound by ZSTD_TARGETCBLOCKSIZE_MIN and ZSTD_TARGETCBLOCKSIZE_MAX.\n                                  * Note that it's not a guarantee, just a convergence target (default:0).\n                                  * No target when targetCBlockSize == 0.\n                                  * This is helpful in low bandwidth streaming environments to improve end-to-end latency,\n                                  * when a client can make use of partial documents (a prominent example being Chrome).\n                                  * Note: this parameter is stable since v1.5.6.\n                                  * It was present as an experimental parameter in earlier versions,\n                                  * but it's not recommended using it with earlier library versions\n                                  * due to massive performance regressions.\n                                  */\n    /* LDM mode parameters */\n    ZSTD_c_enableLongDistanceMatching=160, /* Enable long distance matching.\n                                     * This parameter is designed to improve compression ratio\n                                     * for large inputs, by finding large matches at long distance.\n                                     * It increases memory usage and window size.\n                                     * Note: enabling this parameter increases default ZSTD_c_windowLog to 128 MB\n                                     * except when expressly set to a different value.\n                                     * Note: will be enabled by default if ZSTD_c_windowLog >= 128 MB and\n                                     * compression strategy >= ZSTD_btopt (== compression level 16+) */\n    ZSTD_c_ldmHashLog=161,   /* Size of the table for long distance matching, as a power of 2.\n                              * Larger values increase memory usage and compression ratio,\n                              * but decrease compression speed.\n                              * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX\n                              * default: windowlog - 7.\n                              * Special: value 0 means \"automatically determine hashlog\". */\n    ZSTD_c_ldmMinMatch=162,  /* Minimum match size for long distance matcher.\n                              * Larger/too small values usually decrease compression ratio.\n                              * Must be clamped between ZSTD_LDM_MINMATCH_MIN and ZSTD_LDM_MINMATCH_MAX.\n                              * Special: value 0 means \"use default value\" (default: 64). */\n    ZSTD_c_ldmBucketSizeLog=163, /* Log size of each bucket in the LDM hash table for collision resolution.\n                              * Larger values improve collision resolution but decrease compression speed.\n                              * The maximum value is ZSTD_LDM_BUCKETSIZELOG_MAX.\n                              * Special: value 0 means \"use default value\" (default: 3). */\n    ZSTD_c_ldmHashRateLog=164, /* Frequency of inserting/looking up entries into the LDM hash table.\n                              * Must be clamped between 0 and (ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN).\n                              * Default is MAX(0, (windowLog - ldmHashLog)), optimizing hash table usage.\n                              * Larger values improve compression speed.\n                              * Deviating far from default value will likely result in a compression ratio decrease.\n                              * Special: value 0 means \"automatically determine hashRateLog\". */\n\n    /* frame parameters */\n    ZSTD_c_contentSizeFlag=200, /* Content size will be written into frame header _whenever known_ (default:1)\n                              * Content size must be known at the beginning of compression.\n                              * This is automatically the case when using ZSTD_compress2(),\n                              * For streaming scenarios, content size must be provided with ZSTD_CCtx_setPledgedSrcSize() */\n    ZSTD_c_checksumFlag=201, /* A 32-bits checksum of content is written at end of frame (default:0) */\n    ZSTD_c_dictIDFlag=202,   /* When applicable, dictionary's ID is written into frame header (default:1) */\n\n    /* multi-threading parameters */\n    /* These parameters are only active if multi-threading is enabled (compiled with build macro ZSTD_MULTITHREAD).\n     * Otherwise, trying to set any other value than default (0) will be a no-op and return an error.\n     * In a situation where it's unknown if the linked library supports multi-threading or not,\n     * setting ZSTD_c_nbWorkers to any value >= 1 and consulting the return value provides a quick way to check this property.\n     */\n    ZSTD_c_nbWorkers=400,    /* Select how many threads will be spawned to compress in parallel.\n                              * When nbWorkers >= 1, triggers asynchronous mode when invoking ZSTD_compressStream*() :\n                              * ZSTD_compressStream*() consumes input and flush output if possible, but immediately gives back control to caller,\n                              * while compression is performed in parallel, within worker thread(s).\n                              * (note : a strong exception to this rule is when first invocation of ZSTD_compressStream2() sets ZSTD_e_end :\n                              *  in which case, ZSTD_compressStream2() delegates to ZSTD_compress2(), which is always a blocking call).\n                              * More workers improve speed, but also increase memory usage.\n                              * Default value is `0`, aka \"single-threaded mode\" : no worker is spawned,\n                              * compression is performed inside Caller's thread, and all invocations are blocking */\n    ZSTD_c_jobSize=401,      /* Size of a compression job. This value is enforced only when nbWorkers >= 1.\n                              * Each compression job is completed in parallel, so this value can indirectly impact the nb of active threads.\n                              * 0 means default, which is dynamically determined based on compression parameters.\n                              * Job size must be a minimum of overlap size, or ZSTDMT_JOBSIZE_MIN (= 512 KB), whichever is largest.\n                              * The minimum size is automatically and transparently enforced. */\n    ZSTD_c_overlapLog=402,   /* Control the overlap size, as a fraction of window size.\n                              * The overlap size is an amount of data reloaded from previous job at the beginning of a new job.\n                              * It helps preserve compression ratio, while each job is compressed in parallel.\n                              * This value is enforced only when nbWorkers >= 1.\n                              * Larger values increase compression ratio, but decrease speed.\n                              * Possible values range from 0 to 9 :\n                              * - 0 means \"default\" : value will be determined by the library, depending on strategy\n                              * - 1 means \"no overlap\"\n                              * - 9 means \"full overlap\", using a full window size.\n                              * Each intermediate rank increases/decreases load size by a factor 2 :\n                              * 9: full window;  8: w/2;  7: w/4;  6: w/8;  5:w/16;  4: w/32;  3:w/64;  2:w/128;  1:no overlap;  0:default\n                              * default value varies between 6 and 9, depending on strategy */\n\n    /* note : additional experimental parameters are also available\n     * within the experimental section of the API.\n     * At the time of this writing, they include :\n     * ZSTD_c_rsyncable\n     * ZSTD_c_format\n     * ZSTD_c_forceMaxWindow\n     * ZSTD_c_forceAttachDict\n     * ZSTD_c_literalCompressionMode\n     * ZSTD_c_srcSizeHint\n     * ZSTD_c_enableDedicatedDictSearch\n     * ZSTD_c_stableInBuffer\n     * ZSTD_c_stableOutBuffer\n     * ZSTD_c_blockDelimiters\n     * ZSTD_c_validateSequences\n     * ZSTD_c_blockSplitterLevel\n     * ZSTD_c_splitAfterSequences\n     * ZSTD_c_useRowMatchFinder\n     * ZSTD_c_prefetchCDictTables\n     * ZSTD_c_enableSeqProducerFallback\n     * ZSTD_c_maxBlockSize\n     * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.\n     * note : never ever use experimentalParam? names directly;\n     *        also, the enums values themselves are unstable and can still change.\n     */\n     ZSTD_c_experimentalParam1=500,\n     ZSTD_c_experimentalParam2=10,\n     ZSTD_c_experimentalParam3=1000,\n     ZSTD_c_experimentalParam4=1001,\n     ZSTD_c_experimentalParam5=1002,\n     /* was ZSTD_c_experimentalParam6=1003; is now ZSTD_c_targetCBlockSize */\n     ZSTD_c_experimentalParam7=1004,\n     ZSTD_c_experimentalParam8=1005,\n     ZSTD_c_experimentalParam9=1006,\n     ZSTD_c_experimentalParam10=1007,\n     ZSTD_c_experimentalParam11=1008,\n     ZSTD_c_experimentalParam12=1009,\n     ZSTD_c_experimentalParam13=1010,\n     ZSTD_c_experimentalParam14=1011,\n     ZSTD_c_experimentalParam15=1012,\n     ZSTD_c_experimentalParam16=1013,\n     ZSTD_c_experimentalParam17=1014,\n     ZSTD_c_experimentalParam18=1015,\n     ZSTD_c_experimentalParam19=1016,\n     ZSTD_c_experimentalParam20=1017\n} ZSTD_cParameter;\n\ntypedef struct {\n    size_t error;\n    int lowerBound;\n    int upperBound;\n} ZSTD_bounds;\n\n/*! ZSTD_cParam_getBounds() :\n *  All parameters must belong to an interval with lower and upper bounds,\n *  otherwise they will either trigger an error or be automatically clamped.\n * @return : a structure, ZSTD_bounds, which contains\n *         - an error status field, which must be tested using ZSTD_isError()\n *         - lower and upper bounds, both inclusive\n */\nZSTDLIB_API ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter cParam);\n\n/*! ZSTD_CCtx_setParameter() :\n *  Set one compression parameter, selected by enum ZSTD_cParameter.\n *  All parameters have valid bounds. Bounds can be queried using ZSTD_cParam_getBounds().\n *  Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter).\n *  Setting a parameter is generally only possible during frame initialization (before starting compression).\n *  Exception : when using multi-threading mode (nbWorkers >= 1),\n *              the following parameters can be updated _during_ compression (within same frame):\n *              => compressionLevel, hashLog, chainLog, searchLog, minMatch, targetLength and strategy.\n *              new parameters will be active for next job only (after a flush()).\n * @return : an error code (which can be tested using ZSTD_isError()).\n */\nZSTDLIB_API size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value);\n\n/*! ZSTD_CCtx_setPledgedSrcSize() :\n *  Total input data size to be compressed as a single frame.\n *  Value will be written in frame header, unless if explicitly forbidden using ZSTD_c_contentSizeFlag.\n *  This value will also be controlled at end of frame, and trigger an error if not respected.\n * @result : 0, or an error code (which can be tested with ZSTD_isError()).\n *  Note 1 : pledgedSrcSize==0 actually means zero, aka an empty frame.\n *           In order to mean \"unknown content size\", pass constant ZSTD_CONTENTSIZE_UNKNOWN.\n *           ZSTD_CONTENTSIZE_UNKNOWN is default value for any new frame.\n *  Note 2 : pledgedSrcSize is only valid once, for the next frame.\n *           It's discarded at the end of the frame, and replaced by ZSTD_CONTENTSIZE_UNKNOWN.\n *  Note 3 : Whenever all input data is provided and consumed in a single round,\n *           for example with ZSTD_compress2(),\n *           or invoking immediately ZSTD_compressStream2(,,,ZSTD_e_end),\n *           this value is automatically overridden by srcSize instead.\n */\nZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize);\n\ntypedef enum {\n    ZSTD_reset_session_only = 1,\n    ZSTD_reset_parameters = 2,\n    ZSTD_reset_session_and_parameters = 3\n} ZSTD_ResetDirective;\n\n/*! ZSTD_CCtx_reset() :\n *  There are 2 different things that can be reset, independently or jointly :\n *  - The session : will stop compressing current frame, and make CCtx ready to start a new one.\n *                  Useful after an error, or to interrupt any ongoing compression.\n *                  Any internal data not yet flushed is cancelled.\n *                  Compression parameters and dictionary remain unchanged.\n *                  They will be used to compress next frame.\n *                  Resetting session never fails.\n *  - The parameters : changes all parameters back to \"default\".\n *                  This also removes any reference to any dictionary or external sequence producer.\n *                  Parameters can only be changed between 2 sessions (i.e. no compression is currently ongoing)\n *                  otherwise the reset fails, and function returns an error value (which can be tested using ZSTD_isError())\n *  - Both : similar to resetting the session, followed by resetting parameters.\n */\nZSTDLIB_API size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset);\n\n/*! ZSTD_compress2() :\n *  Behave the same as ZSTD_compressCCtx(), but compression parameters are set using the advanced API.\n *  (note that this entry point doesn't even expose a compression level parameter).\n *  ZSTD_compress2() always starts a new frame.\n *  Should cctx hold data from a previously unfinished frame, everything about it is forgotten.\n *  - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()\n *  - The function is always blocking, returns when compression is completed.\n *  NOTE: Providing `dstCapacity >= ZSTD_compressBound(srcSize)` guarantees that zstd will have\n *        enough space to successfully compress the data, though it is possible it fails for other reasons.\n * @return : compressed size written into `dst` (<= `dstCapacity),\n *           or an error code if it fails (which can be tested using ZSTD_isError()).\n */\nZSTDLIB_API size_t ZSTD_compress2( ZSTD_CCtx* cctx,\n                                   void* dst, size_t dstCapacity,\n                             const void* src, size_t srcSize);\n\n\n/***********************************************\n*  Advanced decompression API (Requires v1.4.0+)\n************************************************/\n\n/* The advanced API pushes parameters one by one into an existing DCtx context.\n * Parameters are sticky, and remain valid for all following frames\n * using the same DCtx context.\n * It's possible to reset parameters to default values using ZSTD_DCtx_reset().\n * Note : This API is compatible with existing ZSTD_decompressDCtx() and ZSTD_decompressStream().\n *        Therefore, no new decompression function is necessary.\n */\n\ntypedef enum {\n\n    ZSTD_d_windowLogMax=100, /* Select a size limit (in power of 2) beyond which\n                              * the streaming API will refuse to allocate memory buffer\n                              * in order to protect the host from unreasonable memory requirements.\n                              * This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode.\n                              * By default, a decompression context accepts window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT).\n                              * Special: value 0 means \"use default maximum windowLog\". */\n\n    /* note : additional experimental parameters are also available\n     * within the experimental section of the API.\n     * At the time of this writing, they include :\n     * ZSTD_d_format\n     * ZSTD_d_stableOutBuffer\n     * ZSTD_d_forceIgnoreChecksum\n     * ZSTD_d_refMultipleDDicts\n     * ZSTD_d_disableHuffmanAssembly\n     * ZSTD_d_maxBlockSize\n     * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.\n     * note : never ever use experimentalParam? names directly\n     */\n     ZSTD_d_experimentalParam1=1000,\n     ZSTD_d_experimentalParam2=1001,\n     ZSTD_d_experimentalParam3=1002,\n     ZSTD_d_experimentalParam4=1003,\n     ZSTD_d_experimentalParam5=1004,\n     ZSTD_d_experimentalParam6=1005\n\n} ZSTD_dParameter;\n\n/*! ZSTD_dParam_getBounds() :\n *  All parameters must belong to an interval with lower and upper bounds,\n *  otherwise they will either trigger an error or be automatically clamped.\n * @return : a structure, ZSTD_bounds, which contains\n *         - an error status field, which must be tested using ZSTD_isError()\n *         - both lower and upper bounds, inclusive\n */\nZSTDLIB_API ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam);\n\n/*! ZSTD_DCtx_setParameter() :\n *  Set one compression parameter, selected by enum ZSTD_dParameter.\n *  All parameters have valid bounds. Bounds can be queried using ZSTD_dParam_getBounds().\n *  Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter).\n *  Setting a parameter is only possible during frame initialization (before starting decompression).\n * @return : 0, or an error code (which can be tested using ZSTD_isError()).\n */\nZSTDLIB_API size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int value);\n\n/*! ZSTD_DCtx_reset() :\n *  Return a DCtx to clean state.\n *  Session and parameters can be reset jointly or separately.\n *  Parameters can only be reset when no active frame is being decompressed.\n * @return : 0, or an error code, which can be tested with ZSTD_isError()\n */\nZSTDLIB_API size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset);\n\n\n/****************************\n*  Streaming\n****************************/\n\ntypedef struct ZSTD_inBuffer_s {\n  const void* src;    /**< start of input buffer */\n  size_t size;        /**< size of input buffer */\n  size_t pos;         /**< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */\n} ZSTD_inBuffer;\n\ntypedef struct ZSTD_outBuffer_s {\n  void*  dst;         /**< start of output buffer */\n  size_t size;        /**< size of output buffer */\n  size_t pos;         /**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */\n} ZSTD_outBuffer;\n\n\n\n/*-***********************************************************************\n*  Streaming compression - HowTo\n*\n*  A ZSTD_CStream object is required to track streaming operation.\n*  Use ZSTD_createCStream() and ZSTD_freeCStream() to create/release resources.\n*  ZSTD_CStream objects can be reused multiple times on consecutive compression operations.\n*  It is recommended to reuse ZSTD_CStream since it will play nicer with system's memory, by re-using already allocated memory.\n*\n*  For parallel execution, use one separate ZSTD_CStream per thread.\n*\n*  note : since v1.3.0, ZSTD_CStream and ZSTD_CCtx are the same thing.\n*\n*  Parameters are sticky : when starting a new compression on the same context,\n*  it will reuse the same sticky parameters as previous compression session.\n*  When in doubt, it's recommended to fully initialize the context before usage.\n*  Use ZSTD_CCtx_reset() to reset the context and ZSTD_CCtx_setParameter(),\n*  ZSTD_CCtx_setPledgedSrcSize(), or ZSTD_CCtx_loadDictionary() and friends to\n*  set more specific parameters, the pledged source size, or load a dictionary.\n*\n*  Use ZSTD_compressStream2() with ZSTD_e_continue as many times as necessary to\n*  consume input stream. The function will automatically update both `pos`\n*  fields within `input` and `output`.\n*  Note that the function may not consume the entire input, for example, because\n*  the output buffer is already full, in which case `input.pos < input.size`.\n*  The caller must check if input has been entirely consumed.\n*  If not, the caller must make some room to receive more compressed data,\n*  and then present again remaining input data.\n*  note: ZSTD_e_continue is guaranteed to make some forward progress when called,\n*        but doesn't guarantee maximal forward progress. This is especially relevant\n*        when compressing with multiple threads. The call won't block if it can\n*        consume some input, but if it can't it will wait for some, but not all,\n*        output to be flushed.\n* @return : provides a minimum amount of data remaining to be flushed from internal buffers\n*           or an error code, which can be tested using ZSTD_isError().\n*\n*  At any moment, it's possible to flush whatever data might remain stuck within internal buffer,\n*  using ZSTD_compressStream2() with ZSTD_e_flush. `output->pos` will be updated.\n*  Note that, if `output->size` is too small, a single invocation with ZSTD_e_flush might not be enough (return code > 0).\n*  In which case, make some room to receive more compressed data, and call again ZSTD_compressStream2() with ZSTD_e_flush.\n*  You must continue calling ZSTD_compressStream2() with ZSTD_e_flush until it returns 0, at which point you can change the\n*  operation.\n*  note: ZSTD_e_flush will flush as much output as possible, meaning when compressing with multiple threads, it will\n*        block until the flush is complete or the output buffer is full.\n*  @return : 0 if internal buffers are entirely flushed,\n*            >0 if some data still present within internal buffer (the value is minimal estimation of remaining size),\n*            or an error code, which can be tested using ZSTD_isError().\n*\n*  Calling ZSTD_compressStream2() with ZSTD_e_end instructs to finish a frame.\n*  It will perform a flush and write frame epilogue.\n*  The epilogue is required for decoders to consider a frame completed.\n*  flush operation is the same, and follows same rules as calling ZSTD_compressStream2() with ZSTD_e_flush.\n*  You must continue calling ZSTD_compressStream2() with ZSTD_e_end until it returns 0, at which point you are free to\n*  start a new frame.\n*  note: ZSTD_e_end will flush as much output as possible, meaning when compressing with multiple threads, it will\n*        block until the flush is complete or the output buffer is full.\n*  @return : 0 if frame fully completed and fully flushed,\n*            >0 if some data still present within internal buffer (the value is minimal estimation of remaining size),\n*            or an error code, which can be tested using ZSTD_isError().\n*\n* *******************************************************************/\n\ntypedef ZSTD_CCtx ZSTD_CStream;  /**< CCtx and CStream are now effectively same object (>= v1.3.0) */\n                                 /* Continue to distinguish them for compatibility with older versions <= v1.2.0 */\n/*===== ZSTD_CStream management functions =====*/\nZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void);\nZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs);  /* accept NULL pointer */\n\n/*===== Streaming compression functions =====*/\ntypedef enum {\n    ZSTD_e_continue=0, /* collect more data, encoder decides when to output compressed result, for optimal compression ratio */\n    ZSTD_e_flush=1,    /* flush any data provided so far,\n                        * it creates (at least) one new block, that can be decoded immediately on reception;\n                        * frame will continue: any future data can still reference previously compressed data, improving compression.\n                        * note : multithreaded compression will block to flush as much output as possible. */\n    ZSTD_e_end=2       /* flush any remaining data _and_ close current frame.\n                        * note that frame is only closed after compressed data is fully flushed (return value == 0).\n                        * After that point, any additional data starts a new frame.\n                        * note : each frame is independent (does not reference any content from previous frame).\n                        : note : multithreaded compression will block to flush as much output as possible. */\n} ZSTD_EndDirective;\n\n/*! ZSTD_compressStream2() : Requires v1.4.0+\n *  Behaves about the same as ZSTD_compressStream, with additional control on end directive.\n *  - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()\n *  - Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode)\n *  - output->pos must be <= dstCapacity, input->pos must be <= srcSize\n *  - output->pos and input->pos will be updated. They are guaranteed to remain below their respective limit.\n *  - endOp must be a valid directive\n *  - When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller.\n *  - When nbWorkers>=1, function is non-blocking : it copies a portion of input, distributes jobs to internal worker threads, flush to output whatever is available,\n *                                                  and then immediately returns, just indicating that there is some data remaining to be flushed.\n *                                                  The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte.\n *  - Exception : if the first call requests a ZSTD_e_end directive and provides enough dstCapacity, the function delegates to ZSTD_compress2() which is always blocking.\n *  - @return provides a minimum amount of data remaining to be flushed from internal buffers\n *            or an error code, which can be tested using ZSTD_isError().\n *            if @return != 0, flush is not fully completed, there is still some data left within internal buffers.\n *            This is useful for ZSTD_e_flush, since in this case more flushes are necessary to empty all buffers.\n *            For ZSTD_e_end, @return == 0 when internal buffers are fully flushed and frame is completed.\n *  - after a ZSTD_e_end directive, if internal buffer is not fully flushed (@return != 0),\n *            only ZSTD_e_end or ZSTD_e_flush operations are allowed.\n *            Before starting a new compression job, or changing compression parameters,\n *            it is required to fully flush internal buffers.\n *  - note: if an operation ends with an error, it may leave @cctx in an undefined state.\n *          Therefore, it's UB to invoke ZSTD_compressStream2() of ZSTD_compressStream() on such a state.\n *          In order to be re-employed after an error, a state must be reset,\n *          which can be done explicitly (ZSTD_CCtx_reset()),\n *          or is sometimes implied by methods starting a new compression job (ZSTD_initCStream(), ZSTD_compressCCtx())\n */\nZSTDLIB_API size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,\n                                         ZSTD_outBuffer* output,\n                                         ZSTD_inBuffer* input,\n                                         ZSTD_EndDirective endOp);\n\n\n/* These buffer sizes are softly recommended.\n * They are not required : ZSTD_compressStream*() happily accepts any buffer size, for both input and output.\n * Respecting the recommended size just makes it a bit easier for ZSTD_compressStream*(),\n * reducing the amount of memory shuffling and buffering, resulting in minor performance savings.\n *\n * However, note that these recommendations are from the perspective of a C caller program.\n * If the streaming interface is invoked from some other language,\n * especially managed ones such as Java or Go, through a foreign function interface such as jni or cgo,\n * a major performance rule is to reduce crossing such interface to an absolute minimum.\n * It's not rare that performance ends being spent more into the interface, rather than compression itself.\n * In which cases, prefer using large buffers, as large as practical,\n * for both input and output, to reduce the nb of roundtrips.\n */\nZSTDLIB_API size_t ZSTD_CStreamInSize(void);    /**< recommended size for input buffer */\nZSTDLIB_API size_t ZSTD_CStreamOutSize(void);   /**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block. */\n\n\n/* *****************************************************************************\n * This following is a legacy streaming API, available since v1.0+ .\n * It can be replaced by ZSTD_CCtx_reset() and ZSTD_compressStream2().\n * It is redundant, but remains fully supported.\n ******************************************************************************/\n\n/*!\n * Equivalent to:\n *\n *     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n *     ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)\n *     ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);\n *\n * Note that ZSTD_initCStream() clears any previously set dictionary. Use the new API\n * to compress with a dictionary.\n */\nZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel);\n/*!\n * Alternative for ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue).\n * NOTE: The return value is different. ZSTD_compressStream() returns a hint for\n * the next read size (if non-zero and not an error). ZSTD_compressStream2()\n * returns the minimum nb of bytes left to flush (if non-zero and not an error).\n */\nZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input);\n/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_flush). */\nZSTDLIB_API size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);\n/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_end). */\nZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);\n\n\n/*-***************************************************************************\n*  Streaming decompression - HowTo\n*\n*  A ZSTD_DStream object is required to track streaming operations.\n*  Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources.\n*  ZSTD_DStream objects can be re-employed multiple times.\n*\n*  Use ZSTD_initDStream() to start a new decompression operation.\n* @return : recommended first input size\n*  Alternatively, use advanced API to set specific properties.\n*\n*  Use ZSTD_decompressStream() repetitively to consume your input.\n*  The function will update both `pos` fields.\n*  If `input.pos < input.size`, some input has not been consumed.\n*  It's up to the caller to present again remaining data.\n*\n*  The function tries to flush all data decoded immediately, respecting output buffer size.\n*  If `output.pos < output.size`, decoder has flushed everything it could.\n*\n*  However, when `output.pos == output.size`, it's more difficult to know.\n*  If @return > 0, the frame is not complete, meaning\n*  either there is still some data left to flush within internal buffers,\n*  or there is more input to read to complete the frame (or both).\n*  In which case, call ZSTD_decompressStream() again to flush whatever remains in the buffer.\n*  Note : with no additional input provided, amount of data flushed is necessarily <= ZSTD_BLOCKSIZE_MAX.\n* @return : 0 when a frame is completely decoded and fully flushed,\n*        or an error code, which can be tested using ZSTD_isError(),\n*        or any other value > 0, which means there is still some decoding or flushing to do to complete current frame :\n*                                the return value is a suggested next input size (just a hint for better latency)\n*                                that will never request more than the remaining content of the compressed frame.\n* *******************************************************************************/\n\ntypedef ZSTD_DCtx ZSTD_DStream;  /**< DCtx and DStream are now effectively same object (>= v1.3.0) */\n                                 /* For compatibility with versions <= v1.2.0, prefer differentiating them. */\n/*===== ZSTD_DStream management functions =====*/\nZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void);\nZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds);  /* accept NULL pointer */\n\n/*===== Streaming decompression functions =====*/\n\n/*! ZSTD_initDStream() :\n * Initialize/reset DStream state for new decompression operation.\n * Call before new decompression operation using same DStream.\n *\n * Note : This function is redundant with the advanced API and equivalent to:\n *     ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);\n *     ZSTD_DCtx_refDDict(zds, NULL);\n */\nZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream* zds);\n\n/*! ZSTD_decompressStream() :\n * Streaming decompression function.\n * Call repetitively to consume full input updating it as necessary.\n * Function will update both input and output `pos` fields exposing current state via these fields:\n * - `input.pos < input.size`, some input remaining and caller should provide remaining input\n *   on the next call.\n * - `output.pos < output.size`, decoder flushed internal output buffer.\n * - `output.pos == output.size`, unflushed data potentially present in the internal buffers,\n *   check ZSTD_decompressStream() @return value,\n *   if > 0, invoke it again to flush remaining data to output.\n * Note : with no additional input, amount of data flushed <= ZSTD_BLOCKSIZE_MAX.\n *\n * @return : 0 when a frame is completely decoded and fully flushed,\n *           or an error code, which can be tested using ZSTD_isError(),\n *           or any other value > 0, which means there is some decoding or flushing to do to complete current frame.\n *\n * Note: when an operation returns with an error code, the @zds state may be left in undefined state.\n *       It's UB to invoke `ZSTD_decompressStream()` on such a state.\n *       In order to re-use such a state, it must be first reset,\n *       which can be done explicitly (`ZSTD_DCtx_reset()`),\n *       or is implied for operations starting some new decompression job (`ZSTD_initDStream`, `ZSTD_decompressDCtx()`, `ZSTD_decompress_usingDict()`)\n */\nZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input);\n\nZSTDLIB_API size_t ZSTD_DStreamInSize(void);    /*!< recommended size for input buffer */\nZSTDLIB_API size_t ZSTD_DStreamOutSize(void);   /*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */\n\n\n/**************************\n*  Simple dictionary API\n***************************/\n/*! ZSTD_compress_usingDict() :\n *  Compression at an explicit compression level using a Dictionary.\n *  A dictionary can be any arbitrary data segment (also called a prefix),\n *  or a buffer with specified information (see zdict.h).\n *  Note : This function loads the dictionary, resulting in significant startup delay.\n *         It's intended for a dictionary used only once.\n *  Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used. */\nZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx,\n                                           void* dst, size_t dstCapacity,\n                                     const void* src, size_t srcSize,\n                                     const void* dict,size_t dictSize,\n                                           int compressionLevel);\n\n/*! ZSTD_decompress_usingDict() :\n *  Decompression using a known Dictionary.\n *  Dictionary must be identical to the one used during compression.\n *  Note : This function loads the dictionary, resulting in significant startup delay.\n *         It's intended for a dictionary used only once.\n *  Note : When `dict == NULL || dictSize < 8` no dictionary is used. */\nZSTDLIB_API size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,\n                                             void* dst, size_t dstCapacity,\n                                       const void* src, size_t srcSize,\n                                       const void* dict,size_t dictSize);\n\n\n/***********************************\n *  Bulk processing dictionary API\n **********************************/\ntypedef struct ZSTD_CDict_s ZSTD_CDict;\n\n/*! ZSTD_createCDict() :\n *  When compressing multiple messages or blocks using the same dictionary,\n *  it's recommended to digest the dictionary only once, since it's a costly operation.\n *  ZSTD_createCDict() will create a state from digesting a dictionary.\n *  The resulting state can be used for future compression operations with very limited startup cost.\n *  ZSTD_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only.\n * @dictBuffer can be released after ZSTD_CDict creation, because its content is copied within CDict.\n *  Note 1 : Consider experimental function `ZSTD_createCDict_byReference()` if you prefer to not duplicate @dictBuffer content.\n *  Note 2 : A ZSTD_CDict can be created from an empty @dictBuffer,\n *      in which case the only thing that it transports is the @compressionLevel.\n *      This can be useful in a pipeline featuring ZSTD_compress_usingCDict() exclusively,\n *      expecting a ZSTD_CDict parameter with any data, including those without a known dictionary. */\nZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize,\n                                         int compressionLevel);\n\n/*! ZSTD_freeCDict() :\n *  Function frees memory allocated by ZSTD_createCDict().\n *  If a NULL pointer is passed, no operation is performed. */\nZSTDLIB_API size_t      ZSTD_freeCDict(ZSTD_CDict* CDict);\n\n/*! ZSTD_compress_usingCDict() :\n *  Compression using a digested Dictionary.\n *  Recommended when same dictionary is used multiple times.\n *  Note : compression level is _decided at dictionary creation time_,\n *     and frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no) */\nZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,\n                                            void* dst, size_t dstCapacity,\n                                      const void* src, size_t srcSize,\n                                      const ZSTD_CDict* cdict);\n\n\ntypedef struct ZSTD_DDict_s ZSTD_DDict;\n\n/*! ZSTD_createDDict() :\n *  Create a digested dictionary, ready to start decompression operation without startup delay.\n *  dictBuffer can be released after DDict creation, as its content is copied inside DDict. */\nZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize);\n\n/*! ZSTD_freeDDict() :\n *  Function frees memory allocated with ZSTD_createDDict()\n *  If a NULL pointer is passed, no operation is performed. */\nZSTDLIB_API size_t      ZSTD_freeDDict(ZSTD_DDict* ddict);\n\n/*! ZSTD_decompress_usingDDict() :\n *  Decompression using a digested Dictionary.\n *  Recommended when same dictionary is used multiple times. */\nZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,\n                                              void* dst, size_t dstCapacity,\n                                        const void* src, size_t srcSize,\n                                        const ZSTD_DDict* ddict);\n\n\n/********************************\n *  Dictionary helper functions\n *******************************/\n\n/*! ZSTD_getDictID_fromDict() : Requires v1.4.0+\n *  Provides the dictID stored within dictionary.\n *  if @return == 0, the dictionary is not conformant with Zstandard specification.\n *  It can still be loaded, but as a content-only dictionary. */\nZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize);\n\n/*! ZSTD_getDictID_fromCDict() : Requires v1.5.0+\n *  Provides the dictID of the dictionary loaded into `cdict`.\n *  If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.\n *  Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */\nZSTDLIB_API unsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* cdict);\n\n/*! ZSTD_getDictID_fromDDict() : Requires v1.4.0+\n *  Provides the dictID of the dictionary loaded into `ddict`.\n *  If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.\n *  Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */\nZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);\n\n/*! ZSTD_getDictID_fromFrame() : Requires v1.4.0+\n *  Provides the dictID required to decompressed the frame stored within `src`.\n *  If @return == 0, the dictID could not be decoded.\n *  This could for one of the following reasons :\n *  - The frame does not require a dictionary to be decoded (most common case).\n *  - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden piece of information.\n *    Note : this use case also happens when using a non-conformant dictionary.\n *  - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).\n *  - This is not a Zstandard frame.\n *  When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code. */\nZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);\n\n\n/*******************************************************************************\n * Advanced dictionary and prefix API (Requires v1.4.0+)\n *\n * This API allows dictionaries to be used with ZSTD_compress2(),\n * ZSTD_compressStream2(), and ZSTD_decompressDCtx().\n * Dictionaries are sticky, they remain valid when same context is reused,\n * they only reset when the context is reset\n * with ZSTD_reset_parameters or ZSTD_reset_session_and_parameters.\n * In contrast, Prefixes are single-use.\n ******************************************************************************/\n\n\n/*! ZSTD_CCtx_loadDictionary() : Requires v1.4.0+\n *  Create an internal CDict from `dict` buffer.\n *  Decompression will have to use same dictionary.\n * @result : 0, or an error code (which can be tested with ZSTD_isError()).\n *  Special: Loading a NULL (or 0-size) dictionary invalidates previous dictionary,\n *           meaning \"return to no-dictionary mode\".\n *  Note 1 : Dictionary is sticky, it will be used for all future compressed frames,\n *           until parameters are reset, a new dictionary is loaded, or the dictionary\n *           is explicitly invalidated by loading a NULL dictionary.\n *  Note 2 : Loading a dictionary involves building tables.\n *           It's also a CPU consuming operation, with non-negligible impact on latency.\n *           Tables are dependent on compression parameters, and for this reason,\n *           compression parameters can no longer be changed after loading a dictionary.\n *  Note 3 :`dict` content will be copied internally.\n *           Use experimental ZSTD_CCtx_loadDictionary_byReference() to reference content instead.\n *           In such a case, dictionary buffer must outlive its users.\n *  Note 4 : Use ZSTD_CCtx_loadDictionary_advanced()\n *           to precisely select how dictionary content must be interpreted.\n *  Note 5 : This method does not benefit from LDM (long distance mode).\n *           If you want to employ LDM on some large dictionary content,\n *           prefer employing ZSTD_CCtx_refPrefix() described below.\n */\nZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);\n\n/*! ZSTD_CCtx_refCDict() : Requires v1.4.0+\n *  Reference a prepared dictionary, to be used for all future compressed frames.\n *  Note that compression parameters are enforced from within CDict,\n *  and supersede any compression parameter previously set within CCtx.\n *  The parameters ignored are labelled as \"superseded-by-cdict\" in the ZSTD_cParameter enum docs.\n *  The ignored parameters will be used again if the CCtx is returned to no-dictionary mode.\n *  The dictionary will remain valid for future compressed frames using same CCtx.\n * @result : 0, or an error code (which can be tested with ZSTD_isError()).\n *  Special : Referencing a NULL CDict means \"return to no-dictionary mode\".\n *  Note 1 : Currently, only one dictionary can be managed.\n *           Referencing a new dictionary effectively \"discards\" any previous one.\n *  Note 2 : CDict is just referenced, its lifetime must outlive its usage within CCtx. */\nZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);\n\n/*! ZSTD_CCtx_refPrefix() : Requires v1.4.0+\n *  Reference a prefix (single-usage dictionary) for next compressed frame.\n *  A prefix is **only used once**. Tables are discarded at end of frame (ZSTD_e_end).\n *  Decompression will need same prefix to properly regenerate data.\n *  Compressing with a prefix is similar in outcome as performing a diff and compressing it,\n *  but performs much faster, especially during decompression (compression speed is tunable with compression level).\n *  This method is compatible with LDM (long distance mode).\n * @result : 0, or an error code (which can be tested with ZSTD_isError()).\n *  Special: Adding any prefix (including NULL) invalidates any previous prefix or dictionary\n *  Note 1 : Prefix buffer is referenced. It **must** outlive compression.\n *           Its content must remain unmodified during compression.\n *  Note 2 : If the intention is to diff some large src data blob with some prior version of itself,\n *           ensure that the window size is large enough to contain the entire source.\n *           See ZSTD_c_windowLog.\n *  Note 3 : Referencing a prefix involves building tables, which are dependent on compression parameters.\n *           It's a CPU consuming operation, with non-negligible impact on latency.\n *           If there is a need to use the same prefix multiple times, consider loadDictionary instead.\n *  Note 4 : By default, the prefix is interpreted as raw content (ZSTD_dct_rawContent).\n *           Use experimental ZSTD_CCtx_refPrefix_advanced() to alter dictionary interpretation. */\nZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx,\n                                 const void* prefix, size_t prefixSize);\n\n/*! ZSTD_DCtx_loadDictionary() : Requires v1.4.0+\n *  Create an internal DDict from dict buffer, to be used to decompress all future frames.\n *  The dictionary remains valid for all future frames, until explicitly invalidated, or\n *  a new dictionary is loaded.\n * @result : 0, or an error code (which can be tested with ZSTD_isError()).\n *  Special : Adding a NULL (or 0-size) dictionary invalidates any previous dictionary,\n *            meaning \"return to no-dictionary mode\".\n *  Note 1 : Loading a dictionary involves building tables,\n *           which has a non-negligible impact on CPU usage and latency.\n *           It's recommended to \"load once, use many times\", to amortize the cost\n *  Note 2 :`dict` content will be copied internally, so `dict` can be released after loading.\n *           Use ZSTD_DCtx_loadDictionary_byReference() to reference dictionary content instead.\n *  Note 3 : Use ZSTD_DCtx_loadDictionary_advanced() to take control of\n *           how dictionary content is loaded and interpreted.\n */\nZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);\n\n/*! ZSTD_DCtx_refDDict() : Requires v1.4.0+\n *  Reference a prepared dictionary, to be used to decompress next frames.\n *  The dictionary remains active for decompression of future frames using same DCtx.\n *\n *  If called with ZSTD_d_refMultipleDDicts enabled, repeated calls of this function\n *  will store the DDict references in a table, and the DDict used for decompression\n *  will be determined at decompression time, as per the dict ID in the frame.\n *  The memory for the table is allocated on the first call to refDDict, and can be\n *  freed with ZSTD_freeDCtx().\n *\n *  If called with ZSTD_d_refMultipleDDicts disabled (the default), only one dictionary\n *  will be managed, and referencing a dictionary effectively \"discards\" any previous one.\n *\n * @result : 0, or an error code (which can be tested with ZSTD_isError()).\n *  Special: referencing a NULL DDict means \"return to no-dictionary mode\".\n *  Note 2 : DDict is just referenced, its lifetime must outlive its usage from DCtx.\n */\nZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);\n\n/*! ZSTD_DCtx_refPrefix() : Requires v1.4.0+\n *  Reference a prefix (single-usage dictionary) to decompress next frame.\n *  This is the reverse operation of ZSTD_CCtx_refPrefix(),\n *  and must use the same prefix as the one used during compression.\n *  Prefix is **only used once**. Reference is discarded at end of frame.\n *  End of frame is reached when ZSTD_decompressStream() returns 0.\n * @result : 0, or an error code (which can be tested with ZSTD_isError()).\n *  Note 1 : Adding any prefix (including NULL) invalidates any previously set prefix or dictionary\n *  Note 2 : Prefix buffer is referenced. It **must** outlive decompression.\n *           Prefix buffer must remain unmodified up to the end of frame,\n *           reached when ZSTD_decompressStream() returns 0.\n *  Note 3 : By default, the prefix is treated as raw content (ZSTD_dct_rawContent).\n *           Use ZSTD_CCtx_refPrefix_advanced() to alter dictMode (Experimental section)\n *  Note 4 : Referencing a raw content prefix has almost no cpu nor memory cost.\n *           A full dictionary is more costly, as it requires building tables.\n */\nZSTDLIB_API size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx,\n                                 const void* prefix, size_t prefixSize);\n\n/* ===   Memory management   === */\n\n/*! ZSTD_sizeof_*() : Requires v1.4.0+\n *  These functions give the _current_ memory usage of selected object.\n *  Note that object memory usage can evolve (increase or decrease) over time. */\nZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);\nZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);\nZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);\nZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);\nZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict);\nZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* ZSTD_H_235446 */\n\n\n/* **************************************************************************************\n *   ADVANCED AND EXPERIMENTAL FUNCTIONS\n ****************************************************************************************\n * The definitions in the following section are considered experimental.\n * They are provided for advanced scenarios.\n * They should never be used with a dynamic library, as prototypes may change in the future.\n * Use them only in association with static linking.\n * ***************************************************************************************/\n\n#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY)\n#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* This can be overridden externally to hide static symbols. */\n#ifndef ZSTDLIB_STATIC_API\n#  if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)\n#    define ZSTDLIB_STATIC_API __declspec(dllexport) ZSTDLIB_VISIBLE\n#  elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)\n#    define ZSTDLIB_STATIC_API __declspec(dllimport) ZSTDLIB_VISIBLE\n#  else\n#    define ZSTDLIB_STATIC_API ZSTDLIB_VISIBLE\n#  endif\n#endif\n\n/****************************************************************************************\n *   experimental API (static linking only)\n ****************************************************************************************\n * The following symbols and constants\n * are not planned to join \"stable API\" status in the near future.\n * They can still change in future versions.\n * Some of them are planned to remain in the static_only section indefinitely.\n * Some of them might be removed in the future (especially when redundant with existing stable functions)\n * ***************************************************************************************/\n\n#define ZSTD_FRAMEHEADERSIZE_PREFIX(format) ((format) == ZSTD_f_zstd1 ? 5 : 1)   /* minimum input size required to query frame header size */\n#define ZSTD_FRAMEHEADERSIZE_MIN(format)    ((format) == ZSTD_f_zstd1 ? 6 : 2)\n#define ZSTD_FRAMEHEADERSIZE_MAX   18   /* can be useful for static allocation */\n#define ZSTD_SKIPPABLEHEADERSIZE    8\n\n/* compression parameter bounds */\n#define ZSTD_WINDOWLOG_MAX_32    30\n#define ZSTD_WINDOWLOG_MAX_64    31\n#define ZSTD_WINDOWLOG_MAX     ((int)(sizeof(size_t) == 4 ? ZSTD_WINDOWLOG_MAX_32 : ZSTD_WINDOWLOG_MAX_64))\n#define ZSTD_WINDOWLOG_MIN       10\n#define ZSTD_HASHLOG_MAX       ((ZSTD_WINDOWLOG_MAX < 30) ? ZSTD_WINDOWLOG_MAX : 30)\n#define ZSTD_HASHLOG_MIN          6\n#define ZSTD_CHAINLOG_MAX_32     29\n#define ZSTD_CHAINLOG_MAX_64     30\n#define ZSTD_CHAINLOG_MAX      ((int)(sizeof(size_t) == 4 ? ZSTD_CHAINLOG_MAX_32 : ZSTD_CHAINLOG_MAX_64))\n#define ZSTD_CHAINLOG_MIN        ZSTD_HASHLOG_MIN\n#define ZSTD_SEARCHLOG_MAX      (ZSTD_WINDOWLOG_MAX-1)\n#define ZSTD_SEARCHLOG_MIN        1\n#define ZSTD_MINMATCH_MAX         7   /* only for ZSTD_fast, other strategies are limited to 6 */\n#define ZSTD_MINMATCH_MIN         3   /* only for ZSTD_btopt+, faster strategies are limited to 4 */\n#define ZSTD_TARGETLENGTH_MAX    ZSTD_BLOCKSIZE_MAX\n#define ZSTD_TARGETLENGTH_MIN     0   /* note : comparing this constant to an unsigned results in a tautological test */\n#define ZSTD_STRATEGY_MIN        ZSTD_fast\n#define ZSTD_STRATEGY_MAX        ZSTD_btultra2\n#define ZSTD_BLOCKSIZE_MAX_MIN (1 << 10) /* The minimum valid max blocksize. Maximum blocksizes smaller than this make compressBound() inaccurate. */\n\n\n#define ZSTD_OVERLAPLOG_MIN       0\n#define ZSTD_OVERLAPLOG_MAX       9\n\n#define ZSTD_WINDOWLOG_LIMIT_DEFAULT 27   /* by default, the streaming decoder will refuse any frame\n                                           * requiring larger than (1<<ZSTD_WINDOWLOG_LIMIT_DEFAULT) window size,\n                                           * to preserve host's memory from unreasonable requirements.\n                                           * This limit can be overridden using ZSTD_DCtx_setParameter(,ZSTD_d_windowLogMax,).\n                                           * The limit does not apply for one-pass decoders (such as ZSTD_decompress()), since no additional memory is allocated */\n\n\n/* LDM parameter bounds */\n#define ZSTD_LDM_HASHLOG_MIN      ZSTD_HASHLOG_MIN\n#define ZSTD_LDM_HASHLOG_MAX      ZSTD_HASHLOG_MAX\n#define ZSTD_LDM_MINMATCH_MIN        4\n#define ZSTD_LDM_MINMATCH_MAX     4096\n#define ZSTD_LDM_BUCKETSIZELOG_MIN   1\n#define ZSTD_LDM_BUCKETSIZELOG_MAX   8\n#define ZSTD_LDM_HASHRATELOG_MIN     0\n#define ZSTD_LDM_HASHRATELOG_MAX (ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN)\n\n/* Advanced parameter bounds */\n#define ZSTD_TARGETCBLOCKSIZE_MIN   1340 /* suitable to fit into an ethernet / wifi / 4G transport frame */\n#define ZSTD_TARGETCBLOCKSIZE_MAX   ZSTD_BLOCKSIZE_MAX\n#define ZSTD_SRCSIZEHINT_MIN        0\n#define ZSTD_SRCSIZEHINT_MAX        INT_MAX\n\n\n/* ---  Advanced types  --- */\n\ntypedef struct ZSTD_CCtx_params_s ZSTD_CCtx_params;\n\ntypedef struct {\n    unsigned int offset;      /* The offset of the match. (NOT the same as the offset code)\n                               * If offset == 0 and matchLength == 0, this sequence represents the last\n                               * literals in the block of litLength size.\n                               */\n\n    unsigned int litLength;   /* Literal length of the sequence. */\n    unsigned int matchLength; /* Match length of the sequence. */\n\n                              /* Note: Users of this API may provide a sequence with matchLength == litLength == offset == 0.\n                               * In this case, we will treat the sequence as a marker for a block boundary.\n                               */\n\n    unsigned int rep;         /* Represents which repeat offset is represented by the field 'offset'.\n                               * Ranges from [0, 3].\n                               *\n                               * Repeat offsets are essentially previous offsets from previous sequences sorted in\n                               * recency order. For more detail, see doc/zstd_compression_format.md\n                               *\n                               * If rep == 0, then 'offset' does not contain a repeat offset.\n                               * If rep > 0:\n                               *  If litLength != 0:\n                               *      rep == 1 --> offset == repeat_offset_1\n                               *      rep == 2 --> offset == repeat_offset_2\n                               *      rep == 3 --> offset == repeat_offset_3\n                               *  If litLength == 0:\n                               *      rep == 1 --> offset == repeat_offset_2\n                               *      rep == 2 --> offset == repeat_offset_3\n                               *      rep == 3 --> offset == repeat_offset_1 - 1\n                               *\n                               * Note: This field is optional. ZSTD_generateSequences() will calculate the value of\n                               * 'rep', but repeat offsets do not necessarily need to be calculated from an external\n                               * sequence provider perspective. For example, ZSTD_compressSequences() does not\n                               * use this 'rep' field at all (as of now).\n                               */\n} ZSTD_Sequence;\n\ntypedef struct {\n    unsigned windowLog;       /**< largest match distance : larger == more compression, more memory needed during decompression */\n    unsigned chainLog;        /**< fully searched segment : larger == more compression, slower, more memory (useless for fast) */\n    unsigned hashLog;         /**< dispatch table : larger == faster, more memory */\n    unsigned searchLog;       /**< nb of searches : larger == more compression, slower */\n    unsigned minMatch;        /**< match length searched : larger == faster decompression, sometimes less compression */\n    unsigned targetLength;    /**< acceptable match size for optimal parser (only) : larger == more compression, slower */\n    ZSTD_strategy strategy;   /**< see ZSTD_strategy definition above */\n} ZSTD_compressionParameters;\n\ntypedef struct {\n    int contentSizeFlag; /**< 1: content size will be in frame header (when known) */\n    int checksumFlag;    /**< 1: generate a 32-bits checksum using XXH64 algorithm at end of frame, for error detection */\n    int noDictIDFlag;    /**< 1: no dictID will be saved into frame header (dictID is only useful for dictionary compression) */\n} ZSTD_frameParameters;\n\ntypedef struct {\n    ZSTD_compressionParameters cParams;\n    ZSTD_frameParameters fParams;\n} ZSTD_parameters;\n\ntypedef enum {\n    ZSTD_dct_auto = 0,       /* dictionary is \"full\" when starting with ZSTD_MAGIC_DICTIONARY, otherwise it is \"rawContent\" */\n    ZSTD_dct_rawContent = 1, /* ensures dictionary is always loaded as rawContent, even if it starts with ZSTD_MAGIC_DICTIONARY */\n    ZSTD_dct_fullDict = 2    /* refuses to load a dictionary if it does not respect Zstandard's specification, starting with ZSTD_MAGIC_DICTIONARY */\n} ZSTD_dictContentType_e;\n\ntypedef enum {\n    ZSTD_dlm_byCopy = 0,  /**< Copy dictionary content internally */\n    ZSTD_dlm_byRef = 1    /**< Reference dictionary content -- the dictionary buffer must outlive its users. */\n} ZSTD_dictLoadMethod_e;\n\ntypedef enum {\n    ZSTD_f_zstd1 = 0,           /* zstd frame format, specified in zstd_compression_format.md (default) */\n    ZSTD_f_zstd1_magicless = 1  /* Variant of zstd frame format, without initial 4-bytes magic number.\n                                 * Useful to save 4 bytes per generated frame.\n                                 * Decoder cannot recognise automatically this format, requiring this instruction. */\n} ZSTD_format_e;\n\ntypedef enum {\n    /* Note: this enum controls ZSTD_d_forceIgnoreChecksum */\n    ZSTD_d_validateChecksum = 0,\n    ZSTD_d_ignoreChecksum = 1\n} ZSTD_forceIgnoreChecksum_e;\n\ntypedef enum {\n    /* Note: this enum controls ZSTD_d_refMultipleDDicts */\n    ZSTD_rmd_refSingleDDict = 0,\n    ZSTD_rmd_refMultipleDDicts = 1\n} ZSTD_refMultipleDDicts_e;\n\ntypedef enum {\n    /* Note: this enum and the behavior it controls are effectively internal\n     * implementation details of the compressor. They are expected to continue\n     * to evolve and should be considered only in the context of extremely\n     * advanced performance tuning.\n     *\n     * Zstd currently supports the use of a CDict in three ways:\n     *\n     * - The contents of the CDict can be copied into the working context. This\n     *   means that the compression can search both the dictionary and input\n     *   while operating on a single set of internal tables. This makes\n     *   the compression faster per-byte of input. However, the initial copy of\n     *   the CDict's tables incurs a fixed cost at the beginning of the\n     *   compression. For small compressions (< 8 KB), that copy can dominate\n     *   the cost of the compression.\n     *\n     * - The CDict's tables can be used in-place. In this model, compression is\n     *   slower per input byte, because the compressor has to search two sets of\n     *   tables. However, this model incurs no start-up cost (as long as the\n     *   working context's tables can be reused). For small inputs, this can be\n     *   faster than copying the CDict's tables.\n     *\n     * - The CDict's tables are not used at all, and instead we use the working\n     *   context alone to reload the dictionary and use params based on the source\n     *   size. See ZSTD_compress_insertDictionary() and ZSTD_compress_usingDict().\n     *   This method is effective when the dictionary sizes are very small relative\n     *   to the input size, and the input size is fairly large to begin with.\n     *\n     * Zstd has a simple internal heuristic that selects which strategy to use\n     * at the beginning of a compression. However, if experimentation shows that\n     * Zstd is making poor choices, it is possible to override that choice with\n     * this enum.\n     */\n    ZSTD_dictDefaultAttach = 0, /* Use the default heuristic. */\n    ZSTD_dictForceAttach   = 1, /* Never copy the dictionary. */\n    ZSTD_dictForceCopy     = 2, /* Always copy the dictionary. */\n    ZSTD_dictForceLoad     = 3  /* Always reload the dictionary */\n} ZSTD_dictAttachPref_e;\n\ntypedef enum {\n  ZSTD_lcm_auto = 0,          /**< Automatically determine the compression mode based on the compression level.\n                               *   Negative compression levels will be uncompressed, and positive compression\n                               *   levels will be compressed. */\n  ZSTD_lcm_huffman = 1,       /**< Always attempt Huffman compression. Uncompressed literals will still be\n                               *   emitted if Huffman compression is not profitable. */\n  ZSTD_lcm_uncompressed = 2   /**< Always emit uncompressed literals. */\n} ZSTD_literalCompressionMode_e;\n\ntypedef enum {\n  /* Note: This enum controls features which are conditionally beneficial.\n   * Zstd can take a decision on whether or not to enable the feature (ZSTD_ps_auto),\n   * but setting the switch to ZSTD_ps_enable or ZSTD_ps_disable force enable/disable the feature.\n   */\n  ZSTD_ps_auto = 0,         /* Let the library automatically determine whether the feature shall be enabled */\n  ZSTD_ps_enable = 1,       /* Force-enable the feature */\n  ZSTD_ps_disable = 2       /* Do not use the feature */\n} ZSTD_ParamSwitch_e;\n#define ZSTD_paramSwitch_e ZSTD_ParamSwitch_e  /* old name */\n\n/***************************************\n*  Frame header and size functions\n***************************************/\n\n/*! ZSTD_findDecompressedSize() :\n *  `src` should point to the start of a series of ZSTD encoded and/or skippable frames\n *  `srcSize` must be the _exact_ size of this series\n *       (i.e. there should be a frame boundary at `src + srcSize`)\n *  @return : - decompressed size of all data in all successive frames\n *            - if the decompressed size cannot be determined: ZSTD_CONTENTSIZE_UNKNOWN\n *            - if an error occurred: ZSTD_CONTENTSIZE_ERROR\n *\n *   note 1 : decompressed size is an optional field, that may not be present, especially in streaming mode.\n *            When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size.\n *            In which case, it's necessary to use streaming mode to decompress data.\n *   note 2 : decompressed size is always present when compression is done with ZSTD_compress()\n *   note 3 : decompressed size can be very large (64-bits value),\n *            potentially larger than what local system can handle as a single memory segment.\n *            In which case, it's necessary to use streaming mode to decompress data.\n *   note 4 : If source is untrusted, decompressed size could be wrong or intentionally modified.\n *            Always ensure result fits within application's authorized limits.\n *            Each application can set its own limits.\n *   note 5 : ZSTD_findDecompressedSize handles multiple frames, and so it must traverse the input to\n *            read each contained frame header.  This is fast as most of the data is skipped,\n *            however it does mean that all frame data must be present and valid. */\nZSTDLIB_STATIC_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize);\n\n/*! ZSTD_decompressBound() :\n *  `src` should point to the start of a series of ZSTD encoded and/or skippable frames\n *  `srcSize` must be the _exact_ size of this series\n *       (i.e. there should be a frame boundary at `src + srcSize`)\n *  @return : - upper-bound for the decompressed size of all data in all successive frames\n *            - if an error occurred: ZSTD_CONTENTSIZE_ERROR\n *\n *  note 1  : an error can occur if `src` contains an invalid or incorrectly formatted frame.\n *  note 2  : the upper-bound is exact when the decompressed size field is available in every ZSTD encoded frame of `src`.\n *            in this case, `ZSTD_findDecompressedSize` and `ZSTD_decompressBound` return the same value.\n *  note 3  : when the decompressed size field isn't available, the upper-bound for that frame is calculated by:\n *              upper-bound = # blocks * min(128 KB, Window_Size)\n */\nZSTDLIB_STATIC_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize);\n\n/*! ZSTD_frameHeaderSize() :\n *  srcSize must be large enough, aka >= ZSTD_FRAMEHEADERSIZE_PREFIX.\n * @return : size of the Frame Header,\n *           or an error code (if srcSize is too small) */\nZSTDLIB_STATIC_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize);\n\ntypedef enum { ZSTD_frame, ZSTD_skippableFrame } ZSTD_FrameType_e;\n#define ZSTD_frameType_e ZSTD_FrameType_e /* old name */\ntypedef struct {\n    unsigned long long frameContentSize; /* if == ZSTD_CONTENTSIZE_UNKNOWN, it means this field is not available. 0 means \"empty\" */\n    unsigned long long windowSize;       /* can be very large, up to <= frameContentSize */\n    unsigned blockSizeMax;\n    ZSTD_FrameType_e frameType;          /* if == ZSTD_skippableFrame, frameContentSize is the size of skippable content */\n    unsigned headerSize;\n    unsigned dictID;                     /* for ZSTD_skippableFrame, contains the skippable magic variant [0-15] */\n    unsigned checksumFlag;\n    unsigned _reserved1;\n    unsigned _reserved2;\n} ZSTD_FrameHeader;\n#define ZSTD_frameHeader ZSTD_FrameHeader /* old name */\n\n/*! ZSTD_getFrameHeader() :\n *  decode Frame Header into `zfhPtr`, or requires larger `srcSize`.\n * @return : 0 => header is complete, `zfhPtr` is correctly filled,\n *          >0 => `srcSize` is too small, @return value is the wanted `srcSize` amount, `zfhPtr` is not filled,\n *           or an error code, which can be tested using ZSTD_isError() */\nZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader(ZSTD_FrameHeader* zfhPtr, const void* src, size_t srcSize);\n/*! ZSTD_getFrameHeader_advanced() :\n *  same as ZSTD_getFrameHeader(),\n *  with added capability to select a format (like ZSTD_f_zstd1_magicless) */\nZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader_advanced(ZSTD_FrameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format);\n\n/*! ZSTD_decompressionMargin() :\n * Zstd supports in-place decompression, where the input and output buffers overlap.\n * In this case, the output buffer must be at least (Margin + Output_Size) bytes large,\n * and the input buffer must be at the end of the output buffer.\n *\n *  _______________________ Output Buffer ________________________\n * |                                                              |\n * |                                        ____ Input Buffer ____|\n * |                                       |                      |\n * v                                       v                      v\n * |---------------------------------------|-----------|----------|\n * ^                                                   ^          ^\n * |___________________ Output_Size ___________________|_ Margin _|\n *\n * NOTE: See also ZSTD_DECOMPRESSION_MARGIN().\n * NOTE: This applies only to single-pass decompression through ZSTD_decompress() or\n * ZSTD_decompressDCtx().\n * NOTE: This function supports multi-frame input.\n *\n * @param src The compressed frame(s)\n * @param srcSize The size of the compressed frame(s)\n * @returns The decompression margin or an error that can be checked with ZSTD_isError().\n */\nZSTDLIB_STATIC_API size_t ZSTD_decompressionMargin(const void* src, size_t srcSize);\n\n/*! ZSTD_DECOMPRESS_MARGIN() :\n * Similar to ZSTD_decompressionMargin(), but instead of computing the margin from\n * the compressed frame, compute it from the original size and the blockSizeLog.\n * See ZSTD_decompressionMargin() for details.\n *\n * WARNING: This macro does not support multi-frame input, the input must be a single\n * zstd frame. If you need that support use the function, or implement it yourself.\n *\n * @param originalSize The original uncompressed size of the data.\n * @param blockSize    The block size == MIN(windowSize, ZSTD_BLOCKSIZE_MAX).\n *                     Unless you explicitly set the windowLog smaller than\n *                     ZSTD_BLOCKSIZELOG_MAX you can just use ZSTD_BLOCKSIZE_MAX.\n */\n#define ZSTD_DECOMPRESSION_MARGIN(originalSize, blockSize) ((size_t)(                                              \\\n        ZSTD_FRAMEHEADERSIZE_MAX                                                              /* Frame header */ + \\\n        4                                                                                         /* checksum */ + \\\n        ((originalSize) == 0 ? 0 : 3 * (((originalSize) + (blockSize) - 1) / blockSize)) /* 3 bytes per block */ + \\\n        (blockSize)                                                                    /* One block of margin */   \\\n    ))\n\ntypedef enum {\n  ZSTD_sf_noBlockDelimiters = 0,         /* ZSTD_Sequence[] has no block delimiters, just sequences */\n  ZSTD_sf_explicitBlockDelimiters = 1    /* ZSTD_Sequence[] contains explicit block delimiters */\n} ZSTD_SequenceFormat_e;\n#define ZSTD_sequenceFormat_e ZSTD_SequenceFormat_e /* old name */\n\n/*! ZSTD_sequenceBound() :\n * `srcSize` : size of the input buffer\n *  @return : upper-bound for the number of sequences that can be generated\n *            from a buffer of srcSize bytes\n *\n *  note : returns number of sequences - to get bytes, multiply by sizeof(ZSTD_Sequence).\n */\nZSTDLIB_STATIC_API size_t ZSTD_sequenceBound(size_t srcSize);\n\n/*! ZSTD_generateSequences() :\n * WARNING: This function is meant for debugging and informational purposes ONLY!\n * Its implementation is flawed, and it will be deleted in a future version.\n * It is not guaranteed to succeed, as there are several cases where it will give\n * up and fail. You should NOT use this function in production code.\n *\n * This function is deprecated, and will be removed in a future version.\n *\n * Generate sequences using ZSTD_compress2(), given a source buffer.\n *\n * @param zc The compression context to be used for ZSTD_compress2(). Set any\n *           compression parameters you need on this context.\n * @param outSeqs The output sequences buffer of size @p outSeqsSize\n * @param outSeqsCapacity The size of the output sequences buffer.\n *                    ZSTD_sequenceBound(srcSize) is an upper bound on the number\n *                    of sequences that can be generated.\n * @param src The source buffer to generate sequences from of size @p srcSize.\n * @param srcSize The size of the source buffer.\n *\n * Each block will end with a dummy sequence\n * with offset == 0, matchLength == 0, and litLength == length of last literals.\n * litLength may be == 0, and if so, then the sequence of (of: 0 ml: 0 ll: 0)\n * simply acts as a block delimiter.\n *\n * @returns The number of sequences generated, necessarily less than\n *          ZSTD_sequenceBound(srcSize), or an error code that can be checked\n *          with ZSTD_isError().\n */\nZSTD_DEPRECATED(\"For debugging only, will be replaced by ZSTD_extractSequences()\")\nZSTDLIB_STATIC_API size_t\nZSTD_generateSequences(ZSTD_CCtx* zc,\n                       ZSTD_Sequence* outSeqs, size_t outSeqsCapacity,\n                       const void* src, size_t srcSize);\n\n/*! ZSTD_mergeBlockDelimiters() :\n * Given an array of ZSTD_Sequence, remove all sequences that represent block delimiters/last literals\n * by merging them into the literals of the next sequence.\n *\n * As such, the final generated result has no explicit representation of block boundaries,\n * and the final last literals segment is not represented in the sequences.\n *\n * The output of this function can be fed into ZSTD_compressSequences() with CCtx\n * setting of ZSTD_c_blockDelimiters as ZSTD_sf_noBlockDelimiters\n * @return : number of sequences left after merging\n */\nZSTDLIB_STATIC_API size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize);\n\n/*! ZSTD_compressSequences() :\n * Compress an array of ZSTD_Sequence, associated with @src buffer, into dst.\n * @src contains the entire input (not just the literals).\n * If @srcSize > sum(sequence.length), the remaining bytes are considered all literals\n * If a dictionary is included, then the cctx should reference the dict (see: ZSTD_CCtx_refCDict(), ZSTD_CCtx_loadDictionary(), etc.).\n * The entire source is compressed into a single frame.\n *\n * The compression behavior changes based on cctx params. In particular:\n *    If ZSTD_c_blockDelimiters == ZSTD_sf_noBlockDelimiters, the array of ZSTD_Sequence is expected to contain\n *    no block delimiters (defined in ZSTD_Sequence). Block boundaries are roughly determined based on\n *    the block size derived from the cctx, and sequences may be split. This is the default setting.\n *\n *    If ZSTD_c_blockDelimiters == ZSTD_sf_explicitBlockDelimiters, the array of ZSTD_Sequence is expected to contain\n *    valid block delimiters (defined in ZSTD_Sequence). Behavior is undefined if no block delimiters are provided.\n *\n *    When ZSTD_c_blockDelimiters == ZSTD_sf_explicitBlockDelimiters, it's possible to decide generating repcodes\n *    using the advanced parameter ZSTD_c_repcodeResolution. Repcodes will improve compression ratio, though the benefit\n *    can vary greatly depending on Sequences. On the other hand, repcode resolution is an expensive operation.\n *    By default, it's disabled at low (<10) compression levels, and enabled above the threshold (>=10).\n *    ZSTD_c_repcodeResolution makes it possible to directly manage this processing in either direction.\n *\n *    If ZSTD_c_validateSequences == 0, this function blindly accepts the Sequences provided. Invalid Sequences cause undefined\n *    behavior. If ZSTD_c_validateSequences == 1, then the function will detect invalid Sequences (see doc/zstd_compression_format.md for\n *    specifics regarding offset/matchlength requirements) and then bail out and return an error.\n *\n *    In addition to the two adjustable experimental params, there are other important cctx params.\n *    - ZSTD_c_minMatch MUST be set as less than or equal to the smallest match generated by the match finder. It has a minimum value of ZSTD_MINMATCH_MIN.\n *    - ZSTD_c_compressionLevel accordingly adjusts the strength of the entropy coder, as it would in typical compression.\n *    - ZSTD_c_windowLog affects offset validation: this function will return an error at higher debug levels if a provided offset\n *      is larger than what the spec allows for a given window log and dictionary (if present). See: doc/zstd_compression_format.md\n *\n * Note: Repcodes are, as of now, always re-calculated within this function, ZSTD_Sequence.rep is effectively unused.\n * Dev Note: Once ability to ingest repcodes become available, the explicit block delims mode must respect those repcodes exactly,\n *         and cannot emit an RLE block that disagrees with the repcode history.\n * @return : final compressed size, or a ZSTD error code.\n */\nZSTDLIB_STATIC_API size_t\nZSTD_compressSequences(ZSTD_CCtx* cctx,\n                       void* dst, size_t dstCapacity,\n                 const ZSTD_Sequence* inSeqs, size_t inSeqsSize,\n                 const void* src, size_t srcSize);\n\n\n/*! ZSTD_compressSequencesAndLiterals() :\n * This is a variant of ZSTD_compressSequences() which,\n * instead of receiving (src,srcSize) as input parameter, receives (literals,litSize),\n * aka all the literals, already extracted and laid out into a single continuous buffer.\n * This can be useful if the process generating the sequences also happens to generate the buffer of literals,\n * thus skipping an extraction + caching stage.\n * It's a speed optimization, useful when the right conditions are met,\n * but it also features the following limitations:\n * - Only supports explicit delimiter mode\n * - Currently does not support Sequences validation (so input Sequences are trusted)\n * - Not compatible with frame checksum, which must be disabled\n * - If any block is incompressible, will fail and return an error\n * - @litSize must be == sum of all @.litLength fields in @inSeqs. Any discrepancy will generate an error.\n * - @litBufCapacity is the size of the underlying buffer into which literals are written, starting at address @literals.\n *   @litBufCapacity must be at least 8 bytes larger than @litSize.\n * - @decompressedSize must be correct, and correspond to the sum of all Sequences. Any discrepancy will generate an error.\n * @return : final compressed size, or a ZSTD error code.\n */\nZSTDLIB_STATIC_API size_t\nZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx,\n                                  void* dst, size_t dstCapacity,\n                            const ZSTD_Sequence* inSeqs, size_t nbSequences,\n                            const void* literals, size_t litSize, size_t litBufCapacity,\n                            size_t decompressedSize);\n\n\n/*! ZSTD_writeSkippableFrame() :\n * Generates a zstd skippable frame containing data given by src, and writes it to dst buffer.\n *\n * Skippable frames begin with a 4-byte magic number. There are 16 possible choices of magic number,\n * ranging from ZSTD_MAGIC_SKIPPABLE_START to ZSTD_MAGIC_SKIPPABLE_START+15.\n * As such, the parameter magicVariant controls the exact skippable frame magic number variant used,\n * so the magic number used will be ZSTD_MAGIC_SKIPPABLE_START + magicVariant.\n *\n * Returns an error if destination buffer is not large enough, if the source size is not representable\n * with a 4-byte unsigned int, or if the parameter magicVariant is greater than 15 (and therefore invalid).\n *\n * @return : number of bytes written or a ZSTD error.\n */\nZSTDLIB_STATIC_API size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity,\n                                             const void* src, size_t srcSize,\n                                                   unsigned magicVariant);\n\n/*! ZSTD_readSkippableFrame() :\n * Retrieves the content of a zstd skippable frame starting at @src, and writes it to @dst buffer.\n *\n * The parameter @magicVariant will receive the magicVariant that was supplied when the frame was written,\n * i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START.\n * This can be NULL if the caller is not interested in the magicVariant.\n *\n * Returns an error if destination buffer is not large enough, or if the frame is not skippable.\n *\n * @return : number of bytes written or a ZSTD error.\n */\nZSTDLIB_STATIC_API size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity,\n                                                  unsigned* magicVariant,\n                                                  const void* src, size_t srcSize);\n\n/*! ZSTD_isSkippableFrame() :\n *  Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame.\n */\nZSTDLIB_STATIC_API unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size);\n\n\n\n/***************************************\n*  Memory management\n***************************************/\n\n/*! ZSTD_estimate*() :\n *  These functions make it possible to estimate memory usage\n *  of a future {D,C}Ctx, before its creation.\n *  This is useful in combination with ZSTD_initStatic(),\n *  which makes it possible to employ a static buffer for ZSTD_CCtx* state.\n *\n *  ZSTD_estimateCCtxSize() will provide a memory budget large enough\n *  to compress data of any size using one-shot compression ZSTD_compressCCtx() or ZSTD_compress2()\n *  associated with any compression level up to max specified one.\n *  The estimate will assume the input may be arbitrarily large,\n *  which is the worst case.\n *\n *  Note that the size estimation is specific for one-shot compression,\n *  it is not valid for streaming (see ZSTD_estimateCStreamSize*())\n *  nor other potential ways of using a ZSTD_CCtx* state.\n *\n *  When srcSize can be bound by a known and rather \"small\" value,\n *  this knowledge can be used to provide a tighter budget estimation\n *  because the ZSTD_CCtx* state will need less memory for small inputs.\n *  This tighter estimation can be provided by employing more advanced functions\n *  ZSTD_estimateCCtxSize_usingCParams(), which can be used in tandem with ZSTD_getCParams(),\n *  and ZSTD_estimateCCtxSize_usingCCtxParams(), which can be used in tandem with ZSTD_CCtxParams_setParameter().\n *  Both can be used to estimate memory using custom compression parameters and arbitrary srcSize limits.\n *\n *  Note : only single-threaded compression is supported.\n *  ZSTD_estimateCCtxSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1.\n */\nZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize(int maxCompressionLevel);\nZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams);\nZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params);\nZSTDLIB_STATIC_API size_t ZSTD_estimateDCtxSize(void);\n\n/*! ZSTD_estimateCStreamSize() :\n *  ZSTD_estimateCStreamSize() will provide a memory budget large enough for streaming compression\n *  using any compression level up to the max specified one.\n *  It will also consider src size to be arbitrarily \"large\", which is a worst case scenario.\n *  If srcSize is known to always be small, ZSTD_estimateCStreamSize_usingCParams() can provide a tighter estimation.\n *  ZSTD_estimateCStreamSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel.\n *  ZSTD_estimateCStreamSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParams_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1.\n *  Note : CStream size estimation is only correct for single-threaded compression.\n *  ZSTD_estimateCStreamSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1.\n *  Note 2 : ZSTD_estimateCStreamSize* functions are not compatible with the Block-Level Sequence Producer API at this time.\n *  Size estimates assume that no external sequence producer is registered.\n *\n *  ZSTD_DStream memory budget depends on frame's window Size.\n *  This information can be passed manually, using ZSTD_estimateDStreamSize,\n *  or deducted from a valid frame Header, using ZSTD_estimateDStreamSize_fromFrame();\n *  Any frame requesting a window size larger than max specified one will be rejected.\n *  Note : if streaming is init with function ZSTD_init?Stream_usingDict(),\n *         an internal ?Dict will be created, which additional size is not estimated here.\n *         In this case, get total size by adding ZSTD_estimate?DictSize\n */\nZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize(int maxCompressionLevel);\nZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams);\nZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params);\nZSTDLIB_STATIC_API size_t ZSTD_estimateDStreamSize(size_t maxWindowSize);\nZSTDLIB_STATIC_API size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize);\n\n/*! ZSTD_estimate?DictSize() :\n *  ZSTD_estimateCDictSize() will bet that src size is relatively \"small\", and content is copied, like ZSTD_createCDict().\n *  ZSTD_estimateCDictSize_advanced() makes it possible to control compression parameters precisely, like ZSTD_createCDict_advanced().\n *  Note : dictionaries created by reference (`ZSTD_dlm_byRef`) are logically smaller.\n */\nZSTDLIB_STATIC_API size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel);\nZSTDLIB_STATIC_API size_t ZSTD_estimateCDictSize_advanced(size_t dictSize, ZSTD_compressionParameters cParams, ZSTD_dictLoadMethod_e dictLoadMethod);\nZSTDLIB_STATIC_API size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod);\n\n/*! ZSTD_initStatic*() :\n *  Initialize an object using a pre-allocated fixed-size buffer.\n *  workspace: The memory area to emplace the object into.\n *             Provided pointer *must be 8-bytes aligned*.\n *             Buffer must outlive object.\n *  workspaceSize: Use ZSTD_estimate*Size() to determine\n *                 how large workspace must be to support target scenario.\n * @return : pointer to object (same address as workspace, just different type),\n *           or NULL if error (size too small, incorrect alignment, etc.)\n *  Note : zstd will never resize nor malloc() when using a static buffer.\n *         If the object requires more memory than available,\n *         zstd will just error out (typically ZSTD_error_memory_allocation).\n *  Note 2 : there is no corresponding \"free\" function.\n *           Since workspace is allocated externally, it must be freed externally too.\n *  Note 3 : cParams : use ZSTD_getCParams() to convert a compression level\n *           into its associated cParams.\n *  Limitation 1 : currently not compatible with internal dictionary creation, triggered by\n *                 ZSTD_CCtx_loadDictionary(), ZSTD_initCStream_usingDict() or ZSTD_initDStream_usingDict().\n *  Limitation 2 : static cctx currently not compatible with multi-threading.\n *  Limitation 3 : static dctx is incompatible with legacy support.\n */\nZSTDLIB_STATIC_API ZSTD_CCtx*    ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize);\nZSTDLIB_STATIC_API ZSTD_CStream* ZSTD_initStaticCStream(void* workspace, size_t workspaceSize);    /**< same as ZSTD_initStaticCCtx() */\n\nZSTDLIB_STATIC_API ZSTD_DCtx*    ZSTD_initStaticDCtx(void* workspace, size_t workspaceSize);\nZSTDLIB_STATIC_API ZSTD_DStream* ZSTD_initStaticDStream(void* workspace, size_t workspaceSize);    /**< same as ZSTD_initStaticDCtx() */\n\nZSTDLIB_STATIC_API const ZSTD_CDict* ZSTD_initStaticCDict(\n                                        void* workspace, size_t workspaceSize,\n                                        const void* dict, size_t dictSize,\n                                        ZSTD_dictLoadMethod_e dictLoadMethod,\n                                        ZSTD_dictContentType_e dictContentType,\n                                        ZSTD_compressionParameters cParams);\n\nZSTDLIB_STATIC_API const ZSTD_DDict* ZSTD_initStaticDDict(\n                                        void* workspace, size_t workspaceSize,\n                                        const void* dict, size_t dictSize,\n                                        ZSTD_dictLoadMethod_e dictLoadMethod,\n                                        ZSTD_dictContentType_e dictContentType);\n\n\n/*! Custom memory allocation :\n *  These prototypes make it possible to pass your own allocation/free functions.\n *  ZSTD_customMem is provided at creation time, using ZSTD_create*_advanced() variants listed below.\n *  All allocation/free operations will be completed using these custom variants instead of regular <stdlib.h> ones.\n */\ntypedef void* (*ZSTD_allocFunction) (void* opaque, size_t size);\ntypedef void  (*ZSTD_freeFunction) (void* opaque, void* address);\ntypedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem;\n#if defined(__clang__) && __clang_major__ >= 5\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wzero-as-null-pointer-constant\"\n#endif\nstatic\n#ifdef __GNUC__\n__attribute__((__unused__))\n#endif\nZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL };  /**< this constant defers to stdlib's functions */\n#if defined(__clang__) && __clang_major__ >= 5\n#pragma clang diagnostic pop\n#endif\n\nZSTDLIB_STATIC_API ZSTD_CCtx*    ZSTD_createCCtx_advanced(ZSTD_customMem customMem);\nZSTDLIB_STATIC_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem);\nZSTDLIB_STATIC_API ZSTD_DCtx*    ZSTD_createDCtx_advanced(ZSTD_customMem customMem);\nZSTDLIB_STATIC_API ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem);\n\nZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize,\n                                                  ZSTD_dictLoadMethod_e dictLoadMethod,\n                                                  ZSTD_dictContentType_e dictContentType,\n                                                  ZSTD_compressionParameters cParams,\n                                                  ZSTD_customMem customMem);\n\n/*! Thread pool :\n *  These prototypes make it possible to share a thread pool among multiple compression contexts.\n *  This can limit resources for applications with multiple threads where each one uses\n *  a threaded compression mode (via ZSTD_c_nbWorkers parameter).\n *  ZSTD_createThreadPool creates a new thread pool with a given number of threads.\n *  Note that the lifetime of such pool must exist while being used.\n *  ZSTD_CCtx_refThreadPool assigns a thread pool to a context (use NULL argument value\n *  to use an internal thread pool).\n *  ZSTD_freeThreadPool frees a thread pool, accepts NULL pointer.\n */\ntypedef struct POOL_ctx_s ZSTD_threadPool;\nZSTDLIB_STATIC_API ZSTD_threadPool* ZSTD_createThreadPool(size_t numThreads);\nZSTDLIB_STATIC_API void ZSTD_freeThreadPool (ZSTD_threadPool* pool);  /* accept NULL pointer */\nZSTDLIB_STATIC_API size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool);\n\n\n/*\n * This API is temporary and is expected to change or disappear in the future!\n */\nZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_advanced2(\n    const void* dict, size_t dictSize,\n    ZSTD_dictLoadMethod_e dictLoadMethod,\n    ZSTD_dictContentType_e dictContentType,\n    const ZSTD_CCtx_params* cctxParams,\n    ZSTD_customMem customMem);\n\nZSTDLIB_STATIC_API ZSTD_DDict* ZSTD_createDDict_advanced(\n    const void* dict, size_t dictSize,\n    ZSTD_dictLoadMethod_e dictLoadMethod,\n    ZSTD_dictContentType_e dictContentType,\n    ZSTD_customMem customMem);\n\n\n/***************************************\n*  Advanced compression functions\n***************************************/\n\n/*! ZSTD_createCDict_byReference() :\n *  Create a digested dictionary for compression\n *  Dictionary content is just referenced, not duplicated.\n *  As a consequence, `dictBuffer` **must** outlive CDict,\n *  and its content must remain unmodified throughout the lifetime of CDict.\n *  note: equivalent to ZSTD_createCDict_advanced(), with dictLoadMethod==ZSTD_dlm_byRef */\nZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);\n\n/*! ZSTD_getCParams() :\n * @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize.\n * `estimatedSrcSize` value is optional, select 0 if not known */\nZSTDLIB_STATIC_API ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);\n\n/*! ZSTD_getParams() :\n *  same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`.\n *  All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0 */\nZSTDLIB_STATIC_API ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);\n\n/*! ZSTD_checkCParams() :\n *  Ensure param values remain within authorized range.\n * @return 0 on success, or an error code (can be checked with ZSTD_isError()) */\nZSTDLIB_STATIC_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params);\n\n/*! ZSTD_adjustCParams() :\n *  optimize params for a given `srcSize` and `dictSize`.\n * `srcSize` can be unknown, in which case use ZSTD_CONTENTSIZE_UNKNOWN.\n * `dictSize` must be `0` when there is no dictionary.\n *  cPar can be invalid : all parameters will be clamped within valid range in the @return struct.\n *  This function never fails (wide contract) */\nZSTDLIB_STATIC_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize);\n\n/*! ZSTD_CCtx_setCParams() :\n *  Set all parameters provided within @p cparams into the working @p cctx.\n *  Note : if modifying parameters during compression (MT mode only),\n *         note that changes to the .windowLog parameter will be ignored.\n * @return 0 on success, or an error code (can be checked with ZSTD_isError()).\n *         On failure, no parameters are updated.\n */\nZSTDLIB_STATIC_API size_t ZSTD_CCtx_setCParams(ZSTD_CCtx* cctx, ZSTD_compressionParameters cparams);\n\n/*! ZSTD_CCtx_setFParams() :\n *  Set all parameters provided within @p fparams into the working @p cctx.\n * @return 0 on success, or an error code (can be checked with ZSTD_isError()).\n */\nZSTDLIB_STATIC_API size_t ZSTD_CCtx_setFParams(ZSTD_CCtx* cctx, ZSTD_frameParameters fparams);\n\n/*! ZSTD_CCtx_setParams() :\n *  Set all parameters provided within @p params into the working @p cctx.\n * @return 0 on success, or an error code (can be checked with ZSTD_isError()).\n */\nZSTDLIB_STATIC_API size_t ZSTD_CCtx_setParams(ZSTD_CCtx* cctx, ZSTD_parameters params);\n\n/*! ZSTD_compress_advanced() :\n *  Note : this function is now DEPRECATED.\n *         It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_setParameter() and other parameter setters.\n *  This prototype will generate compilation warnings. */\nZSTD_DEPRECATED(\"use ZSTD_compress2\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_compress_advanced(ZSTD_CCtx* cctx,\n                              void* dst, size_t dstCapacity,\n                        const void* src, size_t srcSize,\n                        const void* dict,size_t dictSize,\n                              ZSTD_parameters params);\n\n/*! ZSTD_compress_usingCDict_advanced() :\n *  Note : this function is now DEPRECATED.\n *         It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_loadDictionary() and other parameter setters.\n *  This prototype will generate compilation warnings. */\nZSTD_DEPRECATED(\"use ZSTD_compress2 with ZSTD_CCtx_loadDictionary\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,\n                                              void* dst, size_t dstCapacity,\n                                        const void* src, size_t srcSize,\n                                        const ZSTD_CDict* cdict,\n                                              ZSTD_frameParameters fParams);\n\n\n/*! ZSTD_CCtx_loadDictionary_byReference() :\n *  Same as ZSTD_CCtx_loadDictionary(), but dictionary content is referenced, instead of being copied into CCtx.\n *  It saves some memory, but also requires that `dict` outlives its usage within `cctx` */\nZSTDLIB_STATIC_API size_t ZSTD_CCtx_loadDictionary_byReference(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);\n\n/*! ZSTD_CCtx_loadDictionary_advanced() :\n *  Same as ZSTD_CCtx_loadDictionary(), but gives finer control over\n *  how to load the dictionary (by copy ? by reference ?)\n *  and how to interpret it (automatic ? force raw mode ? full mode only ?) */\nZSTDLIB_STATIC_API size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);\n\n/*! ZSTD_CCtx_refPrefix_advanced() :\n *  Same as ZSTD_CCtx_refPrefix(), but gives finer control over\n *  how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */\nZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);\n\n/* ===   experimental parameters   === */\n/* these parameters can be used with ZSTD_setParameter()\n * they are not guaranteed to remain supported in the future */\n\n /* Enables rsyncable mode,\n  * which makes compressed files more rsync friendly\n  * by adding periodic synchronization points to the compressed data.\n  * The target average block size is ZSTD_c_jobSize / 2.\n  * It's possible to modify the job size to increase or decrease\n  * the granularity of the synchronization point.\n  * Once the jobSize is smaller than the window size,\n  * it will result in compression ratio degradation.\n  * NOTE 1: rsyncable mode only works when multithreading is enabled.\n  * NOTE 2: rsyncable performs poorly in combination with long range mode,\n  * since it will decrease the effectiveness of synchronization points,\n  * though mileage may vary.\n  * NOTE 3: Rsyncable mode limits maximum compression speed to ~400 MB/s.\n  * If the selected compression level is already running significantly slower,\n  * the overall speed won't be significantly impacted.\n  */\n #define ZSTD_c_rsyncable ZSTD_c_experimentalParam1\n\n/* Select a compression format.\n * The value must be of type ZSTD_format_e.\n * See ZSTD_format_e enum definition for details */\n#define ZSTD_c_format ZSTD_c_experimentalParam2\n\n/* Force back-reference distances to remain < windowSize,\n * even when referencing into Dictionary content (default:0) */\n#define ZSTD_c_forceMaxWindow ZSTD_c_experimentalParam3\n\n/* Controls whether the contents of a CDict\n * are used in place, or copied into the working context.\n * Accepts values from the ZSTD_dictAttachPref_e enum.\n * See the comments on that enum for an explanation of the feature. */\n#define ZSTD_c_forceAttachDict ZSTD_c_experimentalParam4\n\n/* Controlled with ZSTD_ParamSwitch_e enum.\n * Default is ZSTD_ps_auto.\n * Set to ZSTD_ps_disable to never compress literals.\n * Set to ZSTD_ps_enable to always compress literals. (Note: uncompressed literals\n * may still be emitted if huffman is not beneficial to use.)\n *\n * By default, in ZSTD_ps_auto, the library will decide at runtime whether to use\n * literals compression based on the compression parameters - specifically,\n * negative compression levels do not use literal compression.\n */\n#define ZSTD_c_literalCompressionMode ZSTD_c_experimentalParam5\n\n/* User's best guess of source size.\n * Hint is not valid when srcSizeHint == 0.\n * There is no guarantee that hint is close to actual source size,\n * but compression ratio may regress significantly if guess considerably underestimates */\n#define ZSTD_c_srcSizeHint ZSTD_c_experimentalParam7\n\n/* Controls whether the new and experimental \"dedicated dictionary search\n * structure\" can be used. This feature is still rough around the edges, be\n * prepared for surprising behavior!\n *\n * How to use it:\n *\n * When using a CDict, whether to use this feature or not is controlled at\n * CDict creation, and it must be set in a CCtxParams set passed into that\n * construction (via ZSTD_createCDict_advanced2()). A compression will then\n * use the feature or not based on how the CDict was constructed; the value of\n * this param, set in the CCtx, will have no effect.\n *\n * However, when a dictionary buffer is passed into a CCtx, such as via\n * ZSTD_CCtx_loadDictionary(), this param can be set on the CCtx to control\n * whether the CDict that is created internally can use the feature or not.\n *\n * What it does:\n *\n * Normally, the internal data structures of the CDict are analogous to what\n * would be stored in a CCtx after compressing the contents of a dictionary.\n * To an approximation, a compression using a dictionary can then use those\n * data structures to simply continue what is effectively a streaming\n * compression where the simulated compression of the dictionary left off.\n * Which is to say, the search structures in the CDict are normally the same\n * format as in the CCtx.\n *\n * It is possible to do better, since the CDict is not like a CCtx: the search\n * structures are written once during CDict creation, and then are only read\n * after that, while the search structures in the CCtx are both read and\n * written as the compression goes along. This means we can choose a search\n * structure for the dictionary that is read-optimized.\n *\n * This feature enables the use of that different structure.\n *\n * Note that some of the members of the ZSTD_compressionParameters struct have\n * different semantics and constraints in the dedicated search structure. It is\n * highly recommended that you simply set a compression level in the CCtxParams\n * you pass into the CDict creation call, and avoid messing with the cParams\n * directly.\n *\n * Effects:\n *\n * This will only have any effect when the selected ZSTD_strategy\n * implementation supports this feature. Currently, that's limited to\n * ZSTD_greedy, ZSTD_lazy, and ZSTD_lazy2.\n *\n * Note that this means that the CDict tables can no longer be copied into the\n * CCtx, so the dict attachment mode ZSTD_dictForceCopy will no longer be\n * usable. The dictionary can only be attached or reloaded.\n *\n * In general, you should expect compression to be faster--sometimes very much\n * so--and CDict creation to be slightly slower. Eventually, we will probably\n * make this mode the default.\n */\n#define ZSTD_c_enableDedicatedDictSearch ZSTD_c_experimentalParam8\n\n/* ZSTD_c_stableInBuffer\n * Experimental parameter.\n * Default is 0 == disabled. Set to 1 to enable.\n *\n * Tells the compressor that input data presented with ZSTD_inBuffer\n * will ALWAYS be the same between calls.\n * Technically, the @src pointer must never be changed,\n * and the @pos field can only be updated by zstd.\n * However, it's possible to increase the @size field,\n * allowing scenarios where more data can be appended after compressions starts.\n * These conditions are checked by the compressor,\n * and compression will fail if they are not respected.\n * Also, data in the ZSTD_inBuffer within the range [src, src + pos)\n * MUST not be modified during compression or it will result in data corruption.\n *\n * When this flag is enabled zstd won't allocate an input window buffer,\n * because the user guarantees it can reference the ZSTD_inBuffer until\n * the frame is complete. But, it will still allocate an output buffer\n * large enough to fit a block (see ZSTD_c_stableOutBuffer). This will also\n * avoid the memcpy() from the input buffer to the input window buffer.\n *\n * NOTE: So long as the ZSTD_inBuffer always points to valid memory, using\n * this flag is ALWAYS memory safe, and will never access out-of-bounds\n * memory. However, compression WILL fail if conditions are not respected.\n *\n * WARNING: The data in the ZSTD_inBuffer in the range [src, src + pos) MUST\n * not be modified during compression or it will result in data corruption.\n * This is because zstd needs to reference data in the ZSTD_inBuffer to find\n * matches. Normally zstd maintains its own window buffer for this purpose,\n * but passing this flag tells zstd to rely on user provided buffer instead.\n */\n#define ZSTD_c_stableInBuffer ZSTD_c_experimentalParam9\n\n/* ZSTD_c_stableOutBuffer\n * Experimental parameter.\n * Default is 0 == disabled. Set to 1 to enable.\n *\n * Tells he compressor that the ZSTD_outBuffer will not be resized between\n * calls. Specifically: (out.size - out.pos) will never grow. This gives the\n * compressor the freedom to say: If the compressed data doesn't fit in the\n * output buffer then return ZSTD_error_dstSizeTooSmall. This allows us to\n * always decompress directly into the output buffer, instead of decompressing\n * into an internal buffer and copying to the output buffer.\n *\n * When this flag is enabled zstd won't allocate an output buffer, because\n * it can write directly to the ZSTD_outBuffer. It will still allocate the\n * input window buffer (see ZSTD_c_stableInBuffer).\n *\n * Zstd will check that (out.size - out.pos) never grows and return an error\n * if it does. While not strictly necessary, this should prevent surprises.\n */\n#define ZSTD_c_stableOutBuffer ZSTD_c_experimentalParam10\n\n/* ZSTD_c_blockDelimiters\n * Default is 0 == ZSTD_sf_noBlockDelimiters.\n *\n * For use with sequence compression API: ZSTD_compressSequences().\n *\n * Designates whether or not the given array of ZSTD_Sequence contains block delimiters\n * and last literals, which are defined as sequences with offset == 0 and matchLength == 0.\n * See the definition of ZSTD_Sequence for more specifics.\n */\n#define ZSTD_c_blockDelimiters ZSTD_c_experimentalParam11\n\n/* ZSTD_c_validateSequences\n * Default is 0 == disabled. Set to 1 to enable sequence validation.\n *\n * For use with sequence compression API: ZSTD_compressSequences*().\n * Designates whether or not provided sequences are validated within ZSTD_compressSequences*()\n * during function execution.\n *\n * When Sequence validation is disabled (default), Sequences are compressed as-is,\n * so they must correct, otherwise it would result in a corruption error.\n *\n * Sequence validation adds some protection, by ensuring that all values respect boundary conditions.\n * If a Sequence is detected invalid (see doc/zstd_compression_format.md for\n * specifics regarding offset/matchlength requirements) then the function will bail out and\n * return an error.\n */\n#define ZSTD_c_validateSequences ZSTD_c_experimentalParam12\n\n/* ZSTD_c_blockSplitterLevel\n * note: this parameter only influences the first splitter stage,\n *       which is active before producing the sequences.\n *       ZSTD_c_splitAfterSequences controls the next splitter stage,\n *       which is active after sequence production.\n *       Note that both can be combined.\n * Allowed values are between 0 and ZSTD_BLOCKSPLITTER_LEVEL_MAX included.\n * 0 means \"auto\", which will select a value depending on current ZSTD_c_strategy.\n * 1 means no splitting.\n * Then, values from 2 to 6 are sorted in increasing cpu load order.\n *\n * Note that currently the first block is never split,\n * to ensure expansion guarantees in presence of incompressible data.\n */\n#define ZSTD_BLOCKSPLITTER_LEVEL_MAX 6\n#define ZSTD_c_blockSplitterLevel ZSTD_c_experimentalParam20\n\n/* ZSTD_c_splitAfterSequences\n * This is a stronger splitter algorithm,\n * based on actual sequences previously produced by the selected parser.\n * It's also slower, and as a consequence, mostly used for high compression levels.\n * While the post-splitter does overlap with the pre-splitter,\n * both can nonetheless be combined,\n * notably with ZSTD_c_blockSplitterLevel at ZSTD_BLOCKSPLITTER_LEVEL_MAX,\n * resulting in higher compression ratio than just one of them.\n *\n * Default is ZSTD_ps_auto.\n * Set to ZSTD_ps_disable to never use block splitter.\n * Set to ZSTD_ps_enable to always use block splitter.\n *\n * By default, in ZSTD_ps_auto, the library will decide at runtime whether to use\n * block splitting based on the compression parameters.\n */\n#define ZSTD_c_splitAfterSequences ZSTD_c_experimentalParam13\n\n/* ZSTD_c_useRowMatchFinder\n * Controlled with ZSTD_ParamSwitch_e enum.\n * Default is ZSTD_ps_auto.\n * Set to ZSTD_ps_disable to never use row-based matchfinder.\n * Set to ZSTD_ps_enable to force usage of row-based matchfinder.\n *\n * By default, in ZSTD_ps_auto, the library will decide at runtime whether to use\n * the row-based matchfinder based on support for SIMD instructions and the window log.\n * Note that this only pertains to compression strategies: greedy, lazy, and lazy2\n */\n#define ZSTD_c_useRowMatchFinder ZSTD_c_experimentalParam14\n\n/* ZSTD_c_deterministicRefPrefix\n * Default is 0 == disabled. Set to 1 to enable.\n *\n * Zstd produces different results for prefix compression when the prefix is\n * directly adjacent to the data about to be compressed vs. when it isn't.\n * This is because zstd detects that the two buffers are contiguous and it can\n * use a more efficient match finding algorithm. However, this produces different\n * results than when the two buffers are non-contiguous. This flag forces zstd\n * to always load the prefix in non-contiguous mode, even if it happens to be\n * adjacent to the data, to guarantee determinism.\n *\n * If you really care about determinism when using a dictionary or prefix,\n * like when doing delta compression, you should select this option. It comes\n * at a speed penalty of about ~2.5% if the dictionary and data happened to be\n * contiguous, and is free if they weren't contiguous. We don't expect that\n * intentionally making the dictionary and data contiguous will be worth the\n * cost to memcpy() the data.\n */\n#define ZSTD_c_deterministicRefPrefix ZSTD_c_experimentalParam15\n\n/* ZSTD_c_prefetchCDictTables\n * Controlled with ZSTD_ParamSwitch_e enum. Default is ZSTD_ps_auto.\n *\n * In some situations, zstd uses CDict tables in-place rather than copying them\n * into the working context. (See docs on ZSTD_dictAttachPref_e above for details).\n * In such situations, compression speed is seriously impacted when CDict tables are\n * \"cold\" (outside CPU cache). This parameter instructs zstd to prefetch CDict tables\n * when they are used in-place.\n *\n * For sufficiently small inputs, the cost of the prefetch will outweigh the benefit.\n * For sufficiently large inputs, zstd will by default memcpy() CDict tables\n * into the working context, so there is no need to prefetch. This parameter is\n * targeted at a middle range of input sizes, where a prefetch is cheap enough to be\n * useful but memcpy() is too expensive. The exact range of input sizes where this\n * makes sense is best determined by careful experimentation.\n *\n * Note: for this parameter, ZSTD_ps_auto is currently equivalent to ZSTD_ps_disable,\n * but in the future zstd may conditionally enable this feature via an auto-detection\n * heuristic for cold CDicts.\n * Use ZSTD_ps_disable to opt out of prefetching under any circumstances.\n */\n#define ZSTD_c_prefetchCDictTables ZSTD_c_experimentalParam16\n\n/* ZSTD_c_enableSeqProducerFallback\n * Allowed values are 0 (disable) and 1 (enable). The default setting is 0.\n *\n * Controls whether zstd will fall back to an internal sequence producer if an\n * external sequence producer is registered and returns an error code. This fallback\n * is block-by-block: the internal sequence producer will only be called for blocks\n * where the external sequence producer returns an error code. Fallback parsing will\n * follow any other cParam settings, such as compression level, the same as in a\n * normal (fully-internal) compression operation.\n *\n * The user is strongly encouraged to read the full Block-Level Sequence Producer API\n * documentation (below) before setting this parameter. */\n#define ZSTD_c_enableSeqProducerFallback ZSTD_c_experimentalParam17\n\n/* ZSTD_c_maxBlockSize\n * Allowed values are between 1KB and ZSTD_BLOCKSIZE_MAX (128KB).\n * The default is ZSTD_BLOCKSIZE_MAX, and setting to 0 will set to the default.\n *\n * This parameter can be used to set an upper bound on the blocksize\n * that overrides the default ZSTD_BLOCKSIZE_MAX. It cannot be used to set upper\n * bounds greater than ZSTD_BLOCKSIZE_MAX or bounds lower than 1KB (will make\n * compressBound() inaccurate). Only currently meant to be used for testing.\n */\n#define ZSTD_c_maxBlockSize ZSTD_c_experimentalParam18\n\n/* ZSTD_c_repcodeResolution\n * This parameter only has an effect if ZSTD_c_blockDelimiters is\n * set to ZSTD_sf_explicitBlockDelimiters (may change in the future).\n *\n * This parameter affects how zstd parses external sequences,\n * provided via the ZSTD_compressSequences*() API\n * or from an external block-level sequence producer.\n *\n * If set to ZSTD_ps_enable, the library will check for repeated offsets within\n * external sequences, even if those repcodes are not explicitly indicated in\n * the \"rep\" field. Note that this is the only way to exploit repcode matches\n * while using compressSequences*() or an external sequence producer, since zstd\n * currently ignores the \"rep\" field of external sequences.\n *\n * If set to ZSTD_ps_disable, the library will not exploit repeated offsets in\n * external sequences, regardless of whether the \"rep\" field has been set. This\n * reduces sequence compression overhead by about 25% while sacrificing some\n * compression ratio.\n *\n * The default value is ZSTD_ps_auto, for which the library will enable/disable\n * based on compression level (currently: level<10 disables, level>=10 enables).\n */\n#define ZSTD_c_repcodeResolution ZSTD_c_experimentalParam19\n#define ZSTD_c_searchForExternalRepcodes ZSTD_c_experimentalParam19 /* older name */\n\n\n/*! ZSTD_CCtx_getParameter() :\n *  Get the requested compression parameter value, selected by enum ZSTD_cParameter,\n *  and store it into int* value.\n * @return : 0, or an error code (which can be tested with ZSTD_isError()).\n */\nZSTDLIB_STATIC_API size_t ZSTD_CCtx_getParameter(const ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value);\n\n\n/*! ZSTD_CCtx_params :\n *  Quick howto :\n *  - ZSTD_createCCtxParams() : Create a ZSTD_CCtx_params structure\n *  - ZSTD_CCtxParams_setParameter() : Push parameters one by one into\n *                                     an existing ZSTD_CCtx_params structure.\n *                                     This is similar to\n *                                     ZSTD_CCtx_setParameter().\n *  - ZSTD_CCtx_setParametersUsingCCtxParams() : Apply parameters to\n *                                    an existing CCtx.\n *                                    These parameters will be applied to\n *                                    all subsequent frames.\n *  - ZSTD_compressStream2() : Do compression using the CCtx.\n *  - ZSTD_freeCCtxParams() : Free the memory, accept NULL pointer.\n *\n *  This can be used with ZSTD_estimateCCtxSize_advanced_usingCCtxParams()\n *  for static allocation of CCtx for single-threaded compression.\n */\nZSTDLIB_STATIC_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void);\nZSTDLIB_STATIC_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);  /* accept NULL pointer */\n\n/*! ZSTD_CCtxParams_reset() :\n *  Reset params to default values.\n */\nZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params);\n\n/*! ZSTD_CCtxParams_init() :\n *  Initializes the compression parameters of cctxParams according to\n *  compression level. All other parameters are reset to their default values.\n */\nZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel);\n\n/*! ZSTD_CCtxParams_init_advanced() :\n *  Initializes the compression and frame parameters of cctxParams according to\n *  params. All other parameters are reset to their default values.\n */\nZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params);\n\n/*! ZSTD_CCtxParams_setParameter() : Requires v1.4.0+\n *  Similar to ZSTD_CCtx_setParameter.\n *  Set one compression parameter, selected by enum ZSTD_cParameter.\n *  Parameters must be applied to a ZSTD_CCtx using\n *  ZSTD_CCtx_setParametersUsingCCtxParams().\n * @result : a code representing success or failure (which can be tested with\n *           ZSTD_isError()).\n */\nZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value);\n\n/*! ZSTD_CCtxParams_getParameter() :\n * Similar to ZSTD_CCtx_getParameter.\n * Get the requested value of one compression parameter, selected by enum ZSTD_cParameter.\n * @result : 0, or an error code (which can be tested with ZSTD_isError()).\n */\nZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_getParameter(const ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value);\n\n/*! ZSTD_CCtx_setParametersUsingCCtxParams() :\n *  Apply a set of ZSTD_CCtx_params to the compression context.\n *  This can be done even after compression is started,\n *    if nbWorkers==0, this will have no impact until a new compression is started.\n *    if nbWorkers>=1, new parameters will be picked up at next job,\n *       with a few restrictions (windowLog, pledgedSrcSize, nbWorkers, jobSize, and overlapLog are not updated).\n */\nZSTDLIB_STATIC_API size_t ZSTD_CCtx_setParametersUsingCCtxParams(\n        ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params);\n\n/*! ZSTD_compressStream2_simpleArgs() :\n *  Same as ZSTD_compressStream2(),\n *  but using only integral types as arguments.\n *  This variant might be helpful for binders from dynamic languages\n *  which have troubles handling structures containing memory pointers.\n */\nZSTDLIB_STATIC_API size_t ZSTD_compressStream2_simpleArgs (\n                            ZSTD_CCtx* cctx,\n                            void* dst, size_t dstCapacity, size_t* dstPos,\n                      const void* src, size_t srcSize, size_t* srcPos,\n                            ZSTD_EndDirective endOp);\n\n\n/***************************************\n*  Advanced decompression functions\n***************************************/\n\n/*! ZSTD_isFrame() :\n *  Tells if the content of `buffer` starts with a valid Frame Identifier.\n *  Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.\n *  Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled.\n *  Note 3 : Skippable Frame Identifiers are considered valid. */\nZSTDLIB_STATIC_API unsigned ZSTD_isFrame(const void* buffer, size_t size);\n\n/*! ZSTD_createDDict_byReference() :\n *  Create a digested dictionary, ready to start decompression operation without startup delay.\n *  Dictionary content is referenced, and therefore stays in dictBuffer.\n *  It is important that dictBuffer outlives DDict,\n *  it must remain read accessible throughout the lifetime of DDict */\nZSTDLIB_STATIC_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize);\n\n/*! ZSTD_DCtx_loadDictionary_byReference() :\n *  Same as ZSTD_DCtx_loadDictionary(),\n *  but references `dict` content instead of copying it into `dctx`.\n *  This saves memory if `dict` remains around.,\n *  However, it's imperative that `dict` remains accessible (and unmodified) while being used, so it must outlive decompression. */\nZSTDLIB_STATIC_API size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);\n\n/*! ZSTD_DCtx_loadDictionary_advanced() :\n *  Same as ZSTD_DCtx_loadDictionary(),\n *  but gives direct control over\n *  how to load the dictionary (by copy ? by reference ?)\n *  and how to interpret it (automatic ? force raw mode ? full mode only ?). */\nZSTDLIB_STATIC_API size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);\n\n/*! ZSTD_DCtx_refPrefix_advanced() :\n *  Same as ZSTD_DCtx_refPrefix(), but gives finer control over\n *  how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */\nZSTDLIB_STATIC_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);\n\n/*! ZSTD_DCtx_setMaxWindowSize() :\n *  Refuses allocating internal buffers for frames requiring a window size larger than provided limit.\n *  This protects a decoder context from reserving too much memory for itself (potential attack scenario).\n *  This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode.\n *  By default, a decompression context accepts all window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT)\n * @return : 0, or an error code (which can be tested using ZSTD_isError()).\n */\nZSTDLIB_STATIC_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize);\n\n/*! ZSTD_DCtx_getParameter() :\n *  Get the requested decompression parameter value, selected by enum ZSTD_dParameter,\n *  and store it into int* value.\n * @return : 0, or an error code (which can be tested with ZSTD_isError()).\n */\nZSTDLIB_STATIC_API size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value);\n\n/* ZSTD_d_format\n * experimental parameter,\n * allowing selection between ZSTD_format_e input compression formats\n */\n#define ZSTD_d_format ZSTD_d_experimentalParam1\n/* ZSTD_d_stableOutBuffer\n * Experimental parameter.\n * Default is 0 == disabled. Set to 1 to enable.\n *\n * Tells the decompressor that the ZSTD_outBuffer will ALWAYS be the same\n * between calls, except for the modifications that zstd makes to pos (the\n * caller must not modify pos). This is checked by the decompressor, and\n * decompression will fail if it ever changes. Therefore the ZSTD_outBuffer\n * MUST be large enough to fit the entire decompressed frame. This will be\n * checked when the frame content size is known. The data in the ZSTD_outBuffer\n * in the range [dst, dst + pos) MUST not be modified during decompression\n * or you will get data corruption.\n *\n * When this flag is enabled zstd won't allocate an output buffer, because\n * it can write directly to the ZSTD_outBuffer, but it will still allocate\n * an input buffer large enough to fit any compressed block. This will also\n * avoid the memcpy() from the internal output buffer to the ZSTD_outBuffer.\n * If you need to avoid the input buffer allocation use the buffer-less\n * streaming API.\n *\n * NOTE: So long as the ZSTD_outBuffer always points to valid memory, using\n * this flag is ALWAYS memory safe, and will never access out-of-bounds\n * memory. However, decompression WILL fail if you violate the preconditions.\n *\n * WARNING: The data in the ZSTD_outBuffer in the range [dst, dst + pos) MUST\n * not be modified during decompression or you will get data corruption. This\n * is because zstd needs to reference data in the ZSTD_outBuffer to regenerate\n * matches. Normally zstd maintains its own buffer for this purpose, but passing\n * this flag tells zstd to use the user provided buffer.\n */\n#define ZSTD_d_stableOutBuffer ZSTD_d_experimentalParam2\n\n/* ZSTD_d_forceIgnoreChecksum\n * Experimental parameter.\n * Default is 0 == disabled. Set to 1 to enable\n *\n * Tells the decompressor to skip checksum validation during decompression, regardless\n * of whether checksumming was specified during compression. This offers some\n * slight performance benefits, and may be useful for debugging.\n * Param has values of type ZSTD_forceIgnoreChecksum_e\n */\n#define ZSTD_d_forceIgnoreChecksum ZSTD_d_experimentalParam3\n\n/* ZSTD_d_refMultipleDDicts\n * Experimental parameter.\n * Default is 0 == disabled. Set to 1 to enable\n *\n * If enabled and dctx is allocated on the heap, then additional memory will be allocated\n * to store references to multiple ZSTD_DDict. That is, multiple calls of ZSTD_refDDict()\n * using a given ZSTD_DCtx, rather than overwriting the previous DDict reference, will instead\n * store all references. At decompression time, the appropriate dictID is selected\n * from the set of DDicts based on the dictID in the frame.\n *\n * Usage is simply calling ZSTD_refDDict() on multiple dict buffers.\n *\n * Param has values of byte ZSTD_refMultipleDDicts_e\n *\n * WARNING: Enabling this parameter and calling ZSTD_DCtx_refDDict(), will trigger memory\n * allocation for the hash table. ZSTD_freeDCtx() also frees this memory.\n * Memory is allocated as per ZSTD_DCtx::customMem.\n *\n * Although this function allocates memory for the table, the user is still responsible for\n * memory management of the underlying ZSTD_DDict* themselves.\n */\n#define ZSTD_d_refMultipleDDicts ZSTD_d_experimentalParam4\n\n/* ZSTD_d_disableHuffmanAssembly\n * Set to 1 to disable the Huffman assembly implementation.\n * The default value is 0, which allows zstd to use the Huffman assembly\n * implementation if available.\n *\n * This parameter can be used to disable Huffman assembly at runtime.\n * If you want to disable it at compile time you can define the macro\n * ZSTD_DISABLE_ASM.\n */\n#define ZSTD_d_disableHuffmanAssembly ZSTD_d_experimentalParam5\n\n/* ZSTD_d_maxBlockSize\n * Allowed values are between 1KB and ZSTD_BLOCKSIZE_MAX (128KB).\n * The default is ZSTD_BLOCKSIZE_MAX, and setting to 0 will set to the default.\n *\n * Forces the decompressor to reject blocks whose content size is\n * larger than the configured maxBlockSize. When maxBlockSize is\n * larger than the windowSize, the windowSize is used instead.\n * This saves memory on the decoder when you know all blocks are small.\n *\n * This option is typically used in conjunction with ZSTD_c_maxBlockSize.\n *\n * WARNING: This causes the decoder to reject otherwise valid frames\n * that have block sizes larger than the configured maxBlockSize.\n */\n#define ZSTD_d_maxBlockSize ZSTD_d_experimentalParam6\n\n\n/*! ZSTD_DCtx_setFormat() :\n *  This function is REDUNDANT. Prefer ZSTD_DCtx_setParameter().\n *  Instruct the decoder context about what kind of data to decode next.\n *  This instruction is mandatory to decode data without a fully-formed header,\n *  such ZSTD_f_zstd1_magicless for example.\n * @return : 0, or an error code (which can be tested using ZSTD_isError()). */\nZSTD_DEPRECATED(\"use ZSTD_DCtx_setParameter() instead\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format);\n\n/*! ZSTD_decompressStream_simpleArgs() :\n *  Same as ZSTD_decompressStream(),\n *  but using only integral types as arguments.\n *  This can be helpful for binders from dynamic languages\n *  which have troubles handling structures containing memory pointers.\n */\nZSTDLIB_STATIC_API size_t ZSTD_decompressStream_simpleArgs (\n                            ZSTD_DCtx* dctx,\n                            void* dst, size_t dstCapacity, size_t* dstPos,\n                      const void* src, size_t srcSize, size_t* srcPos);\n\n\n/********************************************************************\n*  Advanced streaming functions\n*  Warning : most of these functions are now redundant with the Advanced API.\n*  Once Advanced API reaches \"stable\" status,\n*  redundant functions will be deprecated, and then at some point removed.\n********************************************************************/\n\n/*=====   Advanced Streaming compression functions  =====*/\n\n/*! ZSTD_initCStream_srcSize() :\n * This function is DEPRECATED, and equivalent to:\n *     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n *     ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)\n *     ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);\n *     ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);\n *\n * pledgedSrcSize must be correct. If it is not known at init time, use\n * ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs,\n * \"0\" also disables frame content size field. It may be enabled in the future.\n * This prototype will generate compilation warnings.\n */\nZSTD_DEPRECATED(\"use ZSTD_CCtx_reset, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs,\n                         int compressionLevel,\n                         unsigned long long pledgedSrcSize);\n\n/*! ZSTD_initCStream_usingDict() :\n * This function is DEPRECATED, and is equivalent to:\n *     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n *     ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);\n *     ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);\n *\n * Creates of an internal CDict (incompatible with static CCtx), except if\n * dict == NULL or dictSize < 8, in which case no dict is used.\n * Note: dict is loaded with ZSTD_dct_auto (treated as a full zstd dictionary if\n * it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy.\n * This prototype will generate compilation warnings.\n */\nZSTD_DEPRECATED(\"use ZSTD_CCtx_reset, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs,\n                     const void* dict, size_t dictSize,\n                           int compressionLevel);\n\n/*! ZSTD_initCStream_advanced() :\n * This function is DEPRECATED, and is equivalent to:\n *     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n *     ZSTD_CCtx_setParams(zcs, params);\n *     ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);\n *     ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);\n *\n * dict is loaded with ZSTD_dct_auto and ZSTD_dlm_byCopy.\n * pledgedSrcSize must be correct.\n * If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN.\n * This prototype will generate compilation warnings.\n */\nZSTD_DEPRECATED(\"use ZSTD_CCtx_reset, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,\n                    const void* dict, size_t dictSize,\n                          ZSTD_parameters params,\n                          unsigned long long pledgedSrcSize);\n\n/*! ZSTD_initCStream_usingCDict() :\n * This function is DEPRECATED, and equivalent to:\n *     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n *     ZSTD_CCtx_refCDict(zcs, cdict);\n *\n * note : cdict will just be referenced, and must outlive compression session\n * This prototype will generate compilation warnings.\n */\nZSTD_DEPRECATED(\"use ZSTD_CCtx_reset and ZSTD_CCtx_refCDict, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict);\n\n/*! ZSTD_initCStream_usingCDict_advanced() :\n *   This function is DEPRECATED, and is equivalent to:\n *     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n *     ZSTD_CCtx_setFParams(zcs, fParams);\n *     ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);\n *     ZSTD_CCtx_refCDict(zcs, cdict);\n *\n * same as ZSTD_initCStream_usingCDict(), with control over frame parameters.\n * pledgedSrcSize must be correct. If srcSize is not known at init time, use\n * value ZSTD_CONTENTSIZE_UNKNOWN.\n * This prototype will generate compilation warnings.\n */\nZSTD_DEPRECATED(\"use ZSTD_CCtx_reset and ZSTD_CCtx_refCDict, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,\n                               const ZSTD_CDict* cdict,\n                                     ZSTD_frameParameters fParams,\n                                     unsigned long long pledgedSrcSize);\n\n/*! ZSTD_resetCStream() :\n * This function is DEPRECATED, and is equivalent to:\n *     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n *     ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);\n * Note: ZSTD_resetCStream() interprets pledgedSrcSize == 0 as ZSTD_CONTENTSIZE_UNKNOWN, but\n *       ZSTD_CCtx_setPledgedSrcSize() does not do the same, so ZSTD_CONTENTSIZE_UNKNOWN must be\n *       explicitly specified.\n *\n *  start a new frame, using same parameters from previous frame.\n *  This is typically useful to skip dictionary loading stage, since it will reuse it in-place.\n *  Note that zcs must be init at least once before using ZSTD_resetCStream().\n *  If pledgedSrcSize is not known at reset time, use macro ZSTD_CONTENTSIZE_UNKNOWN.\n *  If pledgedSrcSize > 0, its value must be correct, as it will be written in header, and controlled at the end.\n *  For the time being, pledgedSrcSize==0 is interpreted as \"srcSize unknown\" for compatibility with older programs,\n *  but it will change to mean \"empty\" in future version, so use macro ZSTD_CONTENTSIZE_UNKNOWN instead.\n * @return : 0, or an error code (which can be tested using ZSTD_isError())\n *  This prototype will generate compilation warnings.\n */\nZSTD_DEPRECATED(\"use ZSTD_CCtx_reset, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);\n\n\ntypedef struct {\n    unsigned long long ingested;   /* nb input bytes read and buffered */\n    unsigned long long consumed;   /* nb input bytes actually compressed */\n    unsigned long long produced;   /* nb of compressed bytes generated and buffered */\n    unsigned long long flushed;    /* nb of compressed bytes flushed : not provided; can be tracked from caller side */\n    unsigned currentJobID;         /* MT only : latest started job nb */\n    unsigned nbActiveWorkers;      /* MT only : nb of workers actively compressing at probe time */\n} ZSTD_frameProgression;\n\n/* ZSTD_getFrameProgression() :\n * tells how much data has been ingested (read from input)\n * consumed (input actually compressed) and produced (output) for current frame.\n * Note : (ingested - consumed) is amount of input data buffered internally, not yet compressed.\n * Aggregates progression inside active worker threads.\n */\nZSTDLIB_STATIC_API ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx);\n\n/*! ZSTD_toFlushNow() :\n *  Tell how many bytes are ready to be flushed immediately.\n *  Useful for multithreading scenarios (nbWorkers >= 1).\n *  Probe the oldest active job, defined as oldest job not yet entirely flushed,\n *  and check its output buffer.\n * @return : amount of data stored in oldest job and ready to be flushed immediately.\n *  if @return == 0, it means either :\n *  + there is no active job (could be checked with ZSTD_frameProgression()), or\n *  + oldest job is still actively compressing data,\n *    but everything it has produced has also been flushed so far,\n *    therefore flush speed is limited by production speed of oldest job\n *    irrespective of the speed of concurrent (and newer) jobs.\n */\nZSTDLIB_STATIC_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx);\n\n\n/*=====   Advanced Streaming decompression functions  =====*/\n\n/*!\n * This function is deprecated, and is equivalent to:\n *\n *     ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);\n *     ZSTD_DCtx_loadDictionary(zds, dict, dictSize);\n *\n * note: no dictionary will be used if dict == NULL or dictSize < 8\n */\nZSTD_DEPRECATED(\"use ZSTD_DCtx_reset + ZSTD_DCtx_loadDictionary, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);\n\n/*!\n * This function is deprecated, and is equivalent to:\n *\n *     ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);\n *     ZSTD_DCtx_refDDict(zds, ddict);\n *\n * note : ddict is referenced, it must outlive decompression session\n */\nZSTD_DEPRECATED(\"use ZSTD_DCtx_reset + ZSTD_DCtx_refDDict, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict);\n\n/*!\n * This function is deprecated, and is equivalent to:\n *\n *     ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);\n *\n * reuse decompression parameters from previous init; saves dictionary loading\n */\nZSTD_DEPRECATED(\"use ZSTD_DCtx_reset, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);\n\n\n/* ********************* BLOCK-LEVEL SEQUENCE PRODUCER API *********************\n *\n * *** OVERVIEW ***\n * The Block-Level Sequence Producer API allows users to provide their own custom\n * sequence producer which libzstd invokes to process each block. The produced list\n * of sequences (literals and matches) is then post-processed by libzstd to produce\n * valid compressed blocks.\n *\n * This block-level offload API is a more granular complement of the existing\n * frame-level offload API compressSequences() (introduced in v1.5.1). It offers\n * an easier migration story for applications already integrated with libzstd: the\n * user application continues to invoke the same compression functions\n * ZSTD_compress2() or ZSTD_compressStream2() as usual, and transparently benefits\n * from the specific advantages of the external sequence producer. For example,\n * the sequence producer could be tuned to take advantage of known characteristics\n * of the input, to offer better speed / ratio, or could leverage hardware\n * acceleration not available within libzstd itself.\n *\n * See contrib/externalSequenceProducer for an example program employing the\n * Block-Level Sequence Producer API.\n *\n * *** USAGE ***\n * The user is responsible for implementing a function of type\n * ZSTD_sequenceProducer_F. For each block, zstd will pass the following\n * arguments to the user-provided function:\n *\n *   - sequenceProducerState: a pointer to a user-managed state for the sequence\n *     producer.\n *\n *   - outSeqs, outSeqsCapacity: an output buffer for the sequence producer.\n *     outSeqsCapacity is guaranteed >= ZSTD_sequenceBound(srcSize). The memory\n *     backing outSeqs is managed by the CCtx.\n *\n *   - src, srcSize: an input buffer for the sequence producer to parse.\n *     srcSize is guaranteed to be <= ZSTD_BLOCKSIZE_MAX.\n *\n *   - dict, dictSize: a history buffer, which may be empty, which the sequence\n *     producer may reference as it parses the src buffer. Currently, zstd will\n *     always pass dictSize == 0 into external sequence producers, but this will\n *     change in the future.\n *\n *   - compressionLevel: a signed integer representing the zstd compression level\n *     set by the user for the current operation. The sequence producer may choose\n *     to use this information to change its compression strategy and speed/ratio\n *     tradeoff. Note: the compression level does not reflect zstd parameters set\n *     through the advanced API.\n *\n *   - windowSize: a size_t representing the maximum allowed offset for external\n *     sequences. Note that sequence offsets are sometimes allowed to exceed the\n *     windowSize if a dictionary is present, see doc/zstd_compression_format.md\n *     for details.\n *\n * The user-provided function shall return a size_t representing the number of\n * sequences written to outSeqs. This return value will be treated as an error\n * code if it is greater than outSeqsCapacity. The return value must be non-zero\n * if srcSize is non-zero. The ZSTD_SEQUENCE_PRODUCER_ERROR macro is provided\n * for convenience, but any value greater than outSeqsCapacity will be treated as\n * an error code.\n *\n * If the user-provided function does not return an error code, the sequences\n * written to outSeqs must be a valid parse of the src buffer. Data corruption may\n * occur if the parse is not valid. A parse is defined to be valid if the\n * following conditions hold:\n *   - The sum of matchLengths and literalLengths must equal srcSize.\n *   - All sequences in the parse, except for the final sequence, must have\n *     matchLength >= ZSTD_MINMATCH_MIN. The final sequence must have\n *     matchLength >= ZSTD_MINMATCH_MIN or matchLength == 0.\n *   - All offsets must respect the windowSize parameter as specified in\n *     doc/zstd_compression_format.md.\n *   - If the final sequence has matchLength == 0, it must also have offset == 0.\n *\n * zstd will only validate these conditions (and fail compression if they do not\n * hold) if the ZSTD_c_validateSequences cParam is enabled. Note that sequence\n * validation has a performance cost.\n *\n * If the user-provided function returns an error, zstd will either fall back\n * to an internal sequence producer or fail the compression operation. The user can\n * choose between the two behaviors by setting the ZSTD_c_enableSeqProducerFallback\n * cParam. Fallback compression will follow any other cParam settings, such as\n * compression level, the same as in a normal compression operation.\n *\n * The user shall instruct zstd to use a particular ZSTD_sequenceProducer_F\n * function by calling\n *         ZSTD_registerSequenceProducer(cctx,\n *                                       sequenceProducerState,\n *                                       sequenceProducer)\n * This setting will persist until the next parameter reset of the CCtx.\n *\n * The sequenceProducerState must be initialized by the user before calling\n * ZSTD_registerSequenceProducer(). The user is responsible for destroying the\n * sequenceProducerState.\n *\n * *** LIMITATIONS ***\n * This API is compatible with all zstd compression APIs which respect advanced parameters.\n * However, there are three limitations:\n *\n * First, the ZSTD_c_enableLongDistanceMatching cParam is not currently supported.\n * COMPRESSION WILL FAIL if it is enabled and the user tries to compress with a block-level\n * external sequence producer.\n *   - Note that ZSTD_c_enableLongDistanceMatching is auto-enabled by default in some\n *     cases (see its documentation for details). Users must explicitly set\n *     ZSTD_c_enableLongDistanceMatching to ZSTD_ps_disable in such cases if an external\n *     sequence producer is registered.\n *   - As of this writing, ZSTD_c_enableLongDistanceMatching is disabled by default\n *     whenever ZSTD_c_windowLog < 128MB, but that's subject to change. Users should\n *     check the docs on ZSTD_c_enableLongDistanceMatching whenever the Block-Level Sequence\n *     Producer API is used in conjunction with advanced settings (like ZSTD_c_windowLog).\n *\n * Second, history buffers are not currently supported. Concretely, zstd will always pass\n * dictSize == 0 to the external sequence producer (for now). This has two implications:\n *   - Dictionaries are not currently supported. Compression will *not* fail if the user\n *     references a dictionary, but the dictionary won't have any effect.\n *   - Stream history is not currently supported. All advanced compression APIs, including\n *     streaming APIs, work with external sequence producers, but each block is treated as\n *     an independent chunk without history from previous blocks.\n *\n * Third, multi-threading within a single compression is not currently supported. In other words,\n * COMPRESSION WILL FAIL if ZSTD_c_nbWorkers > 0 and an external sequence producer is registered.\n * Multi-threading across compressions is fine: simply create one CCtx per thread.\n *\n * Long-term, we plan to overcome all three limitations. There is no technical blocker to\n * overcoming them. It is purely a question of engineering effort.\n */\n\n#define ZSTD_SEQUENCE_PRODUCER_ERROR ((size_t)(-1))\n\ntypedef size_t (*ZSTD_sequenceProducer_F) (\n  void* sequenceProducerState,\n  ZSTD_Sequence* outSeqs, size_t outSeqsCapacity,\n  const void* src, size_t srcSize,\n  const void* dict, size_t dictSize,\n  int compressionLevel,\n  size_t windowSize\n);\n\n/*! ZSTD_registerSequenceProducer() :\n * Instruct zstd to use a block-level external sequence producer function.\n *\n * The sequenceProducerState must be initialized by the caller, and the caller is\n * responsible for managing its lifetime. This parameter is sticky across\n * compressions. It will remain set until the user explicitly resets compression\n * parameters.\n *\n * Sequence producer registration is considered to be an \"advanced parameter\",\n * part of the \"advanced API\". This means it will only have an effect on compression\n * APIs which respect advanced parameters, such as compress2() and compressStream2().\n * Older compression APIs such as compressCCtx(), which predate the introduction of\n * \"advanced parameters\", will ignore any external sequence producer setting.\n *\n * The sequence producer can be \"cleared\" by registering a NULL function pointer. This\n * removes all limitations described above in the \"LIMITATIONS\" section of the API docs.\n *\n * The user is strongly encouraged to read the full API documentation (above) before\n * calling this function. */\nZSTDLIB_STATIC_API void\nZSTD_registerSequenceProducer(\n  ZSTD_CCtx* cctx,\n  void* sequenceProducerState,\n  ZSTD_sequenceProducer_F sequenceProducer\n);\n\n/*! ZSTD_CCtxParams_registerSequenceProducer() :\n * Same as ZSTD_registerSequenceProducer(), but operates on ZSTD_CCtx_params.\n * This is used for accurate size estimation with ZSTD_estimateCCtxSize_usingCCtxParams(),\n * which is needed when creating a ZSTD_CCtx with ZSTD_initStaticCCtx().\n *\n * If you are using the external sequence producer API in a scenario where ZSTD_initStaticCCtx()\n * is required, then this function is for you. Otherwise, you probably don't need it.\n *\n * See tests/zstreamtest.c for example usage. */\nZSTDLIB_STATIC_API void\nZSTD_CCtxParams_registerSequenceProducer(\n  ZSTD_CCtx_params* params,\n  void* sequenceProducerState,\n  ZSTD_sequenceProducer_F sequenceProducer\n);\n\n\n/*********************************************************************\n*  Buffer-less and synchronous inner streaming functions (DEPRECATED)\n*\n*  This API is deprecated, and will be removed in a future version.\n*  It allows streaming (de)compression with user allocated buffers.\n*  However, it is hard to use, and not as well tested as the rest of\n*  our API.\n*\n*  Please use the normal streaming API instead: ZSTD_compressStream2,\n*  and ZSTD_decompressStream.\n*  If there is functionality that you need, but it doesn't provide,\n*  please open an issue on our GitHub.\n********************************************************************* */\n\n/**\n  Buffer-less streaming compression (synchronous mode)\n\n  A ZSTD_CCtx object is required to track streaming operations.\n  Use ZSTD_createCCtx() / ZSTD_freeCCtx() to manage resource.\n  ZSTD_CCtx object can be reused multiple times within successive compression operations.\n\n  Start by initializing a context.\n  Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary compression.\n\n  Then, consume your input using ZSTD_compressContinue().\n  There are some important considerations to keep in mind when using this advanced function :\n  - ZSTD_compressContinue() has no internal buffer. It uses externally provided buffers only.\n  - Interface is synchronous : input is consumed entirely and produces 1+ compressed blocks.\n  - Caller must ensure there is enough space in `dst` to store compressed data under worst case scenario.\n    Worst case evaluation is provided by ZSTD_compressBound().\n    ZSTD_compressContinue() doesn't guarantee recover after a failed compression.\n  - ZSTD_compressContinue() presumes prior input ***is still accessible and unmodified*** (up to maximum distance size, see WindowLog).\n    It remembers all previous contiguous blocks, plus one separated memory segment (which can itself consists of multiple contiguous blocks)\n  - ZSTD_compressContinue() detects that prior input has been overwritten when `src` buffer overlaps.\n    In which case, it will \"discard\" the relevant memory section from its history.\n\n  Finish a frame with ZSTD_compressEnd(), which will write the last block(s) and optional checksum.\n  It's possible to use srcSize==0, in which case, it will write a final empty block to end the frame.\n  Without last block mark, frames are considered unfinished (hence corrupted) by compliant decoders.\n\n  `ZSTD_CCtx` object can be reused (ZSTD_compressBegin()) to compress again.\n*/\n\n/*=====   Buffer-less streaming compression functions  =====*/\nZSTD_DEPRECATED(\"The buffer-less API is deprecated in favor of the normal streaming API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel);\nZSTD_DEPRECATED(\"The buffer-less API is deprecated in favor of the normal streaming API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel);\nZSTD_DEPRECATED(\"The buffer-less API is deprecated in favor of the normal streaming API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); /**< note: fails if cdict==NULL */\n\nZSTD_DEPRECATED(\"This function will likely be removed in a future release. It is misleading and has very limited utility.\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /**<  note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */\n\nZSTD_DEPRECATED(\"The buffer-less API is deprecated in favor of the normal streaming API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\nZSTD_DEPRECATED(\"The buffer-less API is deprecated in favor of the normal streaming API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n/* The ZSTD_compressBegin_advanced() and ZSTD_compressBegin_usingCDict_advanced() are now DEPRECATED and will generate a compiler warning */\nZSTD_DEPRECATED(\"use advanced API to access custom parameters\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize : If srcSize is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN */\nZSTD_DEPRECATED(\"use advanced API to access custom parameters\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize);   /* compression parameters are already set within cdict. pledgedSrcSize must be correct. If srcSize is not known, use macro ZSTD_CONTENTSIZE_UNKNOWN */\n/**\n  Buffer-less streaming decompression (synchronous mode)\n\n  A ZSTD_DCtx object is required to track streaming operations.\n  Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it.\n  A ZSTD_DCtx object can be reused multiple times.\n\n  First typical operation is to retrieve frame parameters, using ZSTD_getFrameHeader().\n  Frame header is extracted from the beginning of compressed frame, so providing only the frame's beginning is enough.\n  Data fragment must be large enough to ensure successful decoding.\n `ZSTD_frameHeaderSize_max` bytes is guaranteed to always be large enough.\n  result  : 0 : successful decoding, the `ZSTD_frameHeader` structure is correctly filled.\n           >0 : `srcSize` is too small, please provide at least result bytes on next attempt.\n           errorCode, which can be tested using ZSTD_isError().\n\n  It fills a ZSTD_FrameHeader structure with important information to correctly decode the frame,\n  such as the dictionary ID, content size, or maximum back-reference distance (`windowSize`).\n  Note that these values could be wrong, either because of data corruption, or because a 3rd party deliberately spoofs false information.\n  As a consequence, check that values remain within valid application range.\n  For example, do not allocate memory blindly, check that `windowSize` is within expectation.\n  Each application can set its own limits, depending on local restrictions.\n  For extended interoperability, it is recommended to support `windowSize` of at least 8 MB.\n\n  ZSTD_decompressContinue() needs previous data blocks during decompression, up to `windowSize` bytes.\n  ZSTD_decompressContinue() is very sensitive to contiguity,\n  if 2 blocks don't follow each other, make sure that either the compressor breaks contiguity at the same place,\n  or that previous contiguous segment is large enough to properly handle maximum back-reference distance.\n  There are multiple ways to guarantee this condition.\n\n  The most memory efficient way is to use a round buffer of sufficient size.\n  Sufficient size is determined by invoking ZSTD_decodingBufferSize_min(),\n  which can return an error code if required value is too large for current system (in 32-bits mode).\n  In a round buffer methodology, ZSTD_decompressContinue() decompresses each block next to previous one,\n  up to the moment there is not enough room left in the buffer to guarantee decoding another full block,\n  which maximum size is provided in `ZSTD_frameHeader` structure, field `blockSizeMax`.\n  At which point, decoding can resume from the beginning of the buffer.\n  Note that already decoded data stored in the buffer should be flushed before being overwritten.\n\n  There are alternatives possible, for example using two or more buffers of size `windowSize` each, though they consume more memory.\n\n  Finally, if you control the compression process, you can also ignore all buffer size rules,\n  as long as the encoder and decoder progress in \"lock-step\",\n  aka use exactly the same buffer sizes, break contiguity at the same place, etc.\n\n  Once buffers are setup, start decompression, with ZSTD_decompressBegin().\n  If decompression requires a dictionary, use ZSTD_decompressBegin_usingDict() or ZSTD_decompressBegin_usingDDict().\n\n  Then use ZSTD_nextSrcSizeToDecompress() and ZSTD_decompressContinue() alternatively.\n  ZSTD_nextSrcSizeToDecompress() tells how many bytes to provide as 'srcSize' to ZSTD_decompressContinue().\n  ZSTD_decompressContinue() requires this _exact_ amount of bytes, or it will fail.\n\n  result of ZSTD_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity).\n  It can be zero : it just means ZSTD_decompressContinue() has decoded some metadata item.\n  It can also be an error code, which can be tested with ZSTD_isError().\n\n  A frame is fully decoded when ZSTD_nextSrcSizeToDecompress() returns zero.\n  Context can then be reset to start a new decompression.\n\n  Note : it's possible to know if next input to present is a header or a block, using ZSTD_nextInputType().\n  This information is not required to properly decode a frame.\n\n  == Special case : skippable frames ==\n\n  Skippable frames allow integration of user-defined data into a flow of concatenated frames.\n  Skippable frames will be ignored (skipped) by decompressor.\n  The format of skippable frames is as follows :\n  a) Skippable frame ID - 4 Bytes, Little endian format, any value from 0x184D2A50 to 0x184D2A5F\n  b) Frame Size - 4 Bytes, Little endian format, unsigned 32-bits\n  c) Frame Content - any content (User Data) of length equal to Frame Size\n  For skippable frames ZSTD_getFrameHeader() returns zfhPtr->frameType==ZSTD_skippableFrame.\n  For skippable frames ZSTD_decompressContinue() always returns 0 : it only skips the content.\n*/\n\n/*=====   Buffer-less streaming decompression functions  =====*/\n\nZSTDLIB_STATIC_API size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize);  /**< when frame content size is not known, pass in frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN */\n\nZSTDLIB_STATIC_API size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx);\nZSTDLIB_STATIC_API size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);\nZSTDLIB_STATIC_API size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);\n\nZSTDLIB_STATIC_API size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx);\nZSTDLIB_STATIC_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n/* misc */\nZSTD_DEPRECATED(\"This function will likely be removed in the next minor release. It is misleading and has very limited utility.\")\nZSTDLIB_STATIC_API void   ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx);\ntypedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e;\nZSTDLIB_STATIC_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx);\n\n\n\n/*! ZSTD_isDeterministicBuild() :\n * Returns 1 if the library is built using standard compilation flags,\n * and participates in determinism guarantees with other builds of the\n * same version.\n * If this function returns 0, it means the library was compiled with\n * non-standard compilation flags that change the output of the\n * compressor.\n * This is mainly used for Zstd's determinism test suite, which is only\n * run when this function returns 1.\n */\nZSTDLIB_API int ZSTD_isDeterministicBuild(void);\n\n\n/* ========================================= */\n/**       Block level API (DEPRECATED)       */\n/* ========================================= */\n\n/*!\n\n    This API is deprecated in favor of the regular compression API.\n    You can get the frame header down to 2 bytes by setting:\n      - ZSTD_c_format = ZSTD_f_zstd1_magicless\n      - ZSTD_c_contentSizeFlag = 0\n      - ZSTD_c_checksumFlag = 0\n      - ZSTD_c_dictIDFlag = 0\n\n    This API is not as well tested as our normal API, so we recommend not using it.\n    We will be removing it in a future version. If the normal API doesn't provide\n    the functionality you need, please open a GitHub issue.\n\n    Block functions produce and decode raw zstd blocks, without frame metadata.\n    Frame metadata cost is typically ~12 bytes, which can be non-negligible for very small blocks (< 100 bytes).\n    But users will have to take in charge needed metadata to regenerate data, such as compressed and content sizes.\n\n    A few rules to respect :\n    - Compressing and decompressing require a context structure\n      + Use ZSTD_createCCtx() and ZSTD_createDCtx()\n    - It is necessary to init context before starting\n      + compression : any ZSTD_compressBegin*() variant, including with dictionary\n      + decompression : any ZSTD_decompressBegin*() variant, including with dictionary\n    - Block size is limited, it must be <= ZSTD_getBlockSize() <= ZSTD_BLOCKSIZE_MAX == 128 KB\n      + If input is larger than a block size, it's necessary to split input data into multiple blocks\n      + For inputs larger than a single block, consider using regular ZSTD_compress() instead.\n        Frame metadata is not that costly, and quickly becomes negligible as source size grows larger than a block.\n    - When a block is considered not compressible enough, ZSTD_compressBlock() result will be 0 (zero) !\n      ===> In which case, nothing is produced into `dst` !\n      + User __must__ test for such outcome and deal directly with uncompressed data\n      + A block cannot be declared incompressible if ZSTD_compressBlock() return value was != 0.\n        Doing so would mess up with statistics history, leading to potential data corruption.\n      + ZSTD_decompressBlock() _doesn't accept uncompressed data as input_ !!\n      + In case of multiple successive blocks, should some of them be uncompressed,\n        decoder must be informed of their existence in order to follow proper history.\n        Use ZSTD_insertBlock() for such a case.\n*/\n\n/*=====   Raw zstd block functions  =====*/\nZSTD_DEPRECATED(\"The block API is deprecated in favor of the normal compression API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_getBlockSize   (const ZSTD_CCtx* cctx);\nZSTD_DEPRECATED(\"The block API is deprecated in favor of the normal compression API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_compressBlock  (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\nZSTD_DEPRECATED(\"The block API is deprecated in favor of the normal compression API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\nZSTD_DEPRECATED(\"The block API is deprecated in favor of the normal compression API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_insertBlock    (ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize);  /**< insert uncompressed block into `dctx` history. Useful for multi-blocks decompression. */\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif   /* ZSTD_H_ZSTD_STATIC_LINKING_ONLY */\n"
  },
  {
    "path": "lib/zstd_errors.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_ERRORS_H_398273423\n#define ZSTD_ERRORS_H_398273423\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* =====   ZSTDERRORLIB_API : control library symbols visibility   ===== */\n#ifndef ZSTDERRORLIB_VISIBLE\n   /* Backwards compatibility with old macro name */\n#  ifdef ZSTDERRORLIB_VISIBILITY\n#    define ZSTDERRORLIB_VISIBLE ZSTDERRORLIB_VISIBILITY\n#  elif defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)\n#    define ZSTDERRORLIB_VISIBLE __attribute__ ((visibility (\"default\")))\n#  else\n#    define ZSTDERRORLIB_VISIBLE\n#  endif\n#endif\n\n#ifndef ZSTDERRORLIB_HIDDEN\n#  if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)\n#    define ZSTDERRORLIB_HIDDEN __attribute__ ((visibility (\"hidden\")))\n#  else\n#    define ZSTDERRORLIB_HIDDEN\n#  endif\n#endif\n\n#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)\n#  define ZSTDERRORLIB_API __declspec(dllexport) ZSTDERRORLIB_VISIBLE\n#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)\n#  define ZSTDERRORLIB_API __declspec(dllimport) ZSTDERRORLIB_VISIBLE /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/\n#else\n#  define ZSTDERRORLIB_API ZSTDERRORLIB_VISIBLE\n#endif\n\n/*-*********************************************\n *  Error codes list\n *-*********************************************\n *  Error codes _values_ are pinned down since v1.3.1 only.\n *  Therefore, don't rely on values if you may link to any version < v1.3.1.\n *\n *  Only values < 100 are considered stable.\n *\n *  note 1 : this API shall be used with static linking only.\n *           dynamic linking is not yet officially supported.\n *  note 2 : Prefer relying on the enum than on its value whenever possible\n *           This is the only supported way to use the error list < v1.3.1\n *  note 3 : ZSTD_isError() is always correct, whatever the library version.\n **********************************************/\ntypedef enum {\n  ZSTD_error_no_error = 0,\n  ZSTD_error_GENERIC  = 1,\n  ZSTD_error_prefix_unknown                = 10,\n  ZSTD_error_version_unsupported           = 12,\n  ZSTD_error_frameParameter_unsupported    = 14,\n  ZSTD_error_frameParameter_windowTooLarge = 16,\n  ZSTD_error_corruption_detected = 20,\n  ZSTD_error_checksum_wrong      = 22,\n  ZSTD_error_literals_headerWrong = 24,\n  ZSTD_error_dictionary_corrupted      = 30,\n  ZSTD_error_dictionary_wrong          = 32,\n  ZSTD_error_dictionaryCreation_failed = 34,\n  ZSTD_error_parameter_unsupported   = 40,\n  ZSTD_error_parameter_combination_unsupported = 41,\n  ZSTD_error_parameter_outOfBound    = 42,\n  ZSTD_error_tableLog_tooLarge       = 44,\n  ZSTD_error_maxSymbolValue_tooLarge = 46,\n  ZSTD_error_maxSymbolValue_tooSmall = 48,\n  ZSTD_error_cannotProduce_uncompressedBlock = 49,\n  ZSTD_error_stabilityCondition_notRespected = 50,\n  ZSTD_error_stage_wrong       = 60,\n  ZSTD_error_init_missing      = 62,\n  ZSTD_error_memory_allocation = 64,\n  ZSTD_error_workSpace_tooSmall= 66,\n  ZSTD_error_dstSize_tooSmall = 70,\n  ZSTD_error_srcSize_wrong    = 72,\n  ZSTD_error_dstBuffer_null   = 74,\n  ZSTD_error_noForwardProgress_destFull = 80,\n  ZSTD_error_noForwardProgress_inputEmpty = 82,\n  /* following error codes are __NOT STABLE__, they can be removed or changed in future versions */\n  ZSTD_error_frameIndex_tooLarge = 100,\n  ZSTD_error_seekableIO          = 102,\n  ZSTD_error_dstBuffer_wrong     = 104,\n  ZSTD_error_srcBuffer_wrong     = 105,\n  ZSTD_error_sequenceProducer_failed = 106,\n  ZSTD_error_externalSequences_invalid = 107,\n  ZSTD_error_maxCode = 120  /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */\n} ZSTD_ErrorCode;\n\nZSTDERRORLIB_API const char* ZSTD_getErrorString(ZSTD_ErrorCode code);   /**< Same as ZSTD_getErrorName, but using a `ZSTD_ErrorCode` enum argument */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* ZSTD_ERRORS_H_398273423 */\n"
  },
  {
    "path": "programs/.gitignore",
    "content": "# local binary (Makefile)\nzstd\nzstd32\nzstd4\nzstd-compress\nzstd-decompress\nzstd-frugal\nzstd-small\nzstd-nolegacy\nzstd-dictBuilder\nzstd-dll\nzstd_arm64\nzstd_x64\n\n# Object files\n*.o\n*.ko\ndefault.profraw\nhave_zlib\n\n# Executables\n*.exe\n*.out\n*.app\n\n# Default result files\ndictionary\ngrillResults.txt\n_*\ntmp*\n*.zst\nresult\nout\n\n# fuzzer\nafl\n\n# Misc files\n*.bat\n!windres/generate_res.bat\ndirTest*\n"
  },
  {
    "path": "programs/BUCK",
    "content": "cxx_binary(\n    name='zstd',\n    headers=glob(['*.h'], excludes=['datagen.h', 'platform.h', 'util.h']),\n    srcs=glob(['*.c'], excludes=['datagen.c']),\n    deps=[\n        ':datagen',\n        ':util',\n        '//lib:zstd',\n        '//lib:zdict',\n        '//lib:mem',\n        '//lib:xxhash',\n    ],\n    preprocessor_flags=[\n        '-DZSTD_GZCOMPRESS',\n        '-DZSTD_GZDECOMPRESS',\n        '-DZSTD_LZMACOMPRESS',\n        '-DZSTD_LZMADECOMPRES',\n        '-DZSTD_LZ4COMPRESS',\n        '-DZSTD_LZ4DECOMPRES',\n    ],\n    linker_flags=[\n        '-lz',\n        '-llzma',\n        '-llz4',\n    ],\n)\n\ncxx_library(\n    name='datagen',\n    visibility=['PUBLIC'],\n    header_namespace='',\n    exported_headers=['datagen.h'],\n    srcs=['datagen.c'],\n    deps=['//lib:mem'],\n)\n\n\ncxx_library(\n    name='util',\n    visibility=['PUBLIC'],\n    header_namespace='',\n    exported_headers=['util.h', 'platform.h'],\n    deps=['//lib:mem'],\n)\n"
  },
  {
    "path": "programs/Makefile",
    "content": "# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ##########################################################################\n# zstd : Command Line Utility, supporting gzip-like arguments\n# zstd32 : Same as zstd, but forced to compile in 32-bits mode\n# zstd-nolegacy : zstd without support of decompression of legacy versions\n# zstd-small : minimal zstd without dictionary builder and benchmark\n# zstd-compress : compressor-only version of zstd\n# zstd-decompress : decompressor-only version of zstd\n# ##########################################################################\n\n# default target (when running `make` with no argument)\nzstd-release:\n\nLIBZSTD_MK_DIR = ../lib\ninclude $(LIBZSTD_MK_DIR)/libzstd.mk\n\nifeq ($(shell $(CC) -v 2>&1 | $(GREP) -c \"gcc version \"), 1)\n  ALIGN_LOOP = -falign-loops=32\nelse\n  ALIGN_LOOP =\nendif\n\nZSTDLIB_COMMON_SRC := $(sort $(ZSTD_COMMON_FILES))\nZSTDLIB_COMPRESS_SRC := $(sort $(ZSTD_COMPRESS_FILES))\nZSTDLIB_DECOMPRESS_SRC := $(sort $(ZSTD_DECOMPRESS_FILES))\nZSTDLIB_CORE_SRC := $(sort $(ZSTD_DECOMPRESS_FILES) $(ZSTD_COMMON_FILES) $(ZSTD_COMPRESS_FILES))\nZDICT_SRC := $(sort $(ZSTD_DICTBUILDER_FILES))\nZSTDLEGACY_SRC := $(sort $(ZSTD_LEGACY_FILES))\n\n# Sort files in alphabetical order for reproducible builds\nZSTDLIB_FULL_SRC = $(sort $(ZSTDLIB_CORE_SRC) $(ZSTDLEGACY_SRC) $(ZDICT_SRC))\nZSTDLIB_LOCAL_SRC = $(notdir $(ZSTDLIB_FULL_SRC))\nZSTDLIB_LOCAL_OBJ0 := $(ZSTDLIB_LOCAL_SRC:.c=.o)\nZSTDLIB_LOCAL_OBJ := $(ZSTDLIB_LOCAL_OBJ0:.S=.o)\n\nZSTD_CLI_SRC := $(sort $(wildcard *.c))\nZSTD_CLI_OBJ := $(ZSTD_CLI_SRC:.c=.o)\n\nZSTD_ALL_SRC = $(ZSTDLIB_LOCAL_SRC) $(ZSTD_CLI_SRC)\nZSTD_ALL_OBJ0 := $(ZSTD_ALL_SRC:.c=.o)\nZSTD_ALL_OBJ := $(ZSTD_ALL_OBJ0:.S=.o)\n\n# Define *.exe as extension for Windows systems\nifneq (,$(filter Windows%,$(OS)))\n  EXT =.exe\n  RES64_FILE = windres/zstd64.res\n  RES32_FILE = windres/zstd32.res\nifneq (,$(filter x86_64%,$(shell $(CC) -dumpmachine)))\n    RES_FILE = $(RES64_FILE)\nelse\n    RES_FILE = $(RES32_FILE)\nendif\nelse\n  EXT =\nendif\n\n# thread detection\nNO_THREAD_MSG := ==> no threads, building without multithreading support\nHAVE_PTHREAD := $(shell printf '$(NUM_SYMBOL)include <pthread.h>\\nint main(void) { return 0; }' > have_pthread.c && $(CC) $(FLAGS) -o have_pthread$(EXT) have_pthread.c -pthread 2> $(VOID) && rm have_pthread$(EXT) && echo 1 || echo 0; rm have_pthread.c)\nHAVE_THREAD := $(shell [ \"$(HAVE_PTHREAD)\" -eq \"1\" -o -n \"$(filter Windows%,$(OS))\" ] && echo 1 || echo 0)\nifeq ($(HAVE_THREAD), 1)\n  THREAD_MSG := ==> building with threading support\n  THREAD_CPP := -DZSTD_MULTITHREAD\n  THREAD_LD := -pthread\nelse\n  THREAD_MSG := $(NO_THREAD_MSG)\nendif\n\n# zlib detection\nNO_ZLIB_MSG := ==> no zlib, building zstd without .gz support\nHAVE_ZLIB ?= $(shell printf '$(NUM_SYMBOL)include <zlib.h>\\nint main(void) { return 0; }' > have_zlib.c && $(CC) $(FLAGS) -o have_zlib$(EXT) have_zlib.c -lz 2> $(VOID) && rm have_zlib$(EXT) && echo 1 || echo 0; rm have_zlib.c)\nifeq ($(HAVE_ZLIB), 1)\n  ZLIB_MSG := ==> building zstd with .gz compression support\n  ZLIBCPP = -DZSTD_GZCOMPRESS -DZSTD_GZDECOMPRESS\n  ZLIBLD = -lz\nelse\n  ZLIB_MSG := $(NO_ZLIB_MSG)\nendif\n\n# lzma detection\nNO_LZMA_MSG := ==> no liblzma, building zstd without .xz/.lzma support\nHAVE_LZMA ?= $(shell printf '$(NUM_SYMBOL)include <lzma.h>\\nint main(void) { return 0; }' > have_lzma.c && $(CC) $(FLAGS) -o have_lzma$(EXT) have_lzma.c -llzma 2> $(VOID) && rm have_lzma$(EXT) && echo 1 || echo 0; rm have_lzma.c)\nifeq ($(HAVE_LZMA), 1)\n  LZMA_MSG := ==> building zstd with .xz/.lzma compression support\n  LZMACPP = -DZSTD_LZMACOMPRESS -DZSTD_LZMADECOMPRESS\n  LZMALD = -llzma\nelse\n  LZMA_MSG := $(NO_LZMA_MSG)\nendif\n\n# lz4 detection\nNO_LZ4_MSG := ==> no liblz4, building zstd without .lz4 support\nHAVE_LZ4 ?= $(shell printf '$(NUM_SYMBOL)include <lz4frame.h>\\n$(NUM_SYMBOL)include <lz4.h>\\nint main(void) { return 0; }' > have_lz4.c && $(CC) $(FLAGS) -o have_lz4$(EXT) have_lz4.c -llz4 2> $(VOID) && rm have_lz4$(EXT) && echo 1 || echo 0; rm have_lz4.c)\nifeq ($(HAVE_LZ4), 1)\n  LZ4_MSG := ==> building zstd with .lz4 compression support\n  LZ4CPP = -DZSTD_LZ4COMPRESS -DZSTD_LZ4DECOMPRESS\n  LZ4LD = -llz4\nelse\n  LZ4_MSG := $(NO_LZ4_MSG)\nendif\n\n# explicit backtrace enable/disable for Linux & Darwin\nifeq ($(BACKTRACE), 0)\n  DEBUGFLAGS += -DBACKTRACE_ENABLE=0\nendif\nifeq (,$(filter Windows%, $(OS)))\nifeq ($(BACKTRACE), 1)\n  DEBUGFLAGS += -DBACKTRACE_ENABLE=1\n  DEBUGFLAGS_LD += -rdynamic\nendif\nendif\n\nSET_CACHE_DIRECTORY = \\\n   +$(MAKE) --no-print-directory $@ \\\n    BUILD_DIR=obj/$(HASH_DIR) \\\n    CPPFLAGS=\"$(CPPFLAGS)\" \\\n    CFLAGS=\"$(CFLAGS)\" \\\n    LDFLAGS=\"$(LDFLAGS)\" \\\n    LDLIBS=\"$(LDLIBS)\" \\\n    ZSTD_ALL_SRC=\"$(ZSTD_ALL_SRC)\"\n\n\n.PHONY: all\nall: zstd zstd-compress zstd-decompress zstd-small\n\n.PHONY: allVariants\nallVariants: all zstd-frugal zstd-nolegacy zstd-dictBuilder\n\n.PHONY: zstd  # must always be run\nzstd : CPPFLAGS += $(THREAD_CPP) $(ZLIBCPP) $(LZMACPP) $(LZ4CPP)\nzstd : LDFLAGS += $(THREAD_LD) $(DEBUGFLAGS_LD)\nzstd : LDLIBS += $(ZLIBLD) $(LZMALD) $(LZ4LD)\nzstd : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT)\nifneq (,$(filter Windows%,$(OS)))\nzstd : $(RES_FILE)\nendif\n\nifndef BUILD_DIR\n# generate BUILD_DIR from flags\n\nzstd:\n\t$(SET_CACHE_DIRECTORY)\n\nelse\n# BUILD_DIR is defined\n\nZSTD_OBJ := $(addprefix $(BUILD_DIR)/, $(ZSTD_ALL_OBJ))\n$(BUILD_DIR)/zstd : $(ZSTD_OBJ)\n\t@echo \"$(THREAD_MSG)\"\n\t@echo \"$(ZLIB_MSG)\"\n\t@echo \"$(LZMA_MSG)\"\n\t@echo \"$(LZ4_MSG)\"\n\t@echo LINK $@\n\t$(CC) $(FLAGS) $^ $(LDLIBS) -o $@$(EXT)\n\nifeq ($(HAVE_HASH),1)\nSRCBIN_HASH = $(shell cat $(BUILD_DIR)/zstd$(EXT) 2> $(VOID) | $(HASH) | cut -f 1 -d \" \")\nDSTBIN_HASH = $(shell cat zstd$(EXT) 2> $(VOID) | $(HASH) | cut -f 1 -d \" \")\nBIN_ISDIFFERENT = $(if $(filter $(SRCBIN_HASH),$(DSTBIN_HASH)),0,1)\nelse\nBIN_ISDIFFERENT = 1\nendif\n\nzstd : $(BUILD_DIR)/zstd\n\tif [ $(BIN_ISDIFFERENT) -eq 1 ]; then \\\n\t\t$(CP) $<$(EXT) $@$(EXT); \\\n\t\techo zstd build completed; \\\n\telse \\\n\t\techo zstd already built; \\\n\tfi\n\nendif  # BUILD_DIR\n\n\nCLEAN += zstd\n.PHONY: zstd-release\nzstd-release: DEBUGFLAGS := -DBACKTRACE_ENABLE=0\nzstd-release: DEBUGFLAGS_LD :=\nzstd-release: zstd\n\nCLEAN += zstd32\nzstd32 : CPPFLAGS += $(THREAD_CPP)\nzstd32 : LDFLAGS  += $(THREAD_LD)\nzstd32 : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT)\nifneq (,$(filter Windows%,$(OS)))\nzstd32 : $(RES32_FILE)\nendif\nzstd32 : $(ZSTDLIB_FULL_SRC) $(ZSTD_CLI_SRC)\n\t$(CC) -m32 $(FLAGS) $^ -o $@$(EXT)\n\n## zstd-nolegacy: same scope as zstd, with removed support of legacy formats\nCLEAN += zstd-nolegacy\nzstd-nolegacy : LDFLAGS += $(THREAD_LD) $(ZLIBLD) $(LZMALD) $(LZ4LD) $(DEBUGFLAGS_LD)\nzstd-nolegacy : CPPFLAGS += -UZSTD_LEGACY_SUPPORT -DZSTD_LEGACY_SUPPORT=0\nzstd-nolegacy : $(ZSTDLIB_CORE_SRC) $(ZDICT_SRC) $(ZSTD_CLI_OBJ)\n\t$(CC) $(FLAGS) $^ -o $@$(EXT) $(LDFLAGS)\n\n.PHONY: zstd-nomt\nzstd-nomt : THREAD_CPP :=\nzstd-nomt : THREAD_LD  :=\nzstd-nomt : THREAD_MSG := - multi-threading disabled\nzstd-nomt : zstd\n\n.PHONY: zstd-nogz\nzstd-nogz : ZLIBCPP :=\nzstd-nogz : ZLIBLD  :=\nzstd-nogz : ZLIB_MSG := - gzip support is disabled\nzstd-nogz : zstd\n\n.PHONY: zstd-noxz\nzstd-noxz : LZMACPP :=\nzstd-noxz : LZMALD  :=\nzstd-noxz : LZMA_MSG := - xz/lzma support is disabled\nzstd-noxz : zstd\n\n## zstd-dll: zstd executable linked to dynamic library libzstd (must have same version)\n.PHONY: zstd-dll\nzstd-dll : LDFLAGS+= -L$(LIB_BINDIR)\nzstd-dll : LDLIBS += -lzstd\nzstd-dll : ZSTDLIB_LOCAL_SRC = xxhash.c pool.c threading.c\nzstd-dll : zstd\n\n\n## zstd-pgo: zstd executable optimized with PGO.\n.PHONY: zstd-pgo\nzstd-pgo : LLVM_PROFDATA?=llvm-profdata\nzstd-pgo : PROF_GENERATE_FLAGS=-fprofile-generate $(if $(findstring gcc,$(CC)),-fprofile-dir=.)\nzstd-pgo : PROF_USE_FLAGS=-fprofile-use $(if $(findstring gcc,$(CC)),-fprofile-dir=. -Wno-error=missing-profile -Wno-error=coverage-mismatch)\nzstd-pgo :\n\t$(MAKE) clean HASH_DIR=$(HASH_DIR)\n\t$(MAKE) zstd HASH_DIR=$(HASH_DIR) MOREFLAGS=\"$(PROF_GENERATE_FLAGS)\"\n\t./zstd -b19i1 $(PROFILE_WITH)\n\t./zstd -b16i1 $(PROFILE_WITH)\n\t./zstd -b9i2 $(PROFILE_WITH)\n\t./zstd -b $(PROFILE_WITH)\n\t./zstd -b7i2 $(PROFILE_WITH)\n\t./zstd -b5 $(PROFILE_WITH)\nifndef BUILD_DIR\n\t$(RM) zstd obj/$(HASH_DIR)/zstd obj/$(HASH_DIR)/*.o\nelse\n\t$(RM) zstd $(BUILD_DIR)/zstd $(BUILD_DIR)/*.o\nendif\n\tcase $(CC) in *clang*) if ! [ -e default.profdata ]; then $(LLVM_PROFDATA) merge -output=default.profdata default*.profraw; fi ;; esac\n\t$(MAKE) zstd HASH_DIR=$(HASH_DIR) MOREFLAGS=\"$(PROF_USE_FLAGS)\"\n\n## zstd-small: minimal target, supporting only zstd compression and decompression. no bench. no legacy. no other format.\nCLEAN += zstd-small zstd-frugal\nzstd-small: CFLAGS = -Os -Wl,-s\nzstd-frugal zstd-small: $(ZSTDLIB_CORE_SRC) zstdcli.c util.c timefn.c fileio.c fileio_asyncio.c\n\t$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NOTRACE -UZSTD_LEGACY_SUPPORT -DZSTD_LEGACY_SUPPORT=0 $^ -o $@$(EXT)\n\nCLEAN += zstd-decompress\nzstd-decompress: $(ZSTDLIB_COMMON_SRC) $(ZSTDLIB_DECOMPRESS_SRC) zstdcli.c util.c timefn.c fileio.c fileio_asyncio.c\n\t$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NOCOMPRESS -DZSTD_NOTRACE -UZSTD_LEGACY_SUPPORT -DZSTD_LEGACY_SUPPORT=0 $^ -o $@$(EXT)\n\nCLEAN += zstd-compress\nzstd-compress: $(ZSTDLIB_COMMON_SRC) $(ZSTDLIB_COMPRESS_SRC) zstdcli.c util.c timefn.c fileio.c fileio_asyncio.c\n\t$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NODECOMPRESS -DZSTD_NOTRACE -UZSTD_LEGACY_SUPPORT -DZSTD_LEGACY_SUPPORT=0 $^ -o $@$(EXT)\n\n## zstd-dictBuilder: executable supporting dictionary creation and compression (only)\nCLEAN += zstd-dictBuilder\nzstd-dictBuilder: $(ZSTDLIB_COMMON_SRC) $(ZSTDLIB_COMPRESS_SRC) $(ZDICT_SRC) zstdcli.c util.c timefn.c fileio.c fileio_asyncio.c dibio.c\n\t$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODECOMPRESS -DZSTD_NOTRACE $^ -o $@$(EXT)\n\nCLEAN += zstdmt\nzstdmt: zstd\n\t$(LN) -sf zstd zstdmt\n\n.PHONY: generate_res\ngenerate_res: $(RES64_FILE) $(RES32_FILE)\n\nifneq (,$(filter Windows%,$(OS)))\nRC ?= windres\n# https://stackoverflow.com/questions/708238/how-do-i-add-an-icon-to-a-mingw-gcc-compiled-executable\n$(RES64_FILE): windres/zstd.rc\n\t$(RC) -o $@ -I ../lib -I windres -i $< -O coff -F pe-x86-64\n$(RES32_FILE): windres/zstd.rc\n\t$(RC) -o $@ -I ../lib -I windres -i $< -O coff -F pe-i386\nendif\n\n.PHONY: clean\nclean:\n\t$(RM) $(CLEAN) core *.o tmp* result* dictionary *.zst \\\n        *.gcda default*.profraw default.profdata have_zlib\n\t$(RM) -r obj/*\n\t@echo Cleaning completed\n\nMD2ROFF = ronn\nMD2ROFF_FLAGS = --roff --warnings --manual=\"User Commands\" --organization=\"zstd $(ZSTD_VERSION)\"\n\nzstd.1: zstd.1.md ../lib/zstd.h\n\tcat $< | $(MD2ROFF) $(MD2ROFF_FLAGS) | sed -n '/^\\.\\\\\\\".*/!p' > $@\n\nzstdgrep.1: zstdgrep.1.md ../lib/zstd.h\n\tcat $< | $(MD2ROFF) $(MD2ROFF_FLAGS) | sed -n '/^\\.\\\\\\\".*/!p' > $@\n\nzstdless.1: zstdless.1.md ../lib/zstd.h\n\tcat $< | $(MD2ROFF) $(MD2ROFF_FLAGS) | sed -n '/^\\.\\\\\\\".*/!p' > $@\n\n.PHONY: man\nman: zstd.1 zstdgrep.1 zstdless.1\n\n.PHONY: clean-man\nclean-man:\n\t$(RM) zstd.1\n\t$(RM) zstdgrep.1\n\t$(RM) zstdless.1\n\n.PHONY: preview-man\npreview-man: clean-man man\n\tman ./zstd.1\n\tman ./zstdgrep.1\n\tman ./zstdless.1\n\n\n# Generate .h dependencies automatically\n\nDEPFLAGS = -MT $@ -MMD -MP -MF\n\n$(BUILD_DIR)/%.o : %.c $(BUILD_DIR)/%.d | $(BUILD_DIR)\n\t@echo CC $@\n\t$(COMPILE.c) $(DEPFLAGS) $(BUILD_DIR)/$*.d $(OUTPUT_OPTION) $<\n\n$(BUILD_DIR)/%.o : %.S | $(BUILD_DIR)\n\t@echo AS $@\n\t$(COMPILE.S) $(OUTPUT_OPTION) $<\n\nMKDIR ?= mkdir\n$(BUILD_DIR): ; $(MKDIR) -p $@\n\nDEPFILES := $(ZSTD_OBJ:.o=.d)\n$(DEPFILES):\n\ninclude $(wildcard $(DEPFILES))\n\n\n\n#-----------------------------------------------------------------------------\n# make install is validated only for Linux, macOS, BSD, Hurd and Solaris targets\n#-----------------------------------------------------------------------------\nifneq (,$(filter $(INSTALL_OS_LIST),$(UNAME)))\n\nHAVE_COLORNEVER = $(shell echo a | egrep --color=never a > /dev/null 2> /dev/null && echo 1 || echo 0)\nEGREP_OPTIONS ?=\nifeq ($(HAVE_COLORNEVER), 1)\n  EGREP_OPTIONS += --color=never\nendif\nEGREP = egrep $(EGREP_OPTIONS)\nAWK = awk\n\n# Print a two column output of targets and their description. To add a target description, put a\n# comment in the Makefile with the format \"## <TARGET>: <DESCRIPTION>\".  For example:\n#\n## list: Print all targets and their descriptions (if provided)\n.PHONY: list\nlist:\n\tTARGETS=$$($(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null \\\n\t\t| $(AWK) -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ \"^[#.]\") {print $$1}}' \\\n\t\t| $(EGREP) -v  -e '^[^[:alnum:]]' | sort); \\\n\t{ \\\n\t    printf \"Target Name\\tDescription\\n\"; \\\n\t    printf \"%0.s-\" {1..16}; printf \"\\t\"; printf \"%0.s-\" {1..40}; printf \"\\n\"; \\\n\t    for target in $$TARGETS; do \\\n\t        line=$$($(EGREP) \"^##[[:space:]]+$$target:\" $(lastword $(MAKEFILE_LIST))); \\\n\t        description=$$(echo $$line | $(AWK) '{i=index($$0,\":\"); print substr($$0,i+1)}' | xargs); \\\n\t        printf \"$$target\\t$$description\\n\"; \\\n\t    done \\\n\t} | column -t -s $$'\\t'\n\n\nDESTDIR     ?=\n# directory variables : GNU conventions prefer lowercase\n# see https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html\n# support both lower and uppercase (BSD), use uppercase in script\nprefix      ?= /usr/local\nPREFIX      ?= $(prefix)\nexec_prefix ?= $(PREFIX)\nbindir      ?= $(exec_prefix)/bin\nBINDIR      ?= $(bindir)\ndatarootdir ?= $(PREFIX)/share\nmandir      ?= $(datarootdir)/man\nman1dir     ?= $(mandir)/man1\n\nifneq (,$(filter OpenBSD NetBSD DragonFly SunOS,$(UNAME)))\n  MANDIR  ?= $(PREFIX)/man\n  MAN1DIR ?= $(MANDIR)/man1\nelse\n  MAN1DIR ?= $(man1dir)\nendif\n\nifneq (,$(filter SunOS,$(UNAME)))\n  INSTALL ?= ginstall\nelse\n  INSTALL ?= install\nendif\n\nINSTALL_PROGRAM ?= $(INSTALL)\nINSTALL_SCRIPT  ?= $(INSTALL_PROGRAM)\nINSTALL_DATA    ?= $(INSTALL) -m 644\nINSTALL_MAN     ?= $(INSTALL_DATA)\n\n.PHONY: install\ninstall:\n\t# generate zstd only if not already present\n\t[ -e zstd ] || $(MAKE) zstd-release\n\t[ -e $(DESTDIR)$(BINDIR) ] || $(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR)/\n\t[ -e $(DESTDIR)$(MAN1DIR) ] || $(INSTALL) -d -m 755 $(DESTDIR)$(MAN1DIR)/\n\t@echo Installing binaries\n\t$(INSTALL_PROGRAM) zstd$(EXT) $(DESTDIR)$(BINDIR)/zstd$(EXT)\n\t$(LN) -sf zstd$(EXT) $(DESTDIR)$(BINDIR)/zstdcat$(EXT)\n\t$(LN) -sf zstd$(EXT) $(DESTDIR)$(BINDIR)/unzstd$(EXT)\n\t$(LN) -sf zstd$(EXT) $(DESTDIR)$(BINDIR)/zstdmt$(EXT)\n\t$(INSTALL_SCRIPT) zstdless $(DESTDIR)$(BINDIR)/zstdless\n\t$(INSTALL_SCRIPT) zstdgrep $(DESTDIR)$(BINDIR)/zstdgrep\n\t@echo Installing man pages\n\t$(INSTALL_MAN) zstd.1 $(DESTDIR)$(MAN1DIR)/zstd.1\n\t$(LN) -sf zstd.1 $(DESTDIR)$(MAN1DIR)/zstdcat.1\n\t$(LN) -sf zstd.1 $(DESTDIR)$(MAN1DIR)/unzstd.1\n\t$(INSTALL_MAN) zstdgrep.1 $(DESTDIR)$(MAN1DIR)/zstdgrep.1\n\t$(INSTALL_MAN) zstdless.1 $(DESTDIR)$(MAN1DIR)/zstdless.1\n\t@echo zstd installation completed\n\n.PHONY: uninstall\nuninstall:\n\t$(RM) $(DESTDIR)$(BINDIR)/zstdgrep\n\t$(RM) $(DESTDIR)$(BINDIR)/zstdless\n\t$(RM) $(DESTDIR)$(BINDIR)/zstdcat\n\t$(RM) $(DESTDIR)$(BINDIR)/unzstd\n\t$(RM) $(DESTDIR)$(BINDIR)/zstdmt\n\t$(RM) $(DESTDIR)$(BINDIR)/zstd\n\t$(RM) $(DESTDIR)$(MAN1DIR)/zstdless.1\n\t$(RM) $(DESTDIR)$(MAN1DIR)/zstdgrep.1\n\t$(RM) $(DESTDIR)$(MAN1DIR)/zstdcat.1\n\t$(RM) $(DESTDIR)$(MAN1DIR)/unzstd.1\n\t$(RM) $(DESTDIR)$(MAN1DIR)/zstd.1\n\t@echo zstd programs successfully uninstalled\n\nendif\n"
  },
  {
    "path": "programs/README.md",
    "content": "Command Line Interface for Zstandard library\n============================================\n\nCommand Line Interface (CLI) can be created using the `make` command without any additional parameters.\nThere are however other Makefile targets that create different variations of CLI:\n- `zstd` : default CLI supporting gzip-like arguments; includes dictionary builder, benchmark, and supports decompression of legacy zstd formats\n- `zstd_nolegacy` : Same as `zstd` but without support for legacy zstd formats\n- `zstd-small` : CLI optimized for minimal size; no dictionary builder, no benchmark, and no support for legacy zstd formats\n- `zstd-compress` : version of CLI which can only compress into zstd format\n- `zstd-decompress` : version of CLI which can only decompress zstd format\n\n\n### Compilation variables\n`zstd` scope can be altered by modifying the following `make` variables :\n\n- __HAVE_THREAD__ : multithreading is automatically enabled when `pthread` is detected.\n  It's possible to disable multithread support, by setting `HAVE_THREAD=0`.\n  Example : `make zstd HAVE_THREAD=0`\n  It's also possible to force multithread support, using `HAVE_THREAD=1`.\n  In which case, linking stage will fail if neither `pthread` nor `windows.h` library can be found.\n  This is useful to ensure this feature is not silently disabled.\n\n- __ZSTD_LEGACY_SUPPORT__ : `zstd` can decompress files compressed by older versions of `zstd`.\n  Starting v0.8.0, all versions of `zstd` produce frames compliant with the [specification](../doc/zstd_compression_format.md), and are therefore compatible.\n  But older versions (< v0.8.0) produced different, incompatible, frames.\n  By default, `zstd` supports decoding legacy formats >= v0.4.0 (`ZSTD_LEGACY_SUPPORT=4`).\n  This can be altered by modifying this compilation variable.\n  `ZSTD_LEGACY_SUPPORT=1` means \"support all formats >= v0.1.0\".\n  `ZSTD_LEGACY_SUPPORT=2` means \"support all formats >= v0.2.0\", and so on.\n  `ZSTD_LEGACY_SUPPORT=0` means _DO NOT_ support any legacy format.\n  if `ZSTD_LEGACY_SUPPORT >= 8`, it's the same as `0`, since there is no legacy format after `7`.\n  Note : `zstd` only supports decoding older formats, and cannot generate any legacy format.\n\n- __HAVE_ZLIB__ : `zstd` can compress and decompress files in `.gz` format.\n  This is ordered through command `--format=gzip`.\n  Alternatively, symlinks named `gzip` or `gunzip` will mimic intended behavior.\n  `.gz` support is automatically enabled when `zlib` library is detected at build time.\n  It's possible to disable `.gz` support, by setting `HAVE_ZLIB=0`.\n  Example : `make zstd HAVE_ZLIB=0`\n  It's also possible to force compilation with zlib support, using `HAVE_ZLIB=1`.\n  In which case, linking stage will fail if `zlib` library cannot be found.\n  This is useful to prevent silent feature disabling.\n\n- __HAVE_LZMA__ : `zstd` can compress and decompress files in `.xz` and `.lzma` formats.\n  This is ordered through commands `--format=xz` and `--format=lzma` respectively.\n  Alternatively, symlinks named `xz`, `unxz`, `lzma`, or `unlzma` will mimic intended behavior.\n  `.xz` and `.lzma` support is automatically enabled when `lzma` library is detected at build time.\n  It's possible to disable `.xz` and `.lzma` support, by setting `HAVE_LZMA=0`.\n  Example : `make zstd HAVE_LZMA=0`\n  It's also possible to force compilation with lzma support, using `HAVE_LZMA=1`.\n  In which case, linking stage will fail if `lzma` library cannot be found.\n  This is useful to prevent silent feature disabling.\n\n- __HAVE_LZ4__ : `zstd` can compress and decompress files in `.lz4` formats.\n  This is ordered through commands `--format=lz4`.\n  Alternatively, symlinks named `lz4`, or `unlz4` will mimic intended behavior.\n  `.lz4` support is automatically enabled when `lz4` library is detected at build time.\n  It's possible to disable `.lz4` support, by setting `HAVE_LZ4=0` .\n  Example : `make zstd HAVE_LZ4=0`\n  It's also possible to force compilation with lz4 support, using `HAVE_LZ4=1`.\n  In which case, linking stage will fail if `lz4` library cannot be found.\n  This is useful to prevent silent feature disabling.\n\n- __ZSTD_NOBENCH__ : `zstd` cli will be compiled without its integrated benchmark module.\n  This can be useful to produce smaller binaries.\n  In this case, the corresponding unit can also be excluded from compilation target.\n\n- __ZSTD_NODICT__ : `zstd` cli will be compiled without support for the integrated dictionary builder.\n  This can be useful to produce smaller binaries.\n  In this case, the corresponding unit can also be excluded from compilation target.\n\n- __ZSTD_NOCOMPRESS__ : `zstd` cli will be compiled without support for compression.\n  The resulting binary will only be able to decompress files.\n  This can be useful to produce smaller binaries.\n  A corresponding `Makefile` target using this ability is `zstd-decompress`.\n\n- __ZSTD_NODECOMPRESS__ : `zstd` cli will be compiled without support for decompression.\n  The resulting binary will only be able to compress files.\n  This can be useful to produce smaller binaries.\n  A corresponding `Makefile` target using this ability is `zstd-compress`.\n\n- __ZSTD_DISPLAY_LEVEL_DEFAULT__ : Controls the default verbosity level of `zstd` output.\n  The default value is `2`. Lower values (e.g., `1`) reduce output verbosity,\n  while higher values (e.g., `3`) increase it.\n  This allows setting preferred verbosity at compile time,\n  rather than passing `-q` or `-v` flags at runtime.\n  Example : `CPPFLAGS=\"-DZSTD_DISPLAY_LEVEL_DEFAULT=1\" make`\n\n- __BACKTRACE__ : `zstd` can display a stack backtrace when execution\n  generates a runtime exception. By default, this feature may be\n  degraded/disabled on some platforms unless additional compiler directives are\n  applied. When triaging a runtime issue, enabling this feature can provide\n  more context to determine the location of the fault.\n  Example : `make zstd BACKTRACE=1`\n\n\n### Aggregation of parameters\nCLI supports aggregation of parameters i.e. `-b1`, `-e18`, and `-i1` can be joined into `-b1e18i1`.\n\n\n### Symlink shortcuts\nIt's possible to invoke `zstd` through a symlink.\nWhen the name of the symlink has a specific value, it triggers an associated behavior.\n- `zstdmt` : compress using all cores available on local system.\n- `zcat` : will decompress and output target file using any of the supported formats. `gzcat` and `zstdcat` are also equivalent.\n- `gzip` : if zlib support is enabled, will mimic `gzip` by compressing file using `.gz` format, removing source file by default (use `--keep` to preserve). If zlib is not supported, triggers an error.\n- `xz` : if lzma support is enabled, will mimic `xz` by compressing file using `.xz` format, removing source file by default (use `--keep` to preserve). If xz is not supported, triggers an error.\n- `lzma` : if lzma support is enabled, will mimic `lzma` by compressing file using `.lzma` format, removing source file by default (use `--keep` to preserve). If lzma is not supported, triggers an error.\n- `lz4` : if lz4 support is enabled, will mimic `lz4` by compressing file using `.lz4` format. If lz4 is not supported, triggers an error.\n- `unzstd` and `unlz4` will decompress any of the supported format.\n- `ungz`, `unxz` and `unlzma` will do the same, and will also remove source file by default (use `--keep` to preserve).\n\n\n### Dictionary builder in Command Line Interface\nZstd offers a training mode, which can be used to tune the algorithm for a selected\ntype of data, by providing it with a few samples. The result of the training is stored\nin a file selected with the `-o` option (default name is `dictionary`),\nwhich can be loaded before compression and decompression.\n\nUsing a dictionary, the compression ratio achievable on small data improves dramatically.\nThese compression gains are achieved while simultaneously providing faster compression and decompression speeds.\nDictionary work if there is some correlation in a family of small data (there is no universal dictionary).\nHence, deploying one dictionary per type of data will provide the greater benefits.\nDictionary gains are mostly effective in the first few KB. Then, the compression algorithm\nwill rely more and more on previously decoded content to compress the rest of the file.\n\nUsage of the dictionary builder and created dictionaries with CLI:\n\n1. Create the dictionary : `zstd --train PathToTrainingSet/* -o dictionaryName`\n2. Compress with the dictionary: `zstd FILE -D dictionaryName`\n3. Decompress with the dictionary: `zstd --decompress FILE.zst -D dictionaryName`\n\n\n### Benchmark in Command Line Interface\nCLI includes in-memory compression benchmark module for zstd.\nThe benchmark is conducted using given filenames. The files are read into memory and joined together.\nIt makes benchmark more precise as it eliminates I/O overhead.\nMultiple filenames can be supplied, as multiple parameters, with wildcards,\nor directory names can be used with `-r` option.\nIf no file is provided, the benchmark will use a procedurally generated \"lorem ipsum\" content.\n\nThe benchmark measures ratio, compressed size, compression and decompression speed.\nOne can select compression levels starting from `-b` and ending with `-e`.\nThe `-i` parameter selects minimal time used for each of tested levels.\n\nThe benchmark can also be used to test specific parameters,\nsuch as number of threads (`-T#`), or advanced parameters (`--zstd=#`), or dictionary compression (`-D DICTIONARY`),\nand many others available on command for regular compression and decompression.\n\n\n### Usage of Command Line Interface\nThe full list of options can be obtained with `-h` or `-H` parameter:\n```\n*** Zstandard CLI (64-bit) v1.5.6, by Yann Collet ***\n\nCompress or decompress the INPUT file(s); reads from STDIN if INPUT is `-` or not provided.\n\nUsage: zstd [OPTIONS...] [INPUT... | -] [-o OUTPUT]\n\nOptions:\n  -o OUTPUT                     Write output to a single file, OUTPUT.\n  -k, --keep                    Preserve INPUT file(s). [Default]\n  --rm                          Remove INPUT file(s) after successful (de)compression to file.\n\n  -#                            Desired compression level, where `#` is a number between 1 and 19;\n                                lower numbers provide faster compression, higher numbers yield\n                                better compression ratios. [Default: 3]\n\n  -d, --decompress              Perform decompression.\n  -D DICT                       Use DICT as the dictionary for compression or decompression.\n\n  -f, --force                   Disable input and output checks. Allows overwriting existing files,\n                                receiving input from the console, printing output to STDOUT, and\n                                operating on links, block devices, etc. Unrecognized formats will be\n                                passed-through through as-is.\n\n  -h                            Display short usage and exit.\n  -H, --help                    Display full help and exit.\n  -V, --version                 Display the program version and exit.\n\nAdvanced options:\n  -c, --stdout                  Write to STDOUT (even if it is a console) and keep the INPUT file(s).\n\n  -v, --verbose                 Enable verbose output; pass multiple times to increase verbosity.\n  -q, --quiet                   Suppress warnings; pass twice to suppress errors.\n  --trace LOG                   Log tracing information to LOG.\n\n  --[no-]progress               Forcibly show/hide the progress counter. NOTE: Any (de)compressed\n                                output to terminal will mix with progress counter text.\n\n  -r                            Operate recursively on directories.\n  --filelist LIST               Read a list of files to operate on from LIST.\n  --output-dir-flat DIR         Store processed files in DIR.\n  --output-dir-mirror DIR       Store processed files in DIR, respecting original directory structure.\n  --[no-]asyncio                Use asynchronous IO. [Default: Enabled]\n\n  --[no-]check                  Add XXH64 integrity checksums during compression. [Default: Add, Validate]\n                                If `-d` is present, ignore/validate checksums during decompression.\n\n  --                            Treat remaining arguments after `--` as files.\n\nAdvanced compression options:\n  --ultra                       Enable levels beyond 19, up to 22; requires more memory.\n  --fast[=#]                    Use to very fast compression levels. [Default: 1]\n  --adapt                       Dynamically adapt compression level to I/O conditions.\n  --long[=#]                    Enable long distance matching with window log #. [Default: 27]\n  --patch-from=REF              Use REF as the reference point for Zstandard's diff engine.\n\n  -T#                           Spawn # compression threads. [Default: 1; pass 0 for core count.]\n  --single-thread               Share a single thread for I/O and compression (slightly different than `-T1`).\n  --auto-threads={physical|logical}\n                                Use physical/logical cores when using `-T0`. [Default: Physical]\n\n  -B#                           Set job size to #. [Default: 0 (automatic)]\n  --rsyncable                   Compress using a rsync-friendly method (`-B` sets block size).\n\n  --exclude-compressed          Only compress files that are not already compressed.\n\n  --stream-size=#               Specify size of streaming input from STDIN.\n  --size-hint=#                 Optimize compression parameters for streaming input of approximately size #.\n  --target-compressed-block-size=#\n                                Generate compressed blocks of approximately # size.\n\n  --no-dictID                   Don't write `dictID` into the header (dictionary compression only).\n  --[no-]compress-literals      Force (un)compressed literals.\n  --[no-]row-match-finder       Explicitly enable/disable the fast, row-based matchfinder for\n                                the 'greedy', 'lazy', and 'lazy2' strategies.\n\n  --format=zstd                 Compress files to the `.zst` format. [Default]\n  --[no-]mmap-dict              Memory-map dictionary file rather than mallocing and loading all at once\n  --format=gzip                 Compress files to the `.gz` format.\n  --format=xz                   Compress files to the `.xz` format.\n  --format=lzma                 Compress files to the `.lzma` format.\n  --format=lz4                  Compress files to the `.lz4` format.\n\nAdvanced decompression options:\n  -l                            Print information about Zstandard-compressed files.\n  --test                        Test compressed file integrity.\n  -M#                           Set the memory usage limit to # megabytes.\n  --[no-]sparse                 Enable sparse mode. [Default: Enabled for files, disabled for STDOUT.]\n  --[no-]pass-through           Pass through uncompressed files as-is. [Default: Disabled]\n\nDictionary builder:\n  --train                       Create a dictionary from a training set of files.\n\n  --train-cover[=k=#,d=#,steps=#,split=#,shrink[=#]]\n                                Use the cover algorithm (with optional arguments).\n  --train-fastcover[=k=#,d=#,f=#,steps=#,split=#,accel=#,shrink[=#]]\n                                Use the fast cover algorithm (with optional arguments).\n\n  --train-legacy[=s=#]          Use the legacy algorithm with selectivity #. [Default: 9]\n  -o NAME                       Use NAME as dictionary name. [Default: dictionary]\n  --maxdict=#                   Limit dictionary to specified size #. [Default: 112640]\n  --dictID=#                    Force dictionary ID to #. [Default: Random]\n\nBenchmark options:\n  -b#                           Perform benchmarking with compression level #. [Default: 3]\n  -e#                           Test all compression levels up to #; starting level is `-b#`. [Default: 1]\n  -i#                           Set the minimum evaluation to time # seconds. [Default: 3]\n  -B#                           Cut file into independent chunks of size #. [Default: No chunking]\n  -S                            Output one benchmark result per input file. [Default: Consolidated result]\n  -D dictionary                 Benchmark using dictionary\n  --priority=rt                 Set process priority to real-time.\n```\n\n### Passing parameters through Environment Variables\nThere is no \"generic\" way to pass \"any kind of parameter\" to `zstd` in a pass-through manner.\nUsing environment variables for this purpose has security implications.\nTherefore, this avenue is intentionally restricted and only supports `ZSTD_CLEVEL` and `ZSTD_NBTHREADS`.\n\n`ZSTD_CLEVEL` can be used to modify the default compression level of `zstd`\n(usually set to `3`) to another value between 1 and 19 (the \"normal\" range).\n\n`ZSTD_NBTHREADS` can be used to specify a number of threads\nthat `zstd` will use for compression, which by default is `1`.\nThis functionality only exists when `zstd` is compiled with multithread support.\n`0` means \"use as many threads as detected cpu cores on local system\".\nThe max # of threads is capped at `ZSTDMT_NBWORKERS_MAX`,\nwhich is either 64 in 32-bit mode, or 256 for 64-bit environments.\n\nThis functionality can be useful when `zstd` CLI is invoked in a way that doesn't allow passing arguments.\nOne such scenario is `tar --zstd`.\nAs `ZSTD_CLEVEL` and `ZSTD_NBTHREADS` only replace the default compression level\nand number of threads respectively, they can both be overridden by corresponding command line arguments:\n`-#` for compression level and `-T#` for number of threads.\n\n\n### Long distance matching mode\nThe long distance matching mode, enabled with `--long`, is designed to improve\nthe compression ratio for files with long matches at a large distance (up to the\nmaximum window size, `128 MiB`) while still maintaining compression speed.\n\nEnabling this mode sets the window size to `128 MiB` and thus increases the memory\nusage for both the compressor and decompressor. Performance in terms of speed is\ndependent on long matches being found. Compression speed may degrade if few long\nmatches are found. Decompression speed usually improves when there are many long\ndistance matches.\n\nBelow are graphs comparing the compression speed, compression ratio, and\ndecompression speed with and without long distance matching on an ideal use\ncase: a tar of four versions of clang (versions `3.4.1`, `3.4.2`, `3.5.0`,\n`3.5.1`) with a total size of `244889600 B`. This is an ideal use case as there\nare many long distance matches within the maximum window size of `128 MiB` (each\nversion is less than `128 MiB`).\n\nCompression Speed vs Ratio | Decompression Speed\n---------------------------|---------------------\n![Compression Speed vs Ratio](https://raw.githubusercontent.com/facebook/zstd/v1.3.3/doc/images/ldmCspeed.png \"Compression Speed vs Ratio\") | ![Decompression Speed](https://raw.githubusercontent.com/facebook/zstd/v1.3.3/doc/images/ldmDspeed.png \"Decompression Speed\")\n\n| Method | Compression ratio | Compression speed | Decompression speed  |\n|:-------|------------------:|-------------------------:|---------------------------:|\n| `zstd -1`  | `5.065`    | `284.8 MB/s`  | `759.3 MB/s`  |\n| `zstd -5`  | `5.826`    | `124.9 MB/s`  | `674.0 MB/s`  |\n| `zstd -10` | `6.504`    | `29.5 MB/s`   | `771.3 MB/s`  |\n| `zstd -1 --long` | `17.426` | `220.6 MB/s` | `1638.4 MB/s` |\n| `zstd -5 --long` | `19.661` | `165.5 MB/s` | `1530.6 MB/s` |\n| `zstd -10 --long`| `21.949` |  `75.6 MB/s` | `1632.6 MB/s` |\n\nOn this file, the compression ratio improves significantly with minimal impact\non compression speed, and the decompression speed doubles.\n\nOn the other extreme, compressing a file with few long distance matches (such as\nthe [Silesia compression corpus]) will likely lead to a deterioration in\ncompression speed (for lower levels) with minimal change in compression ratio.\n\nThe below table illustrates this on the [Silesia compression corpus].\n\n[Silesia compression corpus]: https://sun.aei.polsl.pl//~sdeor/index.php?page=silesia\n\n| Method | Compression ratio | Compression speed | Decompression speed  |\n|:-------|------------------:|------------------:|---------------------:|\n| `zstd -1`        | `2.878` | `231.7 MB/s`      | `594.4 MB/s`   |\n| `zstd -1 --long` | `2.929` | `106.5 MB/s`      | `517.9 MB/s`   |\n| `zstd -5`        | `3.274` | `77.1 MB/s`       | `464.2 MB/s`   |\n| `zstd -5 --long` | `3.319` | `51.7 MB/s`       | `371.9 MB/s`   |\n| `zstd -10`       | `3.523` | `16.4 MB/s`       | `489.2 MB/s`   |\n| `zstd -10 --long`| `3.566` | `16.2 MB/s`       | `415.7 MB/s`   |\n\n\n### zstdgrep\n\n`zstdgrep` is a utility which makes it possible to `grep` directly a `.zst` compressed file.\nIt's used the same way as normal `grep`, for example :\n`zstdgrep pattern file.zst`\n\n`zstdgrep` is _not_ compatible with dictionary compression.\n\nTo search into a file compressed with a dictionary,\nit's necessary to decompress it using `zstd` or `zstdcat`,\nand then pipe the result to `grep`. For example  :\n`zstdcat -D dictionary -qc -- file.zst | grep pattern`\n"
  },
  {
    "path": "programs/benchfn.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n\n/* *************************************\n*  Includes\n***************************************/\n#include <stdlib.h>      /* malloc, free */\n#include <string.h>      /* memset */\n#include <assert.h>      /* assert */\n\n#include \"timefn.h\"        /* UTIL_time_t, UTIL_getTime */\n#include \"benchfn.h\"\n\n\n/* *************************************\n*  Constants\n***************************************/\n#define TIMELOOP_MICROSEC     SEC_TO_MICRO      /* 1 second */\n#define TIMELOOP_NANOSEC      (1*1000000000ULL) /* 1 second */\n\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\n\n/* *************************************\n*  Debug errors\n***************************************/\n#if defined(DEBUG) && (DEBUG >= 1)\n#  include <stdio.h>       /* fprintf */\n#  define DISPLAY(...)       fprintf(stderr, __VA_ARGS__)\n#  define DEBUGOUTPUT(...) { if (DEBUG) DISPLAY(__VA_ARGS__); }\n#else\n#  define DEBUGOUTPUT(...)\n#endif\n\n\n/* error without displaying */\n#define RETURN_QUIET_ERROR(retValue, ...) {           \\\n    DEBUGOUTPUT(\"%s: %i: \\n\", __FILE__, __LINE__);    \\\n    DEBUGOUTPUT(\"Error : \");                          \\\n    DEBUGOUTPUT(__VA_ARGS__);                         \\\n    DEBUGOUTPUT(\" \\n\");                               \\\n    return retValue;                                  \\\n}\n\n/* Abort execution if a condition is not met */\n#define CONTROL(c) { if (!(c)) { DEBUGOUTPUT(\"error: %s \\n\", #c); abort(); } }\n\n\n/* *************************************\n*  Benchmarking an arbitrary function\n***************************************/\n\nint BMK_isSuccessful_runOutcome(BMK_runOutcome_t outcome)\n{\n    return outcome.error_tag_never_ever_use_directly == 0;\n}\n\n/* warning : this function will stop program execution if outcome is invalid !\n *           check outcome validity first, using BMK_isValid_runResult() */\nBMK_runTime_t BMK_extract_runTime(BMK_runOutcome_t outcome)\n{\n    CONTROL(outcome.error_tag_never_ever_use_directly == 0);\n    return outcome.internal_never_ever_use_directly;\n}\n\nsize_t BMK_extract_errorResult(BMK_runOutcome_t outcome)\n{\n    CONTROL(outcome.error_tag_never_ever_use_directly != 0);\n    return outcome.error_result_never_ever_use_directly;\n}\n\nstatic BMK_runOutcome_t BMK_runOutcome_error(size_t errorResult)\n{\n    BMK_runOutcome_t b;\n    memset(&b, 0, sizeof(b));\n    b.error_tag_never_ever_use_directly = 1;\n    b.error_result_never_ever_use_directly = errorResult;\n    return b;\n}\n\nstatic BMK_runOutcome_t BMK_setValid_runTime(BMK_runTime_t runTime)\n{\n    BMK_runOutcome_t outcome;\n    outcome.error_tag_never_ever_use_directly = 0;\n    outcome.internal_never_ever_use_directly = runTime;\n    return outcome;\n}\n\n\n/* initFn will be measured once, benchFn will be measured `nbLoops` times */\n/* initFn is optional, provide NULL if none */\n/* benchFn must return a size_t value that errorFn can interpret */\n/* takes # of blocks and list of size & stuff for each. */\n/* can report result of benchFn for each block into blockResult. */\n/* blockResult is optional, provide NULL if this information is not required */\n/* note : time per loop can be reported as zero if run time < timer resolution */\nBMK_runOutcome_t BMK_benchFunction(BMK_benchParams_t p,\n                                   unsigned nbLoops)\n{\n    nbLoops += !nbLoops;   /* minimum nbLoops is 1 */\n\n    /* init */\n    {   size_t i;\n        for(i = 0; i < p.blockCount; i++) {\n            memset(p.dstBuffers[i], 0xE5, p.dstCapacities[i]);  /* warm up and erase result buffer */\n    }   }\n\n    /* benchmark */\n    {   size_t dstSize = 0;\n        UTIL_time_t const clockStart = UTIL_getTime();\n        unsigned loopNb, blockNb;\n        if (p.initFn != NULL) p.initFn(p.initPayload);\n        for (loopNb = 0; loopNb < nbLoops; loopNb++) {\n            for (blockNb = 0; blockNb < p.blockCount; blockNb++) {\n                size_t const res = p.benchFn(p.srcBuffers[blockNb], p.srcSizes[blockNb],\n                                   p.dstBuffers[blockNb], p.dstCapacities[blockNb],\n                                   p.benchPayload);\n                if (loopNb == 0) {\n                    if (p.blockResults != NULL) p.blockResults[blockNb] = res;\n                    if ((p.errorFn != NULL) && (p.errorFn(res))) {\n                        RETURN_QUIET_ERROR(BMK_runOutcome_error(res),\n                            \"Function benchmark failed on block %u (of size %u) with error %i\",\n                            blockNb, (unsigned)p.srcSizes[blockNb], (int)res);\n                    }\n                    dstSize += res;\n            }   }\n        }  /* for (loopNb = 0; loopNb < nbLoops; loopNb++) */\n\n        {   PTime const totalTime = UTIL_clockSpanNano(clockStart);\n            BMK_runTime_t rt;\n            rt.nanoSecPerRun = (double)totalTime / nbLoops;\n            rt.sumOfReturn = dstSize;\n            return BMK_setValid_runTime(rt);\n    }   }\n}\n\n\n/* ====  Benchmarking any function, providing intermediate results  ==== */\n\nstruct BMK_timedFnState_s {\n    PTime timeSpent_ns;\n    PTime timeBudget_ns;\n    PTime runBudget_ns;\n    BMK_runTime_t fastestRun;\n    unsigned nbLoops;\n    UTIL_time_t coolTime;\n};  /* typedef'd to BMK_timedFnState_t within bench.h */\n\nBMK_timedFnState_t* BMK_createTimedFnState(unsigned total_ms, unsigned run_ms)\n{\n    BMK_timedFnState_t* const r = (BMK_timedFnState_t*)malloc(sizeof(*r));\n    if (r == NULL) return NULL;   /* malloc() error */\n    BMK_resetTimedFnState(r, total_ms, run_ms);\n    return r;\n}\n\nvoid BMK_freeTimedFnState(BMK_timedFnState_t* state) { free(state); }\n\nBMK_timedFnState_t*\nBMK_initStatic_timedFnState(void* buffer, size_t size, unsigned total_ms, unsigned run_ms)\n{\n    typedef char check_size[ 2 * (sizeof(BMK_timedFnState_shell) >= sizeof(struct BMK_timedFnState_s)) - 1];  /* static assert : a compilation failure indicates that BMK_timedFnState_shell is not large enough */\n    typedef struct { check_size c; BMK_timedFnState_t tfs; } tfs_align;  /* force tfs to be aligned at its next best position */\n    size_t const tfs_alignment = offsetof(tfs_align, tfs); /* provides the minimal alignment restriction for BMK_timedFnState_t */\n    BMK_timedFnState_t* const r = (BMK_timedFnState_t*)buffer;\n    if (buffer == NULL) return NULL;\n    if (size < sizeof(struct BMK_timedFnState_s)) return NULL;\n    if ((size_t)buffer % tfs_alignment) return NULL;  /* buffer must be properly aligned */\n    BMK_resetTimedFnState(r, total_ms, run_ms);\n    return r;\n}\n\nvoid BMK_resetTimedFnState(BMK_timedFnState_t* timedFnState, unsigned total_ms, unsigned run_ms)\n{\n    if (!total_ms) total_ms = 1 ;\n    if (!run_ms) run_ms = 1;\n    if (run_ms > total_ms) run_ms = total_ms;\n    timedFnState->timeSpent_ns = 0;\n    timedFnState->timeBudget_ns = (PTime)total_ms * TIMELOOP_NANOSEC / 1000;\n    timedFnState->runBudget_ns = (PTime)run_ms * TIMELOOP_NANOSEC / 1000;\n    timedFnState->fastestRun.nanoSecPerRun = (double)TIMELOOP_NANOSEC * 2000000000;  /* hopefully large enough : must be larger than any potential measurement */\n    timedFnState->fastestRun.sumOfReturn = (size_t)(-1LL);\n    timedFnState->nbLoops = 1;\n    timedFnState->coolTime = UTIL_getTime();\n}\n\n/* Tells if nb of seconds set in timedFnState for all runs is spent.\n * note : this function will return 1 if BMK_benchFunctionTimed() has actually errored. */\nint BMK_isCompleted_TimedFn(const BMK_timedFnState_t* timedFnState)\n{\n    return (timedFnState->timeSpent_ns >= timedFnState->timeBudget_ns);\n}\n\n\n#undef MIN\n#define MIN(a,b)   ( (a) < (b) ? (a) : (b) )\n\n#define MINUSABLETIME  (TIMELOOP_NANOSEC / 2)  /* 0.5 seconds */\n\nBMK_runOutcome_t BMK_benchTimedFn(BMK_timedFnState_t* cont,\n                                  BMK_benchParams_t p)\n{\n    PTime const runBudget_ns = cont->runBudget_ns;\n    PTime const runTimeMin_ns = runBudget_ns / 2;\n    int completed = 0;\n    BMK_runTime_t bestRunTime = cont->fastestRun;\n\n    while (!completed) {\n        BMK_runOutcome_t const runResult = BMK_benchFunction(p, cont->nbLoops);\n\n        if(!BMK_isSuccessful_runOutcome(runResult)) { /* error : move out */\n            return runResult;\n        }\n\n        {   BMK_runTime_t const newRunTime = BMK_extract_runTime(runResult);\n            double const loopDuration_ns = newRunTime.nanoSecPerRun * cont->nbLoops;\n\n            cont->timeSpent_ns += (unsigned long long)loopDuration_ns;\n\n            /* estimate nbLoops for next run to last approximately 1 second */\n            if (loopDuration_ns > ((double)runBudget_ns / 50)) {\n                double const fastestRun_ns = MIN(bestRunTime.nanoSecPerRun, newRunTime.nanoSecPerRun);\n                cont->nbLoops = (unsigned)((double)runBudget_ns / fastestRun_ns) + 1;\n            } else {\n                /* previous run was too short : blindly increase workload by x multiplier */\n                const unsigned multiplier = 10;\n                assert(cont->nbLoops < ((unsigned)-1) / multiplier);  /* avoid overflow */\n                cont->nbLoops *= multiplier;\n            }\n\n            if(loopDuration_ns < (double)runTimeMin_ns) {\n                /* don't report results for which benchmark run time was too small : increased risks of rounding errors */\n                assert(completed == 0);\n                continue;\n            } else {\n                if(newRunTime.nanoSecPerRun < bestRunTime.nanoSecPerRun) {\n                    bestRunTime = newRunTime;\n                }\n                completed = 1;\n            }\n        }\n    }   /* while (!completed) */\n\n    return BMK_setValid_runTime(bestRunTime);\n}\n"
  },
  {
    "path": "programs/benchfn.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/* benchfn :\n * benchmark any function on a set of input\n * providing result in nanoSecPerRun\n * or detecting and returning an error\n */\n\n#ifndef BENCH_FN_H_23876\n#define BENCH_FN_H_23876\n\n/* ===  Dependencies  === */\n#include <stddef.h>   /* size_t */\n\n/* ====  Benchmark any function, iterated on a set of blocks  ==== */\n\n/* BMK_runTime_t: valid result return type */\n\ntypedef struct {\n    double nanoSecPerRun;  /* time per iteration (over all blocks) */\n    size_t sumOfReturn;         /* sum of return values */\n} BMK_runTime_t;\n\n\n/* BMK_runOutcome_t:\n * type expressing the outcome of a benchmark run by BMK_benchFunction(),\n * which can be either valid or invalid.\n * benchmark outcome can be invalid if errorFn is provided.\n * BMK_runOutcome_t must be considered \"opaque\" : never access its members directly.\n * Instead, use its assigned methods :\n * BMK_isSuccessful_runOutcome, BMK_extract_runTime, BMK_extract_errorResult.\n * The structure is only described here to allow its allocation on stack. */\n\ntypedef struct {\n    BMK_runTime_t internal_never_ever_use_directly;\n    size_t error_result_never_ever_use_directly;\n    int error_tag_never_ever_use_directly;\n} BMK_runOutcome_t;\n\n\n/* prototypes for benchmarked functions */\ntypedef size_t (*BMK_benchFn_t)(const void* src, size_t srcSize, void* dst, size_t dstCapacity, void* customPayload);\ntypedef size_t (*BMK_initFn_t)(void* initPayload);\ntypedef unsigned (*BMK_errorFn_t)(size_t);\n\n\n/* BMK_benchFunction() parameters are provided via the following structure.\n * A structure is preferable for readability,\n * as the number of parameters required is fairly large.\n * No initializer is provided, because it doesn't make sense to provide some \"default\" :\n * all parameters must be specified by the caller.\n * optional parameters are labelled explicitly, and accept value NULL when not used */\ntypedef struct {\n    BMK_benchFn_t benchFn;    /* the function to benchmark, over the set of blocks */\n    void* benchPayload;       /* pass custom parameters to benchFn  :\n                               * (*benchFn)(srcBuffers[i], srcSizes[i], dstBuffers[i], dstCapacities[i], benchPayload) */\n    BMK_initFn_t initFn;      /* (*initFn)(initPayload) is run once per run, at the beginning. */\n    void* initPayload;        /* Both arguments can be NULL, in which case nothing is run. */\n    BMK_errorFn_t errorFn;    /* errorFn will check each return value of benchFn over each block, to determine if it failed or not.\n                               * errorFn can be NULL, in which case no check is performed.\n                               * errorFn must return 0 when benchFn was successful, and >= 1 if it detects an error.\n                               * Execution is stopped as soon as an error is detected.\n                               * the triggering return value can be retrieved using BMK_extract_errorResult(). */\n    size_t blockCount;        /* number of blocks to operate benchFn on.\n                               * It's also the size of all array parameters :\n                               * srcBuffers, srcSizes, dstBuffers, dstCapacities, blockResults */\n    const void *const * srcBuffers; /* read-only array of buffers to be operated on by benchFn */\n    const size_t* srcSizes;   /* read-only array containing sizes of srcBuffers */\n    void *const * dstBuffers; /* array of buffers to be written into by benchFn. This array is not optional, it must be provided even if unused by benchfn. */\n    const size_t* dstCapacities; /* read-only array containing capacities of dstBuffers. This array must be present. */\n    size_t* blockResults;     /* Optional: store the return value of benchFn for each block. Use NULL if this result is not requested. */\n} BMK_benchParams_t;\n\n\n/* BMK_benchFunction() :\n * This function benchmarks benchFn and initFn, providing a result.\n *\n * params : see description of BMK_benchParams_t above.\n * nbLoops: defines number of times benchFn is run over the full set of blocks.\n *          Minimum value is 1. A 0 is interpreted as a 1.\n *\n * @return: can express either an error or a successful result.\n *          Use BMK_isSuccessful_runOutcome() to check if benchmark was successful.\n *          If yes, extract the result with BMK_extract_runTime(),\n *          it will contain :\n *              .sumOfReturn : the sum of all return values of benchFn through all of blocks\n *              .nanoSecPerRun : time per run of benchFn + (time for initFn / nbLoops)\n *          .sumOfReturn is generally intended for functions which return a # of bytes written into dstBuffer,\n *              in which case, this value will be the total amount of bytes written into dstBuffer.\n *\n * blockResults : when provided (!= NULL), and when benchmark is successful,\n *                params.blockResults contains all return values of `benchFn` over all blocks.\n *                when provided (!= NULL), and when benchmark failed,\n *                params.blockResults contains return values of `benchFn` over all blocks preceding and including the failed block.\n */\nBMK_runOutcome_t BMK_benchFunction(BMK_benchParams_t params, unsigned nbLoops);\n\n\n\n/* check first if the benchmark was successful or not */\nint BMK_isSuccessful_runOutcome(BMK_runOutcome_t outcome);\n\n/* If the benchmark was successful, extract the result.\n * note : this function will abort() program execution if benchmark failed !\n *        always check if benchmark was successful first !\n */\nBMK_runTime_t BMK_extract_runTime(BMK_runOutcome_t outcome);\n\n/* when benchmark failed, it means one invocation of `benchFn` failed.\n * The failure was detected by `errorFn`, operating on return values of `benchFn`.\n * Returns the faulty return value.\n * note : this function will abort() program execution if benchmark did not fail.\n *        always check if benchmark failed first !\n */\nsize_t BMK_extract_errorResult(BMK_runOutcome_t outcome);\n\n\n\n/* ====  Benchmark any function, returning intermediate results  ==== */\n\n/* state information tracking benchmark session */\ntypedef struct BMK_timedFnState_s BMK_timedFnState_t;\n\n/* BMK_benchTimedFn() :\n * Similar to BMK_benchFunction(), most arguments being identical.\n * Automatically determines `nbLoops` so that each result is regularly produced at interval of about run_ms.\n * Note : minimum `nbLoops` is 1, therefore a run may last more than run_ms, and possibly even more than total_ms.\n * Usage - initialize timedFnState, select benchmark duration (total_ms) and each measurement duration (run_ms)\n *         call BMK_benchTimedFn() repetitively, each measurement is supposed to last about run_ms\n *         Check if total time budget is spent or exceeded, using BMK_isCompleted_TimedFn()\n */\nBMK_runOutcome_t BMK_benchTimedFn(BMK_timedFnState_t* timedFnState,\n                                  BMK_benchParams_t params);\n\n/* Tells if duration of all benchmark runs has exceeded total_ms\n */\nint BMK_isCompleted_TimedFn(const BMK_timedFnState_t* timedFnState);\n\n/* BMK_createTimedFnState() and BMK_resetTimedFnState() :\n * Create/Set BMK_timedFnState_t for next benchmark session,\n * which shall last a minimum of total_ms milliseconds,\n * producing intermediate results, paced at interval of (approximately) run_ms.\n */\nBMK_timedFnState_t* BMK_createTimedFnState(unsigned total_ms, unsigned run_ms);\nvoid BMK_resetTimedFnState(BMK_timedFnState_t* timedFnState, unsigned total_ms, unsigned run_ms);\nvoid BMK_freeTimedFnState(BMK_timedFnState_t* state);\n\n\n/* BMK_timedFnState_shell and BMK_initStatic_timedFnState() :\n * Makes it possible to statically allocate a BMK_timedFnState_t on stack.\n * BMK_timedFnState_shell is only there to allocate space,\n * never ever access its members.\n * BMK_timedFnState_t() actually accepts any buffer.\n * It will check if provided buffer is large enough and is correctly aligned,\n * and will return NULL if conditions are not respected.\n */\n#define BMK_TIMEDFNSTATE_SIZE 64\ntypedef union {\n    char never_access_space[BMK_TIMEDFNSTATE_SIZE];\n    long long alignment_enforcer;  /* must be aligned on 8-bytes boundaries */\n} BMK_timedFnState_shell;\nBMK_timedFnState_t* BMK_initStatic_timedFnState(void* buffer, size_t size, unsigned total_ms, unsigned run_ms);\n\n#endif   /* BENCH_FN_H_23876 */\n"
  },
  {
    "path": "programs/benchzstd.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* **************************************\n *  Tuning parameters\n ****************************************/\n#ifndef BMK_TIMETEST_DEFAULT_S /* default minimum time per test */\n#    define BMK_TIMETEST_DEFAULT_S 3\n#endif\n\n/* *************************************\n *  Includes\n ***************************************/\n/* this must be included first */\n#include \"platform.h\" /* Large Files support, compiler specifics */\n\n/* then following system includes */\n#include <assert.h> /* assert */\n#include <errno.h>\n#include <stdio.h>    /* fprintf, fopen */\n#include <stdlib.h>   /* malloc, free */\n#include <string.h>   /* memset, strerror */\n#include \"util.h\"     /* UTIL_getFileSize, UTIL_sleep */\n#include \"../lib/common/mem.h\"\n#include \"benchfn.h\"\n#include \"timefn.h\" /* UTIL_time_t */\n#ifndef ZSTD_STATIC_LINKING_ONLY\n#    define ZSTD_STATIC_LINKING_ONLY\n#endif\n#include \"../lib/zstd.h\"\n#include \"datagen.h\" /* RDG_genBuffer */\n#include \"lorem.h\"   /* LOREM_genBuffer */\n#ifndef XXH_INLINE_ALL\n#    define XXH_INLINE_ALL\n#endif\n#include \"../lib/common/xxhash.h\"\n#include \"../lib/zstd_errors.h\"\n#include \"benchzstd.h\"\n\n/* *************************************\n *  Constants\n ***************************************/\n#ifndef ZSTD_GIT_COMMIT\n#    define ZSTD_GIT_COMMIT_STRING \"\"\n#else\n#    define ZSTD_GIT_COMMIT_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_GIT_COMMIT)\n#endif\n\n#define TIMELOOP_MICROSEC (1 * 1000000ULL)             /* 1 second */\n#define TIMELOOP_NANOSEC (1 * 1000000000ULL)           /* 1 second */\n#define ACTIVEPERIOD_MICROSEC (70 * TIMELOOP_MICROSEC) /* 70 seconds */\n#define COOLPERIOD_SEC 10\n\n#define KB *(1 << 10)\n#define MB *(1 << 20)\n#define GB *(1U << 30)\n\n#define BMK_RUNTEST_DEFAULT_MS 1000\n\nstatic const size_t maxMemory = (sizeof(size_t) == 4)\n        ?\n        /* 32-bit */ (2 GB - 64 MB)\n        :\n        /* 64-bit */ (size_t)(1ULL << ((sizeof(size_t) * 8) - 31));\n\n/* *************************************\n *  console display\n ***************************************/\n#define DISPLAY(...)                  \\\n    {                                 \\\n        fprintf(stderr, __VA_ARGS__); \\\n        fflush(NULL);                 \\\n    }\n#define DISPLAYLEVEL(l, ...)  \\\n    if (displayLevel >= l) {  \\\n        DISPLAY(__VA_ARGS__); \\\n    }\n/* 0 : no display;   1: errors;   2 : + result + interaction + warnings;   3 : +\n * progression;   4 : + information */\n#define OUTPUT(...)                   \\\n    {                                 \\\n        fprintf(stdout, __VA_ARGS__); \\\n        fflush(NULL);                 \\\n    }\n#define OUTPUTLEVEL(l, ...)  \\\n    if (displayLevel >= l) { \\\n        OUTPUT(__VA_ARGS__); \\\n    }\n\n/* *************************************\n *  Exceptions\n ***************************************/\n#ifndef DEBUG\n#    define DEBUG 0\n#endif\n#define DEBUGOUTPUT(...)          \\\n    {                             \\\n        if (DEBUG)                \\\n            DISPLAY(__VA_ARGS__); \\\n    }\n\n#define RETURN_ERROR_INT(errorNum, ...)                \\\n    {                                                  \\\n        DEBUGOUTPUT(\"%s: %i: \\n\", __FILE__, __LINE__); \\\n        DISPLAYLEVEL(1, \"Error %i : \", errorNum);      \\\n        DISPLAYLEVEL(1, __VA_ARGS__);                  \\\n        DISPLAYLEVEL(1, \" \\n\");                        \\\n        return errorNum;                               \\\n    }\n\n#define CHECK_Z(zf)                                                  \\\n    {                                                                \\\n        size_t const zerr = zf;                                      \\\n        if (ZSTD_isError(zerr)) {                                    \\\n            DEBUGOUTPUT(\"%s: %i: \\n\", __FILE__, __LINE__);           \\\n            DISPLAY(\"Error : \");                                     \\\n            DISPLAY(\"%s failed : %s\", #zf, ZSTD_getErrorName(zerr)); \\\n            DISPLAY(\" \\n\");                                          \\\n            exit(1);                                                 \\\n        }                                                            \\\n    }\n\n#define RETURN_ERROR(errorNum, retType, ...)           \\\n    {                                                  \\\n        retType r;                                     \\\n        memset(&r, 0, sizeof(retType));                \\\n        DEBUGOUTPUT(\"%s: %i: \\n\", __FILE__, __LINE__); \\\n        DISPLAYLEVEL(1, \"Error %i : \", errorNum);      \\\n        DISPLAYLEVEL(1, __VA_ARGS__);                  \\\n        DISPLAYLEVEL(1, \" \\n\");                        \\\n        r.tag = errorNum;                              \\\n        return r;                                      \\\n    }\n\nstatic size_t uintSize(unsigned value)\n{\n    size_t size = 1;\n    while (value >= 10) {\n        size++;\n        value /= 10;\n    }\n    return size;\n}\n\n/* Note: presume @buffer is large enough */\nstatic void writeUint_varLen(char* buffer, size_t capacity, unsigned value)\n{\n    int endPos = (int)uintSize(value) - 1;\n    assert(uintSize(value) >= 1);\n    assert(uintSize(value) < capacity); (void)capacity;\n    while (endPos >= 0) {\n        char c = '0' + (char)(value % 10);\n        buffer[endPos--] = c;\n        value /= 10;\n    }\n}\n\n/* replacement for snprintf(), which is not supported by C89.\n * sprintf() would be the supported one, but it's labelled unsafe:\n * modern static analyzer will flag sprintf() as dangerous, making it unusable.\n * formatString_u() replaces snprintf() for the specific case where there is only one %u argument */\nstatic int formatString_u(char* buffer, size_t buffer_size, const char* formatString, unsigned int value)\n{\n    size_t const valueSize = uintSize(value);\n    size_t written = 0;\n    int i;\n\n    for (i = 0; formatString[i] != '\\0' && written < buffer_size - 1; i++) {\n        if (formatString[i] != '%') {\n            buffer[written++] = formatString[i];\n            continue;\n        }\n\n        i++;\n        if (formatString[i] == 'u') {\n            if (written + valueSize >= buffer_size) abort(); /* buffer not large enough */\n            writeUint_varLen(buffer + written, buffer_size - written, value);\n            written += valueSize;\n        } else if (formatString[i] == '%') { /* Check for escaped percent sign */\n            buffer[written++] = '%';\n        } else {\n            abort(); /* unsupported format */\n        }\n    }\n\n    if (written < buffer_size) {\n        buffer[written] = '\\0';\n    } else {\n        abort(); /* buffer not large enough */\n    }\n\n    return (int)written;\n}\n\n/* *************************************\n *  Benchmark Parameters\n ***************************************/\n\nBMK_advancedParams_t BMK_initAdvancedParams(void)\n{\n    BMK_advancedParams_t const res = {\n        BMK_both,               /* mode */\n        BMK_TIMETEST_DEFAULT_S, /* nbSeconds */\n        0,                      /* chunkSizeMax */\n        0,               /* targetCBlockSize */\n        0,                      /* nbWorkers */\n        0,                      /* realTime */\n        0,                      /* additionalParam */\n        0,                      /* ldmFlag */\n        0,                      /* ldmMinMatch */\n        0,                      /* ldmHashLog */\n        0,                      /* ldmBuckSizeLog */\n        0,                      /* ldmHashRateLog */\n        ZSTD_ps_auto,           /* literalCompressionMode */\n        0                       /* useRowMatchFinder */\n    };\n    return res;\n}\n\n/* ********************************************************\n *  Bench functions\n **********************************************************/\n#undef MIN\n#undef MAX\n#define MIN(a, b) ((a) < (b) ? (a) : (b))\n#define MAX(a, b) ((a) > (b) ? (a) : (b))\n\nstatic void BMK_initCCtx(\n        ZSTD_CCtx* ctx,\n        const void* dictBuffer,\n        size_t dictBufferSize,\n        int cLevel,\n        const ZSTD_compressionParameters* comprParams,\n        const BMK_advancedParams_t* adv)\n{\n    ZSTD_CCtx_reset(ctx, ZSTD_reset_session_and_parameters);\n    if (adv->nbWorkers == 1) {\n        CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_nbWorkers, 0));\n    } else {\n        CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_nbWorkers, adv->nbWorkers));\n    }\n    CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_compressionLevel, cLevel));\n    CHECK_Z(ZSTD_CCtx_setParameter(\n            ctx, ZSTD_c_useRowMatchFinder, adv->useRowMatchFinder));\n    CHECK_Z(ZSTD_CCtx_setParameter(\n            ctx, ZSTD_c_enableLongDistanceMatching, adv->ldmFlag));\n    CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmMinMatch, adv->ldmMinMatch));\n    CHECK_Z(ZSTD_CCtx_setParameter(ctx, ZSTD_c_ldmHashLog, adv->ldmHashLog));\n    CHECK_Z(ZSTD_CCtx_setParameter(\n            ctx, ZSTD_c_ldmBucketSizeLog, adv->ldmBucketSizeLog));\n    CHECK_Z(ZSTD_CCtx_setParameter(\n            ctx, ZSTD_c_ldmHashRateLog, adv->ldmHashRateLog));\n    CHECK_Z(ZSTD_CCtx_setParameter(\n            ctx, ZSTD_c_windowLog, (int)comprParams->windowLog));\n    CHECK_Z(ZSTD_CCtx_setParameter(\n            ctx, ZSTD_c_hashLog, (int)comprParams->hashLog));\n    CHECK_Z(ZSTD_CCtx_setParameter(\n            ctx, ZSTD_c_chainLog, (int)comprParams->chainLog));\n    CHECK_Z(ZSTD_CCtx_setParameter(\n            ctx, ZSTD_c_searchLog, (int)comprParams->searchLog));\n    CHECK_Z(ZSTD_CCtx_setParameter(\n            ctx, ZSTD_c_minMatch, (int)comprParams->minMatch));\n    CHECK_Z(ZSTD_CCtx_setParameter(\n            ctx, ZSTD_c_targetLength, (int)comprParams->targetLength));\n    CHECK_Z(ZSTD_CCtx_setParameter(\n            ctx,\n            ZSTD_c_literalCompressionMode,\n            (int)adv->literalCompressionMode));\n    CHECK_Z(ZSTD_CCtx_setParameter(\n            ctx, ZSTD_c_strategy, (int)comprParams->strategy));\n    CHECK_Z(ZSTD_CCtx_setParameter(\n            ctx, ZSTD_c_targetCBlockSize, (int)adv->targetCBlockSize));\n    CHECK_Z(ZSTD_CCtx_loadDictionary(ctx, dictBuffer, dictBufferSize));\n}\n\nstatic void\nBMK_initDCtx(ZSTD_DCtx* dctx, const void* dictBuffer, size_t dictBufferSize)\n{\n    CHECK_Z(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters));\n    CHECK_Z(ZSTD_DCtx_loadDictionary(dctx, dictBuffer, dictBufferSize));\n}\n\ntypedef struct {\n    ZSTD_CCtx* cctx;\n    const void* dictBuffer;\n    size_t dictBufferSize;\n    int cLevel;\n    const ZSTD_compressionParameters* comprParams;\n    const BMK_advancedParams_t* adv;\n} BMK_initCCtxArgs;\n\nstatic size_t local_initCCtx(void* payload)\n{\n    BMK_initCCtxArgs* ag = (BMK_initCCtxArgs*)payload;\n    BMK_initCCtx(\n            ag->cctx,\n            ag->dictBuffer,\n            ag->dictBufferSize,\n            ag->cLevel,\n            ag->comprParams,\n            ag->adv);\n    return 0;\n}\n\ntypedef struct {\n    ZSTD_DCtx* dctx;\n    const void* dictBuffer;\n    size_t dictBufferSize;\n} BMK_initDCtxArgs;\n\nstatic size_t local_initDCtx(void* payload)\n{\n    BMK_initDCtxArgs* ag = (BMK_initDCtxArgs*)payload;\n    BMK_initDCtx(ag->dctx, ag->dictBuffer, ag->dictBufferSize);\n    return 0;\n}\n\n/* `addArgs` is the context */\nstatic size_t local_defaultCompress(\n        const void* srcBuffer,\n        size_t srcSize,\n        void* dstBuffer,\n        size_t dstSize,\n        void* addArgs)\n{\n    ZSTD_CCtx* const cctx = (ZSTD_CCtx*)addArgs;\n    return ZSTD_compress2(cctx, dstBuffer, dstSize, srcBuffer, srcSize);\n}\n\n/* `addArgs` is the context */\nstatic size_t local_defaultDecompress(\n        const void* srcBuffer,\n        size_t srcSize,\n        void* dstBuffer,\n        size_t dstCapacity,\n        void* addArgs)\n{\n    size_t moreToFlush    = 1;\n    ZSTD_DCtx* const dctx = (ZSTD_DCtx*)addArgs;\n    ZSTD_inBuffer in;\n    ZSTD_outBuffer out;\n    in.src   = srcBuffer;\n    in.size  = srcSize;\n    in.pos   = 0;\n    out.dst  = dstBuffer;\n    out.size = dstCapacity;\n    out.pos  = 0;\n    while (moreToFlush) {\n        if (out.pos == out.size) {\n            return (size_t)-ZSTD_error_dstSize_tooSmall;\n        }\n        moreToFlush = ZSTD_decompressStream(dctx, &out, &in);\n        if (ZSTD_isError(moreToFlush)) {\n            return moreToFlush;\n        }\n    }\n    return out.pos;\n}\n\n/* ================================================================= */\n/*      Benchmark Zstandard, mem-to-mem scenarios                    */\n/* ================================================================= */\n\nint BMK_isSuccessful_benchOutcome(BMK_benchOutcome_t outcome)\n{\n    return outcome.tag == 0;\n}\n\nBMK_benchResult_t BMK_extract_benchResult(BMK_benchOutcome_t outcome)\n{\n    assert(outcome.tag == 0);\n    return outcome.internal_never_use_directly;\n}\n\nstatic BMK_benchOutcome_t BMK_benchOutcome_error(void)\n{\n    BMK_benchOutcome_t b;\n    memset(&b, 0, sizeof(b));\n    b.tag = 1;\n    return b;\n}\n\nstatic BMK_benchOutcome_t BMK_benchOutcome_setValidResult(\n        BMK_benchResult_t result)\n{\n    BMK_benchOutcome_t b;\n    b.tag                         = 0;\n    b.internal_never_use_directly = result;\n    return b;\n}\n\n/* benchMem with no allocation */\nstatic BMK_benchOutcome_t BMK_benchMemAdvancedNoAlloc(\n        const void** srcPtrs,\n        size_t* srcSizes,\n        void** cPtrs,\n        size_t* cCapacities,\n        size_t* cSizes,\n        void** resPtrs,\n        size_t* resSizes,\n        void** resultBufferPtr,\n        void* compressedBuffer,\n        size_t maxCompressedSize,\n        BMK_timedFnState_t* timeStateCompress,\n        BMK_timedFnState_t* timeStateDecompress,\n\n        const void* srcBuffer,\n        size_t srcSize,\n        const size_t* fileSizes,\n        unsigned nbFiles,\n        const int cLevel,\n        const ZSTD_compressionParameters* comprParams,\n        const void* dictBuffer,\n        size_t dictBufferSize,\n        ZSTD_CCtx* cctx,\n        ZSTD_DCtx* dctx,\n        int displayLevel,\n        const char* displayName,\n        const BMK_advancedParams_t* adv)\n{\n    size_t const chunkSizeMax =\n            ((adv->chunkSizeMax >= 32 && (adv->mode != BMK_decodeOnly))\n                     ? adv->chunkSizeMax\n                     : srcSize)\n            + (!srcSize); /* avoid div by 0 */\n    BMK_benchResult_t benchResult;\n    size_t const loadedCompressedSize = srcSize;\n    size_t cSize                      = 0;\n    double ratio                      = 0.;\n    U32 nbChunks = 0;\n\n    assert(cctx != NULL);\n    assert(dctx != NULL);\n\n    /* init */\n    memset(&benchResult, 0, sizeof(benchResult));\n    if (strlen(displayName) > 17)\n        displayName +=\n                strlen(displayName) - 17; /* display last 17 characters */\n    if (adv->mode == BMK_decodeOnly) {\n        /* benchmark only decompression : source must be already compressed */\n        const char* srcPtr = (const char*)srcBuffer;\n        U64 totalDSize64   = 0;\n        U32 fileNb;\n        for (fileNb = 0; fileNb < nbFiles; fileNb++) {\n            U64 const fSize64 =\n                    ZSTD_findDecompressedSize(srcPtr, fileSizes[fileNb]);\n            if (fSize64 == ZSTD_CONTENTSIZE_UNKNOWN) {\n                RETURN_ERROR(\n                        32,\n                        BMK_benchOutcome_t,\n                        \"Decompressed size cannot be determined: cannot benchmark\");\n            }\n            if (fSize64 == ZSTD_CONTENTSIZE_ERROR) {\n                RETURN_ERROR(\n                        32,\n                        BMK_benchOutcome_t,\n                        \"Error while trying to assess decompressed size: data may be invalid\");\n            }\n            totalDSize64 += fSize64;\n            srcPtr += fileSizes[fileNb];\n        }\n        {\n            size_t const decodedSize = (size_t)totalDSize64;\n            assert((U64)decodedSize == totalDSize64); /* check overflow */\n            free(*resultBufferPtr);\n            if (totalDSize64 > decodedSize) { /* size_t overflow */\n                RETURN_ERROR(\n                        32,\n                        BMK_benchOutcome_t,\n                        \"decompressed size is too large for local system\");\n            }\n            *resultBufferPtr = malloc(decodedSize);\n            if (!(*resultBufferPtr)) {\n                RETURN_ERROR(\n                        33,\n                        BMK_benchOutcome_t,\n                        \"allocation error: not enough memory\");\n            }\n            cSize   = srcSize;\n            srcSize = decodedSize;\n            ratio   = (double)srcSize / (double)cSize;\n        }\n    }\n\n    /* Init data chunks  */\n    {\n        const char* srcPtr = (const char*)srcBuffer;\n        char* cPtr         = (char*)compressedBuffer;\n        char* resPtr       = (char*)(*resultBufferPtr);\n        U32 fileNb, chunkID;\n        for (chunkID = 0, fileNb = 0; fileNb < nbFiles; fileNb++) {\n            size_t remaining              = fileSizes[fileNb];\n            U32 const nbChunksforThisFile = (adv->mode == BMK_decodeOnly)\n                    ? 1\n                    : (U32)((remaining + (chunkSizeMax - 1)) / chunkSizeMax);\n            U32 const chunkIdEnd       = chunkID + nbChunksforThisFile;\n            for (; chunkID < chunkIdEnd; chunkID++) {\n                size_t const chunkSize = MIN(remaining, chunkSizeMax);\n                srcPtrs[chunkID]       = srcPtr;\n                srcSizes[chunkID]      = chunkSize;\n                cPtrs[chunkID]         = cPtr;\n                cCapacities[chunkID]   = (adv->mode == BMK_decodeOnly)\n                             ? chunkSize\n                             : ZSTD_compressBound(chunkSize);\n                resPtrs[chunkID]       = resPtr;\n                resSizes[chunkID]      = (adv->mode == BMK_decodeOnly)\n                                ? (size_t)ZSTD_findDecompressedSize(\n                                srcPtr, chunkSize)\n                                : chunkSize;\n                srcPtr += chunkSize;\n                cPtr += cCapacities[chunkID];\n                resPtr += chunkSize;\n                remaining -= chunkSize;\n                if (adv->mode == BMK_decodeOnly) {\n                    cSizes[chunkID]  = chunkSize;\n                    benchResult.cSize = chunkSize;\n                }\n            }\n        }\n        nbChunks = chunkID;\n    }\n\n    /* warming up `compressedBuffer` */\n    if (adv->mode == BMK_decodeOnly) {\n        memcpy(compressedBuffer, srcBuffer, loadedCompressedSize);\n    } else {\n        RDG_genBuffer(compressedBuffer, maxCompressedSize, 0.10, 0.50, 1);\n    }\n\n    if (!UTIL_support_MT_measurements() && adv->nbWorkers > 1) {\n        OUTPUTLEVEL(\n                2,\n                \"Warning : time measurements may be incorrect in multithreading mode... \\n\")\n    }\n\n    /* Bench */\n    {\n        U64 const crcOrig = (adv->mode == BMK_decodeOnly)\n                ? 0\n                : XXH64(srcBuffer, srcSize, 0);\n#define NB_MARKS 4\n        const char* marks[NB_MARKS] = { \" |\", \" /\", \" =\", \" \\\\\" };\n        U32 markNb                  = 0;\n        int compressionCompleted    = (adv->mode == BMK_decodeOnly);\n        int decompressionCompleted  = (adv->mode == BMK_compressOnly);\n        BMK_benchParams_t cbp, dbp;\n        BMK_initCCtxArgs cctxprep;\n        BMK_initDCtxArgs dctxprep;\n\n        cbp.benchFn       = local_defaultCompress; /* ZSTD_compress2 */\n        cbp.benchPayload  = cctx;\n        cbp.initFn        = local_initCCtx; /* BMK_initCCtx */\n        cbp.initPayload   = &cctxprep;\n        cbp.errorFn       = ZSTD_isError;\n        cbp.blockCount    = nbChunks;\n        cbp.srcBuffers    = srcPtrs;\n        cbp.srcSizes      = srcSizes;\n        cbp.dstBuffers    = cPtrs;\n        cbp.dstCapacities = cCapacities;\n        cbp.blockResults  = cSizes;\n\n        cctxprep.cctx           = cctx;\n        cctxprep.dictBuffer     = dictBuffer;\n        cctxprep.dictBufferSize = dictBufferSize;\n        cctxprep.cLevel         = cLevel;\n        cctxprep.comprParams    = comprParams;\n        cctxprep.adv            = adv;\n\n        dbp.benchFn       = local_defaultDecompress;\n        dbp.benchPayload  = dctx;\n        dbp.initFn        = local_initDCtx;\n        dbp.initPayload   = &dctxprep;\n        dbp.errorFn       = ZSTD_isError;\n        dbp.blockCount    = nbChunks;\n        dbp.srcBuffers    = (const void* const*)cPtrs;\n        dbp.srcSizes      = cSizes;\n        dbp.dstBuffers    = resPtrs;\n        dbp.dstCapacities = resSizes;\n        dbp.blockResults  = NULL;\n\n        dctxprep.dctx           = dctx;\n        dctxprep.dictBuffer     = dictBuffer;\n        dctxprep.dictBufferSize = dictBufferSize;\n\n        OUTPUTLEVEL(2, \"\\r%70s\\r\", \"\"); /* blank line */\n        assert(srcSize < UINT_MAX);\n        OUTPUTLEVEL(\n                2,\n                \"%2s-%-17.17s :%10u -> \\r\",\n                marks[markNb],\n                displayName,\n                (unsigned)srcSize);\n\n        while (!(compressionCompleted && decompressionCompleted)) {\n            if (!compressionCompleted) {\n                BMK_runOutcome_t const cOutcome =\n                        BMK_benchTimedFn(timeStateCompress, cbp);\n\n                if (!BMK_isSuccessful_runOutcome(cOutcome)) {\n                    RETURN_ERROR(30, BMK_benchOutcome_t, \"compression error\");\n                }\n\n                {\n                    BMK_runTime_t const cResult = BMK_extract_runTime(cOutcome);\n                    cSize                       = cResult.sumOfReturn;\n                    ratio = (double)srcSize / (double)cSize;\n                    {\n                        BMK_benchResult_t newResult;\n                        newResult.cSpeed =\n                                (U64)((double)srcSize * TIMELOOP_NANOSEC\n                                      / cResult.nanoSecPerRun);\n                        benchResult.cSize = cSize;\n                        if (newResult.cSpeed > benchResult.cSpeed)\n                            benchResult.cSpeed = newResult.cSpeed;\n                    }\n                }\n\n                {\n                    int const ratioDigits = 1 + (ratio < 100.) + (ratio < 10.);\n                    assert(cSize < UINT_MAX);\n                    OUTPUTLEVEL(\n                            2,\n                            \"%2s-%-17.17s :%10u ->%10u (x%5.*f), %6.*f MB/s \\r\",\n                            marks[markNb],\n                            displayName,\n                            (unsigned)srcSize,\n                            (unsigned)cSize,\n                            ratioDigits,\n                            ratio,\n                            benchResult.cSpeed < (10 * MB_UNIT) ? 2 : 1,\n                            (double)benchResult.cSpeed / MB_UNIT);\n                }\n                compressionCompleted =\n                        BMK_isCompleted_TimedFn(timeStateCompress);\n            }\n\n            if (!decompressionCompleted) {\n                BMK_runOutcome_t const dOutcome =\n                        BMK_benchTimedFn(timeStateDecompress, dbp);\n\n                if (!BMK_isSuccessful_runOutcome(dOutcome)) {\n                    RETURN_ERROR(30, BMK_benchOutcome_t, \"decompression error\");\n                }\n\n                {\n                    BMK_runTime_t const dResult = BMK_extract_runTime(dOutcome);\n                    U64 const newDSpeed =\n                            (U64)((double)srcSize * TIMELOOP_NANOSEC\n                                  / dResult.nanoSecPerRun);\n                    if (newDSpeed > benchResult.dSpeed)\n                        benchResult.dSpeed = newDSpeed;\n                }\n\n                {\n                    int const ratioDigits = 1 + (ratio < 100.) + (ratio < 10.);\n                    OUTPUTLEVEL(\n                            2,\n                            \"%2s-%-17.17s :%10u ->%10u (x%5.*f), %6.*f MB/s, %6.1f MB/s\\r\",\n                            marks[markNb],\n                            displayName,\n                            (unsigned)srcSize,\n                            (unsigned)cSize,\n                            ratioDigits,\n                            ratio,\n                            benchResult.cSpeed < (10 * MB_UNIT) ? 2 : 1,\n                            (double)benchResult.cSpeed / MB_UNIT,\n                            (double)benchResult.dSpeed / MB_UNIT);\n                }\n                decompressionCompleted =\n                        BMK_isCompleted_TimedFn(timeStateDecompress);\n            }\n            markNb = (markNb + 1) % NB_MARKS;\n        } /* while (!(compressionCompleted && decompressionCompleted)) */\n\n        /* CRC Checking */\n        {   const BYTE* resultBuffer = (const BYTE*)(*resultBufferPtr);\n            U64 const crcCheck       = XXH64(resultBuffer, srcSize, 0);\n            if ((adv->mode == BMK_both) && (crcOrig != crcCheck)) {\n                size_t u;\n                DISPLAY(\"!!! WARNING !!! %14s : Invalid Checksum : %x != %x   \\n\",\n                        displayName,\n                        (unsigned)crcOrig,\n                        (unsigned)crcCheck);\n                for (u = 0; u < srcSize; u++) {\n                    if (((const BYTE*)srcBuffer)[u] != resultBuffer[u]) {\n                        unsigned segNb, bNb, pos;\n                        size_t bacc = 0;\n                        DISPLAY(\"Decoding error at pos %u \", (unsigned)u);\n                        for (segNb = 0; segNb < nbChunks; segNb++) {\n                            if (bacc + srcSizes[segNb] > u)\n                                break;\n                            bacc += srcSizes[segNb];\n                        }\n                        pos = (U32)(u - bacc);\n                        bNb = pos / (128 KB);\n                        DISPLAY(\"(sample %u, chunk %u, pos %u) \\n\",\n                                segNb,\n                                bNb,\n                                pos);\n                        {\n                            size_t const lowest = (u > 5) ? 5 : u;\n                            size_t n;\n                            DISPLAY(\"origin: \");\n                            for (n = lowest; n > 0; n--)\n                                DISPLAY(\"%02X \",\n                                        ((const BYTE*)srcBuffer)[u - n]);\n                            DISPLAY(\" :%02X:  \", ((const BYTE*)srcBuffer)[u]);\n                            for (n = 1; n < 3; n++)\n                                DISPLAY(\"%02X \",\n                                        ((const BYTE*)srcBuffer)[u + n]);\n                            DISPLAY(\" \\n\");\n                            DISPLAY(\"decode: \");\n                            for (n = lowest; n > 0; n--)\n                                DISPLAY(\"%02X \", resultBuffer[u - n]);\n                            DISPLAY(\" :%02X:  \", resultBuffer[u]);\n                            for (n = 1; n < 3; n++)\n                                DISPLAY(\"%02X \", resultBuffer[u + n]);\n                            DISPLAY(\" \\n\");\n                        }\n                        break;\n                    }\n                    if (u == srcSize - 1) { /* should never happen */\n                        DISPLAY(\"no difference detected\\n\");\n                    }\n                } /* for (u=0; u<srcSize; u++) */\n            }     /* if ((adv->mode == BMK_both) && (crcOrig!=crcCheck)) */\n        }         /* CRC Checking */\n\n        if (displayLevel\n            == 1) { /* hidden display mode -q, used by python speed benchmark */\n            double const cSpeed = (double)benchResult.cSpeed / MB_UNIT;\n            double const dSpeed = (double)benchResult.dSpeed / MB_UNIT;\n            if (adv->additionalParam) {\n                OUTPUT(\"-%-3i%11i (%5.3f) %6.2f MB/s %6.1f MB/s  %s (param=%d)\\n\",\n                       cLevel,\n                       (int)cSize,\n                       ratio,\n                       cSpeed,\n                       dSpeed,\n                       displayName,\n                       adv->additionalParam);\n            } else {\n                OUTPUT(\"-%-3i%11i (%5.3f) %6.2f MB/s %6.1f MB/s  %s\\n\",\n                       cLevel,\n                       (int)cSize,\n                       ratio,\n                       cSpeed,\n                       dSpeed,\n                       displayName);\n            }\n        }\n\n        OUTPUTLEVEL(2, \"%2i#\\n\", cLevel);\n    } /* Bench */\n\n    benchResult.cMem =\n            (1ULL << (comprParams->windowLog)) + ZSTD_sizeof_CCtx(cctx);\n    return BMK_benchOutcome_setValidResult(benchResult);\n}\n\nBMK_benchOutcome_t BMK_benchMemAdvanced(\n        const void* srcBuffer,\n        size_t srcSize,\n        void* dstBuffer,\n        size_t dstCapacity,\n        const size_t* fileSizes,\n        unsigned nbFiles,\n        int cLevel,\n        const ZSTD_compressionParameters* comprParams,\n        const void* dictBuffer,\n        size_t dictBufferSize,\n        int displayLevel,\n        const char* displayName,\n        const BMK_advancedParams_t* adv)\n\n{\n    int const dstParamsError =\n            !dstBuffer ^ !dstCapacity; /* must be both NULL or none */\n\n    size_t const chunkSize =\n            ((adv->chunkSizeMax >= 32 && (adv->mode != BMK_decodeOnly))\n                     ? adv->chunkSizeMax\n                     : srcSize)\n            + (!srcSize) /* avoid div by 0 */;\n    U32 const nbChunksMax =\n            (U32)((srcSize + (chunkSize - 1)) / chunkSize) + nbFiles;\n\n    const void** const srcPtrs =\n            (const void**)malloc(nbChunksMax * sizeof(void*));\n    size_t* const srcSizes = (size_t*)malloc(nbChunksMax * sizeof(size_t));\n\n    void** const cPtrs        = (void**)malloc(nbChunksMax * sizeof(void*));\n    size_t* const cSizes      = (size_t*)malloc(nbChunksMax * sizeof(size_t));\n    size_t* const cCapacities = (size_t*)malloc(nbChunksMax * sizeof(size_t));\n\n    void** const resPtrs   = (void**)malloc(nbChunksMax * sizeof(void*));\n    size_t* const resSizes = (size_t*)malloc(nbChunksMax * sizeof(size_t));\n\n    BMK_timedFnState_t* timeStateCompress = BMK_createTimedFnState(\n            adv->nbSeconds * 1000, BMK_RUNTEST_DEFAULT_MS);\n    BMK_timedFnState_t* timeStateDecompress = BMK_createTimedFnState(\n            adv->nbSeconds * 1000, BMK_RUNTEST_DEFAULT_MS);\n\n    ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n    ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n\n    const size_t maxCompressedSize = dstCapacity\n            ? dstCapacity\n            : ZSTD_compressBound(srcSize) + (nbChunksMax * 1024);\n\n    void* const internalDstBuffer =\n            dstBuffer ? NULL : malloc(maxCompressedSize);\n    void* const compressedBuffer = dstBuffer ? dstBuffer : internalDstBuffer;\n\n    BMK_benchOutcome_t outcome =\n            BMK_benchOutcome_error(); /* error by default */\n\n    void* resultBuffer = srcSize ? malloc(srcSize) : NULL;\n\n    int const allocationincomplete = !srcPtrs || !srcSizes || !cPtrs || !cSizes\n            || !cCapacities || !resPtrs || !resSizes || !timeStateCompress\n            || !timeStateDecompress || !cctx || !dctx || !compressedBuffer\n            || !resultBuffer;\n\n    if (!allocationincomplete && !dstParamsError) {\n        outcome = BMK_benchMemAdvancedNoAlloc(\n                srcPtrs,\n                srcSizes,\n                cPtrs,\n                cCapacities,\n                cSizes,\n                resPtrs,\n                resSizes,\n                &resultBuffer,\n                compressedBuffer,\n                maxCompressedSize,\n                timeStateCompress,\n                timeStateDecompress,\n                srcBuffer,\n                srcSize,\n                fileSizes,\n                nbFiles,\n                cLevel,\n                comprParams,\n                dictBuffer,\n                dictBufferSize,\n                cctx,\n                dctx,\n                displayLevel,\n                displayName,\n                adv);\n    }\n\n    /* clean up */\n    BMK_freeTimedFnState(timeStateCompress);\n    BMK_freeTimedFnState(timeStateDecompress);\n\n    ZSTD_freeCCtx(cctx);\n    ZSTD_freeDCtx(dctx);\n\n    free(internalDstBuffer);\n    free(resultBuffer);\n\n    free((void*)srcPtrs);\n    free(srcSizes);\n    free(cPtrs);\n    free(cSizes);\n    free(cCapacities);\n    free(resPtrs);\n    free(resSizes);\n\n    if (allocationincomplete) {\n        RETURN_ERROR(\n                31, BMK_benchOutcome_t, \"allocation error : not enough memory\");\n    }\n\n    if (dstParamsError) {\n        RETURN_ERROR(32, BMK_benchOutcome_t, \"Dst parameters not coherent\");\n    }\n    return outcome;\n}\n\nBMK_benchOutcome_t BMK_benchMem(\n        const void* srcBuffer,\n        size_t srcSize,\n        const size_t* fileSizes,\n        unsigned nbFiles,\n        int cLevel,\n        const ZSTD_compressionParameters* comprParams,\n        const void* dictBuffer,\n        size_t dictBufferSize,\n        int displayLevel,\n        const char* displayName)\n{\n    BMK_advancedParams_t const adv = BMK_initAdvancedParams();\n    return BMK_benchMemAdvanced(\n            srcBuffer,\n            srcSize,\n            NULL,\n            0,\n            fileSizes,\n            nbFiles,\n            cLevel,\n            comprParams,\n            dictBuffer,\n            dictBufferSize,\n            displayLevel,\n            displayName,\n            &adv);\n}\n\n/* @return: 0 on success, !0 if error */\nstatic int BMK_benchCLevels(\n        const void* srcBuffer,\n        size_t benchedSize,\n        const size_t* fileSizes,\n        unsigned nbFiles,\n        int startCLevel, int endCLevel,\n        const ZSTD_compressionParameters* comprParams,\n        const void* dictBuffer,\n        size_t dictBufferSize,\n        int displayLevel,\n        const char* displayName,\n        BMK_advancedParams_t const* const adv)\n{\n    int level;\n    const char* pch = strrchr(displayName, '\\\\'); /* Windows */\n    if (!pch)\n        pch = strrchr(displayName, '/'); /* Linux */\n    if (pch)\n        displayName = pch + 1;\n\n    if (endCLevel > ZSTD_maxCLevel()) {\n        DISPLAYLEVEL(1, \"Invalid Compression Level \\n\");\n        return 15;\n    }\n    if (endCLevel < startCLevel) {\n        DISPLAYLEVEL(1, \"Invalid Compression Level Range \\n\");\n        return 15;\n    }\n\n    if (adv->realTime) {\n        DISPLAYLEVEL(2, \"Note : switching to real-time priority \\n\");\n        SET_REALTIME_PRIORITY;\n    }\n\n    if (displayLevel == 1 && !adv->additionalParam) /* --quiet mode */\n        OUTPUT(\"bench %s %s: input %u bytes, %u seconds, %u KB chunks\\n\",\n               ZSTD_VERSION_STRING,\n               ZSTD_GIT_COMMIT_STRING,\n               (unsigned)benchedSize,\n               adv->nbSeconds,\n               (unsigned)(adv->chunkSizeMax >> 10));\n\n    for (level = startCLevel; level <= endCLevel; level++) {\n        BMK_benchOutcome_t res = BMK_benchMemAdvanced(\n            srcBuffer,\n            benchedSize,\n            NULL,\n            0,\n            fileSizes,\n            nbFiles,\n            level,\n            comprParams,\n            dictBuffer,\n            dictBufferSize,\n            displayLevel,\n            displayName,\n            adv);\n        if (!BMK_isSuccessful_benchOutcome(res)) return 1;\n    }\n    return 0;\n}\n\nint BMK_syntheticTest(\n        double compressibility,\n        int startingCLevel, int endCLevel,\n        const ZSTD_compressionParameters* compressionParams,\n        int displayLevel,\n        const BMK_advancedParams_t* adv)\n{\n    char nameBuff[20]        = { 0 };\n    const char* name         = nameBuff;\n    size_t const benchedSize = adv->chunkSizeMax ? adv->chunkSizeMax : 10000000;\n\n    /* Memory allocation */\n    void* const srcBuffer = malloc(benchedSize);\n    if (!srcBuffer) {\n        DISPLAYLEVEL(1, \"allocation error : not enough memory \\n\");\n        return 16;\n    }\n\n    /* Fill input buffer */\n    if (compressibility < 0.0) {\n        LOREM_genBuffer(srcBuffer, benchedSize, 0);\n        name = \"Lorem ipsum\";\n    } else {\n        RDG_genBuffer(srcBuffer, benchedSize, compressibility, 0.0, 0);\n        formatString_u(\n                nameBuff,\n                sizeof(nameBuff),\n                \"Synthetic %u%%\",\n                (unsigned)(compressibility * 100));\n    }\n\n    /* Bench */\n    {   int res = BMK_benchCLevels(\n                srcBuffer,\n                benchedSize,\n                &benchedSize,\n                1,\n                startingCLevel, endCLevel,\n                compressionParams,\n                NULL,\n                0, /* dictionary */\n                displayLevel,\n                name,\n                adv);\n        free(srcBuffer);\n        return res;\n    }\n}\n\nstatic size_t BMK_findMaxMem(U64 requiredMem)\n{\n    size_t const step = 64 MB;\n    BYTE* testmem     = NULL;\n\n    requiredMem = (((requiredMem >> 26) + 1) << 26);\n    requiredMem += step;\n    if (requiredMem > maxMemory)\n        requiredMem = maxMemory;\n\n    do {\n        testmem = (BYTE*)malloc((size_t)requiredMem);\n        requiredMem -= step;\n    } while (!testmem && requiredMem > 0);\n\n    free(testmem);\n    return (size_t)(requiredMem);\n}\n\n/*! BMK_loadFiles() :\n *  Loads `buffer` with content of files listed within `fileNamesTable`.\n *  At most, fills `buffer` entirely. */\nstatic int BMK_loadFiles(\n        void* buffer,\n        size_t bufferSize,\n        size_t* fileSizes,\n        const char* const* fileNamesTable,\n        unsigned nbFiles,\n        int displayLevel)\n{\n    size_t pos = 0, totalSize = 0;\n    unsigned n;\n    for (n = 0; n < nbFiles; n++) {\n        const char* const filename = fileNamesTable[n];\n        U64 fileSize = UTIL_getFileSize(\n                filename); /* last file may be shortened */\n        if (UTIL_isDirectory(filename)) {\n            DISPLAYLEVEL(\n                    2, \"Ignoring %s directory...       \\n\", filename);\n            fileSizes[n] = 0;\n            continue;\n        }\n        if (fileSize == UTIL_FILESIZE_UNKNOWN) {\n            DISPLAYLEVEL(\n                    2,\n                    \"Cannot evaluate size of %s, ignoring ... \\n\",\n                    filename);\n            fileSizes[n] = 0;\n            continue;\n        }\n        if (fileSize > bufferSize - pos) {\n            /* buffer too small - limit quantity loaded */\n            fileSize = bufferSize - pos;\n            nbFiles  = n; /* stop after this file */\n        }\n\n        {   FILE* const f = fopen(filename, \"rb\");\n            if (f == NULL) {\n                RETURN_ERROR_INT(\n                        10, \"cannot open file %s\", filename);\n            }\n            OUTPUTLEVEL(2, \"Loading %s...       \\r\", filename);\n            {   size_t const readSize =\n                        fread(((char*)buffer) + pos, 1, (size_t)fileSize, f);\n                if (readSize != (size_t)fileSize) {\n                    fclose(f);\n                    RETURN_ERROR_INT(\n                            11, \"invalid read %s\", filename);\n                }\n                pos += readSize;\n            }\n            fileSizes[n] = (size_t)fileSize;\n            totalSize += (size_t)fileSize;\n            fclose(f);\n        }\n    }\n\n    if (totalSize == 0)\n        RETURN_ERROR_INT(12, \"no data to bench\");\n    return 0;\n}\n\nint BMK_benchFilesAdvanced(\n        const char* const* fileNamesTable,\n        unsigned nbFiles,\n        const char* dictFileName,\n        int startCLevel, int endCLevel,\n        const ZSTD_compressionParameters* compressionParams,\n        int displayLevel,\n        const BMK_advancedParams_t* adv)\n{\n    void* srcBuffer = NULL;\n    size_t benchedSize;\n    void* dictBuffer      = NULL;\n    size_t dictBufferSize = 0;\n    size_t* fileSizes     = NULL;\n    int res = 1;\n    U64 const totalSizeToLoad = UTIL_getTotalFileSize(fileNamesTable, nbFiles);\n\n    if (!nbFiles) {\n        DISPLAYLEVEL(1, \"No Files to Benchmark\");\n        return 13;\n    }\n\n    if (endCLevel > ZSTD_maxCLevel()) {\n        DISPLAYLEVEL(1, \"Invalid Compression Level\");\n        return 14;\n    }\n\n    if (totalSizeToLoad == UTIL_FILESIZE_UNKNOWN) {\n        DISPLAYLEVEL(1, \"Error loading files\");\n        return 15;\n    }\n\n    fileSizes = (size_t*)calloc(nbFiles, sizeof(size_t));\n    if (!fileSizes) {\n        DISPLAYLEVEL(1, \"not enough memory for fileSizes\");\n        return 16;\n    }\n\n    /* Load dictionary */\n    if (dictFileName != NULL) {\n        U64 const dictFileSize = UTIL_getFileSize(dictFileName);\n        if (dictFileSize == UTIL_FILESIZE_UNKNOWN) {\n            DISPLAYLEVEL(\n                    1,\n                    \"error loading %s : %s \\n\",\n                    dictFileName,\n                    strerror(errno));\n            free(fileSizes);\n            DISPLAYLEVEL(1, \"benchmark aborted\");\n            return 17;\n        }\n        if (dictFileSize > 64 MB) {\n            free(fileSizes);\n            DISPLAYLEVEL(1, \"dictionary file %s too large\", dictFileName);\n            return 18;\n        }\n        dictBufferSize = (size_t)dictFileSize;\n        dictBuffer     = malloc(dictBufferSize);\n        if (dictBuffer == NULL) {\n            free(fileSizes);\n            DISPLAYLEVEL(\n                    1,\n                    \"not enough memory for dictionary (%u bytes)\",\n                    (unsigned)dictBufferSize);\n            return 19;\n        }\n\n        {\n            int const errorCode = BMK_loadFiles(\n                    dictBuffer,\n                    dictBufferSize,\n                    fileSizes,\n                    &dictFileName /*?*/,\n                    1 /*?*/,\n                    displayLevel);\n            if (errorCode) {\n                goto _cleanUp;\n            }\n        }\n    }\n\n    /* Memory allocation & restrictions */\n    benchedSize = BMK_findMaxMem(totalSizeToLoad * 3) / 3;\n    if ((U64)benchedSize > totalSizeToLoad)\n        benchedSize = (size_t)totalSizeToLoad;\n    if (benchedSize < totalSizeToLoad)\n        DISPLAY(\"Not enough memory; testing %u MB only...\\n\",\n                (unsigned)(benchedSize >> 20));\n\n    srcBuffer = benchedSize ? malloc(benchedSize) : NULL;\n    if (!srcBuffer) {\n        free(dictBuffer);\n        free(fileSizes);\n        DISPLAYLEVEL(1, \"not enough memory for srcBuffer\");\n        return 20;\n    }\n\n    /* Load input buffer */\n    {\n        int const errorCode = BMK_loadFiles(\n                srcBuffer,\n                benchedSize,\n                fileSizes,\n                fileNamesTable,\n                nbFiles,\n                displayLevel);\n        if (errorCode) {\n            goto _cleanUp;\n        }\n    }\n\n    /* Bench */\n    {\n        char mfName[20] = { 0 };\n        formatString_u(mfName, sizeof(mfName), \" %u files\", nbFiles);\n        {   const char* const displayName =\n                    (nbFiles > 1) ? mfName : fileNamesTable[0];\n            res = BMK_benchCLevels(\n                    srcBuffer,\n                    benchedSize,\n                    fileSizes,\n                    nbFiles,\n                    startCLevel, endCLevel,\n                    compressionParams,\n                    dictBuffer,\n                    dictBufferSize,\n                    displayLevel,\n                    displayName,\n                    adv);\n        }\n    }\n\n_cleanUp:\n    free(srcBuffer);\n    free(dictBuffer);\n    free(fileSizes);\n    return res;\n}\n\nint BMK_benchFiles(\n        const char* const* fileNamesTable,\n        unsigned nbFiles,\n        const char* dictFileName,\n        int cLevel,\n        const ZSTD_compressionParameters* compressionParams,\n        int displayLevel)\n{\n    BMK_advancedParams_t const adv = BMK_initAdvancedParams();\n    return BMK_benchFilesAdvanced(\n            fileNamesTable,\n            nbFiles,\n            dictFileName,\n            cLevel, cLevel,\n            compressionParams,\n            displayLevel,\n            &adv);\n}\n"
  },
  {
    "path": "programs/benchzstd.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n /* benchzstd :\n  * benchmark Zstandard compression / decompression\n  * over a set of files or buffers\n  * and display progress result and final summary\n  */\n\n#ifndef BENCH_ZSTD_H_3242387\n#define BENCH_ZSTD_H_3242387\n\n/* ===  Dependencies  === */\n#include <stddef.h>   /* size_t */\n#define ZSTD_STATIC_LINKING_ONLY   /* ZSTD_compressionParameters */\n#include \"../lib/zstd.h\"     /* ZSTD_compressionParameters */\n\n/* ===  Constants  === */\n\n#define MB_UNIT 1000000\n\n\n/* ===  Benchmark functions  === */\n\n/* Creates a variant `typeName`, able to express \"error or valid result\".\n * Functions with return type `typeName`\n * must first check if result is valid, using BMK_isSuccessful_*(),\n * and only then can extract `baseType`.\n */\n#define VARIANT_ERROR_RESULT(baseType, variantName)  \\\n                                             \\\ntypedef struct {                             \\\n    baseType internal_never_use_directly;    \\\n    int tag;                                 \\\n} variantName\n\n\ntypedef struct {\n    size_t cSize;\n    unsigned long long cSpeed;   /* bytes / sec */\n    unsigned long long dSpeed;\n    size_t cMem;                 /* memory usage during compression */\n} BMK_benchResult_t;\n\nVARIANT_ERROR_RESULT(BMK_benchResult_t, BMK_benchOutcome_t);\n\n/* check first if the return structure represents an error or a valid result */\nint BMK_isSuccessful_benchOutcome(BMK_benchOutcome_t outcome);\n\n/* extract result from variant type.\n * note : this function will abort() program execution if result is not valid\n *        check result validity first, by using BMK_isSuccessful_benchOutcome()\n */\nBMK_benchResult_t BMK_extract_benchResult(BMK_benchOutcome_t outcome);\n\n\n/*! BMK_benchFiles() -- called by zstdcli */\n/*  Loads files from fileNamesTable into memory,\n *  and an optional dictionary from dictFileName (can be NULL),\n *  then uses benchMem().\n *  fileNamesTable - name of files to benchmark.\n *  nbFiles - number of files (size of fileNamesTable), must be > 0.\n *  dictFileName - name of dictionary file to load.\n *  cLevel - compression level to benchmark, errors if invalid.\n *  compressionParams - advanced compression Parameters.\n *  displayLevel - what gets printed:\n *      0 : no display;\n *      1 : errors;\n *      2 : + result + interaction + warnings;\n *      3 : + information;\n *      4 : + debug\n * @return: 0 on success, !0 on error\n */\nint BMK_benchFiles(\n            const char* const * fileNamesTable, unsigned nbFiles,\n            const char* dictFileName,\n            int cLevel, const ZSTD_compressionParameters* compressionParams,\n            int displayLevel);\n\n\ntypedef enum {\n    BMK_both = 0,\n    BMK_decodeOnly = 1,\n    BMK_compressOnly = 2\n} BMK_mode_t;\n\ntypedef struct {\n    BMK_mode_t mode;        /* 0: both, 1: compress only 2: decode only */\n    unsigned nbSeconds;     /* default timing is in nbSeconds */\n    size_t chunkSizeMax;    /* Maximum size of each independent chunk */\n    size_t targetCBlockSize;/* Approximative size of compressed blocks */\n    int nbWorkers;          /* multithreading */\n    unsigned realTime;      /* real time priority */\n    int additionalParam;    /* used by python speed benchmark */\n    int ldmFlag;            /* enables long distance matching */\n    int ldmMinMatch;        /* below: parameters for long distance matching, see zstd.1.md */\n    int ldmHashLog;\n    int ldmBucketSizeLog;\n    int ldmHashRateLog;\n    ZSTD_ParamSwitch_e literalCompressionMode;\n    int useRowMatchFinder;  /* use row-based matchfinder if possible */\n} BMK_advancedParams_t;\n\n/* returns default parameters used by nonAdvanced functions */\nBMK_advancedParams_t BMK_initAdvancedParams(void);\n\n/*! BMK_benchFilesAdvanced():\n *  Same as BMK_benchFiles(),\n *  with more controls, provided through advancedParams_t structure */\nint BMK_benchFilesAdvanced(\n               const char* const * fileNamesTable, unsigned nbFiles,\n               const char* dictFileName,\n               int startCLevel, int endCLevel,\n               const ZSTD_compressionParameters* compressionParams,\n               int displayLevel, const BMK_advancedParams_t* adv);\n\n/*! BMK_syntheticTest() -- called from zstdcli */\n/*  Generates a sample with datagen, using @compressibility argument\n * @cLevel - compression level to benchmark, errors if invalid\n * @compressibility - determines compressibility of sample, range [0.0 - 1.0]\n *        if @compressibility < 0.0, uses the lorem ipsum generator\n * @compressionParams - basic compression Parameters\n * @displayLevel - see benchFiles\n * @adv - see advanced_Params_t\n * @return: 0 on success, !0 on error\n */\nint BMK_syntheticTest(double compressibility,\n                      int startingCLevel, int endCLevel,\n                      const ZSTD_compressionParameters* compressionParams,\n                      int displayLevel, const BMK_advancedParams_t* adv);\n\n\n\n/* ===  Benchmark Zstandard in a memory-to-memory scenario  === */\n\n/** BMK_benchMem() -- core benchmarking function, called in paramgrill\n *  applies ZSTD_compress_generic() and ZSTD_decompress_generic() on data in srcBuffer\n *  with specific compression parameters provided by other arguments using benchFunction\n *  (cLevel, comprParams + adv in advanced Mode) */\n/*  srcBuffer - data source, expected to be valid compressed data if in Decode Only Mode\n *  srcSize - size of data in srcBuffer\n *  fileSizes - srcBuffer is considered cut into 1+ segments, to compress separately.\n *              note : sum(fileSizes) must be == srcSize.  (<== ensure it's properly checked)\n *  nbFiles - nb of segments\n *  cLevel - compression level\n *  comprParams - basic compression parameters\n *  dictBuffer - a dictionary if used, null otherwise\n *  dictBufferSize - size of dictBuffer, 0 otherwise\n *  displayLevel - see BMK_benchFiles\n *  displayName - name used by display\n * @return:\n *      a variant, which expresses either an error, or a valid result.\n *      Use BMK_isSuccessful_benchOutcome() to check if function was successful.\n *      If yes, extract the valid result with BMK_extract_benchResult(),\n *      it will contain :\n *          .cSpeed: compression speed in bytes per second,\n *          .dSpeed: decompression speed in bytes per second,\n *          .cSize : compressed size, in bytes\n *          .cMem  : memory budget required for the compression context\n */\nBMK_benchOutcome_t BMK_benchMem(const void* srcBuffer, size_t srcSize,\n                        const size_t* fileSizes, unsigned nbFiles,\n                        int cLevel, const ZSTD_compressionParameters* comprParams,\n                        const void* dictBuffer, size_t dictBufferSize,\n                        int displayLevel, const char* displayName);\n\n\n/* BMK_benchMemAdvanced() : used by Paramgrill\n * same as BMK_benchMem() with following additional options :\n * dstBuffer - destination buffer to write compressed output in, NULL if none provided.\n * dstCapacity - capacity of destination buffer, give 0 if dstBuffer = NULL\n * adv = see advancedParams_t\n */\nBMK_benchOutcome_t BMK_benchMemAdvanced(const void* srcBuffer, size_t srcSize,\n                        void* dstBuffer, size_t dstCapacity,\n                        const size_t* fileSizes, unsigned nbFiles,\n                        int cLevel, const ZSTD_compressionParameters* comprParams,\n                        const void* dictBuffer, size_t dictBufferSize,\n                        int displayLevel, const char* displayName,\n                        const BMK_advancedParams_t* adv);\n\n\n\n#endif   /* BENCH_ZSTD_H_3242387 */\n"
  },
  {
    "path": "programs/datagen.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n\n/*-************************************\n*  Dependencies\n**************************************/\n#include \"datagen.h\"\n#include \"platform.h\"  /* SET_BINARY_MODE */\n#include <stdlib.h>    /* malloc, free */\n#include <stdio.h>     /* FILE, fwrite, fprintf */\n#include <string.h>    /* memcpy */\n#include \"../lib/common/mem.h\"  /* U32 */\n\n\n/*-************************************\n*  Macros\n**************************************/\n#define KB *(1 <<10)\n#define MIN(a,b)  ( (a) < (b) ? (a) : (b) )\n\n#define RDG_DEBUG 0\n#define TRACE(...)   if (RDG_DEBUG) fprintf(stderr, __VA_ARGS__ )\n\n\n/*-************************************\n*  Local constants\n**************************************/\n#define LTLOG 13\n#define LTSIZE (1<<LTLOG)\n#define LTMASK (LTSIZE-1)\n\n\n/*-*******************************************************\n*  Local Functions\n*********************************************************/\n#define RDG_rotl32(x,r) ((x << r) | (x >> (32 - r)))\nstatic U32 RDG_rand(U32* src)\n{\n    static const U32 prime1 = 2654435761U;\n    static const U32 prime2 = 2246822519U;\n    U32 rand32 = *src;\n    rand32 *= prime1;\n    rand32 ^= prime2;\n    rand32  = RDG_rotl32(rand32, 13);\n    *src = rand32;\n    return rand32 >> 5;\n}\n\ntypedef U32 fixedPoint_24_8;\n\nstatic void RDG_fillLiteralDistrib(BYTE* ldt, fixedPoint_24_8 ld)\n{\n    BYTE const firstChar = (ld<=0.0) ?   0 : '(';\n    BYTE const lastChar  = (ld<=0.0) ? 255 : '}';\n    BYTE character = (ld<=0.0) ? 0 : '0';\n    U32 u;\n\n    if (ld<=0) ld = 0;\n    for (u=0; u<LTSIZE; ) {\n        U32 const weight = (((LTSIZE - u) * ld) >> 8) + 1;\n        U32 const end = MIN ( u + weight , LTSIZE);\n        while (u < end) ldt[u++] = character;\n        character++;\n        if (character > lastChar) character = firstChar;\n    }\n}\n\n\nstatic BYTE RDG_genChar(U32* seed, const BYTE* ldt)\n{\n    U32 const id = RDG_rand(seed) & LTMASK;\n    return ldt[id];  /* memory-sanitizer fails here, stating \"uninitialized value\" when table initialized with P==0.0. Checked : table is fully initialized */\n}\n\n\nstatic U32 RDG_rand15Bits (U32* seedPtr)\n{\n    return RDG_rand(seedPtr) & 0x7FFF;\n}\n\nstatic U32 RDG_randLength(U32* seedPtr)\n{\n    if (RDG_rand(seedPtr) & 7) return (RDG_rand(seedPtr) & 0xF);   /* small length */\n    return (RDG_rand(seedPtr) & 0x1FF) + 0xF;\n}\n\nstatic void RDG_genBlock(void* buffer, size_t buffSize, size_t prefixSize,\n                         double matchProba, const BYTE* ldt, U32* seedPtr)\n{\n    BYTE* const buffPtr = (BYTE*)buffer;\n    U32 const matchProba32 = (U32)(32768 * matchProba);\n    size_t pos = prefixSize;\n    U32 prevOffset = 1;\n\n    /* special case : sparse content */\n    while (matchProba >= 1.0) {\n        size_t size0 = RDG_rand(seedPtr) & 3;\n        size0  = (size_t)1 << (16 + size0 * 2);\n        size0 += RDG_rand(seedPtr) & (size0-1);   /* because size0 is power of 2*/\n        if (buffSize < pos + size0) {\n            memset(buffPtr+pos, 0, buffSize-pos);\n            return;\n        }\n        memset(buffPtr+pos, 0, size0);\n        pos += size0;\n        buffPtr[pos-1] = RDG_genChar(seedPtr, ldt);\n        continue;\n    }\n\n    /* init */\n    if (pos==0) buffPtr[0] = RDG_genChar(seedPtr, ldt), pos=1;\n\n    /* Generate compressible data */\n    while (pos < buffSize) {\n        /* Select : Literal (char) or Match (within 32K) */\n        if (RDG_rand15Bits(seedPtr) < matchProba32) {\n            /* Copy (within 32K) */\n            U32 const length = RDG_randLength(seedPtr) + 4;\n            U32 const d = (U32) MIN(pos + length , buffSize);\n            U32 const repeatOffset = (RDG_rand(seedPtr) & 15) == 2;\n            U32 const randOffset = RDG_rand15Bits(seedPtr) + 1;\n            U32 const offset = repeatOffset ? prevOffset : (U32) MIN(randOffset , pos);\n            size_t match = pos - offset;\n            while (pos < d) { buffPtr[pos++] = buffPtr[match++];   /* correctly manages overlaps */ }\n            prevOffset = offset;\n        } else {\n            /* Literal (noise) */\n            U32 const length = RDG_randLength(seedPtr);\n            U32 const d = (U32) MIN(pos + length, buffSize);\n            while (pos < d) { buffPtr[pos++] = RDG_genChar(seedPtr, ldt); }\n    }   }\n}\n\n\nvoid RDG_genBuffer(void* buffer, size_t size, double matchProba, double litProba, unsigned seed)\n{\n    U32 seed32 = seed;\n    BYTE ldt[LTSIZE];\n    memset(ldt, '0', sizeof(ldt));  /* yes, character '0', this is intentional */\n    if (litProba<=0.0) litProba = matchProba / 4.5;\n    RDG_fillLiteralDistrib(ldt, (fixedPoint_24_8)(litProba * 256 + 0.001));\n    RDG_genBlock(buffer, size, 0, matchProba, ldt, &seed32);\n}\n\n\nvoid RDG_genStdout(unsigned long long size, double matchProba, double litProba, unsigned seed)\n{\n    U32 seed32 = seed;\n    size_t const stdBlockSize = 128 KB;\n    size_t const stdDictSize = 32 KB;\n    BYTE* const buff = (BYTE*)malloc(stdDictSize + stdBlockSize);\n    U64 total = 0;\n    BYTE ldt[LTSIZE];   /* literals distribution table */\n\n    /* init */\n    if (buff==NULL) { perror(\"datagen\"); exit(1); }\n    if (litProba<=0.0) litProba = matchProba / 4.5;\n    memset(ldt, '0', sizeof(ldt));   /* yes, character '0', this is intentional */\n    RDG_fillLiteralDistrib(ldt, (fixedPoint_24_8)(litProba * 256 + 0.001));\n    SET_BINARY_MODE(stdout);\n\n    /* Generate initial dict */\n    RDG_genBlock(buff, stdDictSize, 0, matchProba, ldt, &seed32);\n\n    /* Generate compressible data */\n    while (total < size) {\n        size_t const genBlockSize = (size_t) (MIN (stdBlockSize, size-total));\n        RDG_genBlock(buff, stdDictSize+stdBlockSize, stdDictSize, matchProba, ldt, &seed32);\n        total += genBlockSize;\n        { size_t const unused = fwrite(buff, 1, genBlockSize, stdout); (void)unused; }\n        /* update dict */\n        memcpy(buff, buff + stdBlockSize, stdDictSize);\n    }\n\n    /* cleanup */\n    free(buff);\n}\n"
  },
  {
    "path": "programs/datagen.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n#ifndef DATAGEN_H\n#define DATAGEN_H\n\n#include <stddef.h>   /* size_t */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nvoid RDG_genStdout(unsigned long long size, double matchProba, double litProba, unsigned seed);\nvoid RDG_genBuffer(void* buffer, size_t size, double matchProba, double litProba, unsigned seed);\n/*!RDG_genBuffer\n   Generate 'size' bytes of compressible data into 'buffer'.\n   Compressibility can be controlled using 'matchProba', which is floating point value between 0 and 1.\n   'LitProba' is optional, it affect variability of individual bytes. If litProba==0.0, default value will be used.\n   Generated data pattern can be modified using different 'seed'.\n   For a triplet (matchProba, litProba, seed), the function always generate the same content.\n\n   RDG_genStdout\n   Same as RDG_genBuffer, but generates data into stdout\n*/\n\n#if defined (__cplusplus)\n} /* extern \"C\" */\n#endif\n\n#endif\n"
  },
  {
    "path": "programs/dibio.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n\n/* **************************************\n*  Compiler Warnings\n****************************************/\n#ifdef _MSC_VER\n#  pragma warning(disable : 4127)    /* disable: C4127: conditional expression is constant */\n#endif\n\n\n/*-*************************************\n*  Includes\n***************************************/\n#include \"platform.h\"       /* Large Files support */\n#include \"util.h\"           /* UTIL_getFileSize, UTIL_getTotalFileSize */\n#include <stdlib.h>         /* malloc, free */\n#include <string.h>         /* memset */\n#include <stdio.h>          /* fprintf, fopen, ftello64 */\n#include <errno.h>          /* errno */\n\n#include \"timefn.h\"         /* UTIL_time_t, UTIL_clockSpanMicro, UTIL_getTime */\n#include \"../lib/common/debug.h\" /* assert */\n#include \"../lib/common/mem.h\"  /* read */\n#include \"../lib/zstd_errors.h\"\n#include \"dibio.h\"\n\n\n/*-*************************************\n*  Constants\n***************************************/\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\n#define SAMPLESIZE_MAX (128 KB)\n#define MEMMULT 11    /* rough estimation : memory cost to analyze 1 byte of sample */\n#define COVER_MEMMULT 9    /* rough estimation : memory cost to analyze 1 byte of sample */\n#define FASTCOVER_MEMMULT 1    /* rough estimation : memory cost to analyze 1 byte of sample */\nstatic const size_t g_maxMemory = (sizeof(size_t) == 4) ? (2 GB - 64 MB) : ((size_t)(512 MB) << sizeof(size_t));\n\n#define NOISELENGTH 32\n#define MAX_SAMPLES_SIZE (2 GB) /* training dataset limited to 2GB */\n\n\n/*-*************************************\n*  Console display\n***************************************/\n#define DISPLAY(...)         fprintf(stderr, __VA_ARGS__)\n#define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); }\n\nstatic const U64 g_refreshRate = SEC_TO_MICRO / 6;\nstatic UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER;\n\n#define DISPLAYUPDATE(l, ...) { if (displayLevel>=l) { \\\n            if ((UTIL_clockSpanMicro(g_displayClock) > g_refreshRate) || (displayLevel>=4)) \\\n            { g_displayClock = UTIL_getTime(); DISPLAY(__VA_ARGS__); \\\n            if (displayLevel>=4) fflush(stderr); } } }\n\n/*-*************************************\n*  Exceptions\n***************************************/\n#ifndef DEBUG\n#  define DEBUG 0\n#endif\n#define DEBUGOUTPUT(...) if (DEBUG) DISPLAY(__VA_ARGS__);\n#define EXM_THROW(error, ...)                                             \\\n{                                                                         \\\n    DEBUGOUTPUT(\"Error defined at %s, line %i : \\n\", __FILE__, __LINE__); \\\n    DISPLAY(\"Error %i : \", error);                                        \\\n    DISPLAY(__VA_ARGS__);                                                 \\\n    DISPLAY(\"\\n\");                                                        \\\n    exit(error);                                                          \\\n}\n\n\n/* ********************************************************\n*  Helper functions\n**********************************************************/\n#undef MIN\n#define MIN(a,b)    ((a) < (b) ? (a) : (b))\n\n/**\n  Returns the size of a file.\n  If error returns -1.\n*/\nstatic S64 DiB_getFileSize (const char * fileName)\n{\n    U64 const fileSize = UTIL_getFileSize(fileName);\n    return (fileSize == UTIL_FILESIZE_UNKNOWN) ? -1 : (S64)fileSize;\n}\n\n/* ********************************************************\n*  File related operations\n**********************************************************/\n/** DiB_loadFiles() :\n *  load samples from files listed in fileNamesTable into buffer.\n *  works even if buffer is too small to load all samples.\n *  Also provides the size of each sample into sampleSizes table\n *  which must be sized correctly, using DiB_fileStats().\n * @return : nb of samples effectively loaded into `buffer`\n * *bufferSizePtr is modified, it provides the amount data loaded within buffer.\n *  sampleSizes is filled with the size of each sample.\n */\nstatic int DiB_loadFiles(\n    void* buffer, size_t* bufferSizePtr,\n    size_t* sampleSizes, int sstSize,\n    const char** fileNamesTable, int nbFiles,\n    size_t targetChunkSize, int displayLevel )\n{\n    char* const buff = (char*)buffer;\n    size_t totalDataLoaded = 0;\n    int nbSamplesLoaded = 0;\n    int fileIndex = 0;\n    FILE * f = NULL;\n\n    assert(targetChunkSize <= SAMPLESIZE_MAX);\n\n    while ( nbSamplesLoaded < sstSize && fileIndex < nbFiles ) {\n        size_t fileDataLoaded;\n        S64 const fileSize = DiB_getFileSize(fileNamesTable[fileIndex]);\n        if (fileSize <= 0) {\n            /* skip if zero-size or file error */\n            ++fileIndex;\n            continue;\n        }\n\n        f = fopen( fileNamesTable[fileIndex], \"rb\");\n        if (f == NULL)\n            EXM_THROW(10, \"zstd: dictBuilder: %s %s \", fileNamesTable[fileIndex], strerror(errno));\n        DISPLAYUPDATE(2, \"Loading %s...       \\r\", fileNamesTable[fileIndex]);\n\n        /* Load the first chunk of data from the file */\n        fileDataLoaded = targetChunkSize > 0 ?\n                            (size_t)MIN(fileSize, (S64)targetChunkSize) :\n                            (size_t)MIN(fileSize, SAMPLESIZE_MAX );\n        if (totalDataLoaded + fileDataLoaded > *bufferSizePtr)\n            break;\n        if (fread( buff+totalDataLoaded, 1, fileDataLoaded, f ) != fileDataLoaded)\n            EXM_THROW(11, \"Pb reading %s\", fileNamesTable[fileIndex]);\n        sampleSizes[nbSamplesLoaded++] = fileDataLoaded;\n        totalDataLoaded += fileDataLoaded;\n\n        /* If file-chunking is enabled, load the rest of the file as more samples */\n        if (targetChunkSize > 0) {\n            while( (S64)fileDataLoaded < fileSize && nbSamplesLoaded < sstSize ) {\n                size_t const chunkSize = MIN((size_t)(fileSize-fileDataLoaded), targetChunkSize);\n                if (totalDataLoaded + chunkSize > *bufferSizePtr) /* buffer is full */\n                    break;\n\n                if (fread( buff+totalDataLoaded, 1, chunkSize, f ) != chunkSize)\n                    EXM_THROW(11, \"Pb reading %s\", fileNamesTable[fileIndex]);\n                sampleSizes[nbSamplesLoaded++] = chunkSize;\n                totalDataLoaded += chunkSize;\n                fileDataLoaded += chunkSize;\n            }\n        }\n        fileIndex += 1;\n        fclose(f); f = NULL;\n    }\n    if (f != NULL)\n        fclose(f);\n\n    DISPLAYLEVEL(2, \"\\r%79s\\r\", \"\");\n    DISPLAYLEVEL(4, \"Loaded %d KB total training data, %d nb samples \\n\",\n        (int)(totalDataLoaded / (1 KB)), nbSamplesLoaded );\n    *bufferSizePtr = totalDataLoaded;\n    return nbSamplesLoaded;\n}\n\n#define DiB_rotl32(x,r) ((x << r) | (x >> (32 - r)))\nstatic U32 DiB_rand(U32* src)\n{\n    static const U32 prime1 = 2654435761U;\n    static const U32 prime2 = 2246822519U;\n    U32 rand32 = *src;\n    rand32 *= prime1;\n    rand32 ^= prime2;\n    rand32  = DiB_rotl32(rand32, 13);\n    *src = rand32;\n    return rand32 >> 5;\n}\n\n/* DiB_shuffle() :\n * shuffle a table of file names in a semi-random way\n * It improves dictionary quality by reducing \"locality\" impact, so if sample set is very large,\n * it will load random elements from it, instead of just the first ones. */\nstatic void DiB_shuffle(const char** fileNamesTable, unsigned nbFiles) {\n    U32 seed = 0xFD2FB528;\n    unsigned i;\n    if (nbFiles == 0)\n        return;\n    for (i = nbFiles - 1; i > 0; --i) {\n        unsigned const j = DiB_rand(&seed) % (i + 1);\n        const char* const tmp = fileNamesTable[j];\n        fileNamesTable[j] = fileNamesTable[i];\n        fileNamesTable[i] = tmp;\n    }\n}\n\n\n/*-********************************************************\n*  Dictionary training functions\n**********************************************************/\nstatic size_t DiB_findMaxMem(unsigned long long requiredMem)\n{\n    size_t const step = 8 MB;\n    void* testmem = NULL;\n\n    requiredMem = (((requiredMem >> 23) + 1) << 23);\n    requiredMem += step;\n    if (requiredMem > g_maxMemory) requiredMem = g_maxMemory;\n\n    while (!testmem) {\n        testmem = malloc((size_t)requiredMem);\n        requiredMem -= step;\n    }\n\n    free(testmem);\n    return (size_t)requiredMem;\n}\n\n\nstatic void DiB_fillNoise(void* buffer, size_t length)\n{\n    unsigned const prime1 = 2654435761U;\n    unsigned const prime2 = 2246822519U;\n    unsigned acc = prime1;\n    size_t p=0;\n\n    for (p=0; p<length; p++) {\n        acc *= prime2;\n        ((unsigned char*)buffer)[p] = (unsigned char)(acc >> 21);\n    }\n}\n\n\nstatic void DiB_saveDict(const char* dictFileName,\n                         const void* buff, size_t buffSize)\n{\n    FILE* const f = fopen(dictFileName, \"wb\");\n    if (f==NULL) EXM_THROW(3, \"cannot open %s \", dictFileName);\n\n    { size_t const n = fwrite(buff, 1, buffSize, f);\n      if (n!=buffSize) EXM_THROW(4, \"%s : write error\", dictFileName) }\n\n    { size_t const n = (size_t)fclose(f);\n      if (n!=0) EXM_THROW(5, \"%s : flush error\", dictFileName) }\n}\n\ntypedef struct {\n    S64 totalSizeToLoad;\n    int nbSamples;\n    int oneSampleTooLarge;\n} fileStats;\n\n/*! DiB_fileStats() :\n *  Given a list of files, and a chunkSize (0 == no chunk, whole files)\n *  provides the amount of data to be loaded and the resulting nb of samples.\n *  This is useful primarily for allocation purpose => sample buffer, and sample sizes table.\n */\nstatic fileStats DiB_fileStats(const char** fileNamesTable, int nbFiles, size_t chunkSize, int displayLevel)\n{\n    fileStats fs;\n    int n;\n    memset(&fs, 0, sizeof(fs));\n\n    /* We assume that if chunking is requested, the chunk size is < SAMPLESIZE_MAX */\n    assert( chunkSize <= SAMPLESIZE_MAX );\n\n    for (n=0; n<nbFiles; n++) {\n      S64 const fileSize = DiB_getFileSize(fileNamesTable[n]);\n      /* TODO: is there a minimum sample size? What if the file is 1-byte? */\n      /* Skip empty or invalid files */\n      if (fileSize <= 0) {\n        if (fileSize < 0) {\n          DISPLAYLEVEL(3, \"Sample file '%s' is unreadable or stat failed, skipping...\\n\",\n                       fileNamesTable[n]);\n        } else {\n          DISPLAYLEVEL(3, \"Sample file '%s' has zero size, skipping...\\n\",\n                     fileNamesTable[n]);\n        }\n        continue;\n      }\n\n      /* the case where we are breaking up files in sample chunks */\n      if (chunkSize > 0) {\n        /* TODO: is there a minimum sample size? Can we have a 1-byte sample? */\n        fs.nbSamples += (int)((fileSize + chunkSize-1) / chunkSize);\n        fs.totalSizeToLoad += fileSize;\n      }\n      else {\n      /* the case where one file is one sample */\n        if (fileSize > SAMPLESIZE_MAX) {\n          /* flag excessively large sample files */\n          fs.oneSampleTooLarge |= (fileSize > 2*SAMPLESIZE_MAX);\n\n          /* Limit to the first SAMPLESIZE_MAX (128kB) of the file */\n          DISPLAYLEVEL(3, \"Sample file '%s' is too large, limiting to %d KB\\n\",\n              fileNamesTable[n], SAMPLESIZE_MAX / (1 KB));\n        }\n        fs.nbSamples += 1;\n        fs.totalSizeToLoad += MIN(fileSize, SAMPLESIZE_MAX);\n      }\n    }\n    DISPLAYLEVEL(4, \"Found training data %d files, %d KB, %d samples\\n\", nbFiles, (int)(fs.totalSizeToLoad / (1 KB)), fs.nbSamples);\n    return fs;\n}\n\nint DiB_trainFromFiles(const char* dictFileName, size_t maxDictSize,\n                       const char** fileNamesTable, int nbFiles, size_t chunkSize,\n                       ZDICT_legacy_params_t* params, ZDICT_cover_params_t* coverParams,\n                       ZDICT_fastCover_params_t* fastCoverParams, int optimize, unsigned memLimit)\n{\n    fileStats fs;\n    size_t* sampleSizes; /* vector of sample sizes. Each sample can be up to SAMPLESIZE_MAX */\n    int nbSamplesLoaded; /* nb of samples effectively loaded in srcBuffer */\n    size_t loadedSize; /* total data loaded in srcBuffer for all samples */\n    void* srcBuffer /* contiguous buffer with training data/samples */;\n    void* const dictBuffer = malloc(maxDictSize);\n    int result = 0;\n\n    int const displayLevel = params ? params->zParams.notificationLevel :\n        coverParams ? coverParams->zParams.notificationLevel :\n        fastCoverParams ? fastCoverParams->zParams.notificationLevel : 0;\n\n    /* Shuffle input files before we start assessing how much sample datA to load.\n       The purpose of the shuffle is to pick random samples when the sample\n       set is larger than what we can load in memory. */\n    DISPLAYLEVEL(3, \"Shuffling input files\\n\");\n    DiB_shuffle(fileNamesTable, nbFiles);\n\n    /* Figure out how much sample data to load with how many samples */\n    fs = DiB_fileStats(fileNamesTable, nbFiles, chunkSize, displayLevel);\n\n    {\n        int const memMult = params ? MEMMULT :\n                            coverParams ? COVER_MEMMULT:\n                            FASTCOVER_MEMMULT;\n        size_t const maxMem =  DiB_findMaxMem(fs.totalSizeToLoad * memMult) / memMult;\n        /* Limit the size of the training data to the free memory */\n        /* Limit the size of the training data to 2GB */\n        /* TODO: there is opportunity to stop DiB_fileStats() early when the data limit is reached */\n        loadedSize = (size_t)MIN( MIN((S64)maxMem, fs.totalSizeToLoad), MAX_SAMPLES_SIZE );\n        if (memLimit != 0) {\n            DISPLAYLEVEL(2, \"!  Warning : setting manual memory limit for dictionary training data at %u MB \\n\",\n                (unsigned)(memLimit / (1 MB)));\n            loadedSize = (size_t)MIN(loadedSize, memLimit);\n        }\n        srcBuffer = malloc(loadedSize+NOISELENGTH);\n        sampleSizes = (size_t*)malloc(fs.nbSamples * sizeof(size_t));\n    }\n\n    /* Checks */\n    if ((fs.nbSamples && !sampleSizes) || (!srcBuffer) || (!dictBuffer))\n        EXM_THROW(12, \"not enough memory for DiB_trainFiles\");   /* should not happen */\n    if (fs.oneSampleTooLarge) {\n        DISPLAYLEVEL(2, \"!  Warning : some sample(s) are very large \\n\");\n        DISPLAYLEVEL(2, \"!  Note that dictionary is only useful for small samples. \\n\");\n        DISPLAYLEVEL(2, \"!  As a consequence, only the first %u bytes of each sample are loaded \\n\", SAMPLESIZE_MAX);\n    }\n    if (fs.nbSamples < 5) {\n        DISPLAYLEVEL(2, \"!  Warning : nb of samples too low for proper processing !\\n\");\n        DISPLAYLEVEL(2, \"!  Please provide _one file per sample_.\\n\");\n        DISPLAYLEVEL(2, \"!  Alternatively, split file(s) into fixed-size samples, with --split=#\\n\");\n        EXM_THROW(14, \"nb of samples too low\");   /* we now clearly forbid this case */\n    }\n    if (fs.totalSizeToLoad < (S64)maxDictSize * 8) {\n        DISPLAYLEVEL(2, \"!  Warning : data size of samples too small for target dictionary size \\n\");\n        DISPLAYLEVEL(2, \"!  Samples should be about 100x larger than target dictionary size \\n\");\n    }\n\n    /* init */\n    if ((S64)loadedSize < fs.totalSizeToLoad)\n        DISPLAYLEVEL(1, \"Training samples set too large (%u MB); training on %u MB only...\\n\",\n            (unsigned)(fs.totalSizeToLoad / (1 MB)),\n            (unsigned)(loadedSize / (1 MB)));\n\n    /* Load input buffer */\n    nbSamplesLoaded = DiB_loadFiles(\n        srcBuffer, &loadedSize, sampleSizes, fs.nbSamples, fileNamesTable,\n        nbFiles, chunkSize, displayLevel);\n\n    {   size_t dictSize = ZSTD_error_GENERIC;\n        if (params) {\n            DiB_fillNoise((char*)srcBuffer + loadedSize, NOISELENGTH);   /* guard band, for end of buffer condition */\n            dictSize = ZDICT_trainFromBuffer_legacy(dictBuffer, maxDictSize,\n                                                    srcBuffer, sampleSizes, nbSamplesLoaded,\n                                                    *params);\n        } else if (coverParams) {\n            if (optimize) {\n              dictSize = ZDICT_optimizeTrainFromBuffer_cover(dictBuffer, maxDictSize,\n                                                             srcBuffer, sampleSizes, nbSamplesLoaded,\n                                                             coverParams);\n              if (!ZDICT_isError(dictSize)) {\n                  unsigned splitPercentage = (unsigned)(coverParams->splitPoint * 100);\n                  DISPLAYLEVEL(2, \"k=%u\\nd=%u\\nsteps=%u\\nsplit=%u\\n\", coverParams->k, coverParams->d,\n                              coverParams->steps, splitPercentage);\n              }\n            } else {\n              dictSize = ZDICT_trainFromBuffer_cover(dictBuffer, maxDictSize, srcBuffer,\n                                                     sampleSizes, nbSamplesLoaded, *coverParams);\n            }\n        } else if (fastCoverParams != NULL) {\n            if (optimize) {\n              dictSize = ZDICT_optimizeTrainFromBuffer_fastCover(dictBuffer, maxDictSize,\n                                                              srcBuffer, sampleSizes, nbSamplesLoaded,\n                                                              fastCoverParams);\n              if (!ZDICT_isError(dictSize)) {\n                unsigned splitPercentage = (unsigned)(fastCoverParams->splitPoint * 100);\n                DISPLAYLEVEL(2, \"k=%u\\nd=%u\\nf=%u\\nsteps=%u\\nsplit=%u\\naccel=%u\\n\", fastCoverParams->k,\n                            fastCoverParams->d, fastCoverParams->f, fastCoverParams->steps, splitPercentage,\n                            fastCoverParams->accel);\n              }\n            } else {\n              dictSize = ZDICT_trainFromBuffer_fastCover(dictBuffer, maxDictSize, srcBuffer,\n                                                        sampleSizes, nbSamplesLoaded, *fastCoverParams);\n            }\n        } else {\n            assert(0 /* Impossible */);\n        }\n        if (ZDICT_isError(dictSize)) {\n            DISPLAYLEVEL(1, \"dictionary training failed : %s \\n\", ZDICT_getErrorName(dictSize));   /* should not happen */\n            result = 1;\n            goto _cleanup;\n        }\n        /* save dict */\n        DISPLAYLEVEL(2, \"Save dictionary of size %u into file %s \\n\", (unsigned)dictSize, dictFileName);\n        DiB_saveDict(dictFileName, dictBuffer, dictSize);\n    }\n\n    /* clean up */\n_cleanup:\n    free(srcBuffer);\n    free(sampleSizes);\n    free(dictBuffer);\n    return result;\n}\n"
  },
  {
    "path": "programs/dibio.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* This library is designed for a single-threaded console application.\n*  It exit() and printf() into stderr when it encounters an error condition. */\n\n#ifndef DIBIO_H_003\n#define DIBIO_H_003\n\n\n/*-*************************************\n*  Dependencies\n***************************************/\n#define ZDICT_STATIC_LINKING_ONLY\n#include \"../lib/zdict.h\"     /* ZDICT_params_t */\n\n\n/*-*************************************\n*  Public functions\n***************************************/\n/*! DiB_trainFromFiles() :\n    Train a dictionary from a set of files provided by `fileNamesTable`.\n    Resulting dictionary is written into file `dictFileName`.\n    `parameters` is optional and can be provided with values set to 0, meaning \"default\".\n    @return : 0 == ok. Any other : error.\n*/\nint DiB_trainFromFiles(const char* dictFileName, size_t maxDictSize,\n                       const char** fileNamesTable, int nbFiles, size_t chunkSize,\n                       ZDICT_legacy_params_t* params, ZDICT_cover_params_t* coverParams,\n                       ZDICT_fastCover_params_t* fastCoverParams, int optimize, unsigned memLimit);\n\n#endif\n"
  },
  {
    "path": "programs/fileio.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/* *************************************\n*  Compiler Options\n***************************************/\n#ifdef _MSC_VER   /* Visual */\n#  pragma warning(disable : 4127)  /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4204)  /* non-constant aggregate initializer */\n#endif\n#if defined(__MINGW32__) && !defined(_POSIX_SOURCE)\n#  define _POSIX_SOURCE 1          /* disable %llu warnings with MinGW on Windows */\n#endif\n\n/*-*************************************\n*  Includes\n***************************************/\n#include \"platform.h\"   /* Large Files support, SET_BINARY_MODE */\n#include \"util.h\"       /* UTIL_getFileSize, UTIL_isRegularFile, UTIL_isSameFile */\n#include <stdio.h>      /* fprintf, open, fdopen, fread, _fileno, stdin, stdout */\n#include <stdlib.h>     /* malloc, free */\n#include <string.h>     /* strcmp, strlen */\n#include <time.h>       /* clock_t, to measure process time */\n#include <fcntl.h>      /* O_WRONLY */\n#include <assert.h>\n#include <errno.h>      /* errno */\n#include <limits.h>     /* INT_MAX */\n#include <signal.h>\n#include \"timefn.h\"     /* UTIL_getTime, UTIL_clockSpanMicro */\n\n#if defined (_MSC_VER)\n#  include <sys/stat.h>\n#  include <io.h>\n#endif\n\n#include \"fileio.h\"\n#include \"fileio_asyncio.h\"\n#include \"fileio_common.h\"\n\nFIO_display_prefs_t g_display_prefs = {2, FIO_ps_auto};\nUTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER;\n\n#define ZSTD_STATIC_LINKING_ONLY   /* ZSTD_magicNumber, ZSTD_frameHeaderSize_max */\n#include \"../lib/zstd.h\"\n#include \"../lib/zstd_errors.h\"  /* ZSTD_error_frameParameter_windowTooLarge */\n\n#if defined(ZSTD_GZCOMPRESS) || defined(ZSTD_GZDECOMPRESS)\n#  include <zlib.h>\n#  if !defined(z_const)\n#    define z_const\n#  endif\n#endif\n\n#if defined(ZSTD_LZMACOMPRESS) || defined(ZSTD_LZMADECOMPRESS)\n#  include <lzma.h>\n#endif\n\n#define LZ4_MAGICNUMBER 0x184D2204\n#if defined(ZSTD_LZ4COMPRESS) || defined(ZSTD_LZ4DECOMPRESS)\n#  define LZ4F_ENABLE_OBSOLETE_ENUMS\n#  include <lz4frame.h>\n#  include <lz4.h>\n#endif\n\nchar const* FIO_zlibVersion(void)\n{\n#if defined(ZSTD_GZCOMPRESS) || defined(ZSTD_GZDECOMPRESS)\n    return zlibVersion();\n#else\n    return \"Unsupported\";\n#endif\n}\n\nchar const* FIO_lz4Version(void)\n{\n#if defined(ZSTD_LZ4COMPRESS) || defined(ZSTD_LZ4DECOMPRESS)\n    /* LZ4_versionString() added in v1.7.3 */\n#   if LZ4_VERSION_NUMBER >= 10703\n        return LZ4_versionString();\n#   else\n#       define ZSTD_LZ4_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE\n#       define ZSTD_LZ4_VERSION_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_LZ4_VERSION)\n        return ZSTD_LZ4_VERSION_STRING;\n#   endif\n#else\n    return \"Unsupported\";\n#endif\n}\n\nchar const* FIO_lzmaVersion(void)\n{\n#if defined(ZSTD_LZMACOMPRESS) || defined(ZSTD_LZMADECOMPRESS)\n    return lzma_version_string();\n#else\n    return \"Unsupported\";\n#endif\n}\n\n\n/*-*************************************\n*  Constants\n***************************************/\n#define ADAPT_WINDOWLOG_DEFAULT 23   /* 8 MB */\n#define DICTSIZE_MAX (32 MB)   /* protection against large input (attack scenario) */\n\n#define FNSPACE 30\n\n/* Default file permissions 0666 (modulated by umask) */\n/* Temporary restricted file permissions are used when we're going to\n * chmod/chown at the end of the operation. */\n#if !defined(_WIN32)\n/* These macros aren't defined on windows. */\n#define DEFAULT_FILE_PERMISSIONS (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)\n#define TEMPORARY_FILE_PERMISSIONS (S_IRUSR|S_IWUSR)\n#else\n#define DEFAULT_FILE_PERMISSIONS (0666)\n#define TEMPORARY_FILE_PERMISSIONS (0600)\n#endif\n\n\n#ifndef ZSTD_NOCOMPRESS\n\n/* *************************************\n*  Synchronous compression IO helpers\n*  Lightweight wrapper used by compression paths to manage buffered\n*  reads/writes without the async job machinery.\n***************************************/\ntypedef struct {\n    const FIO_prefs_t* prefs;\n    FILE* srcFile;\n    FILE* dstFile;\n    unsigned storedSkips;\n    U8* inBuffer;\n    size_t inCapacity;\n    U8* srcBuffer;\n    size_t srcBufferLoaded;\n    U8* outBuffer;\n    size_t outCapacity;\n} FIO_SyncCompressIO;\n\nstatic void FIO_SyncCompressIO_init(FIO_SyncCompressIO* io,\n                                    const FIO_prefs_t* prefs,\n                                    size_t inCapacity,\n                                    size_t outCapacity);\nstatic void FIO_SyncCompressIO_destroy(FIO_SyncCompressIO* io);\nstatic void FIO_SyncCompressIO_setSrc(FIO_SyncCompressIO* io, FILE* file);\nstatic void FIO_SyncCompressIO_clearSrc(FIO_SyncCompressIO* io);\nstatic void FIO_SyncCompressIO_setDst(FIO_SyncCompressIO* io, FILE* file);\nstatic int  FIO_SyncCompressIO_closeDst(FIO_SyncCompressIO* io);\nstatic size_t FIO_SyncCompressIO_fillBuffer(FIO_SyncCompressIO* io, size_t minToHave);\nstatic void FIO_SyncCompressIO_consumeBytes(FIO_SyncCompressIO* io, size_t n);\nstatic void FIO_SyncCompressIO_commitOut(FIO_SyncCompressIO* io, const void* buffer, size_t size);\nstatic void FIO_SyncCompressIO_finish(FIO_SyncCompressIO* io);\n\n\nstatic unsigned FIO_sparseWrite(FILE* file,\n                                const void* buffer, size_t bufferSize,\n                                const FIO_prefs_t* const prefs,\n                                unsigned storedSkips)\n{\n    const size_t* const bufferT = (const size_t*)buffer;   /* Buffer is supposed malloc'ed, hence aligned on size_t */\n    size_t bufferSizeT = bufferSize / sizeof(size_t);\n    const size_t* const bufferTEnd = bufferT + bufferSizeT;\n    const size_t* ptrT = bufferT;\n    static const size_t segmentSizeT = (32 KB) / sizeof(size_t);   /* check every 32 KB */\n\n    if (prefs->testMode) return 0;  /* do not output anything in test mode */\n\n    if (!prefs->sparseFileSupport) {  /* normal write */\n        size_t const sizeCheck = fwrite(buffer, 1, bufferSize, file);\n        if (sizeCheck != bufferSize)\n            EXM_THROW(70, \"Write error : cannot write block : %s\",\n                      strerror(errno));\n        return 0;\n    }\n\n    /* avoid int overflow */\n    if (storedSkips > 1 GB) {\n        if (LONG_SEEK(file, 1 GB, SEEK_CUR) != 0)\n            EXM_THROW(91, \"1 GB skip error (sparse file support)\");\n        storedSkips -= 1 GB;\n    }\n\n    while (ptrT < bufferTEnd) {\n        size_t nb0T;\n\n        /* adjust last segment if < 32 KB */\n        size_t seg0SizeT = segmentSizeT;\n        if (seg0SizeT > bufferSizeT) seg0SizeT = bufferSizeT;\n        bufferSizeT -= seg0SizeT;\n\n        /* count leading zeroes */\n        for (nb0T=0; (nb0T < seg0SizeT) && (ptrT[nb0T] == 0); nb0T++) ;\n        storedSkips += (unsigned)(nb0T * sizeof(size_t));\n\n        if (nb0T != seg0SizeT) {   /* not all 0s */\n            size_t const nbNon0ST = seg0SizeT - nb0T;\n            /* skip leading zeros */\n            if (LONG_SEEK(file, storedSkips, SEEK_CUR) != 0)\n                EXM_THROW(92, \"Sparse skip error ; try --no-sparse\");\n            storedSkips = 0;\n            /* write the rest */\n            if (fwrite(ptrT + nb0T, sizeof(size_t), nbNon0ST, file) != nbNon0ST)\n                EXM_THROW(93, \"Write error : cannot write block : %s\",\n                          strerror(errno));\n        }\n        ptrT += seg0SizeT;\n    }\n\n    {   static size_t const maskT = sizeof(size_t)-1;\n        if (bufferSize & maskT) {\n            /* size not multiple of sizeof(size_t) : implies end of block */\n            const char* const restStart = (const char*)bufferTEnd;\n            const char* restPtr = restStart;\n            const char* const restEnd = (const char*)buffer + bufferSize;\n            assert(restEnd > restStart && restEnd < restStart + sizeof(size_t));\n            for ( ; (restPtr < restEnd) && (*restPtr == 0); restPtr++) ;\n            storedSkips += (unsigned) (restPtr - restStart);\n            if (restPtr != restEnd) {\n                /* not all remaining bytes are 0 */\n                size_t const restSize = (size_t)(restEnd - restPtr);\n                if (LONG_SEEK(file, storedSkips, SEEK_CUR) != 0)\n                    EXM_THROW(92, \"Sparse skip error ; try --no-sparse\");\n                if (fwrite(restPtr, 1, restSize, file) != restSize)\n                    EXM_THROW(95, \"Write error : cannot write end of decoded block : %s\",\n                              strerror(errno));\n                storedSkips = 0;\n            }   }   }\n\n    return storedSkips;\n}\n\nstatic void FIO_sparseWriteEnd(const FIO_prefs_t* const prefs, FILE* file, unsigned storedSkips)\n{\n    if (file == NULL) return;\n    if (prefs->testMode) {\n        assert(storedSkips == 0);\n        return;\n    }\n    if (storedSkips>0) {\n        assert(prefs->sparseFileSupport > 0);  /* storedSkips>0 implies sparse support is enabled */\n        if (LONG_SEEK(file, storedSkips-1, SEEK_CUR) != 0)\n            EXM_THROW(69, \"Final skip error (sparse file support)\");\n        /* last zero must be explicitly written,\n         * so that skipped ones get implicitly translated as zero by FS */\n        {   const char lastZeroByte[1] = { 0 };\n            if (fwrite(lastZeroByte, 1, 1, file) != 1)\n                EXM_THROW(69, \"Write error : cannot write last zero : %s\", strerror(errno));\n        }\n    }\n}\n\nstatic void FIO_SyncCompressIO_init(FIO_SyncCompressIO* io,\n                                    const FIO_prefs_t* prefs,\n                                    size_t inCapacity,\n                                    size_t outCapacity)\n{\n    memset(io, 0, sizeof(*io));\n    io->prefs = prefs;\n    io->inCapacity = inCapacity;\n    io->outCapacity = outCapacity;\n    io->inBuffer = (U8*)malloc(inCapacity);\n    if (!io->inBuffer)\n        EXM_THROW(101, \"Allocation error : not enough memory\");\n    io->outBuffer = (U8*)malloc(outCapacity);\n    if (!io->outBuffer) {\n        free(io->inBuffer);\n        io->inBuffer = NULL;\n        EXM_THROW(101, \"Allocation error : not enough memory\");\n    }\n    io->srcBuffer = io->inBuffer;\n    io->srcBufferLoaded = 0;\n}\n\nstatic void FIO_SyncCompressIO_destroy(FIO_SyncCompressIO* io)\n{\n    if (!io) return;\n    free(io->inBuffer);\n    free(io->outBuffer);\n    io->inBuffer = NULL;\n    io->outBuffer = NULL;\n    io->srcBuffer = NULL;\n    io->srcBufferLoaded = 0;\n    io->srcFile = NULL;\n    io->dstFile = NULL;\n    io->storedSkips = 0;\n}\n\nstatic void FIO_SyncCompressIO_setSrc(FIO_SyncCompressIO* io, FILE* file)\n{\n    io->srcFile = file;\n    io->srcBuffer = io->inBuffer;\n    io->srcBufferLoaded = 0;\n}\n\nstatic void FIO_SyncCompressIO_clearSrc(FIO_SyncCompressIO* io)\n{\n    io->srcFile = NULL;\n    io->srcBuffer = io->inBuffer;\n    io->srcBufferLoaded = 0;\n}\n\nstatic void FIO_SyncCompressIO_setDst(FIO_SyncCompressIO* io, FILE* file)\n{\n    io->dstFile = file;\n    io->storedSkips = 0;\n}\n\nstatic int FIO_SyncCompressIO_closeDst(FIO_SyncCompressIO* io)\n{\n    int result = 0;\n    if (io->dstFile != NULL) {\n        FIO_SyncCompressIO_finish(io);\n        result = fclose(io->dstFile);\n        io->dstFile = NULL;\n    }\n    return result;\n}\n\nstatic size_t FIO_SyncCompressIO_fillBuffer(FIO_SyncCompressIO* io, size_t minToHave)\n{\n    size_t added = 0;\n    if (io->srcFile == NULL)\n        return 0;\n\n    if (minToHave > io->inCapacity)\n        minToHave = io->inCapacity;\n\n    if (io->srcBufferLoaded >= minToHave)\n        return 0;\n\n    if (io->srcBuffer != io->inBuffer) {\n        if (io->srcBufferLoaded > 0)\n            memmove(io->inBuffer, io->srcBuffer, io->srcBufferLoaded);\n        io->srcBuffer = io->inBuffer;\n    }\n\n    while (io->srcBufferLoaded < minToHave) {\n        size_t const toRead = io->inCapacity - io->srcBufferLoaded;\n        size_t const readBytes = fread(io->inBuffer + io->srcBufferLoaded, 1, toRead, io->srcFile);\n        if (readBytes == 0) {\n            if (ferror(io->srcFile))\n                EXM_THROW(37, \"Read error\");\n            break; /* EOF */\n        }\n        io->srcBufferLoaded += readBytes;\n        added += readBytes;\n        if (readBytes < toRead)\n            break;\n    }\n\n    return added;\n}\n\nstatic void FIO_SyncCompressIO_consumeBytes(FIO_SyncCompressIO* io, size_t n)\n{\n    assert(n <= io->srcBufferLoaded);\n    io->srcBuffer += n;\n    io->srcBufferLoaded -= n;\n    if (io->srcBufferLoaded == 0)\n        io->srcBuffer = io->inBuffer;\n}\n\nstatic void FIO_SyncCompressIO_commitOut(FIO_SyncCompressIO* io, const void* buffer, size_t size)\n{\n    if (size == 0)\n        return;\n    if (io->dstFile == NULL) {\n        assert(io->prefs->testMode);\n        return;\n    }\n    io->storedSkips = FIO_sparseWrite(io->dstFile, buffer, size, io->prefs, io->storedSkips);\n}\n\nstatic void FIO_SyncCompressIO_finish(FIO_SyncCompressIO* io)\n{\n    if (io->dstFile == NULL)\n        return;\n    FIO_sparseWriteEnd(io->prefs, io->dstFile, io->storedSkips);\n    io->storedSkips = 0;\n}\n\n#endif /* ZSTD_NOCOMPRESS */\n\n/*-************************************\n*  Signal (Ctrl-C trapping)\n**************************************/\nstatic const char* g_artefact = NULL;\nstatic void INThandler(int sig)\n{\n    assert(sig==SIGINT); (void)sig;\n#if !defined(_MSC_VER)\n    signal(sig, SIG_IGN);  /* this invocation generates a buggy warning in Visual Studio */\n#endif\n    if (g_artefact) {\n        assert(UTIL_isRegularFile(g_artefact));\n        remove(g_artefact);\n    }\n    DISPLAY(\"\\n\");\n    exit(2);\n}\nstatic void addHandler(char const* dstFileName)\n{\n    if (UTIL_isRegularFile(dstFileName)) {\n        g_artefact = dstFileName;\n        signal(SIGINT, INThandler);\n    } else {\n        g_artefact = NULL;\n    }\n}\n/* Idempotent */\nstatic void clearHandler(void)\n{\n    if (g_artefact) signal(SIGINT, SIG_DFL);\n    g_artefact = NULL;\n}\n\n\n/*-*********************************************************\n*  Termination signal trapping (Print debug stack trace)\n***********************************************************/\n#if defined(__has_feature) && !defined(BACKTRACE_ENABLE) /* Clang compiler */\n#  if (__has_feature(address_sanitizer))\n#    define BACKTRACE_ENABLE 0\n#  endif /* __has_feature(address_sanitizer) */\n#elif defined(__SANITIZE_ADDRESS__) && !defined(BACKTRACE_ENABLE) /* GCC compiler */\n#  define BACKTRACE_ENABLE 0\n#endif\n\n#if !defined(BACKTRACE_ENABLE)\n/* automatic detector : backtrace enabled by default on linux+glibc and osx */\n#  if (defined(__linux__) && (defined(__GLIBC__) && !defined(__UCLIBC__))) \\\n     || (defined(__APPLE__) && defined(__MACH__))\n#    define BACKTRACE_ENABLE 1\n#  else\n#    define BACKTRACE_ENABLE 0\n#  endif\n#endif\n\n/* note : after this point, BACKTRACE_ENABLE is necessarily defined */\n\n\n#if BACKTRACE_ENABLE\n\n#include <execinfo.h>   /* backtrace, backtrace_symbols */\n\n#define MAX_STACK_FRAMES    50\n\nstatic void ABRThandler(int sig) {\n    const char* name;\n    void* addrlist[MAX_STACK_FRAMES];\n    char** symbollist;\n    int addrlen, i;\n\n    switch (sig) {\n        case SIGABRT: name = \"SIGABRT\"; break;\n        case SIGFPE: name = \"SIGFPE\"; break;\n        case SIGILL: name = \"SIGILL\"; break;\n        case SIGINT: name = \"SIGINT\"; break;\n        case SIGSEGV: name = \"SIGSEGV\"; break;\n        default: name = \"UNKNOWN\";\n    }\n\n    DISPLAY(\"Caught %s signal, printing stack:\\n\", name);\n    /* Retrieve current stack addresses. */\n    addrlen = backtrace(addrlist, MAX_STACK_FRAMES);\n    if (addrlen == 0) {\n        DISPLAY(\"\\n\");\n        return;\n    }\n    /* Create readable strings to each frame. */\n    symbollist = backtrace_symbols(addrlist, addrlen);\n    /* Print the stack trace, excluding calls handling the signal. */\n    for (i = ZSTD_START_SYMBOLLIST_FRAME; i < addrlen; i++) {\n        DISPLAY(\"%s\\n\", symbollist[i]);\n    }\n    free(symbollist);\n    /* Reset and raise the signal so default handler runs. */\n    signal(sig, SIG_DFL);\n    raise(sig);\n}\n#endif\n\nvoid FIO_addAbortHandler(void)\n{\n#if BACKTRACE_ENABLE\n    signal(SIGABRT, ABRThandler);\n    signal(SIGFPE, ABRThandler);\n    signal(SIGILL, ABRThandler);\n    signal(SIGSEGV, ABRThandler);\n    signal(SIGBUS, ABRThandler);\n#endif\n}\n\n/*-*************************************\n*  Parameters: FIO_ctx_t\n***************************************/\n\n/* typedef'd to FIO_ctx_t within fileio.h */\nstruct FIO_ctx_s {\n\n    /* file i/o info */\n    int nbFilesTotal;\n    int hasStdinInput;\n    int hasStdoutOutput;\n\n    /* file i/o state */\n    int currFileIdx;\n    int nbFilesProcessed;\n    size_t totalBytesInput;\n    size_t totalBytesOutput;\n};\n\nstatic int FIO_shouldDisplayFileSummary(FIO_ctx_t const* fCtx)\n{\n    return fCtx->nbFilesTotal <= 1 || g_display_prefs.displayLevel >= 3;\n}\n\nstatic int FIO_shouldDisplayMultipleFileSummary(FIO_ctx_t const* fCtx)\n{\n    int const shouldDisplay = (fCtx->nbFilesProcessed >= 1 && fCtx->nbFilesTotal > 1);\n    assert(shouldDisplay || FIO_shouldDisplayFileSummary(fCtx) || fCtx->nbFilesProcessed == 0);\n    return shouldDisplay;\n}\n\n\n/*-*************************************\n*  Parameters: Initialization\n***************************************/\n\n#define FIO_OVERLAP_LOG_NOTSET 9999\n#define FIO_LDM_PARAM_NOTSET 9999\n\n\nFIO_prefs_t* FIO_createPreferences(void)\n{\n    FIO_prefs_t* const ret = (FIO_prefs_t*)malloc(sizeof(FIO_prefs_t));\n    if (!ret) EXM_THROW(21, \"Allocation error : not enough memory\");\n\n    ret->compressionType = FIO_zstdCompression;\n    ret->overwrite = 0;\n    ret->sparseFileSupport = ZSTD_SPARSE_DEFAULT;\n    ret->dictIDFlag = 1;\n    ret->checksumFlag = 1;\n    ret->removeSrcFile = 0;\n    ret->memLimit = 0;\n    ret->nbWorkers = 1;\n    ret->jobSize = 0;\n    ret->overlapLog = FIO_OVERLAP_LOG_NOTSET;\n    ret->adaptiveMode = 0;\n    ret->rsyncable = 0;\n    ret->minAdaptLevel = -50;   /* initializing this value requires a constant, so ZSTD_minCLevel() doesn't work */\n    ret->maxAdaptLevel = 22;   /* initializing this value requires a constant, so ZSTD_maxCLevel() doesn't work */\n    ret->ldmFlag = 0;\n    ret->ldmHashLog = 0;\n    ret->ldmMinMatch = 0;\n    ret->ldmBucketSizeLog = FIO_LDM_PARAM_NOTSET;\n    ret->ldmHashRateLog = FIO_LDM_PARAM_NOTSET;\n    ret->streamSrcSize = 0;\n    ret->targetCBlockSize = 0;\n    ret->srcSizeHint = 0;\n    ret->testMode = 0;\n    ret->literalCompressionMode = ZSTD_ps_auto;\n    ret->excludeCompressedFiles = 0;\n    ret->allowBlockDevices = 0;\n    ret->asyncIO = AIO_supported();\n    ret->passThrough = -1;\n    return ret;\n}\n\nFIO_ctx_t* FIO_createContext(void)\n{\n    FIO_ctx_t* const ret = (FIO_ctx_t*)malloc(sizeof(FIO_ctx_t));\n    if (!ret) EXM_THROW(21, \"Allocation error : not enough memory\");\n\n    ret->currFileIdx = 0;\n    ret->hasStdinInput = 0;\n    ret->hasStdoutOutput = 0;\n    ret->nbFilesTotal = 1;\n    ret->nbFilesProcessed = 0;\n    ret->totalBytesInput = 0;\n    ret->totalBytesOutput = 0;\n    return ret;\n}\n\nvoid FIO_freePreferences(FIO_prefs_t* const prefs)\n{\n    free(prefs);\n}\n\nvoid FIO_freeContext(FIO_ctx_t* const fCtx)\n{\n    free(fCtx);\n}\n\n\n/*-*************************************\n*  Parameters: Display Options\n***************************************/\n\nvoid FIO_setNotificationLevel(int level) { g_display_prefs.displayLevel=level; }\n\nvoid FIO_setProgressSetting(FIO_progressSetting_e setting) { g_display_prefs.progressSetting = setting; }\n\n\n/*-*************************************\n*  Parameters: Setters\n***************************************/\n\n/* FIO_prefs_t functions */\n\nvoid FIO_setCompressionType(FIO_prefs_t* const prefs, FIO_compressionType_t compressionType) { prefs->compressionType = compressionType; }\n\nvoid FIO_overwriteMode(FIO_prefs_t* const prefs) { prefs->overwrite = 1; }\n\nvoid FIO_setSparseWrite(FIO_prefs_t* const prefs, int sparse) { prefs->sparseFileSupport = sparse; }\n\nvoid FIO_setDictIDFlag(FIO_prefs_t* const prefs, int dictIDFlag) { prefs->dictIDFlag = dictIDFlag; }\n\nvoid FIO_setChecksumFlag(FIO_prefs_t* const prefs, int checksumFlag) { prefs->checksumFlag = checksumFlag; }\n\nvoid FIO_setRemoveSrcFile(FIO_prefs_t* const prefs, int flag) { prefs->removeSrcFile = (flag!=0); }\n\nvoid FIO_setMemLimit(FIO_prefs_t* const prefs, unsigned memLimit) { prefs->memLimit = memLimit; }\n\nvoid FIO_setNbWorkers(FIO_prefs_t* const prefs, int nbWorkers) {\n#ifndef ZSTD_MULTITHREAD\n    if (nbWorkers > 0) DISPLAYLEVEL(2, \"Note : multi-threading is disabled \\n\");\n#endif\n    prefs->nbWorkers = nbWorkers;\n}\n\nvoid FIO_setExcludeCompressedFile(FIO_prefs_t* const prefs, int excludeCompressedFiles) { prefs->excludeCompressedFiles = excludeCompressedFiles; }\n\nvoid FIO_setAllowBlockDevices(FIO_prefs_t* const prefs, int allowBlockDevices) { prefs->allowBlockDevices = allowBlockDevices; }\n\nvoid FIO_setJobSize(FIO_prefs_t* const prefs, int jobSize) {\n    if (jobSize && prefs->nbWorkers==0)\n        DISPLAYLEVEL(2, \"Setting block size is useless in single-thread mode \\n\");\n    prefs->jobSize = jobSize;\n}\n\nvoid FIO_setOverlapLog(FIO_prefs_t* const prefs, int overlapLog){\n    if (overlapLog && prefs->nbWorkers==0)\n        DISPLAYLEVEL(2, \"Setting overlapLog is useless in single-thread mode \\n\");\n    prefs->overlapLog = overlapLog;\n}\n\nvoid FIO_setAdaptiveMode(FIO_prefs_t* const prefs, int adapt) {\n    if ((adapt>0) && (prefs->nbWorkers==0))\n        EXM_THROW(1, \"Adaptive mode is not compatible with single thread mode \\n\");\n    prefs->adaptiveMode = adapt;\n}\n\nvoid FIO_setUseRowMatchFinder(FIO_prefs_t* const prefs, int useRowMatchFinder) {\n    prefs->useRowMatchFinder = useRowMatchFinder;\n}\n\nvoid FIO_setRsyncable(FIO_prefs_t* const prefs, int rsyncable) {\n    if ((rsyncable>0) && (prefs->nbWorkers==0))\n        EXM_THROW(1, \"Rsyncable mode is not compatible with single thread mode \\n\");\n    prefs->rsyncable = rsyncable;\n}\n\nvoid FIO_setStreamSrcSize(FIO_prefs_t* const prefs, size_t streamSrcSize) {\n    prefs->streamSrcSize = streamSrcSize;\n}\n\nvoid FIO_setTargetCBlockSize(FIO_prefs_t* const prefs, size_t targetCBlockSize) {\n    prefs->targetCBlockSize = targetCBlockSize;\n}\n\nvoid FIO_setSrcSizeHint(FIO_prefs_t* const prefs, size_t srcSizeHint) {\n    prefs->srcSizeHint = (int)MIN((size_t)INT_MAX, srcSizeHint);\n}\n\nvoid FIO_setTestMode(FIO_prefs_t* const prefs, int testMode) {\n    prefs->testMode = (testMode!=0);\n}\n\nvoid FIO_setLiteralCompressionMode(\n        FIO_prefs_t* const prefs,\n        ZSTD_ParamSwitch_e mode) {\n    prefs->literalCompressionMode = mode;\n}\n\nvoid FIO_setAdaptMin(FIO_prefs_t* const prefs, int minCLevel)\n{\n#ifndef ZSTD_NOCOMPRESS\n    assert(minCLevel >= ZSTD_minCLevel());\n#endif\n    prefs->minAdaptLevel = minCLevel;\n}\n\nvoid FIO_setAdaptMax(FIO_prefs_t* const prefs, int maxCLevel)\n{\n    prefs->maxAdaptLevel = maxCLevel;\n}\n\nvoid FIO_setLdmFlag(FIO_prefs_t* const prefs, unsigned ldmFlag) {\n    prefs->ldmFlag = (ldmFlag>0);\n}\n\nvoid FIO_setLdmHashLog(FIO_prefs_t* const prefs, int ldmHashLog) {\n    prefs->ldmHashLog = ldmHashLog;\n}\n\nvoid FIO_setLdmMinMatch(FIO_prefs_t* const prefs, int ldmMinMatch) {\n    prefs->ldmMinMatch = ldmMinMatch;\n}\n\nvoid FIO_setLdmBucketSizeLog(FIO_prefs_t* const prefs, int ldmBucketSizeLog) {\n    prefs->ldmBucketSizeLog = ldmBucketSizeLog;\n}\n\n\nvoid FIO_setLdmHashRateLog(FIO_prefs_t* const prefs, int ldmHashRateLog) {\n    prefs->ldmHashRateLog = ldmHashRateLog;\n}\n\nvoid FIO_setPatchFromMode(FIO_prefs_t* const prefs, int value)\n{\n    prefs->patchFromMode = value != 0;\n}\n\nvoid FIO_setContentSize(FIO_prefs_t* const prefs, int value)\n{\n    prefs->contentSize = value != 0;\n}\n\nvoid FIO_setAsyncIOFlag(FIO_prefs_t* const prefs, int value) {\n#ifdef ZSTD_MULTITHREAD\n    prefs->asyncIO = value;\n#else\n    (void) prefs;\n    (void) value;\n    DISPLAYLEVEL(2, \"Note : asyncio is disabled (lack of multithreading support) \\n\");\n#endif\n}\n\nvoid FIO_setPassThroughFlag(FIO_prefs_t* const prefs, int value) {\n    prefs->passThrough = (value != 0);\n}\n\nvoid FIO_setMMapDict(FIO_prefs_t* const prefs, ZSTD_ParamSwitch_e value)\n{\n    prefs->mmapDict = value;\n}\n\n/* FIO_ctx_t functions */\n\nvoid FIO_setHasStdoutOutput(FIO_ctx_t* const fCtx, int value) {\n    fCtx->hasStdoutOutput = value;\n}\n\nvoid FIO_setNbFilesTotal(FIO_ctx_t* const fCtx, int value)\n{\n    fCtx->nbFilesTotal = value;\n}\n\nvoid FIO_determineHasStdinInput(FIO_ctx_t* const fCtx, const FileNamesTable* const filenames) {\n    size_t i = 0;\n    for ( ; i < filenames->tableSize; ++i) {\n        if (!strcmp(stdinmark, filenames->fileNames[i])) {\n            fCtx->hasStdinInput = 1;\n            return;\n        }\n    }\n}\n\n/*-*************************************\n*  Functions\n***************************************/\n/** FIO_removeFile() :\n * @result : Unlink `fileName`, even if it's read-only */\nstatic int FIO_removeFile(const char* path)\n{\n    stat_t statbuf;\n    if (!UTIL_stat(path, &statbuf)) {\n        DISPLAYLEVEL(2, \"zstd: Failed to stat %s while trying to remove it\\n\", path);\n        return 0;\n    }\n    if (!UTIL_isRegularFileStat(&statbuf)) {\n        DISPLAYLEVEL(2, \"zstd: Refusing to remove non-regular file %s\\n\", path);\n        return 0;\n    }\n#if defined(_WIN32)\n    /* windows doesn't allow remove read-only files,\n     * so try to make it writable first */\n    if (!(statbuf.st_mode & _S_IWRITE)) {\n        UTIL_chmod(path, &statbuf, _S_IWRITE);\n    }\n#endif\n    return remove(path);\n}\n\n/** FIO_openSrcFile() :\n *  condition : `srcFileName` must be non-NULL.\n *  optional: `prefs` may be NULL.\n * @result : FILE* to `srcFileName`, or NULL if it fails */\nstatic FILE* FIO_openSrcFile(const FIO_prefs_t* const prefs, const char* srcFileName, stat_t* statbuf)\n{\n    int allowBlockDevices = prefs != NULL ? prefs->allowBlockDevices : 0;\n    assert(srcFileName != NULL);\n    assert(statbuf != NULL);\n\n    if (!strcmp(srcFileName, stdinmark)) {\n        DISPLAYLEVEL(4,\"Using stdin for input \\n\");\n        SET_BINARY_MODE(stdin);\n        return stdin;\n    }\n\n    if (!UTIL_stat(srcFileName, statbuf)) {\n        DISPLAYLEVEL(1, \"zstd: can't stat %s : %s -- ignored \\n\",\n                        srcFileName, strerror(errno));\n        return NULL;\n    }\n\n    /* Accept regular files, FIFOs, and process substitution file descriptors */\n    if (!UTIL_isRegularFileStat(statbuf)\n     && !UTIL_isFIFOStat(statbuf)\n     && !UTIL_isFileDescriptorPipe(srcFileName)  /* Process substitution support */\n     && !(allowBlockDevices && UTIL_isBlockDevStat(statbuf))\n    ) {\n        DISPLAYLEVEL(1, \"zstd: %s is not a regular file -- ignored \\n\",\n                        srcFileName);\n        return NULL;\n    }\n\n    {   FILE* const f = fopen(srcFileName, \"rb\");\n        if (f == NULL)\n            DISPLAYLEVEL(1, \"zstd: %s: %s \\n\", srcFileName, strerror(errno));\n        return f;\n    }\n}\n\n/** FIO_openDstFile() :\n *  condition : `dstFileName` must be non-NULL.\n * @result : FILE* to `dstFileName`, or NULL if it fails */\nstatic FILE*\nFIO_openDstFile(FIO_ctx_t* fCtx, FIO_prefs_t* const prefs,\n                const char* srcFileName, const char* dstFileName,\n                const int mode)\n{\n    if (prefs->testMode) return NULL;  /* do not open file in test mode */\n\n    assert(dstFileName != NULL);\n    if (!strcmp (dstFileName, stdoutmark)) {\n        DISPLAYLEVEL(4,\"Using stdout for output \\n\");\n        SET_BINARY_MODE(stdout);\n        if (prefs->sparseFileSupport == 1) {\n            prefs->sparseFileSupport = 0;\n            DISPLAYLEVEL(4, \"Sparse File Support is automatically disabled on stdout ; try --sparse \\n\");\n        }\n        return stdout;\n    }\n\n    /* ensure dst is not the same as src */\n    if (srcFileName != NULL && UTIL_isSameFile(srcFileName, dstFileName)) {\n        DISPLAYLEVEL(1, \"zstd: Refusing to open an output file which will overwrite the input file \\n\");\n        return NULL;\n    }\n\n    if (UTIL_isRegularFile(dstFileName)) {\n        /* Check if destination file already exists */\n#if !defined(_WIN32)\n        /* this test does not work on Windows :\n         * `NUL` and `nul` are detected as regular files */\n        if (!strcmp(dstFileName, nulmark)) {\n            EXM_THROW(40, \"%s is unexpectedly categorized as a regular file\",\n                        dstFileName);\n        }\n#endif\n        if (!prefs->overwrite) {\n            if (g_display_prefs.displayLevel <= 1) {\n                /* No interaction possible */\n                DISPLAYLEVEL(1, \"zstd: %s already exists; not overwritten  \\n\",\n                        dstFileName);\n                return NULL;\n            }\n            DISPLAY(\"zstd: %s already exists; \", dstFileName);\n            if (UTIL_requireUserConfirmation(\"overwrite (y/n) ? \", \"Not overwritten  \\n\", \"yY\", fCtx->hasStdinInput))\n                return NULL;\n        }\n        /* need to unlink */\n        FIO_removeFile(dstFileName);\n    }\n\n    {\n        int isDstRegFile;\n#if defined(_WIN32)\n        /* Windows requires opening the file as a \"binary\" file to avoid\n         * mangling. This macro doesn't exist on unix. */\n        const int openflags = O_WRONLY|O_CREAT|O_TRUNC|O_BINARY;\n        const int fd = _open(dstFileName, openflags, mode);\n        FILE* f = NULL;\n        if (fd != -1) {\n            f = _fdopen(fd, \"wb\");\n        }\n#else\n        const int openflags = O_WRONLY|O_CREAT|O_TRUNC;\n        const int fd = open(dstFileName, openflags, mode);\n        FILE* f = NULL;\n        if (fd != -1) {\n            f = fdopen(fd, \"wb\");\n        }\n#endif\n\n        /* Check regular file after opening with O_CREAT */\n        isDstRegFile = UTIL_isFdRegularFile(fd);\n        if (prefs->sparseFileSupport == 1) {\n            prefs->sparseFileSupport = ZSTD_SPARSE_DEFAULT;\n            if (!isDstRegFile) {\n                prefs->sparseFileSupport = 0;\n                DISPLAYLEVEL(4, \"Sparse File Support is disabled when output is not a file \\n\");\n            }\n        }\n\n        if (f == NULL) {\n            if (UTIL_isFileDescriptorPipe(dstFileName)) {\n                DISPLAYLEVEL(1, \"zstd: error: no output specified (use -o or -c). \\n\");\n            } else {\n                DISPLAYLEVEL(1, \"zstd: %s: %s\\n\", dstFileName, strerror(errno));\n            }\n        } else {\n            /* An increased buffer size can provide a significant performance\n             * boost on some platforms. Note that providing a NULL buf with a\n             * size that's not 0 is not defined in ANSI C, but is defined in an\n             * extension. There are three possibilities here:\n             * 1. Libc supports the extended version and everything is good.\n             * 2. Libc ignores the size when buf is NULL, in which case\n             *    everything will continue as if we didn't call `setvbuf()`.\n             * 3. We fail the call and execution continues but a warning\n             *    message might be shown.\n             * In all cases due execution continues. For now, I believe that\n             * this is a more cost-effective solution than managing the buffers\n             * allocations ourselves (will require an API change).\n             */\n            if (setvbuf(f, NULL, _IOFBF, 1 MB)) {\n                DISPLAYLEVEL(2, \"Warning: setvbuf failed for %s\\n\", dstFileName);\n            }\n        }\n        return f;\n    }\n}\n\n\n/* FIO_getDictFileStat() :\n */\nstatic void FIO_getDictFileStat(const char* fileName, stat_t* dictFileStat) {\n    assert(dictFileStat != NULL);\n    if (fileName == NULL) return;\n\n    if (!UTIL_stat(fileName, dictFileStat)) {\n        EXM_THROW(31, \"Stat failed on dictionary file %s: %s\", fileName, strerror(errno));\n    }\n\n    if (!UTIL_isRegularFileStat(dictFileStat)) {\n        EXM_THROW(32, \"Dictionary %s must be a regular file.\", fileName);\n    }\n}\n\n/*  FIO_setDictBufferMalloc() :\n *  allocates a buffer, pointed by `dict->dictBuffer`,\n *  loads `filename` content into it, up to DICTSIZE_MAX bytes.\n * @return : loaded size\n *  if fileName==NULL, returns 0 and a NULL pointer\n */\nstatic size_t FIO_setDictBufferMalloc(FIO_Dict_t* dict, const char* fileName, FIO_prefs_t* const prefs, stat_t* dictFileStat)\n{\n    FILE* fileHandle;\n    U64 fileSize;\n    void** bufferPtr = &dict->dictBuffer;\n\n    assert(bufferPtr != NULL);\n    assert(dictFileStat != NULL);\n    *bufferPtr = NULL;\n    if (fileName == NULL) return 0;\n\n    DISPLAYLEVEL(4,\"Loading %s as dictionary \\n\", fileName);\n\n    fileHandle = fopen(fileName, \"rb\");\n\n    if (fileHandle == NULL) {\n        EXM_THROW(33, \"Couldn't open dictionary %s: %s\", fileName, strerror(errno));\n    }\n\n    fileSize = UTIL_getFileSizeStat(dictFileStat);\n    {\n        size_t const dictSizeMax = prefs->patchFromMode ? prefs->memLimit : DICTSIZE_MAX;\n        if (fileSize >  dictSizeMax) {\n            EXM_THROW(34, \"Dictionary file %s is too large (> %u bytes)\",\n                            fileName,  (unsigned)dictSizeMax);   /* avoid extreme cases */\n        }\n    }\n    *bufferPtr = malloc((size_t)fileSize);\n    if (*bufferPtr==NULL) EXM_THROW(34, \"%s\", strerror(errno));\n    {   size_t const readSize = fread(*bufferPtr, 1, (size_t)fileSize, fileHandle);\n        if (readSize != fileSize) {\n            EXM_THROW(35, \"Error reading dictionary file %s : %s\",\n                    fileName, strerror(errno));\n        }\n    }\n    fclose(fileHandle);\n    return (size_t)fileSize;\n}\n\n#if (PLATFORM_POSIX_VERSION > 0)\n#include <sys/mman.h>\nstatic void FIO_munmap(FIO_Dict_t* dict)\n{\n    munmap(dict->dictBuffer, dict->dictBufferSize);\n    dict->dictBuffer = NULL;\n    dict->dictBufferSize = 0;\n}\nstatic size_t FIO_setDictBufferMMap(FIO_Dict_t* dict, const char* fileName, FIO_prefs_t* const prefs, stat_t* dictFileStat)\n{\n    int fileHandle;\n    U64 fileSize;\n    void** bufferPtr = &dict->dictBuffer;\n\n    assert(bufferPtr != NULL);\n    assert(dictFileStat != NULL);\n    *bufferPtr = NULL;\n    if (fileName == NULL) return 0;\n\n    DISPLAYLEVEL(4,\"Loading %s as dictionary \\n\", fileName);\n\n    fileHandle = open(fileName, O_RDONLY);\n\n    if (fileHandle == -1) {\n        EXM_THROW(33, \"Couldn't open dictionary %s: %s\", fileName, strerror(errno));\n    }\n\n    fileSize = UTIL_getFileSizeStat(dictFileStat);\n    {\n        size_t const dictSizeMax = prefs->patchFromMode ? prefs->memLimit : DICTSIZE_MAX;\n        if (fileSize >  dictSizeMax) {\n            EXM_THROW(34, \"Dictionary file %s is too large (> %u bytes)\",\n                            fileName,  (unsigned)dictSizeMax);   /* avoid extreme cases */\n        }\n    }\n\n    *bufferPtr = mmap(NULL, (size_t)fileSize, PROT_READ, MAP_PRIVATE, fileHandle, 0);\n    if (*bufferPtr == MAP_FAILED) {\n      EXM_THROW(34, \"%s\", strerror(errno))\n    }\n\n    close(fileHandle);\n    return (size_t)fileSize;\n}\n#elif defined(_MSC_VER) || defined(_WIN32)\n#include <windows.h>\nstatic void FIO_munmap(FIO_Dict_t* dict)\n{\n    UnmapViewOfFile(dict->dictBuffer);\n    CloseHandle(dict->dictHandle);\n    dict->dictBuffer = NULL;\n    dict->dictBufferSize = 0;\n}\nstatic size_t FIO_setDictBufferMMap(FIO_Dict_t* dict, const char* fileName, FIO_prefs_t* const prefs, stat_t* dictFileStat)\n{\n    HANDLE fileHandle, mapping;\n    U64 fileSize;\n    void** bufferPtr = &dict->dictBuffer;\n\n    assert(bufferPtr != NULL);\n    assert(dictFileStat != NULL);\n    *bufferPtr = NULL;\n    if (fileName == NULL) return 0;\n\n    DISPLAYLEVEL(4,\"Loading %s as dictionary \\n\", fileName);\n\n    fileHandle = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);\n\n    if (fileHandle == INVALID_HANDLE_VALUE) {\n        EXM_THROW(33, \"Couldn't open dictionary %s: %s\", fileName, strerror(errno));\n    }\n\n    fileSize = UTIL_getFileSizeStat(dictFileStat);\n    {\n        size_t const dictSizeMax = prefs->patchFromMode ? prefs->memLimit : DICTSIZE_MAX;\n        if (fileSize >  dictSizeMax) {\n            EXM_THROW(34, \"Dictionary file %s is too large (> %u bytes)\",\n                            fileName,  (unsigned)dictSizeMax);   /* avoid extreme cases */\n        }\n    }\n\n    mapping = CreateFileMapping(fileHandle, NULL, PAGE_READONLY, 0, 0, NULL);\n\tif (mapping == NULL) {\n        EXM_THROW(35, \"Couldn't map dictionary %s: %s\", fileName, strerror(errno));\n    }\n\n\t*bufferPtr = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, (DWORD)fileSize); /* we can only cast to DWORD here because dictSize <= 2GB */\n\tif (*bufferPtr==NULL) EXM_THROW(36, \"%s\", strerror(errno));\n\n    dict->dictHandle = fileHandle;\n    return (size_t)fileSize;\n}\n#else\nstatic size_t FIO_setDictBufferMMap(FIO_Dict_t* dict, const char* fileName, FIO_prefs_t* const prefs, stat_t* dictFileStat)\n{\n   return FIO_setDictBufferMalloc(dict, fileName, prefs, dictFileStat);\n}\nstatic void FIO_munmap(FIO_Dict_t* dict) {\n   free(dict->dictBuffer);\n   dict->dictBuffer = NULL;\n   dict->dictBufferSize = 0;\n}\n#endif\n\nstatic void FIO_freeDict(FIO_Dict_t* dict) {\n    if (dict->dictBufferType == FIO_mallocDict) {\n        free(dict->dictBuffer);\n        dict->dictBuffer = NULL;\n        dict->dictBufferSize = 0;\n    } else if (dict->dictBufferType == FIO_mmapDict)  {\n        FIO_munmap(dict);\n    } else {\n        assert(0); /* Should not reach this case */\n    }\n}\n\nstatic void FIO_initDict(FIO_Dict_t* dict, const char* fileName, FIO_prefs_t* const prefs, stat_t* dictFileStat, FIO_dictBufferType_t dictBufferType) {\n    dict->dictBufferType = dictBufferType;\n    if (dict->dictBufferType == FIO_mallocDict) {\n        dict->dictBufferSize = FIO_setDictBufferMalloc(dict, fileName, prefs, dictFileStat);\n    } else if (dict->dictBufferType == FIO_mmapDict)  {\n        dict->dictBufferSize = FIO_setDictBufferMMap(dict, fileName, prefs, dictFileStat);\n    } else {\n        assert(0); /* Should not reach this case */\n    }\n}\n\n\n/* FIO_checkFilenameCollisions() :\n * Checks for and warns if there are any files that would have the same output path\n */\nint FIO_checkFilenameCollisions(const char** filenameTable, unsigned nbFiles) {\n    const char **filenameTableSorted, *prevElem, *filename;\n    unsigned u;\n\n    filenameTableSorted = (const char**) malloc(sizeof(char*) * nbFiles);\n    if (!filenameTableSorted) {\n        DISPLAYLEVEL(1, \"Allocation error during filename collision checking \\n\");\n        return 1;\n    }\n\n    for (u = 0; u < nbFiles; ++u) {\n        filename = strrchr(filenameTable[u], PATH_SEP);\n        if (filename == NULL) {\n            filenameTableSorted[u] = filenameTable[u];\n        } else {\n            filenameTableSorted[u] = filename+1;\n        }\n    }\n\n    qsort((void*)filenameTableSorted, nbFiles, sizeof(char*), UTIL_compareStr);\n    prevElem = filenameTableSorted[0];\n    for (u = 1; u < nbFiles; ++u) {\n        if (strcmp(prevElem, filenameTableSorted[u]) == 0) {\n            DISPLAYLEVEL(2, \"WARNING: Two files have same filename: %s\\n\", prevElem);\n        }\n        prevElem = filenameTableSorted[u];\n    }\n\n    free((void*)filenameTableSorted);\n    return 0;\n}\n\nstatic const char*\nextractFilename(const char* path, char separator)\n{\n    const char* search = strrchr(path, separator);\n    if (search == NULL) return path;\n    return search+1;\n}\n\n/* FIO_createFilename_fromOutDir() :\n * Takes a source file name and specified output directory, and\n * allocates memory for and returns a pointer to final path.\n * This function never returns an error (it may abort() in case of pb)\n */\nstatic char*\nFIO_createFilename_fromOutDir(const char* path, const char* outDirName, const size_t suffixLen)\n{\n    const char* filenameStart;\n    char separator;\n    char* result;\n\n#if defined(_MSC_VER) || defined(__MINGW32__) || defined (__MSVCRT__) /* windows support */\n    separator = '\\\\';\n#else\n    separator = '/';\n#endif\n\n    filenameStart = extractFilename(path, separator);\n#if defined(_MSC_VER) || defined(__MINGW32__) || defined (__MSVCRT__) /* windows support */\n    filenameStart = extractFilename(filenameStart, '/');  /* sometimes, '/' separator is also used on Windows (mingw+msys2) */\n#endif\n\n    result = (char*) calloc(1, strlen(outDirName) + 1 + strlen(filenameStart) + suffixLen + 1);\n    if (!result) {\n        EXM_THROW(30, \"zstd: FIO_createFilename_fromOutDir: %s\", strerror(errno));\n    }\n\n    memcpy(result, outDirName, strlen(outDirName));\n    if (outDirName[strlen(outDirName)-1] == separator) {\n        memcpy(result + strlen(outDirName), filenameStart, strlen(filenameStart));\n    } else {\n        memcpy(result + strlen(outDirName), &separator, 1);\n        memcpy(result + strlen(outDirName) + 1, filenameStart, strlen(filenameStart));\n    }\n\n    return result;\n}\n\n/* FIO_highbit64() :\n * gives position of highest bit.\n * note : only works for v > 0 !\n */\nstatic unsigned FIO_highbit64(unsigned long long v)\n{\n    unsigned count = 0;\n    assert(v != 0);\n    v >>= 1;\n    while (v) { v >>= 1; count++; }\n    return count;\n}\n\nstatic void FIO_adjustMemLimitForPatchFromMode(FIO_prefs_t* const prefs,\n                                    unsigned long long const dictSize,\n                                    unsigned long long const maxSrcFileSize)\n{\n    unsigned long long maxSize = MAX(prefs->memLimit, MAX(dictSize, maxSrcFileSize));\n    unsigned const maxWindowSize = (1U << ZSTD_WINDOWLOG_MAX);\n    if (maxSize == UTIL_FILESIZE_UNKNOWN)\n        EXM_THROW(42, \"Using --patch-from with stdin requires --stream-size\");\n    assert(maxSize != UTIL_FILESIZE_UNKNOWN);\n    if (maxSize > maxWindowSize)\n        EXM_THROW(42, \"Can't handle files larger than %u GB\\n\", maxWindowSize/(1 GB));\n    FIO_setMemLimit(prefs, (unsigned)maxSize);\n}\n\n/* FIO_multiFilesConcatWarning() :\n * This function handles logic when processing multiple files with -o or -c, displaying the appropriate warnings/prompts.\n * Returns 1 if the console should abort, 0 if console should proceed.\n *\n * If output is stdout or test mode is active, check that `--rm` disabled.\n *\n * If there is just 1 file to process, zstd will proceed as usual.\n * If each file get processed into its own separate destination file, proceed as usual.\n *\n * When multiple files are processed into a single output,\n * display a warning message, then disable --rm if it's set.\n *\n * If -f is specified or if output is stdout, just proceed.\n * If output is set with -o, prompt for confirmation.\n */\nstatic int FIO_multiFilesConcatWarning(const FIO_ctx_t* fCtx, FIO_prefs_t* prefs, const char* outFileName, int displayLevelCutoff)\n{\n    if (fCtx->hasStdoutOutput) {\n        if (prefs->removeSrcFile)\n            /* this should not happen ; hard fail, to protect user's data\n             * note: this should rather be an assert(), but we want to be certain that user's data will not be wiped out in case it nonetheless happen */\n            EXM_THROW(43, \"It's not allowed to remove input files when processed output is piped to stdout. \"\n                \"This scenario is not supposed to be possible. \"\n                \"This is a programming error. File an issue for it to be fixed.\");\n    }\n    if (prefs->testMode) {\n        if (prefs->removeSrcFile)\n            /* this should not happen ; hard fail, to protect user's data\n             * note: this should rather be an assert(), but we want to be certain that user's data will not be wiped out in case it nonetheless happen */\n            EXM_THROW(43, \"Test mode shall not remove input files! \"\n                 \"This scenario is not supposed to be possible. \"\n                 \"This is a programming error. File an issue for it to be fixed.\");\n        return 0;\n    }\n\n    if (fCtx->nbFilesTotal == 1) return 0;\n    assert(fCtx->nbFilesTotal > 1);\n\n    if (!outFileName) return 0;\n\n    if (fCtx->hasStdoutOutput) {\n        DISPLAYLEVEL(2, \"zstd: WARNING: all input files will be processed and concatenated into stdout. \\n\");\n    } else {\n        DISPLAYLEVEL(2, \"zstd: WARNING: all input files will be processed and concatenated into a single output file: %s \\n\", outFileName);\n    }\n    DISPLAYLEVEL(2, \"The concatenated output CANNOT regenerate original file names nor directory structure. \\n\")\n\n    /* multi-input into single output : --rm is not allowed */\n    if (prefs->removeSrcFile) {\n        DISPLAYLEVEL(2, \"Since it's a destructive operation, input files will not be removed. \\n\");\n        prefs->removeSrcFile = 0;\n    }\n\n    if (fCtx->hasStdoutOutput) return 0;\n    if (prefs->overwrite) return 0;\n\n    /* multiple files concatenated into single destination file using -o without -f */\n    if (g_display_prefs.displayLevel <= displayLevelCutoff) {\n        /* quiet mode => no prompt => fail automatically */\n        DISPLAYLEVEL(1, \"Concatenating multiple processed inputs into a single output loses file metadata. \\n\");\n        DISPLAYLEVEL(1, \"Aborting. \\n\");\n        return 1;\n    }\n    /* normal mode => prompt */\n    return UTIL_requireUserConfirmation(\"Proceed? (y/n): \", \"Aborting...\", \"yY\", fCtx->hasStdinInput);\n}\n\nstatic ZSTD_inBuffer setInBuffer(const void* buf, size_t s, size_t pos)\n{\n    ZSTD_inBuffer i;\n    i.src = buf;\n    i.size = s;\n    i.pos = pos;\n    return i;\n}\n\nstatic ZSTD_outBuffer setOutBuffer(void* buf, size_t s, size_t pos)\n{\n    ZSTD_outBuffer o;\n    o.dst = buf;\n    o.size = s;\n    o.pos = pos;\n    return o;\n}\n\n#ifndef ZSTD_NOCOMPRESS\n\n/* **********************************************************************\n *  Compression\n ************************************************************************/\ntypedef struct {\n    FIO_Dict_t dict;\n    const char* dictFileName;\n    stat_t dictFileStat;\n    ZSTD_CStream* cctx;\n    FIO_SyncCompressIO io;\n} cRess_t;\n\n/** ZSTD_cycleLog() :\n *  condition for correct operation : hashLog > 1 */\nstatic U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)\n{\n    U32 const btScale = ((U32)strat >= (U32)ZSTD_btlazy2);\n    assert(hashLog > 1);\n    return hashLog - btScale;\n}\n\nstatic void FIO_adjustParamsForPatchFromMode(FIO_prefs_t* const prefs,\n                                    ZSTD_compressionParameters* comprParams,\n                                    unsigned long long const dictSize,\n                                    unsigned long long const maxSrcFileSize,\n                                    int cLevel)\n{\n    unsigned const fileWindowLog = FIO_highbit64(maxSrcFileSize) + 1;\n    ZSTD_compressionParameters const cParams = ZSTD_getCParams(cLevel, (size_t)maxSrcFileSize, (size_t)dictSize);\n    FIO_adjustMemLimitForPatchFromMode(prefs, dictSize, maxSrcFileSize);\n    if (fileWindowLog > ZSTD_WINDOWLOG_MAX)\n        DISPLAYLEVEL(1, \"Max window log exceeded by file (compression ratio will suffer)\\n\");\n    comprParams->windowLog = MAX(ZSTD_WINDOWLOG_MIN, MIN(ZSTD_WINDOWLOG_MAX, fileWindowLog));\n    if (fileWindowLog > ZSTD_cycleLog(cParams.chainLog, cParams.strategy)) {\n        if (!prefs->ldmFlag)\n            DISPLAYLEVEL(2, \"long mode automatically triggered\\n\");\n        FIO_setLdmFlag(prefs, 1);\n    }\n    if (cParams.strategy >= ZSTD_btopt) {\n        DISPLAYLEVEL(4, \"[Optimal parser notes] Consider the following to improve patch size at the cost of speed:\\n\");\n        DISPLAYLEVEL(4, \"- Set a larger targetLength (e.g. --zstd=targetLength=4096)\\n\");\n        DISPLAYLEVEL(4, \"- Set a larger chainLog (e.g. --zstd=chainLog=%u)\\n\", ZSTD_CHAINLOG_MAX);\n        DISPLAYLEVEL(4, \"- Set a larger LDM hashLog (e.g. --zstd=ldmHashLog=%u)\\n\", ZSTD_LDM_HASHLOG_MAX);\n        DISPLAYLEVEL(4, \"- Set a smaller LDM rateLog (e.g. --zstd=ldmHashRateLog=%u)\\n\", ZSTD_LDM_HASHRATELOG_MIN);\n        DISPLAYLEVEL(4, \"Also consider playing around with searchLog and hashLog\\n\");\n    }\n}\n\nstatic cRess_t FIO_createCResources(FIO_prefs_t* const prefs,\n                                    const char* dictFileName, unsigned long long const maxSrcFileSize,\n                                    int cLevel, ZSTD_compressionParameters comprParams) {\n    int useMMap = prefs->mmapDict == ZSTD_ps_enable;\n    int forceNoUseMMap = prefs->mmapDict == ZSTD_ps_disable;\n    FIO_dictBufferType_t dictBufferType;\n    cRess_t ress;\n    memset(&ress, 0, sizeof(ress));\n\n    DISPLAYLEVEL(6, \"FIO_createCResources \\n\");\n    ress.cctx = ZSTD_createCCtx();\n    if (ress.cctx == NULL)\n        EXM_THROW(30, \"allocation error (%s): can't create ZSTD_CCtx\",\n                    strerror(errno));\n\n    FIO_getDictFileStat(dictFileName, &ress.dictFileStat);\n\n    /* need to update memLimit before calling createDictBuffer\n     * because of memLimit check inside it */\n    if (prefs->patchFromMode) {\n        U64 const dictSize = UTIL_getFileSizeStat(&ress.dictFileStat);\n        unsigned long long const ssSize = (unsigned long long)prefs->streamSrcSize;\n        useMMap |= dictSize > prefs->memLimit;\n        FIO_adjustParamsForPatchFromMode(prefs, &comprParams, dictSize, ssSize > 0 ? ssSize : maxSrcFileSize, cLevel);\n    }\n\n    dictBufferType = (useMMap && !forceNoUseMMap) ? FIO_mmapDict : FIO_mallocDict;\n    FIO_initDict(&ress.dict, dictFileName, prefs, &ress.dictFileStat, dictBufferType);   /* works with dictFileName==NULL */\n\n    FIO_SyncCompressIO_init(&ress.io, prefs, ZSTD_CStreamInSize(), ZSTD_CStreamOutSize());\n\n    /* Advanced parameters, including dictionary */\n    if (dictFileName && (ress.dict.dictBuffer==NULL))\n        EXM_THROW(32, \"allocation error : can't create dictBuffer\");\n    ress.dictFileName = dictFileName;\n\n    if (prefs->adaptiveMode && !prefs->ldmFlag && !comprParams.windowLog)\n        comprParams.windowLog = ADAPT_WINDOWLOG_DEFAULT;\n\n    CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_contentSizeFlag, prefs->contentSize) );  /* always enable content size when available (note: supposed to be default) */\n    CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_dictIDFlag, prefs->dictIDFlag) );\n    CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_checksumFlag, prefs->checksumFlag) );\n    /* compression level */\n    CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_compressionLevel, cLevel) );\n    /* max compressed block size */\n    CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_targetCBlockSize, (int)prefs->targetCBlockSize) );\n    /* source size hint */\n    CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_srcSizeHint, (int)prefs->srcSizeHint) );\n    /* long distance matching */\n    CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_enableLongDistanceMatching, prefs->ldmFlag) );\n    CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmHashLog, prefs->ldmHashLog) );\n    CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmMinMatch, prefs->ldmMinMatch) );\n    if (prefs->ldmBucketSizeLog != FIO_LDM_PARAM_NOTSET) {\n        CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmBucketSizeLog, prefs->ldmBucketSizeLog) );\n    }\n    if (prefs->ldmHashRateLog != FIO_LDM_PARAM_NOTSET) {\n        CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmHashRateLog, prefs->ldmHashRateLog) );\n    }\n    CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_useRowMatchFinder, prefs->useRowMatchFinder));\n    /* compression parameters */\n    CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_windowLog, (int)comprParams.windowLog) );\n    CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_chainLog, (int)comprParams.chainLog) );\n    CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_hashLog, (int)comprParams.hashLog) );\n    CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_searchLog, (int)comprParams.searchLog) );\n    CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_minMatch, (int)comprParams.minMatch) );\n    CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_targetLength, (int)comprParams.targetLength) );\n    CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_strategy, (int)comprParams.strategy) );\n    CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_literalCompressionMode, (int)prefs->literalCompressionMode) );\n    CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_enableDedicatedDictSearch, 1) );\n    /* multi-threading */\n#ifdef ZSTD_MULTITHREAD\n    DISPLAYLEVEL(5,\"set nb workers = %u \\n\", prefs->nbWorkers);\n    CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_nbWorkers, prefs->nbWorkers) );\n    CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_jobSize, prefs->jobSize) );\n    if (prefs->overlapLog != FIO_OVERLAP_LOG_NOTSET) {\n        DISPLAYLEVEL(3,\"set overlapLog = %u \\n\", prefs->overlapLog);\n        CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_overlapLog, prefs->overlapLog) );\n    }\n    CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_rsyncable, prefs->rsyncable) );\n#endif\n    /* dictionary */\n    if (prefs->patchFromMode) {\n        CHECK( ZSTD_CCtx_refPrefix(ress.cctx, ress.dict.dictBuffer, ress.dict.dictBufferSize) );\n    } else {\n        CHECK( ZSTD_CCtx_loadDictionary_byReference(ress.cctx, ress.dict.dictBuffer, ress.dict.dictBufferSize) );\n    }\n\n    return ress;\n}\n\nstatic void FIO_freeCResources(cRess_t* const ress)\n{\n    FIO_freeDict(&(ress->dict));\n    FIO_SyncCompressIO_destroy(&ress->io);\n    ZSTD_freeCStream(ress->cctx);   /* never fails */\n}\n\n\n#ifdef ZSTD_GZCOMPRESS\nstatic unsigned long long\nFIO_compressGzFrame(cRess_t* ress,\n                    const char* srcFileName, U64 const srcFileSize,\n                    int compressionLevel, U64* readsize)\n{\n    FIO_SyncCompressIO* const syncIO = &ress->io;\n    unsigned long long inFileSize = 0, outFileSize = 0;\n    z_stream strm;\n\n    if (compressionLevel > Z_BEST_COMPRESSION)\n        compressionLevel = Z_BEST_COMPRESSION;\n\n    strm.zalloc = Z_NULL;\n    strm.zfree = Z_NULL;\n    strm.opaque = Z_NULL;\n\n    {   int const ret = deflateInit2(&strm, compressionLevel, Z_DEFLATED,\n                        15 /* maxWindowLogSize */ + 16 /* gzip only */,\n                        8, Z_DEFAULT_STRATEGY); /* see https://www.zlib.net/manual.html */\n        if (ret != Z_OK) {\n            EXM_THROW(71, \"zstd: %s: deflateInit2 error %d \\n\", srcFileName, ret);\n    }   }\n\n    strm.next_in = 0;\n    strm.avail_in = 0;\n    strm.next_out = (Bytef*)syncIO->outBuffer;\n    strm.avail_out = (uInt)syncIO->outCapacity;\n\n    while (1) {\n        int ret;\n        if (strm.avail_in == 0) {\n            size_t const added = FIO_SyncCompressIO_fillBuffer(syncIO, ZSTD_CStreamInSize());\n            if (syncIO->srcBufferLoaded == 0) break;\n            inFileSize += added;\n            *readsize += added;\n            strm.next_in = (z_const unsigned char*)syncIO->srcBuffer;\n            strm.avail_in = (uInt)syncIO->srcBufferLoaded;\n        }\n\n        {\n            size_t const availBefore = strm.avail_in;\n            ret = deflate(&strm, Z_NO_FLUSH);\n            FIO_SyncCompressIO_consumeBytes(syncIO, availBefore - strm.avail_in);\n        }\n\n        if (ret != Z_OK)\n            EXM_THROW(72, \"zstd: %s: deflate error %d \\n\", srcFileName, ret);\n        {   size_t const cSize = (size_t)((uInt)syncIO->outCapacity - strm.avail_out);\n            if (cSize) {\n                FIO_SyncCompressIO_commitOut(syncIO, syncIO->outBuffer, cSize);\n                outFileSize += cSize;\n                strm.next_out = (Bytef*)syncIO->outBuffer;\n                strm.avail_out = (uInt)syncIO->outCapacity;\n            }   }\n        if (srcFileSize == UTIL_FILESIZE_UNKNOWN) {\n            DISPLAYUPDATE_PROGRESS(\n                    \"\\rRead : %u MB ==> %.2f%% \",\n                    (unsigned)(inFileSize>>20),\n                    (double)outFileSize/(double)inFileSize*100)\n        } else {\n            DISPLAYUPDATE_PROGRESS(\n                    \"\\rRead : %u / %u MB ==> %.2f%% \",\n                    (unsigned)(inFileSize>>20), (unsigned)(srcFileSize>>20),\n                    (double)outFileSize/(double)inFileSize*100);\n    }   }\n\n    while (1) {\n        int const ret = deflate(&strm, Z_FINISH);\n        {   size_t const cSize = (size_t)((uInt)syncIO->outCapacity - strm.avail_out);\n            if (cSize) {\n                FIO_SyncCompressIO_commitOut(syncIO, syncIO->outBuffer, cSize);\n                outFileSize += cSize;\n                strm.next_out = (Bytef*)syncIO->outBuffer;\n                strm.avail_out = (uInt)syncIO->outCapacity;\n            }   }\n        if (ret == Z_STREAM_END) break;\n        if (ret != Z_BUF_ERROR)\n            EXM_THROW(77, \"zstd: %s: deflate error %d \\n\", srcFileName, ret);\n    }\n\n    {   int const ret = deflateEnd(&strm);\n        if (ret != Z_OK) {\n            EXM_THROW(79, \"zstd: %s: deflateEnd error %d \\n\", srcFileName, ret);\n    }   }\n    *readsize = inFileSize;\n    FIO_SyncCompressIO_finish(syncIO);\n    return outFileSize;\n}\n#endif\n\n\n#ifdef ZSTD_LZMACOMPRESS\nstatic unsigned long long\nFIO_compressLzmaFrame(cRess_t* ress,\n                      const char* srcFileName, U64 const srcFileSize,\n                      int compressionLevel, U64* readsize, int plain_lzma)\n{\n    FIO_SyncCompressIO* const syncIO = &ress->io;\n    unsigned long long inFileSize = 0, outFileSize = 0;\n    lzma_stream strm = LZMA_STREAM_INIT;\n    lzma_action action = LZMA_RUN;\n    lzma_ret ret;\n\n    if (compressionLevel < 0) compressionLevel = 0;\n    if (compressionLevel > 9) compressionLevel = 9;\n\n    if (plain_lzma) {\n        lzma_options_lzma opt_lzma;\n        if (lzma_lzma_preset(&opt_lzma, compressionLevel))\n            EXM_THROW(81, \"zstd: %s: lzma_lzma_preset error\", srcFileName);\n        ret = lzma_alone_encoder(&strm, &opt_lzma); /* LZMA */\n        if (ret != LZMA_OK)\n            EXM_THROW(82, \"zstd: %s: lzma_alone_encoder error %d\", srcFileName, ret);\n    } else {\n        ret = lzma_easy_encoder(&strm, compressionLevel, LZMA_CHECK_CRC64); /* XZ */\n        if (ret != LZMA_OK)\n            EXM_THROW(83, \"zstd: %s: lzma_easy_encoder error %d\", srcFileName, ret);\n    }\n\n    strm.next_out = (BYTE*)syncIO->outBuffer;\n    strm.avail_out = syncIO->outCapacity;\n    strm.next_in = 0;\n    strm.avail_in = 0;\n\n    while (1) {\n        if (strm.avail_in == 0) {\n            size_t const added = FIO_SyncCompressIO_fillBuffer(syncIO, ZSTD_CStreamInSize());\n            if (syncIO->srcBufferLoaded == 0) action = LZMA_FINISH;\n            inFileSize += added;\n            *readsize += added;\n            strm.next_in = (BYTE const*)syncIO->srcBuffer;\n            strm.avail_in = syncIO->srcBufferLoaded;\n        }\n\n        {\n            size_t const availBefore = strm.avail_in;\n            ret = lzma_code(&strm, action);\n            FIO_SyncCompressIO_consumeBytes(syncIO, availBefore - strm.avail_in);\n        }\n\n        if (ret != LZMA_OK && ret != LZMA_STREAM_END)\n            EXM_THROW(84, \"zstd: %s: lzma_code encoding error %d\", srcFileName, ret);\n        {   size_t const compBytes = syncIO->outCapacity - strm.avail_out;\n            if (compBytes) {\n                FIO_SyncCompressIO_commitOut(syncIO, syncIO->outBuffer, compBytes);\n                outFileSize += compBytes;\n                strm.next_out = (BYTE*)syncIO->outBuffer;\n                strm.avail_out = syncIO->outCapacity;\n        }   }\n        if (srcFileSize == UTIL_FILESIZE_UNKNOWN)\n            DISPLAYUPDATE_PROGRESS(\"\\rRead : %u MB ==> %.2f%%\",\n                            (unsigned)(inFileSize>>20),\n                            (double)outFileSize/(double)inFileSize*100)\n        else\n            DISPLAYUPDATE_PROGRESS(\"\\rRead : %u / %u MB ==> %.2f%%\",\n                            (unsigned)(inFileSize>>20), (unsigned)(srcFileSize>>20),\n                            (double)outFileSize/(double)inFileSize*100);\n        if (ret == LZMA_STREAM_END) break;\n    }\n\n    lzma_end(&strm);\n    *readsize = inFileSize;\n\n    FIO_SyncCompressIO_finish(syncIO);\n\n    return outFileSize;\n}\n#endif\n\n#ifdef ZSTD_LZ4COMPRESS\n\n#if LZ4_VERSION_NUMBER <= 10600\n#define LZ4F_blockLinked blockLinked\n#define LZ4F_max64KB max64KB\n#endif\n\nstatic int FIO_LZ4_GetBlockSize_FromBlockId (int id) { return (1 << (8 + (2 * id))); }\n\nstatic unsigned long long\nFIO_compressLz4Frame(cRess_t* ress,\n                     const char* srcFileName, U64 const srcFileSize,\n                     int compressionLevel, int checksumFlag,\n                     U64* readsize)\n{\n    FIO_SyncCompressIO* const syncIO = &ress->io;\n    const size_t blockSize = FIO_LZ4_GetBlockSize_FromBlockId(LZ4F_max64KB);\n    unsigned long long inFileSize = 0, outFileSize = 0;\n\n    LZ4F_preferences_t prefs;\n    LZ4F_compressionContext_t ctx;\n\n    LZ4F_errorCode_t const errorCode = LZ4F_createCompressionContext(&ctx, LZ4F_VERSION);\n    if (LZ4F_isError(errorCode))\n        EXM_THROW(31, \"zstd: failed to create lz4 compression context\");\n\n    memset(&prefs, 0, sizeof(prefs));\n\n    assert(blockSize <= syncIO->inCapacity);\n\n    /* autoflush off to mitigate a bug in lz4<=1.9.3 for compression level 12 */\n    prefs.autoFlush = 0;\n    prefs.compressionLevel = compressionLevel;\n    prefs.frameInfo.blockMode = LZ4F_blockLinked;\n    prefs.frameInfo.blockSizeID = LZ4F_max64KB;\n    prefs.frameInfo.contentChecksumFlag = (contentChecksum_t)checksumFlag;\n#if LZ4_VERSION_NUMBER >= 10600\n    prefs.frameInfo.contentSize = (srcFileSize==UTIL_FILESIZE_UNKNOWN) ? 0 : srcFileSize;\n#endif\n    assert(LZ4F_compressBound(blockSize, &prefs) <= syncIO->outCapacity);\n\n    {\n        size_t headerSize = LZ4F_compressBegin(ctx, syncIO->outBuffer, syncIO->outCapacity, &prefs);\n        if (LZ4F_isError(headerSize))\n            EXM_THROW(33, \"File header generation failed : %s\",\n                            LZ4F_getErrorName(headerSize));\n        FIO_SyncCompressIO_commitOut(syncIO, syncIO->outBuffer, headerSize);\n        outFileSize += headerSize;\n\n        {\n            size_t const added = FIO_SyncCompressIO_fillBuffer(syncIO, blockSize);\n            inFileSize += added;\n            *readsize += added;\n        }\n\n        while (syncIO->srcBufferLoaded) {\n            size_t const inSize = MIN(blockSize, syncIO->srcBufferLoaded);\n            size_t const outSize = LZ4F_compressUpdate(ctx, syncIO->outBuffer, syncIO->outCapacity,\n                                                       syncIO->srcBuffer, inSize, NULL);\n            if (LZ4F_isError(outSize))\n                EXM_THROW(35, \"zstd: %s: lz4 compression failed : %s\",\n                            srcFileName, LZ4F_getErrorName(outSize));\n            outFileSize += outSize;\n            if (srcFileSize == UTIL_FILESIZE_UNKNOWN) {\n                DISPLAYUPDATE_PROGRESS(\"\\rRead : %u MB ==> %.2f%%\",\n                                (unsigned)(inFileSize>>20),\n                                (double)outFileSize/(double)inFileSize*100)\n            } else {\n                DISPLAYUPDATE_PROGRESS(\"\\rRead : %u / %u MB ==> %.2f%%\",\n                                (unsigned)(inFileSize>>20), (unsigned)(srcFileSize>>20),\n                                (double)outFileSize/(double)inFileSize*100);\n            }\n\n            FIO_SyncCompressIO_commitOut(syncIO, syncIO->outBuffer, outSize);\n\n            FIO_SyncCompressIO_consumeBytes(syncIO, inSize);\n            {\n                size_t const added = FIO_SyncCompressIO_fillBuffer(syncIO, blockSize);\n                inFileSize += added;\n                *readsize += added;\n            }\n        }\n\n        headerSize = LZ4F_compressEnd(ctx, syncIO->outBuffer, syncIO->outCapacity, NULL);\n        if (LZ4F_isError(headerSize))\n            EXM_THROW(38, \"zstd: %s: lz4 end of file generation failed : %s\",\n                        srcFileName, LZ4F_getErrorName(headerSize));\n\n        FIO_SyncCompressIO_commitOut(syncIO, syncIO->outBuffer, headerSize);\n        outFileSize += headerSize;\n    }\n\n    LZ4F_freeCompressionContext(ctx);\n    FIO_SyncCompressIO_finish(syncIO);\n\n    return outFileSize;\n}\n#endif\n\nstatic unsigned long long\nFIO_compressZstdFrame(FIO_ctx_t* const fCtx,\n                      FIO_prefs_t* const prefs,\n                      cRess_t* ress,\n                      const char* srcFileName, U64 fileSize,\n                      int compressionLevel, U64* readsize)\n{\n    FIO_SyncCompressIO* const syncIO = &ress->io;\n\n    U64 compressedfilesize = 0;\n    ZSTD_EndDirective directive = ZSTD_e_continue;\n    U64 pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;\n\n    /* stats */\n    ZSTD_frameProgression previous_zfp_update = { 0, 0, 0, 0, 0, 0 };\n    ZSTD_frameProgression previous_zfp_correction = { 0, 0, 0, 0, 0, 0 };\n    typedef enum { noChange, slower, faster } speedChange_e;\n    speedChange_e speedChange = noChange;\n    unsigned flushWaiting = 0;\n    unsigned inputPresented = 0;\n    unsigned inputBlocked = 0;\n    unsigned lastJobID = 0;\n    UTIL_time_t lastAdaptTime = UTIL_getTime();\n    U64 const adaptEveryMicro = REFRESH_RATE;\n\n    UTIL_HumanReadableSize_t const file_hrs = UTIL_makeHumanReadableSize(fileSize);\n\n    DISPLAYLEVEL(6, \"compression using zstd format \\n\");\n\n    /* init */\n    if (fileSize != UTIL_FILESIZE_UNKNOWN) {\n        pledgedSrcSize = fileSize;\n        CHECK(ZSTD_CCtx_setPledgedSrcSize(ress->cctx, fileSize));\n    } else if (prefs->streamSrcSize > 0) {\n      /* unknown source size; use the declared stream size */\n      pledgedSrcSize = prefs->streamSrcSize;\n      CHECK( ZSTD_CCtx_setPledgedSrcSize(ress->cctx, prefs->streamSrcSize) );\n    }\n\n    {   int windowLog;\n        UTIL_HumanReadableSize_t windowSize;\n        CHECK(ZSTD_CCtx_getParameter(ress->cctx, ZSTD_c_windowLog, &windowLog));\n        if (windowLog == 0) {\n            if (prefs->ldmFlag) {\n                /* If long mode is set without a window size libzstd will set this size internally */\n                windowLog = ZSTD_WINDOWLOG_LIMIT_DEFAULT;\n            } else {\n                const ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, fileSize, 0);\n                windowLog = (int)cParams.windowLog;\n            }\n        }\n        windowSize = UTIL_makeHumanReadableSize(MAX(1ULL, MIN(1ULL << windowLog, pledgedSrcSize)));\n        DISPLAYLEVEL(4, \"Decompression will require %.*f%s of memory\\n\", windowSize.precision, windowSize.value, windowSize.suffix);\n    }\n\n    /* Main compression loop */\n    do {\n        size_t stillToFlush;\n        /* Fill input Buffer */\n        size_t const inSize = FIO_SyncCompressIO_fillBuffer(syncIO, ZSTD_CStreamInSize());\n        ZSTD_inBuffer inBuff = setInBuffer( syncIO->srcBuffer, syncIO->srcBufferLoaded, 0 );\n        DISPLAYLEVEL(6, \"fread %u bytes from source \\n\", (unsigned)inSize);\n        *readsize += inSize;\n\n        if ((syncIO->srcBufferLoaded == 0) || (*readsize == fileSize))\n            directive = ZSTD_e_end;\n\n        stillToFlush = 1;\n        while ((inBuff.pos != inBuff.size)   /* input buffer must be entirely ingested */\n            || (directive == ZSTD_e_end && stillToFlush != 0) ) {\n\n            size_t const oldIPos = inBuff.pos;\n            ZSTD_outBuffer outBuff = setOutBuffer( syncIO->outBuffer, syncIO->outCapacity, 0 );\n            size_t const toFlushNow = ZSTD_toFlushNow(ress->cctx);\n            CHECK_V(stillToFlush, ZSTD_compressStream2(ress->cctx, &outBuff, &inBuff, directive));\n            FIO_SyncCompressIO_consumeBytes(syncIO, inBuff.pos - oldIPos);\n\n            /* count stats */\n            inputPresented++;\n            if (oldIPos == inBuff.pos) inputBlocked++;  /* input buffer is full and can't take any more : input speed is faster than consumption rate */\n            if (!toFlushNow) flushWaiting = 1;\n\n            /* Write compressed stream */\n            DISPLAYLEVEL(6, \"ZSTD_compress_generic(end:%u) => input pos(%u)<=(%u)size ; output generated %u bytes \\n\",\n                         (unsigned)directive, (unsigned)inBuff.pos, (unsigned)inBuff.size, (unsigned)outBuff.pos);\n            if (outBuff.pos) {\n                FIO_SyncCompressIO_commitOut(syncIO, syncIO->outBuffer, outBuff.pos);\n                compressedfilesize += outBuff.pos;\n            }\n\n            /* adaptive mode : statistics measurement and speed correction */\n            if (prefs->adaptiveMode && UTIL_clockSpanMicro(lastAdaptTime) > adaptEveryMicro) {\n                ZSTD_frameProgression const zfp = ZSTD_getFrameProgression(ress->cctx);\n\n                lastAdaptTime = UTIL_getTime();\n\n                /* check output speed */\n                if (zfp.currentJobID > 1) {  /* only possible if nbWorkers >= 1 */\n\n                    unsigned long long newlyProduced = zfp.produced - previous_zfp_update.produced;\n                    unsigned long long newlyFlushed = zfp.flushed - previous_zfp_update.flushed;\n                    assert(zfp.produced >= previous_zfp_update.produced);\n                    assert(prefs->nbWorkers >= 1);\n\n                    /* test if compression is blocked\n                        * either because output is slow and all buffers are full\n                        * or because input is slow and no job can start while waiting for at least one buffer to be filled.\n                        * note : exclude starting part, since currentJobID > 1 */\n                    if ( (zfp.consumed == previous_zfp_update.consumed)   /* no data compressed : no data available, or no more buffer to compress to, OR compression is really slow (compression of a single block is slower than update rate)*/\n                        && (zfp.nbActiveWorkers == 0)                       /* confirmed : no compression ongoing */\n                        ) {\n                        DISPLAYLEVEL(6, \"all buffers full : compression stopped => slow down \\n\")\n                        speedChange = slower;\n                    }\n\n                    previous_zfp_update = zfp;\n\n                    if ( (newlyProduced > (newlyFlushed * 9 / 8))   /* compression produces more data than output can flush (though production can be spiky, due to work unit : (N==4)*block sizes) */\n                        && (flushWaiting == 0)                        /* flush speed was never slowed by lack of production, so it's operating at max capacity */\n                        ) {\n                        DISPLAYLEVEL(6, \"compression faster than flush (%llu > %llu), and flushed was never slowed down by lack of production => slow down \\n\", newlyProduced, newlyFlushed);\n                        speedChange = slower;\n                    }\n                    flushWaiting = 0;\n                }\n\n                /* course correct only if there is at least one new job completed */\n                if (zfp.currentJobID > lastJobID) {\n                    DISPLAYLEVEL(6, \"compression level adaptation check \\n\")\n\n                    /* check input speed */\n                    if (zfp.currentJobID > (unsigned)(prefs->nbWorkers+1)) {   /* warm up period, to fill all workers */\n                        if (inputBlocked <= 0) {\n                            DISPLAYLEVEL(6, \"input is never blocked => input is slower than ingestion \\n\");\n                            speedChange = slower;\n                        } else if (speedChange == noChange) {\n                            unsigned long long newlyIngested = zfp.ingested - previous_zfp_correction.ingested;\n                            unsigned long long newlyConsumed = zfp.consumed - previous_zfp_correction.consumed;\n                            unsigned long long newlyProduced = zfp.produced - previous_zfp_correction.produced;\n                            unsigned long long newlyFlushed  = zfp.flushed  - previous_zfp_correction.flushed;\n                            previous_zfp_correction = zfp;\n                            assert(inputPresented > 0);\n                            DISPLAYLEVEL(6, \"input blocked %u/%u(%.2f) - ingested:%u vs %u:consumed - flushed:%u vs %u:produced \\n\",\n                                            inputBlocked, inputPresented, (double)inputBlocked/inputPresented*100,\n                                            (unsigned)newlyIngested, (unsigned)newlyConsumed,\n                                            (unsigned)newlyFlushed, (unsigned)newlyProduced);\n                            if ( (inputBlocked > inputPresented / 8)     /* input is waiting often, because input buffers is full : compression or output too slow */\n                                && (newlyFlushed * 33 / 32 > newlyProduced)  /* flush everything that is produced */\n                                && (newlyIngested * 33 / 32 > newlyConsumed) /* input speed as fast or faster than compression speed */\n                            ) {\n                                DISPLAYLEVEL(6, \"recommend faster as in(%llu) >= (%llu)comp(%llu) <= out(%llu) \\n\",\n                                                newlyIngested, newlyConsumed, newlyProduced, newlyFlushed);\n                                speedChange = faster;\n                            }\n                        }\n                        inputBlocked = 0;\n                        inputPresented = 0;\n                    }\n\n                    if (speedChange == slower) {\n                        DISPLAYLEVEL(6, \"slower speed , higher compression \\n\")\n                        compressionLevel ++;\n                        if (compressionLevel > ZSTD_maxCLevel()) compressionLevel = ZSTD_maxCLevel();\n                        if (compressionLevel > prefs->maxAdaptLevel) compressionLevel = prefs->maxAdaptLevel;\n                        compressionLevel += (compressionLevel == 0);   /* skip 0 */\n                        ZSTD_CCtx_setParameter(ress->cctx, ZSTD_c_compressionLevel, compressionLevel);\n                    }\n                    if (speedChange == faster) {\n                        DISPLAYLEVEL(6, \"faster speed , lighter compression \\n\")\n                        compressionLevel --;\n                        if (compressionLevel < prefs->minAdaptLevel) compressionLevel = prefs->minAdaptLevel;\n                        compressionLevel -= (compressionLevel == 0);   /* skip 0 */\n                        ZSTD_CCtx_setParameter(ress->cctx, ZSTD_c_compressionLevel, compressionLevel);\n                    }\n                    speedChange = noChange;\n\n                    lastJobID = zfp.currentJobID;\n                }  /* if (zfp.currentJobID > lastJobID) */\n            } /* if (prefs->adaptiveMode && UTIL_clockSpanMicro(lastAdaptTime) > adaptEveryMicro) */\n\n            /* display notification */\n            if (SHOULD_DISPLAY_PROGRESS() && READY_FOR_UPDATE()) {\n                ZSTD_frameProgression const zfp = ZSTD_getFrameProgression(ress->cctx);\n                double const cShare = (double)zfp.produced / (double)(zfp.consumed + !zfp.consumed/*avoid div0*/) * 100;\n                UTIL_HumanReadableSize_t const buffered_hrs = UTIL_makeHumanReadableSize(zfp.ingested - zfp.consumed);\n                UTIL_HumanReadableSize_t const consumed_hrs = UTIL_makeHumanReadableSize(zfp.consumed);\n                UTIL_HumanReadableSize_t const produced_hrs = UTIL_makeHumanReadableSize(zfp.produced);\n\n                DELAY_NEXT_UPDATE();\n\n                /* display progress notifications */\n                DISPLAY_PROGRESS(\"\\r%79s\\r\", \"\");    /* Clear out the current displayed line */\n                if (g_display_prefs.displayLevel >= 3) {\n                    /* Verbose progress update */\n                    DISPLAY_PROGRESS(\n                            \"(L%i) Buffered:%5.*f%s - Consumed:%5.*f%s - Compressed:%5.*f%s => %.2f%% \",\n                            compressionLevel,\n                            buffered_hrs.precision, buffered_hrs.value, buffered_hrs.suffix,\n                            consumed_hrs.precision, consumed_hrs.value, consumed_hrs.suffix,\n                            produced_hrs.precision, produced_hrs.value, produced_hrs.suffix,\n                            cShare );\n                } else {\n                    /* Require level 2 or forcibly displayed progress counter for summarized updates */\n                    if (fCtx->nbFilesTotal > 1) {\n                        size_t srcFileNameSize = strlen(srcFileName);\n                        /* Ensure that the string we print is roughly the same size each time */\n                        if (srcFileNameSize > 18) {\n                            const char* truncatedSrcFileName = srcFileName + srcFileNameSize - 15;\n                            DISPLAY_PROGRESS(\"Compress: %u/%u files. Current: ...%s \",\n                                        fCtx->currFileIdx+1, fCtx->nbFilesTotal, truncatedSrcFileName);\n                        } else {\n                            DISPLAY_PROGRESS(\"Compress: %u/%u files. Current: %*s \",\n                                        fCtx->currFileIdx+1, fCtx->nbFilesTotal, (int)(18-srcFileNameSize), srcFileName);\n                        }\n                    }\n                    DISPLAY_PROGRESS(\"Read:%6.*f%4s \", consumed_hrs.precision, consumed_hrs.value, consumed_hrs.suffix);\n                    if (fileSize != UTIL_FILESIZE_UNKNOWN)\n                        DISPLAY_PROGRESS(\"/%6.*f%4s\", file_hrs.precision, file_hrs.value, file_hrs.suffix);\n                    DISPLAY_PROGRESS(\" ==> %2.f%%\", cShare);\n                }\n            }  /* if (SHOULD_DISPLAY_PROGRESS() && READY_FOR_UPDATE()) */\n        }  /* while ((inBuff.pos != inBuff.size) */\n    } while (directive != ZSTD_e_end);\n\n    if (fileSize != UTIL_FILESIZE_UNKNOWN && *readsize != fileSize) {\n        EXM_THROW(27, \"Read error : Incomplete read : %llu / %llu B\",\n                (unsigned long long)*readsize, (unsigned long long)fileSize);\n    }\n\n    FIO_SyncCompressIO_finish(syncIO);\n\n    return compressedfilesize;\n}\n\n/*! FIO_compressFilename_internal() :\n *  same as FIO_compressFilename_extRess(), with `ress.desFile` already opened.\n *  @return : 0 : compression completed correctly,\n *            1 : missing or pb opening srcFileName\n */\nstatic int\nFIO_compressFilename_internal(FIO_ctx_t* const fCtx,\n                              FIO_prefs_t* const prefs,\n                              cRess_t* ress,\n                              const char* dstFileName, const char* srcFileName,\n                              int compressionLevel)\n{\n    UTIL_time_t const timeStart = UTIL_getTime();\n    clock_t const cpuStart = clock();\n    U64 readsize = 0;\n    U64 compressedfilesize = 0;\n    U64 const fileSize = UTIL_getFileSize(srcFileName);\n    DISPLAYLEVEL(5, \"%s: %llu bytes \\n\", srcFileName, (unsigned long long)fileSize);\n\n    /* compression format selection */\n    switch (prefs->compressionType) {\n        default:\n        case FIO_zstdCompression:\n            compressedfilesize = FIO_compressZstdFrame(fCtx, prefs, ress, srcFileName, fileSize, compressionLevel, &readsize);\n            break;\n\n        case FIO_gzipCompression:\n#ifdef ZSTD_GZCOMPRESS\n            compressedfilesize = FIO_compressGzFrame(ress, srcFileName, fileSize, compressionLevel, &readsize);\n#else\n            (void)compressionLevel;\n            EXM_THROW(20, \"zstd: %s: file cannot be compressed as gzip (zstd compiled without ZSTD_GZCOMPRESS) -- ignored \\n\",\n                            srcFileName);\n#endif\n            break;\n\n        case FIO_xzCompression:\n        case FIO_lzmaCompression:\n#ifdef ZSTD_LZMACOMPRESS\n            compressedfilesize = FIO_compressLzmaFrame(ress, srcFileName, fileSize, compressionLevel, &readsize, prefs->compressionType==FIO_lzmaCompression);\n#else\n            (void)compressionLevel;\n            EXM_THROW(20, \"zstd: %s: file cannot be compressed as xz/lzma (zstd compiled without ZSTD_LZMACOMPRESS) -- ignored \\n\",\n                            srcFileName);\n#endif\n            break;\n\n        case FIO_lz4Compression:\n#ifdef ZSTD_LZ4COMPRESS\n            compressedfilesize = FIO_compressLz4Frame(ress, srcFileName, fileSize, compressionLevel, prefs->checksumFlag, &readsize);\n#else\n            (void)compressionLevel;\n            EXM_THROW(20, \"zstd: %s: file cannot be compressed as lz4 (zstd compiled without ZSTD_LZ4COMPRESS) -- ignored \\n\",\n                            srcFileName);\n#endif\n            break;\n    }\n\n    /* Status */\n    fCtx->totalBytesInput += (size_t)readsize;\n    fCtx->totalBytesOutput += (size_t)compressedfilesize;\n    DISPLAY_PROGRESS(\"\\r%79s\\r\", \"\");\n    if (FIO_shouldDisplayFileSummary(fCtx)) {\n        UTIL_HumanReadableSize_t hr_isize = UTIL_makeHumanReadableSize((U64) readsize);\n        UTIL_HumanReadableSize_t hr_osize = UTIL_makeHumanReadableSize((U64) compressedfilesize);\n        if (readsize == 0) {\n            DISPLAY_SUMMARY(\"%-20s :  (%6.*f%s => %6.*f%s, %s) \\n\",\n                srcFileName,\n                hr_isize.precision, hr_isize.value, hr_isize.suffix,\n                hr_osize.precision, hr_osize.value, hr_osize.suffix,\n                dstFileName);\n        } else {\n            DISPLAY_SUMMARY(\"%-20s :%6.2f%%   (%6.*f%s => %6.*f%s, %s) \\n\",\n                srcFileName,\n                (double)compressedfilesize / (double)readsize * 100,\n                hr_isize.precision, hr_isize.value, hr_isize.suffix,\n                hr_osize.precision, hr_osize.value, hr_osize.suffix,\n                dstFileName);\n        }\n    }\n\n    /* Elapsed Time and CPU Load */\n    {   clock_t const cpuEnd = clock();\n        double const cpuLoad_s = (double)(cpuEnd - cpuStart) / CLOCKS_PER_SEC;\n        U64 const timeLength_ns = UTIL_clockSpanNano(timeStart);\n        double const timeLength_s = (double)timeLength_ns / 1000000000;\n        double const cpuLoad_pct = (cpuLoad_s / timeLength_s) * 100;\n        DISPLAYLEVEL(4, \"%-20s : Completed in %.2f sec  (cpu load : %.0f%%)\\n\",\n                        srcFileName, timeLength_s, cpuLoad_pct);\n    }\n    return 0;\n}\n\n\n/*! FIO_compressFilename_dstFile() :\n *  open dstFileName, or pass-through if ress.file != NULL,\n *  then start compression with FIO_compressFilename_internal().\n *  Manages source removal (--rm) and file permissions transfer.\n *  note : ress.srcFile must be != NULL,\n *  so reach this function through FIO_compressFilename_srcFile().\n *  @return : 0 : compression completed correctly,\n *            1 : pb\n */\nstatic int FIO_compressFilename_dstFile(FIO_ctx_t* const fCtx,\n                                        FIO_prefs_t* const prefs,\n                                        cRess_t* ress,\n                                        const char* dstFileName,\n                                        const char* srcFileName,\n                                        const stat_t* srcFileStat,\n                                        int compressionLevel)\n{\n    int closeDstFile = 0;\n    int result;\n    int transferStat = 0;\n    int dstFd = -1;\n\n    if (ress->io.dstFile == NULL) {\n        int dstFileInitialPermissions = DEFAULT_FILE_PERMISSIONS;\n        if ( strcmp (srcFileName, stdinmark)\n          && strcmp (dstFileName, stdoutmark)\n          && UTIL_isRegularFileStat(srcFileStat) ) {\n            transferStat = 1;\n            dstFileInitialPermissions = TEMPORARY_FILE_PERMISSIONS;\n        }\n\n        closeDstFile = 1;\n        DISPLAYLEVEL(6, \"FIO_compressFilename_dstFile: opening dst: %s \\n\", dstFileName);\n        {\n            FILE *dstFile = FIO_openDstFile(fCtx, prefs, srcFileName, dstFileName, dstFileInitialPermissions);\n            if (dstFile==NULL) return 1;  /* could not open dstFileName */\n            dstFd = fileno(dstFile);\n            FIO_SyncCompressIO_setDst(&ress->io, dstFile);\n        }\n        /* Must only be added after FIO_openDstFile() succeeds. */\n        addHandler(dstFileName);\n    }\n\n    result = FIO_compressFilename_internal(fCtx, prefs, ress, dstFileName, srcFileName, compressionLevel);\n\n    if (closeDstFile) {\n        clearHandler();\n\n        if (transferStat) {\n            UTIL_setFDStat(dstFd, dstFileName, srcFileStat);\n        }\n\n        DISPLAYLEVEL(6, \"FIO_compressFilename_dstFile: closing dst: %s \\n\", dstFileName);\n        if (FIO_SyncCompressIO_closeDst(&ress->io)) { /* error closing file */\n            DISPLAYLEVEL(1, \"zstd: %s: %s \\n\", dstFileName, strerror(errno));\n            result=1;\n        }\n\n        if (transferStat) {\n            UTIL_utime(dstFileName, srcFileStat);\n        }\n\n        if ( (result != 0)\n          && strcmp(dstFileName, stdoutmark) ) {\n            FIO_removeFile(dstFileName);\n        }\n    }\n\n    return result;\n}\n\n/* List used to compare file extensions (used with --exclude-compressed flag)\n* Different from the suffixList and should only apply to ZSTD compress operationResult\n*/\nstatic const char *compressedFileExtensions[] = {\n    ZSTD_EXTENSION,\n    TZSTD_EXTENSION,\n    GZ_EXTENSION,\n    TGZ_EXTENSION,\n    LZMA_EXTENSION,\n    XZ_EXTENSION,\n    TXZ_EXTENSION,\n    LZ4_EXTENSION,\n    TLZ4_EXTENSION,\n    \".7z\",\n    \".aa3\",\n    \".aac\",\n    \".aar\",\n    \".ace\",\n    \".alac\",\n    \".ape\",\n    \".apk\",\n    \".apng\",\n    \".arc\",\n    \".archive\",\n    \".arj\",\n    \".ark\",\n    \".asf\",\n    \".avi\",\n    \".avif\",\n    \".ba\",\n    \".br\",\n    \".bz2\",\n    \".cab\",\n    \".cdx\",\n    \".chm\",\n    \".cr2\",\n    \".divx\",\n    \".dmg\",\n    \".dng\",\n    \".docm\",\n    \".docx\",\n    \".dotm\",\n    \".dotx\",\n    \".dsft\",\n    \".ear\",\n    \".eftx\",\n    \".emz\",\n    \".eot\",\n    \".epub\",\n    \".f4v\",\n    \".flac\",\n    \".flv\",\n    \".gho\",\n    \".gif\",\n    \".gifv\",\n    \".gnp\",\n    \".iso\",\n    \".jar\",\n    \".jpeg\",\n    \".jpg\",\n    \".jxl\",\n    \".lz\",\n    \".lzh\",\n    \".m4a\",\n    \".m4v\",\n    \".mkv\",\n    \".mov\",\n    \".mp2\",\n    \".mp3\",\n    \".mp4\",\n    \".mpa\",\n    \".mpc\",\n    \".mpe\",\n    \".mpeg\",\n    \".mpg\",\n    \".mpl\",\n    \".mpv\",\n    \".msi\",\n    \".odp\",\n    \".ods\",\n    \".odt\",\n    \".ogg\",\n    \".ogv\",\n    \".otp\",\n    \".ots\",\n    \".ott\",\n    \".pea\",\n    \".png\",\n    \".pptx\",\n    \".qt\",\n    \".rar\",\n    \".s7z\",\n    \".sfx\",\n    \".sit\",\n    \".sitx\",\n    \".sqx\",\n    \".svgz\",\n    \".swf\",\n    \".tbz2\",\n    \".tib\",\n    \".tlz\",\n    \".vob\",\n    \".war\",\n    \".webm\",\n    \".webp\",\n    \".wma\",\n    \".wmv\",\n    \".woff\",\n    \".woff2\",\n    \".wvl\",\n    \".xlsx\",\n    \".xpi\",\n    \".xps\",\n    \".zip\",\n    \".zipx\",\n    \".zoo\",\n    \".zpaq\",\n    NULL\n};\n\n/*! FIO_compressFilename_srcFile() :\n *  @return : 0 : compression completed correctly,\n *            1 : missing or pb opening srcFileName\n */\nstatic int\nFIO_compressFilename_srcFile(FIO_ctx_t* const fCtx,\n                             FIO_prefs_t* const prefs,\n                             cRess_t* ress,\n                             const char* dstFileName,\n                             const char* srcFileName,\n                             int compressionLevel)\n{\n    int result;\n    FILE* srcFile;\n    stat_t srcFileStat;\n    U64 fileSize = UTIL_FILESIZE_UNKNOWN;\n    DISPLAYLEVEL(6, \"FIO_compressFilename_srcFile: %s \\n\", srcFileName);\n\n    if (strcmp(srcFileName, stdinmark)) {\n        if (UTIL_stat(srcFileName, &srcFileStat)) {\n            /* failure to stat at all is handled during opening */\n\n            /* ensure src is not a directory */\n            if (UTIL_isDirectoryStat(&srcFileStat)) {\n                DISPLAYLEVEL(1, \"zstd: %s is a directory -- ignored \\n\", srcFileName);\n                return 1;\n            }\n\n            /* ensure src is not the same as dict (if present) */\n            if (ress->dictFileName != NULL && UTIL_isSameFileStat(srcFileName, ress->dictFileName, &srcFileStat, &ress->dictFileStat)) {\n                DISPLAYLEVEL(1, \"zstd: cannot use %s as an input file and dictionary \\n\", srcFileName);\n                return 1;\n            }\n        }\n    }\n\n    /* Check if \"srcFile\" is compressed. Only done if --exclude-compressed flag is used\n    * YES => ZSTD will skip compression of the file and will return 0.\n    * NO => ZSTD will resume with compress operation.\n    */\n    if (prefs->excludeCompressedFiles == 1 && UTIL_isCompressedFile(srcFileName, compressedFileExtensions)) {\n        DISPLAYLEVEL(4, \"File is already compressed : %s \\n\", srcFileName);\n        return 0;\n    }\n\n    srcFile = FIO_openSrcFile(prefs, srcFileName, &srcFileStat);\n    if (srcFile == NULL) return 1;   /* srcFile could not be opened */\n\n    if (strcmp(srcFileName, stdinmark)) /* Stdin doesn't have stats */\n        fileSize = UTIL_getFileSizeStat(&srcFileStat);\n    (void)fileSize;\n\n    FIO_SyncCompressIO_setSrc(&ress->io, srcFile);\n    result = FIO_compressFilename_dstFile(\n            fCtx, prefs, ress,\n            dstFileName, srcFileName,\n            &srcFileStat, compressionLevel);\n    FIO_SyncCompressIO_clearSrc(&ress->io);\n\n    if (srcFile != NULL && fclose(srcFile)) {\n        DISPLAYLEVEL(1, \"zstd: %s: %s \\n\", srcFileName, strerror(errno));\n        return 1;\n    }\n\n    if ( prefs->removeSrcFile  /* --rm */\n      && result == 0           /* success */\n      && strcmp(srcFileName, stdinmark)  /* exception : don't erase stdin */\n      ) {\n        /* We must clear the handler, since after this point calling it would\n         * delete both the source and destination files.\n         */\n        clearHandler();\n        if (FIO_removeFile(srcFileName))\n            EXM_THROW(1, \"zstd: %s: %s\", srcFileName, strerror(errno));\n    }\n    return result;\n}\n\nstatic const char*\nchecked_index(const char* options[], size_t length, size_t index) {\n    assert(index < length);\n    /* Necessary to avoid warnings since -O3 will omit the above `assert` */\n    (void) length;\n    return options[index];\n}\n\n#define INDEX(options, index) checked_index((options), sizeof(options)  / sizeof(char*), (size_t)(index))\n\nvoid FIO_displayCompressionParameters(const FIO_prefs_t* prefs)\n{\n    static const char* formatOptions[5] = {ZSTD_EXTENSION, GZ_EXTENSION, XZ_EXTENSION,\n                                           LZMA_EXTENSION, LZ4_EXTENSION};\n    static const char* sparseOptions[3] = {\" --no-sparse\", \"\", \" --sparse\"};\n    static const char* checkSumOptions[3] = {\" --no-check\", \"\", \" --check\"};\n    static const char* rowMatchFinderOptions[3] = {\"\", \" --no-row-match-finder\", \" --row-match-finder\"};\n    static const char* compressLiteralsOptions[3] = {\"\", \" --compress-literals\", \" --no-compress-literals\"};\n\n    assert(g_display_prefs.displayLevel >= 4);\n\n    DISPLAY(\"--format=%s\", formatOptions[prefs->compressionType]);\n    DISPLAY(\"%s\", INDEX(sparseOptions, prefs->sparseFileSupport));\n    DISPLAY(\"%s\", prefs->dictIDFlag ? \"\" : \" --no-dictID\");\n    DISPLAY(\"%s\", INDEX(checkSumOptions, prefs->checksumFlag));\n    DISPLAY(\" --jobsize=%d\", prefs->jobSize);\n    if (prefs->adaptiveMode)\n        DISPLAY(\" --adapt=min=%d,max=%d\", prefs->minAdaptLevel, prefs->maxAdaptLevel);\n    DISPLAY(\"%s\", INDEX(rowMatchFinderOptions, prefs->useRowMatchFinder));\n    DISPLAY(\"%s\", prefs->rsyncable ? \" --rsyncable\" : \"\");\n    if (prefs->streamSrcSize)\n        DISPLAY(\" --stream-size=%u\", (unsigned) prefs->streamSrcSize);\n    if (prefs->srcSizeHint)\n        DISPLAY(\" --size-hint=%d\", prefs->srcSizeHint);\n    if (prefs->targetCBlockSize)\n        DISPLAY(\" --target-compressed-block-size=%u\", (unsigned) prefs->targetCBlockSize);\n    DISPLAY(\"%s\", INDEX(compressLiteralsOptions, prefs->literalCompressionMode));\n    DISPLAY(\" --memory=%u\", prefs->memLimit ? prefs->memLimit : 128 MB);\n    DISPLAY(\" --threads=%d\", prefs->nbWorkers);\n    DISPLAY(\"%s\", prefs->excludeCompressedFiles ? \" --exclude-compressed\" : \"\");\n    DISPLAY(\" --%scontent-size\", prefs->contentSize ? \"\" : \"no-\");\n    DISPLAY(\"\\n\");\n}\n\n#undef INDEX\n\nint FIO_compressFilename(FIO_ctx_t* const fCtx, FIO_prefs_t* const prefs, const char* dstFileName,\n                         const char* srcFileName, const char* dictFileName,\n                         int compressionLevel, ZSTD_compressionParameters comprParams)\n{\n    cRess_t ress = FIO_createCResources(prefs, dictFileName, UTIL_getFileSize(srcFileName), compressionLevel, comprParams);\n    int const result = FIO_compressFilename_srcFile(fCtx, prefs, &ress, dstFileName, srcFileName, compressionLevel);\n\n#ifndef ZSTD_DISPLAY_LEVEL_DEFAULT\n# define ZSTD_DISPLAY_LEVEL_DEFAULT 2\n#endif\n\n    FIO_freeCResources(&ress);\n    return result;\n}\n\n/* FIO_determineCompressedName() :\n * create a destination filename for compressed srcFileName.\n * @return a pointer to it.\n * This function never returns an error (it may abort() in case of pb)\n */\nstatic const char*\nFIO_determineCompressedName(const char* srcFileName, const char* outDirName, const char* suffix)\n{\n    static size_t dfnbCapacity = 0;\n    static char* dstFileNameBuffer = NULL;   /* using static allocation : this function cannot be multi-threaded */\n    char* outDirFilename = NULL;\n    size_t sfnSize = strlen(srcFileName);\n    size_t const srcSuffixLen = strlen(suffix);\n\n    if(!strcmp(srcFileName, stdinmark)) {\n        return stdoutmark;\n    }\n\n    if (outDirName) {\n        outDirFilename = FIO_createFilename_fromOutDir(srcFileName, outDirName, srcSuffixLen);\n        sfnSize = strlen(outDirFilename);\n        assert(outDirFilename != NULL);\n    }\n\n    if (dfnbCapacity <= sfnSize+srcSuffixLen+1) {\n        /* resize buffer for dstName */\n        free(dstFileNameBuffer);\n        dfnbCapacity = sfnSize + srcSuffixLen + 30;\n        dstFileNameBuffer = (char*)malloc(dfnbCapacity);\n        if (!dstFileNameBuffer) {\n            EXM_THROW(30, \"zstd: %s\", strerror(errno));\n        }\n    }\n    assert(dstFileNameBuffer != NULL);\n\n    if (outDirFilename) {\n        memcpy(dstFileNameBuffer, outDirFilename, sfnSize);\n        free(outDirFilename);\n    } else {\n        memcpy(dstFileNameBuffer, srcFileName, sfnSize);\n    }\n    memcpy(dstFileNameBuffer+sfnSize, suffix, srcSuffixLen+1 /* Include terminating null */);\n    return dstFileNameBuffer;\n}\n\nstatic unsigned long long FIO_getLargestFileSize(const char** inFileNames, unsigned nbFiles)\n{\n    size_t i;\n    unsigned long long fileSize, maxFileSize = 0;\n    for (i = 0; i < nbFiles; i++) {\n        fileSize = UTIL_getFileSize(inFileNames[i]);\n        maxFileSize = fileSize > maxFileSize ? fileSize : maxFileSize;\n    }\n    return maxFileSize;\n}\n\n/* FIO_compressMultipleFilenames() :\n * compress nbFiles files\n * into either one destination (outFileName),\n * or into one file each (outFileName == NULL, but suffix != NULL),\n * or into a destination folder (specified with -O)\n */\nint FIO_compressMultipleFilenames(FIO_ctx_t* const fCtx,\n                                  FIO_prefs_t* const prefs,\n                                  const char** inFileNamesTable,\n                                  const char* outMirroredRootDirName,\n                                  const char* outDirName,\n                                  const char* outFileName, const char* suffix,\n                                  const char* dictFileName, int compressionLevel,\n                                  ZSTD_compressionParameters comprParams)\n{\n    int status;\n    int error = 0;\n    cRess_t ress = FIO_createCResources(prefs, dictFileName,\n        FIO_getLargestFileSize(inFileNamesTable, (unsigned)fCtx->nbFilesTotal),\n        compressionLevel, comprParams);\n\n    /* init */\n    assert(outFileName != NULL || suffix != NULL);\n    if (outFileName != NULL) {   /* output into a single destination (stdout typically) */\n        FILE *dstFile;\n        if (FIO_multiFilesConcatWarning(fCtx, prefs, outFileName, 1 /* displayLevelCutoff */)) {\n            FIO_freeCResources(&ress);\n            return 1;\n        }\n        dstFile = FIO_openDstFile(fCtx, prefs, NULL, outFileName, DEFAULT_FILE_PERMISSIONS);\n        if (dstFile == NULL) {  /* could not open outFileName */\n            error = 1;\n        } else {\n            FIO_SyncCompressIO_setDst(&ress.io, dstFile);\n            for (; fCtx->currFileIdx < fCtx->nbFilesTotal; ++fCtx->currFileIdx) {\n                status = FIO_compressFilename_srcFile(fCtx, prefs, &ress, outFileName, inFileNamesTable[fCtx->currFileIdx], compressionLevel);\n                if (!status) fCtx->nbFilesProcessed++;\n                error |= status;\n            }\n            if (FIO_SyncCompressIO_closeDst(&ress.io))\n                EXM_THROW(29, \"Write error (%s) : cannot properly close %s\",\n                            strerror(errno), outFileName);\n        }\n    } else {\n        if (outMirroredRootDirName)\n            UTIL_mirrorSourceFilesDirectories(inFileNamesTable, (unsigned)fCtx->nbFilesTotal, outMirroredRootDirName);\n\n        for (; fCtx->currFileIdx < fCtx->nbFilesTotal; ++fCtx->currFileIdx) {\n            const char* const srcFileName = inFileNamesTable[fCtx->currFileIdx];\n            const char* dstFileName = NULL;\n            if (outMirroredRootDirName) {\n                char* validMirroredDirName = UTIL_createMirroredDestDirName(srcFileName, outMirroredRootDirName);\n                if (validMirroredDirName) {\n                    dstFileName = FIO_determineCompressedName(srcFileName, validMirroredDirName, suffix);\n                    free(validMirroredDirName);\n                } else {\n                    DISPLAYLEVEL(2, \"zstd: --output-dir-mirror cannot compress '%s' into '%s' \\n\", srcFileName, outMirroredRootDirName);\n                    error=1;\n                    continue;\n                }\n            } else {\n                dstFileName = FIO_determineCompressedName(srcFileName, outDirName, suffix);  /* cannot fail */\n            }\n            status = FIO_compressFilename_srcFile(fCtx, prefs, &ress, dstFileName, srcFileName, compressionLevel);\n            if (!status) fCtx->nbFilesProcessed++;\n            error |= status;\n        }\n\n        if (outDirName)\n            FIO_checkFilenameCollisions(inFileNamesTable , (unsigned)fCtx->nbFilesTotal);\n    }\n\n    if (FIO_shouldDisplayMultipleFileSummary(fCtx)) {\n        UTIL_HumanReadableSize_t hr_isize = UTIL_makeHumanReadableSize((U64) fCtx->totalBytesInput);\n        UTIL_HumanReadableSize_t hr_osize = UTIL_makeHumanReadableSize((U64) fCtx->totalBytesOutput);\n\n        DISPLAY_PROGRESS(\"\\r%79s\\r\", \"\");\n        if (fCtx->totalBytesInput == 0) {\n            DISPLAY_SUMMARY(\"%3d files compressed : (%6.*f%4s => %6.*f%4s)\\n\",\n                            fCtx->nbFilesProcessed,\n                            hr_isize.precision, hr_isize.value, hr_isize.suffix,\n                            hr_osize.precision, hr_osize.value, hr_osize.suffix);\n        } else {\n            DISPLAY_SUMMARY(\"%3d files compressed : %.2f%% (%6.*f%4s => %6.*f%4s)\\n\",\n                            fCtx->nbFilesProcessed,\n                            (double)fCtx->totalBytesOutput/((double)fCtx->totalBytesInput)*100,\n                            hr_isize.precision, hr_isize.value, hr_isize.suffix,\n                            hr_osize.precision, hr_osize.value, hr_osize.suffix);\n        }\n    }\n\n    FIO_freeCResources(&ress);\n    return error;\n}\n\n#endif /* #ifndef ZSTD_NOCOMPRESS */\n\n\n\n#ifndef ZSTD_NODECOMPRESS\n\n/* **************************************************************************\n *  Decompression\n ***************************************************************************/\ntypedef struct {\n    FIO_Dict_t dict;\n    ZSTD_DStream* dctx;\n    WritePoolCtx_t *writeCtx;\n    ReadPoolCtx_t *readCtx;\n} dRess_t;\n\nstatic dRess_t FIO_createDResources(FIO_prefs_t* const prefs, const char* dictFileName)\n{\n    int useMMap = prefs->mmapDict == ZSTD_ps_enable;\n    int forceNoUseMMap = prefs->mmapDict == ZSTD_ps_disable;\n    stat_t statbuf;\n    dRess_t ress;\n    memset(&statbuf, 0, sizeof(statbuf));\n    memset(&ress, 0, sizeof(ress));\n\n    FIO_getDictFileStat(dictFileName, &statbuf);\n\n    if (prefs->patchFromMode){\n        U64 const dictSize = UTIL_getFileSizeStat(&statbuf);\n        useMMap |= dictSize > prefs->memLimit;\n        FIO_adjustMemLimitForPatchFromMode(prefs, dictSize, 0 /* just use the dict size */);\n    }\n\n    /* Allocation */\n    ress.dctx = ZSTD_createDStream();\n    if (ress.dctx==NULL)\n        EXM_THROW(60, \"Error: %s : can't create ZSTD_DStream\", strerror(errno));\n    CHECK( ZSTD_DCtx_setMaxWindowSize(ress.dctx, prefs->memLimit) );\n    CHECK( ZSTD_DCtx_setParameter(ress.dctx, ZSTD_d_forceIgnoreChecksum, !prefs->checksumFlag));\n\n    /* dictionary */\n    {\n        FIO_dictBufferType_t dictBufferType = (useMMap && !forceNoUseMMap) ? FIO_mmapDict : FIO_mallocDict;\n        FIO_initDict(&ress.dict, dictFileName, prefs, &statbuf, dictBufferType);\n\n        CHECK(ZSTD_DCtx_reset(ress.dctx, ZSTD_reset_session_only) );\n\n        if (prefs->patchFromMode){\n            CHECK(ZSTD_DCtx_refPrefix(ress.dctx, ress.dict.dictBuffer, ress.dict.dictBufferSize));\n        } else {\n            CHECK(ZSTD_DCtx_loadDictionary_byReference(ress.dctx, ress.dict.dictBuffer, ress.dict.dictBufferSize));\n        }\n    }\n\n    ress.writeCtx = AIO_WritePool_create(prefs, ZSTD_DStreamOutSize());\n    ress.readCtx = AIO_ReadPool_create(prefs, ZSTD_DStreamInSize());\n    return ress;\n}\n\nstatic void FIO_freeDResources(dRess_t ress)\n{\n    FIO_freeDict(&(ress.dict));\n    CHECK( ZSTD_freeDStream(ress.dctx) );\n    AIO_WritePool_free(ress.writeCtx);\n    AIO_ReadPool_free(ress.readCtx);\n}\n\n/* FIO_passThrough() : just copy input into output, for compatibility with gzip -df mode\n * @return : 0 (no error) */\nstatic int FIO_passThrough(dRess_t *ress)\n{\n    size_t const blockSize = MIN(MIN(64 KB, ZSTD_DStreamInSize()), ZSTD_DStreamOutSize());\n    IOJob_t *writeJob = AIO_WritePool_acquireJob(ress->writeCtx);\n    AIO_ReadPool_fillBuffer(ress->readCtx, blockSize);\n\n    while(ress->readCtx->srcBufferLoaded) {\n        size_t writeSize;\n        writeSize = MIN(blockSize, ress->readCtx->srcBufferLoaded);\n        assert(writeSize <= writeJob->bufferSize);\n        memcpy(writeJob->buffer, ress->readCtx->srcBuffer, writeSize);\n        writeJob->usedBufferSize = writeSize;\n        AIO_WritePool_enqueueAndReacquireWriteJob(&writeJob);\n        AIO_ReadPool_consumeBytes(ress->readCtx, writeSize);\n        AIO_ReadPool_fillBuffer(ress->readCtx, blockSize);\n    }\n    assert(ress->readCtx->reachedEof);\n    AIO_WritePool_releaseIoJob(writeJob);\n    AIO_WritePool_sparseWriteEnd(ress->writeCtx);\n    return 0;\n}\n\n/* FIO_zstdErrorHelp() :\n * detailed error message when requested window size is too large */\nstatic void\nFIO_zstdErrorHelp(const FIO_prefs_t* const prefs,\n                  const dRess_t* ress,\n                  size_t err,\n                  const char* srcFileName)\n{\n    ZSTD_FrameHeader header;\n\n    /* Help message only for one specific error */\n    if (ZSTD_getErrorCode(err) != ZSTD_error_frameParameter_windowTooLarge)\n        return;\n\n    /* Try to decode the frame header */\n    err = ZSTD_getFrameHeader(&header, ress->readCtx->srcBuffer, ress->readCtx->srcBufferLoaded);\n    if (err == 0) {\n        unsigned long long const windowSize = header.windowSize;\n        unsigned const windowLog = FIO_highbit64(windowSize) + ((windowSize & (windowSize - 1)) != 0);\n        assert(prefs->memLimit > 0);\n        DISPLAYLEVEL(1, \"%s : Window size larger than maximum : %llu > %u \\n\",\n                        srcFileName, windowSize, prefs->memLimit);\n        if (windowLog <= ZSTD_WINDOWLOG_MAX) {\n            unsigned const windowMB = (unsigned)((windowSize >> 20) + ((windowSize & ((1 MB) - 1)) != 0));\n            assert(windowSize < (U64)(1ULL << 52));   /* ensure now overflow for windowMB */\n            DISPLAYLEVEL(1, \"%s : Use --long=%u or --memory=%uMB \\n\",\n                            srcFileName, windowLog, windowMB);\n            return;\n    }   }\n    DISPLAYLEVEL(1, \"%s : Window log larger than ZSTD_WINDOWLOG_MAX=%u; not supported \\n\",\n                    srcFileName, ZSTD_WINDOWLOG_MAX);\n}\n\n/** FIO_decompressFrame() :\n *  @return : size of decoded zstd frame, or an error code\n */\n#define FIO_ERROR_FRAME_DECODING   ((unsigned long long)(-2))\nstatic unsigned long long\nFIO_decompressZstdFrame(FIO_ctx_t* const fCtx, dRess_t* ress,\n                        const FIO_prefs_t* const prefs,\n                        const char* srcFileName,\n                        U64 alreadyDecoded)  /* for multi-frames streams */\n{\n    U64 frameSize = 0;\n    const char* srcFName20 = srcFileName;\n    IOJob_t* writeJob = AIO_WritePool_acquireJob(ress->writeCtx);\n    assert(writeJob);\n\n    /* display last 20 characters only when not --verbose */\n    {   size_t const srcFileLength = strlen(srcFileName);\n        if ((srcFileLength>20) && (g_display_prefs.displayLevel<3))\n            srcFName20 += srcFileLength-20;\n    }\n\n    ZSTD_DCtx_reset(ress->dctx, ZSTD_reset_session_only);\n\n    /* Header loading : ensures ZSTD_getFrameHeader() will succeed */\n    AIO_ReadPool_fillBuffer(ress->readCtx, ZSTD_FRAMEHEADERSIZE_MAX);\n\n    /* Main decompression Loop */\n    while (1) {\n        ZSTD_inBuffer  inBuff = setInBuffer( ress->readCtx->srcBuffer, ress->readCtx->srcBufferLoaded, 0 );\n        ZSTD_outBuffer outBuff= setOutBuffer( writeJob->buffer, writeJob->bufferSize, 0 );\n        size_t const readSizeHint = ZSTD_decompressStream(ress->dctx, &outBuff, &inBuff);\n        UTIL_HumanReadableSize_t const hrs = UTIL_makeHumanReadableSize(alreadyDecoded+frameSize);\n        if (ZSTD_isError(readSizeHint)) {\n            DISPLAYLEVEL(1, \"%s : Decoding error (36) : %s \\n\",\n                            srcFileName, ZSTD_getErrorName(readSizeHint));\n            FIO_zstdErrorHelp(prefs, ress, readSizeHint, srcFileName);\n            AIO_WritePool_releaseIoJob(writeJob);\n            return FIO_ERROR_FRAME_DECODING;\n        }\n\n        /* Write block */\n        writeJob->usedBufferSize = outBuff.pos;\n        AIO_WritePool_enqueueAndReacquireWriteJob(&writeJob);\n        frameSize += outBuff.pos;\n        if (fCtx->nbFilesTotal > 1) {\n            DISPLAYUPDATE_PROGRESS(\n                        \"\\rDecompress: %2u/%2u files. Current: %s : %.*f%s...    \",\n                        fCtx->currFileIdx+1, fCtx->nbFilesTotal, srcFName20, hrs.precision, hrs.value, hrs.suffix);\n        } else {\n            DISPLAYUPDATE_PROGRESS(\"\\r%-20.20s : %.*f%s...     \",\n                            srcFName20, hrs.precision, hrs.value, hrs.suffix);\n        }\n\n        AIO_ReadPool_consumeBytes(ress->readCtx, inBuff.pos);\n\n        if (readSizeHint == 0) break;   /* end of frame */\n\n        /* Fill input buffer */\n        {   size_t const toDecode = MIN(readSizeHint, ZSTD_DStreamInSize());  /* support large skippable frames */\n            if (ress->readCtx->srcBufferLoaded < toDecode) {\n                size_t const readSize = AIO_ReadPool_fillBuffer(ress->readCtx, toDecode);\n                if (readSize==0) {\n                    DISPLAYLEVEL(1, \"%s : Read error (39) : premature end \\n\",\n                                 srcFileName);\n                    AIO_WritePool_releaseIoJob(writeJob);\n                    return FIO_ERROR_FRAME_DECODING;\n                }\n            }   }   }\n\n    AIO_WritePool_releaseIoJob(writeJob);\n    AIO_WritePool_sparseWriteEnd(ress->writeCtx);\n\n    return frameSize;\n}\n\n\n#ifdef ZSTD_GZDECOMPRESS\nstatic unsigned long long\nFIO_decompressGzFrame(dRess_t* ress, const char* srcFileName)\n{\n    unsigned long long outFileSize = 0;\n    z_stream strm;\n    int flush = Z_NO_FLUSH;\n    int decodingError = 0;\n    IOJob_t *writeJob = NULL;\n\n    strm.zalloc = Z_NULL;\n    strm.zfree = Z_NULL;\n    strm.opaque = Z_NULL;\n    strm.next_in = 0;\n    strm.avail_in = 0;\n    /* see https://www.zlib.net/manual.html */\n    if (inflateInit2(&strm, 15 /* maxWindowLogSize */ + 16 /* gzip only */) != Z_OK)\n        return FIO_ERROR_FRAME_DECODING;\n\n    writeJob = AIO_WritePool_acquireJob(ress->writeCtx);\n    strm.next_out = (Bytef*)writeJob->buffer;\n    strm.avail_out = (uInt)writeJob->bufferSize;\n    strm.avail_in = (uInt)ress->readCtx->srcBufferLoaded;\n    strm.next_in = (z_const unsigned char*)ress->readCtx->srcBuffer;\n\n    for ( ; ; ) {\n        int ret;\n        if (strm.avail_in == 0) {\n            AIO_ReadPool_consumeAndRefill(ress->readCtx);\n            if (ress->readCtx->srcBufferLoaded == 0) flush = Z_FINISH;\n            strm.next_in = (z_const unsigned char*)ress->readCtx->srcBuffer;\n            strm.avail_in = (uInt)ress->readCtx->srcBufferLoaded;\n        }\n        ret = inflate(&strm, flush);\n        if (ret == Z_BUF_ERROR) {\n            DISPLAYLEVEL(1, \"zstd: %s: premature gz end \\n\", srcFileName);\n            decodingError = 1; break;\n        }\n        if (ret != Z_OK && ret != Z_STREAM_END) {\n            DISPLAYLEVEL(1, \"zstd: %s: inflate error %d \\n\", srcFileName, ret);\n            decodingError = 1; break;\n        }\n        {   size_t const decompBytes = writeJob->bufferSize - strm.avail_out;\n            if (decompBytes) {\n                writeJob->usedBufferSize = decompBytes;\n                AIO_WritePool_enqueueAndReacquireWriteJob(&writeJob);\n                outFileSize += decompBytes;\n                strm.next_out = (Bytef*)writeJob->buffer;\n                strm.avail_out = (uInt)writeJob->bufferSize;\n            }\n        }\n        if (ret == Z_STREAM_END) break;\n    }\n\n    AIO_ReadPool_consumeBytes(ress->readCtx, ress->readCtx->srcBufferLoaded - strm.avail_in);\n\n    if ( (inflateEnd(&strm) != Z_OK)  /* release resources ; error detected */\n      && (decodingError==0) ) {\n        DISPLAYLEVEL(1, \"zstd: %s: inflateEnd error \\n\", srcFileName);\n        decodingError = 1;\n    }\n    AIO_WritePool_releaseIoJob(writeJob);\n    AIO_WritePool_sparseWriteEnd(ress->writeCtx);\n    return decodingError ? FIO_ERROR_FRAME_DECODING : outFileSize;\n}\n#endif\n\n#ifdef ZSTD_LZMADECOMPRESS\nstatic unsigned long long\nFIO_decompressLzmaFrame(dRess_t* ress,\n                        const char* srcFileName, int plain_lzma)\n{\n    unsigned long long outFileSize = 0;\n    lzma_stream strm = LZMA_STREAM_INIT;\n    lzma_action action = LZMA_RUN;\n    lzma_ret initRet;\n    int decodingError = 0;\n    IOJob_t *writeJob = NULL;\n\n    strm.next_in = 0;\n    strm.avail_in = 0;\n    if (plain_lzma) {\n        initRet = lzma_alone_decoder(&strm, UINT64_MAX); /* LZMA */\n    } else {\n        initRet = lzma_stream_decoder(&strm, UINT64_MAX, 0); /* XZ */\n    }\n\n    if (initRet != LZMA_OK) {\n        DISPLAYLEVEL(1, \"zstd: %s: %s error %d \\n\",\n                        plain_lzma ? \"lzma_alone_decoder\" : \"lzma_stream_decoder\",\n                        srcFileName, initRet);\n        return FIO_ERROR_FRAME_DECODING;\n    }\n\n    writeJob = AIO_WritePool_acquireJob(ress->writeCtx);\n    strm.next_out = (BYTE*)writeJob->buffer;\n    strm.avail_out = writeJob->bufferSize;\n    strm.next_in = (BYTE const*)ress->readCtx->srcBuffer;\n    strm.avail_in = ress->readCtx->srcBufferLoaded;\n\n    for ( ; ; ) {\n        lzma_ret ret;\n        if (strm.avail_in == 0) {\n            AIO_ReadPool_consumeAndRefill(ress->readCtx);\n            if (ress->readCtx->srcBufferLoaded == 0) action = LZMA_FINISH;\n            strm.next_in = (BYTE const*)ress->readCtx->srcBuffer;\n            strm.avail_in = ress->readCtx->srcBufferLoaded;\n        }\n        ret = lzma_code(&strm, action);\n\n        if (ret == LZMA_BUF_ERROR) {\n            DISPLAYLEVEL(1, \"zstd: %s: premature lzma end \\n\", srcFileName);\n            decodingError = 1; break;\n        }\n        if (ret != LZMA_OK && ret != LZMA_STREAM_END) {\n            DISPLAYLEVEL(1, \"zstd: %s: lzma_code decoding error %d \\n\",\n                            srcFileName, ret);\n            decodingError = 1; break;\n        }\n        {   size_t const decompBytes = writeJob->bufferSize - strm.avail_out;\n            if (decompBytes) {\n                writeJob->usedBufferSize = decompBytes;\n                AIO_WritePool_enqueueAndReacquireWriteJob(&writeJob);\n                outFileSize += decompBytes;\n                strm.next_out = (BYTE*)writeJob->buffer;\n                strm.avail_out = writeJob->bufferSize;\n        }   }\n        if (ret == LZMA_STREAM_END) break;\n    }\n\n    AIO_ReadPool_consumeBytes(ress->readCtx, ress->readCtx->srcBufferLoaded - strm.avail_in);\n    lzma_end(&strm);\n    AIO_WritePool_releaseIoJob(writeJob);\n    AIO_WritePool_sparseWriteEnd(ress->writeCtx);\n    return decodingError ? FIO_ERROR_FRAME_DECODING : outFileSize;\n}\n#endif\n\n#ifdef ZSTD_LZ4DECOMPRESS\nstatic unsigned long long\nFIO_decompressLz4Frame(dRess_t* ress, const char* srcFileName)\n{\n    unsigned long long filesize = 0;\n    LZ4F_errorCode_t nextToLoad = 4;\n    LZ4F_decompressionContext_t dCtx;\n    LZ4F_errorCode_t const errorCode = LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION);\n    int decodingError = 0;\n    IOJob_t *writeJob = NULL;\n\n    if (LZ4F_isError(errorCode)) {\n        DISPLAYLEVEL(1, \"zstd: failed to create lz4 decompression context \\n\");\n        return FIO_ERROR_FRAME_DECODING;\n    }\n\n    writeJob = AIO_WritePool_acquireJob(ress->writeCtx);\n\n    /* Main Loop */\n    for (;nextToLoad;) {\n        size_t pos = 0;\n        size_t decodedBytes = writeJob->bufferSize;\n        int fullBufferDecoded = 0;\n\n        /* Read input */\n        AIO_ReadPool_fillBuffer(ress->readCtx, nextToLoad);\n        if(!ress->readCtx->srcBufferLoaded) break; /* reached end of file */\n\n        while ((pos < ress->readCtx->srcBufferLoaded) || fullBufferDecoded) {  /* still to read, or still to flush */\n            /* Decode Input (at least partially) */\n            size_t remaining = ress->readCtx->srcBufferLoaded - pos;\n            decodedBytes = writeJob->bufferSize;\n            nextToLoad = LZ4F_decompress(dCtx, writeJob->buffer, &decodedBytes, (char*)(ress->readCtx->srcBuffer)+pos,\n                                         &remaining, NULL);\n            if (LZ4F_isError(nextToLoad)) {\n                DISPLAYLEVEL(1, \"zstd: %s: lz4 decompression error : %s \\n\",\n                                srcFileName, LZ4F_getErrorName(nextToLoad));\n                decodingError = 1; nextToLoad = 0; break;\n            }\n            pos += remaining;\n            assert(pos <= ress->readCtx->srcBufferLoaded);\n            fullBufferDecoded = decodedBytes == writeJob->bufferSize;\n\n            /* Write Block */\n            if (decodedBytes) {\n                UTIL_HumanReadableSize_t hrs;\n                writeJob->usedBufferSize = decodedBytes;\n                AIO_WritePool_enqueueAndReacquireWriteJob(&writeJob);\n                filesize += decodedBytes;\n                hrs = UTIL_makeHumanReadableSize(filesize);\n                DISPLAYUPDATE_PROGRESS(\"\\rDecompressed : %.*f%s  \", hrs.precision, hrs.value, hrs.suffix);\n            }\n\n            if (!nextToLoad) break;\n        }\n        AIO_ReadPool_consumeBytes(ress->readCtx, pos);\n    }\n    if (nextToLoad!=0) {\n        DISPLAYLEVEL(1, \"zstd: %s: unfinished lz4 stream \\n\", srcFileName);\n        decodingError=1;\n    }\n\n    LZ4F_freeDecompressionContext(dCtx);\n    AIO_WritePool_releaseIoJob(writeJob);\n    AIO_WritePool_sparseWriteEnd(ress->writeCtx);\n\n    return decodingError ? FIO_ERROR_FRAME_DECODING : filesize;\n}\n#endif\n\n\n\n/** FIO_decompressFrames() :\n *  Find and decode frames inside srcFile\n *  srcFile presumed opened and valid\n * @return : 0 : OK\n *           1 : error\n */\nstatic int FIO_decompressFrames(FIO_ctx_t* const fCtx,\n                                dRess_t ress, const FIO_prefs_t* const prefs,\n                                const char* dstFileName, const char* srcFileName)\n{\n    unsigned readSomething = 0;\n    unsigned long long filesize = 0;\n    int passThrough = prefs->passThrough;\n\n    if (passThrough == -1) {\n        /* If pass-through mode is not explicitly enabled or disabled,\n         * default to the legacy behavior of enabling it if we are writing\n         * to stdout with the overwrite flag enabled.\n         */\n        passThrough = prefs->overwrite && !strcmp(dstFileName, stdoutmark);\n    }\n    assert(passThrough == 0 || passThrough == 1);\n\n    /* for each frame */\n    for ( ; ; ) {\n        /* check magic number -> version */\n        size_t const toRead = 4;\n        const BYTE* buf;\n        AIO_ReadPool_fillBuffer(ress.readCtx, toRead);\n        buf = (const BYTE*)ress.readCtx->srcBuffer;\n        if (ress.readCtx->srcBufferLoaded==0) {\n            if (readSomething==0) {  /* srcFile is empty (which is invalid) */\n                DISPLAYLEVEL(1, \"zstd: %s: unexpected end of file \\n\", srcFileName);\n                return 1;\n            }  /* else, just reached frame boundary */\n            break;   /* no more input */\n        }\n        readSomething = 1;   /* there is at least 1 byte in srcFile */\n        if (ress.readCtx->srcBufferLoaded < toRead) { /* not enough input to check magic number */\n            if (passThrough) {\n                return FIO_passThrough(&ress);\n            }\n            DISPLAYLEVEL(1, \"zstd: %s: unknown header \\n\", srcFileName);\n            return 1;\n        }\n        if (ZSTD_isFrame(buf, ress.readCtx->srcBufferLoaded)) {\n            unsigned long long const frameSize = FIO_decompressZstdFrame(fCtx, &ress, prefs, srcFileName, filesize);\n            if (frameSize == FIO_ERROR_FRAME_DECODING) return 1;\n            filesize += frameSize;\n        } else if (buf[0] == 31 && buf[1] == 139) { /* gz magic number */\n#ifdef ZSTD_GZDECOMPRESS\n            unsigned long long const frameSize = FIO_decompressGzFrame(&ress, srcFileName);\n            if (frameSize == FIO_ERROR_FRAME_DECODING) return 1;\n            filesize += frameSize;\n#else\n            DISPLAYLEVEL(1, \"zstd: %s: gzip file cannot be uncompressed (zstd compiled without HAVE_ZLIB) -- ignored \\n\", srcFileName);\n            return 1;\n#endif\n        } else if ((buf[0] == 0xFD && buf[1] == 0x37)  /* xz magic number */\n                || (buf[0] == 0x5D && buf[1] == 0x00)) { /* lzma header (no magic number) */\n#ifdef ZSTD_LZMADECOMPRESS\n            unsigned long long const frameSize = FIO_decompressLzmaFrame(&ress, srcFileName, buf[0] != 0xFD);\n            if (frameSize == FIO_ERROR_FRAME_DECODING) return 1;\n            filesize += frameSize;\n#else\n            DISPLAYLEVEL(1, \"zstd: %s: xz/lzma file cannot be uncompressed (zstd compiled without HAVE_LZMA) -- ignored \\n\", srcFileName);\n            return 1;\n#endif\n        } else if (MEM_readLE32(buf) == LZ4_MAGICNUMBER) {\n#ifdef ZSTD_LZ4DECOMPRESS\n            unsigned long long const frameSize = FIO_decompressLz4Frame(&ress, srcFileName);\n            if (frameSize == FIO_ERROR_FRAME_DECODING) return 1;\n            filesize += frameSize;\n#else\n            DISPLAYLEVEL(1, \"zstd: %s: lz4 file cannot be uncompressed (zstd compiled without HAVE_LZ4) -- ignored \\n\", srcFileName);\n            return 1;\n#endif\n        } else if (passThrough) {\n            return FIO_passThrough(&ress);\n        } else {\n            DISPLAYLEVEL(1, \"zstd: %s: unsupported format \\n\", srcFileName);\n            return 1;\n    }   }  /* for each frame */\n\n    /* Final Status */\n    fCtx->totalBytesOutput += (size_t)filesize;\n    DISPLAY_PROGRESS(\"\\r%79s\\r\", \"\");\n    if (FIO_shouldDisplayFileSummary(fCtx))\n        DISPLAY_SUMMARY(\"%-20s: %llu bytes \\n\", srcFileName, filesize);\n\n    return 0;\n}\n\n/** FIO_decompressDstFile() :\n    open `dstFileName`, or pass-through if writeCtx's file is already != 0,\n    then start decompression process (FIO_decompressFrames()).\n    @return : 0 : OK\n              1 : operation aborted\n*/\nstatic int FIO_decompressDstFile(FIO_ctx_t* const fCtx,\n                                 FIO_prefs_t* const prefs,\n                                 dRess_t ress,\n                                 const char* dstFileName,\n                                 const char* srcFileName,\n                                 const stat_t* srcFileStat)\n{\n    int result;\n    int releaseDstFile = 0;\n    int transferStat = 0;\n    int dstFd = 0;\n\n    if ((AIO_WritePool_getFile(ress.writeCtx) == NULL) && (prefs->testMode == 0)) {\n        FILE *dstFile;\n        int dstFilePermissions = DEFAULT_FILE_PERMISSIONS;\n        if ( strcmp(srcFileName, stdinmark)   /* special case : don't transfer permissions from stdin */\n          && strcmp(dstFileName, stdoutmark)\n          && UTIL_isRegularFileStat(srcFileStat) ) {\n            transferStat = 1;\n            dstFilePermissions = TEMPORARY_FILE_PERMISSIONS;\n        }\n\n        releaseDstFile = 1;\n\n        dstFile = FIO_openDstFile(fCtx, prefs, srcFileName, dstFileName, dstFilePermissions);\n        if (dstFile==NULL) return 1;\n        dstFd = fileno(dstFile);\n        AIO_WritePool_setFile(ress.writeCtx, dstFile);\n\n        /* Must only be added after FIO_openDstFile() succeeds.\n         * Otherwise we may delete the destination file if it already exists,\n         * and the user presses Ctrl-C when asked if they wish to overwrite.\n         */\n        addHandler(dstFileName);\n    }\n\n    result = FIO_decompressFrames(fCtx, ress, prefs, dstFileName, srcFileName);\n\n    if (releaseDstFile) {\n        clearHandler();\n\n        if (transferStat) {\n            UTIL_setFDStat(dstFd, dstFileName, srcFileStat);\n        }\n\n        if (AIO_WritePool_closeFile(ress.writeCtx)) {\n            DISPLAYLEVEL(1, \"zstd: %s: %s \\n\", dstFileName, strerror(errno));\n            result = 1;\n        }\n\n        if (transferStat) {\n            UTIL_utime(dstFileName, srcFileStat);\n        }\n\n        if ( (result != 0)  /* operation failure */\n          && strcmp(dstFileName, stdoutmark)  /* special case : don't remove() stdout */\n          ) {\n            FIO_removeFile(dstFileName);  /* remove decompression artefact; note: don't do anything special if remove() fails */\n        }\n    }\n\n    return result;\n}\n\n\n/** FIO_decompressSrcFile() :\n    Open `srcFileName`, transfer control to decompressDstFile()\n    @return : 0 : OK\n              1 : error\n*/\nstatic int FIO_decompressSrcFile(FIO_ctx_t* const fCtx, FIO_prefs_t* const prefs, dRess_t ress, const char* dstFileName, const char* srcFileName)\n{\n    FILE* srcFile;\n    stat_t srcFileStat;\n    int result;\n    U64 fileSize = UTIL_FILESIZE_UNKNOWN;\n\n    if (UTIL_isDirectory(srcFileName)) {\n        DISPLAYLEVEL(1, \"zstd: %s is a directory -- ignored \\n\", srcFileName);\n        return 1;\n    }\n\n    srcFile = FIO_openSrcFile(prefs, srcFileName, &srcFileStat);\n    if (srcFile==NULL) return 1;\n\n    /* Don't use AsyncIO for small files */\n    if (strcmp(srcFileName, stdinmark)) /* Stdin doesn't have stats */\n        fileSize = UTIL_getFileSizeStat(&srcFileStat);\n    if(fileSize != UTIL_FILESIZE_UNKNOWN && fileSize < ZSTD_BLOCKSIZE_MAX * 3) {\n        AIO_ReadPool_setAsync(ress.readCtx, 0);\n        AIO_WritePool_setAsync(ress.writeCtx, 0);\n    } else {\n        AIO_ReadPool_setAsync(ress.readCtx, 1);\n        AIO_WritePool_setAsync(ress.writeCtx, 1);\n    }\n\n    AIO_ReadPool_setFile(ress.readCtx, srcFile);\n\n    result = FIO_decompressDstFile(fCtx, prefs, ress, dstFileName, srcFileName, &srcFileStat);\n\n    AIO_ReadPool_setFile(ress.readCtx, NULL);\n\n    /* Close file */\n    if (fclose(srcFile)) {\n        DISPLAYLEVEL(1, \"zstd: %s: %s \\n\", srcFileName, strerror(errno));  /* error should not happen */\n        return 1;\n    }\n    if ( prefs->removeSrcFile  /* --rm */\n      && (result==0)      /* decompression successful */\n      && strcmp(srcFileName, stdinmark) ) /* not stdin */ {\n        /* We must clear the handler, since after this point calling it would\n         * delete both the source and destination files.\n         */\n        clearHandler();\n        if (FIO_removeFile(srcFileName)) {\n            /* failed to remove src file */\n            DISPLAYLEVEL(1, \"zstd: %s: %s \\n\", srcFileName, strerror(errno));\n            return 1;\n    }   }\n    return result;\n}\n\n\n\nint FIO_decompressFilename(FIO_ctx_t* const fCtx, FIO_prefs_t* const prefs,\n                           const char* dstFileName, const char* srcFileName,\n                           const char* dictFileName)\n{\n    dRess_t const ress = FIO_createDResources(prefs, dictFileName);\n\n    int const decodingError = FIO_decompressSrcFile(fCtx, prefs, ress, dstFileName, srcFileName);\n\n\n\n    FIO_freeDResources(ress);\n    return decodingError;\n}\n\nstatic const char *suffixList[] = {\n    ZSTD_EXTENSION,\n    TZSTD_EXTENSION,\n#ifndef ZSTD_NODECOMPRESS\n    ZSTD_ALT_EXTENSION,\n#endif\n#ifdef ZSTD_GZDECOMPRESS\n    GZ_EXTENSION,\n    TGZ_EXTENSION,\n#endif\n#ifdef ZSTD_LZMADECOMPRESS\n    LZMA_EXTENSION,\n    XZ_EXTENSION,\n    TXZ_EXTENSION,\n#endif\n#ifdef ZSTD_LZ4DECOMPRESS\n    LZ4_EXTENSION,\n    TLZ4_EXTENSION,\n#endif\n    NULL\n};\n\nstatic const char *suffixListStr =\n    ZSTD_EXTENSION \"/\" TZSTD_EXTENSION\n#ifdef ZSTD_GZDECOMPRESS\n    \"/\" GZ_EXTENSION \"/\" TGZ_EXTENSION\n#endif\n#ifdef ZSTD_LZMADECOMPRESS\n    \"/\" LZMA_EXTENSION \"/\" XZ_EXTENSION \"/\" TXZ_EXTENSION\n#endif\n#ifdef ZSTD_LZ4DECOMPRESS\n    \"/\" LZ4_EXTENSION \"/\" TLZ4_EXTENSION\n#endif\n;\n\n/* FIO_determineDstName() :\n * create a destination filename from a srcFileName.\n * @return a pointer to it.\n * @return == NULL if there is an error */\nstatic const char*\nFIO_determineDstName(const char* srcFileName, const char* outDirName)\n{\n    static size_t dfnbCapacity = 0;\n    static char* dstFileNameBuffer = NULL;   /* using static allocation : this function cannot be multi-threaded */\n    size_t dstFileNameEndPos;\n    char* outDirFilename = NULL;\n    const char* dstSuffix = \"\";\n    size_t dstSuffixLen = 0;\n\n    size_t sfnSize = strlen(srcFileName);\n\n    size_t srcSuffixLen;\n    const char* const srcSuffix = strrchr(srcFileName, '.');\n\n    if(!strcmp(srcFileName, stdinmark)) {\n        return stdoutmark;\n    }\n\n    if (srcSuffix == NULL) {\n        DISPLAYLEVEL(1,\n            \"zstd: %s: unknown suffix (%s expected). \"\n            \"Can't derive the output file name. \"\n            \"Specify it with -o dstFileName. Ignoring.\\n\",\n            srcFileName, suffixListStr);\n        return NULL;\n    }\n    srcSuffixLen = strlen(srcSuffix);\n\n    {\n        const char** matchedSuffixPtr;\n        for (matchedSuffixPtr = suffixList; *matchedSuffixPtr != NULL; matchedSuffixPtr++) {\n            if (!strcmp(*matchedSuffixPtr, srcSuffix)) {\n                break;\n            }\n        }\n\n        /* check suffix is authorized */\n        if (sfnSize <= srcSuffixLen || *matchedSuffixPtr == NULL) {\n            DISPLAYLEVEL(1,\n                \"zstd: %s: unknown suffix (%s expected). \"\n                \"Can't derive the output file name. \"\n                \"Specify it with -o dstFileName. Ignoring.\\n\",\n                srcFileName, suffixListStr);\n            return NULL;\n        }\n\n        if ((*matchedSuffixPtr)[1] == 't') {\n            dstSuffix = \".tar\";\n            dstSuffixLen = strlen(dstSuffix);\n        }\n    }\n\n    if (outDirName) {\n        outDirFilename = FIO_createFilename_fromOutDir(srcFileName, outDirName, 0);\n        sfnSize = strlen(outDirFilename);\n        assert(outDirFilename != NULL);\n    }\n\n    if (dfnbCapacity+srcSuffixLen <= sfnSize+1+dstSuffixLen) {\n        /* allocate enough space to write dstFilename into it */\n        free(dstFileNameBuffer);\n        dfnbCapacity = sfnSize + 20;\n        dstFileNameBuffer = (char*)malloc(dfnbCapacity);\n        if (dstFileNameBuffer==NULL)\n            EXM_THROW(74, \"%s : not enough memory for dstFileName\",\n                      strerror(errno));\n    }\n\n    /* return dst name == src name truncated from suffix */\n    assert(dstFileNameBuffer != NULL);\n    dstFileNameEndPos = sfnSize - srcSuffixLen;\n    if (outDirFilename) {\n        memcpy(dstFileNameBuffer, outDirFilename, dstFileNameEndPos);\n        free(outDirFilename);\n    } else {\n        memcpy(dstFileNameBuffer, srcFileName, dstFileNameEndPos);\n    }\n\n    /* The short tar extensions tzst, tgz, txz and tlz4 files should have \"tar\"\n     * extension on decompression. Also writes terminating null. */\n    strcpy(dstFileNameBuffer + dstFileNameEndPos, dstSuffix);\n    return dstFileNameBuffer;\n\n    /* note : dstFileNameBuffer memory is not going to be free */\n}\n\nint\nFIO_decompressMultipleFilenames(FIO_ctx_t* const fCtx,\n                                FIO_prefs_t* const prefs,\n                                const char** srcNamesTable,\n                                const char* outMirroredRootDirName,\n                                const char* outDirName, const char* outFileName,\n                                const char* dictFileName)\n{\n    int status;\n    int error = 0;\n    dRess_t ress = FIO_createDResources(prefs, dictFileName);\n\n    if (outFileName) {\n        if (FIO_multiFilesConcatWarning(fCtx, prefs, outFileName, 1 /* displayLevelCutoff */)) {\n            FIO_freeDResources(ress);\n            return 1;\n        }\n        if (!prefs->testMode) {\n            FILE* dstFile = FIO_openDstFile(fCtx, prefs, NULL, outFileName, DEFAULT_FILE_PERMISSIONS);\n            if (dstFile == 0) EXM_THROW(19, \"cannot open %s\", outFileName);\n            AIO_WritePool_setFile(ress.writeCtx, dstFile);\n        }\n        for (; fCtx->currFileIdx < fCtx->nbFilesTotal; fCtx->currFileIdx++) {\n            status = FIO_decompressSrcFile(fCtx, prefs, ress, outFileName, srcNamesTable[fCtx->currFileIdx]);\n            if (!status) fCtx->nbFilesProcessed++;\n            error |= status;\n        }\n        if ((!prefs->testMode) && (AIO_WritePool_closeFile(ress.writeCtx)))\n            EXM_THROW(72, \"Write error : %s : cannot properly close output file\",\n                        strerror(errno));\n    } else {\n        if (outMirroredRootDirName)\n            UTIL_mirrorSourceFilesDirectories(srcNamesTable, (unsigned)fCtx->nbFilesTotal, outMirroredRootDirName);\n\n        for (; fCtx->currFileIdx < fCtx->nbFilesTotal; fCtx->currFileIdx++) {   /* create dstFileName */\n            const char* const srcFileName = srcNamesTable[fCtx->currFileIdx];\n            const char* dstFileName = NULL;\n            if (outMirroredRootDirName) {\n                char* validMirroredDirName = UTIL_createMirroredDestDirName(srcFileName, outMirroredRootDirName);\n                if (validMirroredDirName) {\n                    dstFileName = FIO_determineDstName(srcFileName, validMirroredDirName);\n                    free(validMirroredDirName);\n                } else {\n                    DISPLAYLEVEL(2, \"zstd: --output-dir-mirror cannot decompress '%s' into '%s'\\n\", srcFileName, outMirroredRootDirName);\n                }\n            } else {\n                dstFileName = FIO_determineDstName(srcFileName, outDirName);\n            }\n            if (dstFileName == NULL) { error=1; continue; }\n            status = FIO_decompressSrcFile(fCtx, prefs, ress, dstFileName, srcFileName);\n            if (!status) fCtx->nbFilesProcessed++;\n            error |= status;\n        }\n        if (outDirName)\n            FIO_checkFilenameCollisions(srcNamesTable , (unsigned)fCtx->nbFilesTotal);\n    }\n\n    if (FIO_shouldDisplayMultipleFileSummary(fCtx)) {\n        DISPLAY_PROGRESS(\"\\r%79s\\r\", \"\");\n        DISPLAY_SUMMARY(\"%d files decompressed : %6llu bytes total \\n\",\n            fCtx->nbFilesProcessed, (unsigned long long)fCtx->totalBytesOutput);\n    }\n\n    FIO_freeDResources(ress);\n    return error;\n}\n\n/* **************************************************************************\n *  .zst file info (--list command)\n ***************************************************************************/\n\ntypedef struct {\n    U64 decompressedSize;\n    U64 compressedSize;\n    U64 windowSize;\n    int numActualFrames;\n    int numSkippableFrames;\n    int decompUnavailable;\n    int usesCheck;\n    BYTE checksum[4];\n    U32 nbFiles;\n    unsigned dictID;\n} fileInfo_t;\n\ntypedef enum {\n  info_success=0,\n  info_frame_error=1,\n  info_not_zstd=2,\n  info_file_error=3,\n  info_truncated_input=4\n} InfoError;\n\n#define ERROR_IF(c,n,...) {             \\\n    if (c) {                           \\\n        DISPLAYLEVEL(1, __VA_ARGS__);  \\\n        DISPLAYLEVEL(1, \" \\n\");        \\\n        return n;                      \\\n    }                                  \\\n}\n\nstatic InfoError\nFIO_analyzeFrames(fileInfo_t* info, FILE* const srcFile)\n{\n    /* begin analyzing frame */\n    for ( ; ; ) {\n        BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];\n        size_t const numBytesRead = fread(headerBuffer, 1, sizeof(headerBuffer), srcFile);\n        if (numBytesRead < ZSTD_FRAMEHEADERSIZE_MIN(ZSTD_f_zstd1)) {\n            if ( feof(srcFile)\n              && (numBytesRead == 0)\n              && (info->compressedSize > 0)\n              && (info->compressedSize != UTIL_FILESIZE_UNKNOWN) ) {\n                unsigned long long file_position = (unsigned long long) LONG_TELL(srcFile);\n                unsigned long long file_size = (unsigned long long) info->compressedSize;\n                ERROR_IF(file_position != file_size, info_truncated_input,\n                  \"Error: seeked to position %llu, which is beyond file size of %llu\\n\",\n                  file_position,\n                  file_size);\n                break;  /* correct end of file => success */\n            }\n            ERROR_IF(feof(srcFile), info_not_zstd, \"Error: reached end of file with incomplete frame\");\n            ERROR_IF(1, info_frame_error, \"Error: did not reach end of file but ran out of frames\");\n        }\n        {   U32 const magicNumber = MEM_readLE32(headerBuffer);\n            /* Zstandard frame */\n            if (magicNumber == ZSTD_MAGICNUMBER) {\n                ZSTD_FrameHeader header;\n                U64 const frameContentSize = ZSTD_getFrameContentSize(headerBuffer, numBytesRead);\n                if ( frameContentSize == ZSTD_CONTENTSIZE_ERROR\n                  || frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN ) {\n                    info->decompUnavailable = 1;\n                } else {\n                    info->decompressedSize += frameContentSize;\n                }\n                ERROR_IF(ZSTD_getFrameHeader(&header, headerBuffer, numBytesRead) != 0,\n                        info_frame_error, \"Error: could not decode frame header\");\n                if (info->dictID != 0 && info->dictID != header.dictID) {\n                    DISPLAY(\"WARNING: File contains multiple frames with different dictionary IDs. Showing dictID 0 instead\");\n                    info->dictID = 0;\n                } else {\n                    info->dictID = header.dictID;\n                }\n                info->windowSize = header.windowSize;\n                /* move to the end of the frame header */\n                {   size_t const headerSize = ZSTD_frameHeaderSize(headerBuffer, numBytesRead);\n                    ERROR_IF(ZSTD_isError(headerSize), info_frame_error, \"Error: could not determine frame header size\");\n                    ERROR_IF(fseek(srcFile, ((long)headerSize)-((long)numBytesRead), SEEK_CUR) != 0,\n                            info_frame_error, \"Error: could not move to end of frame header\");\n                }\n\n                /* skip all blocks in the frame */\n                {   int lastBlock = 0;\n                    do {\n                        BYTE blockHeaderBuffer[3];\n                        ERROR_IF(fread(blockHeaderBuffer, 1, 3, srcFile) != 3,\n                                info_frame_error, \"Error while reading block header\");\n                        {   U32 const blockHeader = MEM_readLE24(blockHeaderBuffer);\n                            U32 const blockTypeID = (blockHeader >> 1) & 3;\n                            U32 const isRLE = (blockTypeID == 1);\n                            U32 const isWrongBlock = (blockTypeID == 3);\n                            long const blockSize = isRLE ? 1 : (long)(blockHeader >> 3);\n                            ERROR_IF(isWrongBlock, info_frame_error, \"Error: unsupported block type\");\n                            lastBlock = blockHeader & 1;\n                            ERROR_IF(fseek(srcFile, blockSize, SEEK_CUR) != 0,\n                                    info_frame_error, \"Error: could not skip to end of block\");\n                        }\n                    } while (lastBlock != 1);\n                }\n\n                /* check if checksum is used */\n                {   BYTE const frameHeaderDescriptor = headerBuffer[4];\n                    int const contentChecksumFlag = (frameHeaderDescriptor & (1 << 2)) >> 2;\n                    if (contentChecksumFlag) {\n                        info->usesCheck = 1;\n                        ERROR_IF(fread(info->checksum, 1, 4, srcFile) != 4,\n                                info_frame_error, \"Error: could not read checksum\");\n                }   }\n                info->numActualFrames++;\n            }\n            /* Skippable frame */\n            else if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {\n                U32 const frameSize = MEM_readLE32(headerBuffer + 4);\n                long const seek = (long)(8 + frameSize - numBytesRead);\n                ERROR_IF(LONG_SEEK(srcFile, seek, SEEK_CUR) != 0,\n                        info_frame_error, \"Error: could not find end of skippable frame\");\n                info->numSkippableFrames++;\n            }\n            /* unknown content */\n            else {\n                return info_not_zstd;\n            }\n        }  /* magic number analysis */\n    }  /* end analyzing frames */\n    return info_success;\n}\n\n\nstatic InfoError\ngetFileInfo_fileConfirmed(fileInfo_t* info, const char* inFileName)\n{\n    InfoError status;\n    stat_t srcFileStat;\n    FILE* const srcFile = FIO_openSrcFile(NULL, inFileName, &srcFileStat);\n    ERROR_IF(srcFile == NULL, info_file_error, \"Error: could not open source file %s\", inFileName);\n\n    info->compressedSize = UTIL_getFileSizeStat(&srcFileStat);\n    status = FIO_analyzeFrames(info, srcFile);\n\n    fclose(srcFile);\n    info->nbFiles = 1;\n    return status;\n}\n\n\n/** getFileInfo() :\n *  Reads information from file, stores in *info\n * @return : InfoError status\n */\nstatic InfoError\ngetFileInfo(fileInfo_t* info, const char* srcFileName)\n{\n    ERROR_IF(!UTIL_isRegularFile(srcFileName),\n            info_file_error, \"Error : %s is not a file\", srcFileName);\n    return getFileInfo_fileConfirmed(info, srcFileName);\n}\n\n\nstatic void\ndisplayInfo(const char* inFileName, const fileInfo_t* info, int displayLevel)\n{\n    UTIL_HumanReadableSize_t const window_hrs = UTIL_makeHumanReadableSize(info->windowSize);\n    UTIL_HumanReadableSize_t const compressed_hrs = UTIL_makeHumanReadableSize(info->compressedSize);\n    UTIL_HumanReadableSize_t const decompressed_hrs = UTIL_makeHumanReadableSize(info->decompressedSize);\n    double const ratio = (info->compressedSize == 0) ? 0 : ((double)info->decompressedSize)/(double)info->compressedSize;\n    const char* const checkString = (info->usesCheck ? \"XXH64\" : \"None\");\n    if (displayLevel <= 2) {\n        if (!info->decompUnavailable) {\n            DISPLAYOUT(\"%6d  %5d  %6.*f%4s  %8.*f%4s  %5.3f  %5s  %s\\n\",\n                    info->numSkippableFrames + info->numActualFrames,\n                    info->numSkippableFrames,\n                    compressed_hrs.precision, compressed_hrs.value, compressed_hrs.suffix,\n                    decompressed_hrs.precision, decompressed_hrs.value, decompressed_hrs.suffix,\n                    ratio, checkString, inFileName);\n        } else {\n            DISPLAYOUT(\"%6d  %5d  %6.*f%4s                       %5s  %s\\n\",\n                    info->numSkippableFrames + info->numActualFrames,\n                    info->numSkippableFrames,\n                    compressed_hrs.precision, compressed_hrs.value, compressed_hrs.suffix,\n                    checkString, inFileName);\n        }\n    } else {\n        DISPLAYOUT(\"%s \\n\", inFileName);\n        DISPLAYOUT(\"# Zstandard Frames: %d\\n\", info->numActualFrames);\n        if (info->numSkippableFrames)\n            DISPLAYOUT(\"# Skippable Frames: %d\\n\", info->numSkippableFrames);\n        DISPLAYOUT(\"DictID: %u\\n\", info->dictID);\n        DISPLAYOUT(\"Window Size: %.*f%s (%llu B)\\n\",\n                   window_hrs.precision, window_hrs.value, window_hrs.suffix,\n                   (unsigned long long)info->windowSize);\n        DISPLAYOUT(\"Compressed Size: %.*f%s (%llu B)\\n\",\n                    compressed_hrs.precision, compressed_hrs.value, compressed_hrs.suffix,\n                    (unsigned long long)info->compressedSize);\n        if (!info->decompUnavailable) {\n            DISPLAYOUT(\"Decompressed Size: %.*f%s (%llu B)\\n\",\n                    decompressed_hrs.precision, decompressed_hrs.value, decompressed_hrs.suffix,\n                    (unsigned long long)info->decompressedSize);\n            DISPLAYOUT(\"Ratio: %.4f\\n\", ratio);\n        }\n\n        if (info->usesCheck && info->numActualFrames == 1) {\n            DISPLAYOUT(\"Check: %s %02x%02x%02x%02x\\n\", checkString,\n                info->checksum[3], info->checksum[2],\n                info->checksum[1], info->checksum[0]\n            );\n        } else {\n            DISPLAYOUT(\"Check: %s\\n\", checkString);\n        }\n\n        DISPLAYOUT(\"\\n\");\n    }\n}\n\nstatic fileInfo_t FIO_addFInfo(fileInfo_t fi1, fileInfo_t fi2)\n{\n    fileInfo_t total;\n    memset(&total, 0, sizeof(total));\n    total.numActualFrames = fi1.numActualFrames + fi2.numActualFrames;\n    total.numSkippableFrames = fi1.numSkippableFrames + fi2.numSkippableFrames;\n    total.compressedSize = fi1.compressedSize + fi2.compressedSize;\n    total.decompressedSize = fi1.decompressedSize + fi2.decompressedSize;\n    total.decompUnavailable = fi1.decompUnavailable | fi2.decompUnavailable;\n    total.usesCheck = fi1.usesCheck & fi2.usesCheck;\n    total.nbFiles = fi1.nbFiles + fi2.nbFiles;\n    return total;\n}\n\nstatic int\nFIO_listFile(fileInfo_t* total, const char* inFileName, int displayLevel)\n{\n    fileInfo_t info;\n    memset(&info, 0, sizeof(info));\n    {   InfoError const error = getFileInfo(&info, inFileName);\n        switch (error) {\n            case info_frame_error:\n                /* display error, but provide output */\n                DISPLAYLEVEL(1, \"Error while parsing \\\"%s\\\" \\n\", inFileName);\n                break;\n            case info_not_zstd:\n                DISPLAYOUT(\"File \\\"%s\\\" not compressed by zstd \\n\", inFileName);\n                if (displayLevel > 2) DISPLAYOUT(\"\\n\");\n                return 1;\n            case info_file_error:\n                /* error occurred while opening the file */\n                if (displayLevel > 2) DISPLAYOUT(\"\\n\");\n                return 1;\n            case info_truncated_input:\n                DISPLAYOUT(\"File \\\"%s\\\" is truncated \\n\", inFileName);\n                if (displayLevel > 2) DISPLAYOUT(\"\\n\");\n                return 1;\n            case info_success:\n            default:\n                break;\n        }\n\n        displayInfo(inFileName, &info, displayLevel);\n        *total = FIO_addFInfo(*total, info);\n        assert(error == info_success || error == info_frame_error);\n        return (int)error;\n    }\n}\n\nint FIO_listMultipleFiles(unsigned numFiles, const char** filenameTable, int displayLevel)\n{\n    /* ensure no specified input is stdin (needs fseek() capability) */\n    {   unsigned u;\n        for (u=0; u<numFiles;u++) {\n            ERROR_IF(!strcmp (filenameTable[u], stdinmark),\n                    1, \"zstd: --list does not support reading from standard input\");\n    }   }\n\n    if (numFiles == 0) {\n        if (!UTIL_isConsole(stdin)) {\n            DISPLAYLEVEL(1, \"zstd: --list does not support reading from standard input \\n\");\n        }\n        DISPLAYLEVEL(1, \"No files given \\n\");\n        return 1;\n    }\n\n    if (displayLevel <= 2) {\n        DISPLAYOUT(\"Frames  Skips  Compressed  Uncompressed  Ratio  Check  Filename\\n\");\n    }\n    {   int error = 0;\n        fileInfo_t total;\n        memset(&total, 0, sizeof(total));\n        total.usesCheck = 1;\n        /* --list each file, and check for any error */\n        {   unsigned u;\n            for (u=0; u<numFiles;u++) {\n                error |= FIO_listFile(&total, filenameTable[u], displayLevel);\n        }   }\n        if (numFiles > 1 && displayLevel <= 2) {   /* display total */\n            UTIL_HumanReadableSize_t const compressed_hrs = UTIL_makeHumanReadableSize(total.compressedSize);\n            UTIL_HumanReadableSize_t const decompressed_hrs = UTIL_makeHumanReadableSize(total.decompressedSize);\n            double const ratio = (total.compressedSize == 0) ? 0 : ((double)total.decompressedSize)/(double)total.compressedSize;\n            const char* const checkString = (total.usesCheck ? \"XXH64\" : \"\");\n            DISPLAYOUT(\"----------------------------------------------------------------- \\n\");\n            if (total.decompUnavailable) {\n                DISPLAYOUT(\"%6d  %5d  %6.*f%4s                       %5s  %u files\\n\",\n                        total.numSkippableFrames + total.numActualFrames,\n                        total.numSkippableFrames,\n                        compressed_hrs.precision, compressed_hrs.value, compressed_hrs.suffix,\n                        checkString, (unsigned)total.nbFiles);\n            } else {\n                DISPLAYOUT(\"%6d  %5d  %6.*f%4s  %8.*f%4s  %5.3f  %5s  %u files\\n\",\n                        total.numSkippableFrames + total.numActualFrames,\n                        total.numSkippableFrames,\n                        compressed_hrs.precision, compressed_hrs.value, compressed_hrs.suffix,\n                        decompressed_hrs.precision, decompressed_hrs.value, decompressed_hrs.suffix,\n                        ratio, checkString, (unsigned)total.nbFiles);\n        }   }\n        return error;\n    }\n}\n\n\n#endif /* #ifndef ZSTD_NODECOMPRESS */\n"
  },
  {
    "path": "programs/fileio.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n#ifndef FILEIO_H_23981798732\n#define FILEIO_H_23981798732\n\n#include \"fileio_types.h\"\n#include \"util.h\"                  /* FileNamesTable */\n#define ZSTD_STATIC_LINKING_ONLY   /* ZSTD_compressionParameters */\n#include \"../lib/zstd.h\"           /* ZSTD_* */\n\n/* *************************************\n*  Special i/o constants\n**************************************/\n#define stdinmark  \"/*stdin*\\\\\"\n#define stdoutmark \"/*stdout*\\\\\"\n#ifdef _WIN32\n#  define nulmark \"NUL\"\n#else\n#  define nulmark \"/dev/null\"\n#endif\n\n/**\n * We test whether the extension we found starts with 't', and if so, we append\n * \".tar\" to the end of the output name.\n */\n#define LZMA_EXTENSION  \".lzma\"\n#define XZ_EXTENSION    \".xz\"\n#define TXZ_EXTENSION   \".txz\"\n\n#define GZ_EXTENSION    \".gz\"\n#define TGZ_EXTENSION   \".tgz\"\n\n#define ZSTD_EXTENSION  \".zst\"\n#define TZSTD_EXTENSION \".tzst\"\n#define ZSTD_ALT_EXTENSION  \".zstd\" /* allow decompression of .zstd files */\n\n#define LZ4_EXTENSION   \".lz4\"\n#define TLZ4_EXTENSION  \".tlz4\"\n\n\n/*-*************************************\n*  Types\n***************************************/\nFIO_prefs_t* FIO_createPreferences(void);\nvoid FIO_freePreferences(FIO_prefs_t* const prefs);\n\n/* Mutable struct containing relevant context and state regarding (de)compression with respect to file I/O */\ntypedef struct FIO_ctx_s FIO_ctx_t;\n\nFIO_ctx_t* FIO_createContext(void);\nvoid FIO_freeContext(FIO_ctx_t* const fCtx);\n\n\n/*-*************************************\n*  Parameters\n***************************************/\n/* FIO_prefs_t functions */\nvoid FIO_setCompressionType(FIO_prefs_t* const prefs, FIO_compressionType_t compressionType);\nvoid FIO_overwriteMode(FIO_prefs_t* const prefs);\nvoid FIO_setAdaptiveMode(FIO_prefs_t* const prefs, int adapt);\nvoid FIO_setAdaptMin(FIO_prefs_t* const prefs, int minCLevel);\nvoid FIO_setAdaptMax(FIO_prefs_t* const prefs, int maxCLevel);\nvoid FIO_setUseRowMatchFinder(FIO_prefs_t* const prefs, int useRowMatchFinder);\nvoid FIO_setJobSize(FIO_prefs_t* const prefs, int jobSize);\nvoid FIO_setChecksumFlag(FIO_prefs_t* const prefs, int checksumFlag);\nvoid FIO_setDictIDFlag(FIO_prefs_t* const prefs, int dictIDFlag);\nvoid FIO_setLdmBucketSizeLog(FIO_prefs_t* const prefs, int ldmBucketSizeLog);\nvoid FIO_setLdmFlag(FIO_prefs_t* const prefs, unsigned ldmFlag);\nvoid FIO_setLdmHashRateLog(FIO_prefs_t* const prefs, int ldmHashRateLog);\nvoid FIO_setLdmHashLog(FIO_prefs_t* const prefs, int ldmHashLog);\nvoid FIO_setLdmMinMatch(FIO_prefs_t* const prefs, int ldmMinMatch);\nvoid FIO_setMemLimit(FIO_prefs_t* const prefs, unsigned memLimit);\nvoid FIO_setNbWorkers(FIO_prefs_t* const prefs, int nbWorkers);\nvoid FIO_setOverlapLog(FIO_prefs_t* const prefs, int overlapLog);\nvoid FIO_setRemoveSrcFile(FIO_prefs_t* const prefs, int flag);\nvoid FIO_setSparseWrite(FIO_prefs_t* const prefs, int sparse);  /**< 0: no sparse; 1: disable on stdout; 2: always enabled */\nvoid FIO_setRsyncable(FIO_prefs_t* const prefs, int rsyncable);\nvoid FIO_setStreamSrcSize(FIO_prefs_t* const prefs, size_t streamSrcSize);\nvoid FIO_setTargetCBlockSize(FIO_prefs_t* const prefs, size_t targetCBlockSize);\nvoid FIO_setSrcSizeHint(FIO_prefs_t* const prefs, size_t srcSizeHint);\nvoid FIO_setTestMode(FIO_prefs_t* const prefs, int testMode);\nvoid FIO_setLiteralCompressionMode(\n        FIO_prefs_t* const prefs,\n        ZSTD_ParamSwitch_e mode);\n\nvoid FIO_setProgressSetting(FIO_progressSetting_e progressSetting);\nvoid FIO_setNotificationLevel(int level);\nvoid FIO_setExcludeCompressedFile(FIO_prefs_t* const prefs, int excludeCompressedFiles);\nvoid FIO_setAllowBlockDevices(FIO_prefs_t* const prefs, int allowBlockDevices);\nvoid FIO_setPatchFromMode(FIO_prefs_t* const prefs, int value);\nvoid FIO_setContentSize(FIO_prefs_t* const prefs, int value);\nvoid FIO_displayCompressionParameters(const FIO_prefs_t* prefs);\nvoid FIO_setAsyncIOFlag(FIO_prefs_t* const prefs, int value);\nvoid FIO_setPassThroughFlag(FIO_prefs_t* const prefs, int value);\nvoid FIO_setMMapDict(FIO_prefs_t* const prefs, ZSTD_ParamSwitch_e value);\n\n/* FIO_ctx_t functions */\nvoid FIO_setNbFilesTotal(FIO_ctx_t* const fCtx, int value);\nvoid FIO_setHasStdoutOutput(FIO_ctx_t* const fCtx, int value);\nvoid FIO_determineHasStdinInput(FIO_ctx_t* const fCtx, const FileNamesTable* const filenames);\n\n/*-*************************************\n*  Single File functions\n***************************************/\n/** FIO_compressFilename() :\n * @return : 0 == ok;  1 == pb with src file. */\nint FIO_compressFilename (FIO_ctx_t* const fCtx, FIO_prefs_t* const prefs,\n                          const char* outfilename, const char* infilename,\n                          const char* dictFileName, int compressionLevel,\n                          ZSTD_compressionParameters comprParams);\n\n/** FIO_decompressFilename() :\n * @return : 0 == ok;  1 == pb with src file. */\nint FIO_decompressFilename (FIO_ctx_t* const fCtx, FIO_prefs_t* const prefs,\n                            const char* outfilename, const char* infilename, const char* dictFileName);\n\nint FIO_listMultipleFiles(unsigned numFiles, const char** filenameTable, int displayLevel);\n\n\n/*-*************************************\n*  Multiple File functions\n***************************************/\n/** FIO_compressMultipleFilenames() :\n * @return : nb of missing files */\nint FIO_compressMultipleFilenames(FIO_ctx_t* const fCtx,\n                                  FIO_prefs_t* const prefs,\n                                  const char** inFileNamesTable,\n                                  const char* outMirroredDirName,\n                                  const char* outDirName,\n                                  const char* outFileName, const char* suffix,\n                                  const char* dictFileName, int compressionLevel,\n                                  ZSTD_compressionParameters comprParams);\n\n/** FIO_decompressMultipleFilenames() :\n * @return : nb of missing or skipped files */\nint FIO_decompressMultipleFilenames(FIO_ctx_t* const fCtx,\n                                    FIO_prefs_t* const prefs,\n                                    const char** srcNamesTable,\n                                    const char* outMirroredDirName,\n                                    const char* outDirName,\n                                    const char* outFileName,\n                                    const char* dictFileName);\n\n/* FIO_checkFilenameCollisions() :\n * Checks for and warns if there are any files that would have the same output path\n */\nint FIO_checkFilenameCollisions(const char** filenameTable, unsigned nbFiles);\n\n\n\n/*-*************************************\n*  Advanced stuff (should actually be hosted elsewhere)\n***************************************/\n\n/* custom crash signal handler */\nvoid FIO_addAbortHandler(void);\n\nchar const* FIO_zlibVersion(void);\nchar const* FIO_lz4Version(void);\nchar const* FIO_lzmaVersion(void);\n\n#endif  /* FILEIO_H_23981798732 */\n"
  },
  {
    "path": "programs/fileio_asyncio.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"platform.h\"\n#include <stdio.h>      /* fprintf, open, fdopen, fread, _fileno, stdin, stdout */\n#include <stdlib.h>     /* malloc, free */\n#include <assert.h>\n#include <errno.h>      /* errno */\n\n#if defined (_MSC_VER)\n#  include <sys/stat.h>\n#  include <io.h>\n#endif\n\n#include \"fileio_asyncio.h\"\n#include \"fileio_common.h\"\n\n/* **********************************************************************\n *  Sparse write\n ************************************************************************/\n\n/** AIO_fwriteSparse() :\n*  @return : storedSkips,\n*            argument for next call to AIO_fwriteSparse() or AIO_fwriteSparseEnd() */\nstatic unsigned\nAIO_fwriteSparse(FILE* file,\n                 const void* buffer, size_t bufferSize,\n                 const FIO_prefs_t* const prefs,\n                 unsigned storedSkips)\n{\n    const size_t* const bufferT = (const size_t*)buffer;   /* Buffer is supposed malloc'ed, hence aligned on size_t */\n    size_t bufferSizeT = bufferSize / sizeof(size_t);\n    const size_t* const bufferTEnd = bufferT + bufferSizeT;\n    const size_t* ptrT = bufferT;\n    static const size_t segmentSizeT = (32 KB) / sizeof(size_t);   /* check every 32 KB */\n\n    if (prefs->testMode) return 0;  /* do not output anything in test mode */\n\n    if (!prefs->sparseFileSupport) {  /* normal write */\n        size_t const sizeCheck = fwrite(buffer, 1, bufferSize, file);\n        if (sizeCheck != bufferSize)\n            EXM_THROW(70, \"Write error : cannot write block : %s\",\n                      strerror(errno));\n        return 0;\n    }\n\n    /* avoid int overflow */\n    if (storedSkips > 1 GB) {\n        if (LONG_SEEK(file, 1 GB, SEEK_CUR) != 0)\n        EXM_THROW(91, \"1 GB skip error (sparse file support)\");\n        storedSkips -= 1 GB;\n    }\n\n    while (ptrT < bufferTEnd) {\n        size_t nb0T;\n\n        /* adjust last segment if < 32 KB */\n        size_t seg0SizeT = segmentSizeT;\n        if (seg0SizeT > bufferSizeT) seg0SizeT = bufferSizeT;\n        bufferSizeT -= seg0SizeT;\n\n        /* count leading zeroes */\n        for (nb0T=0; (nb0T < seg0SizeT) && (ptrT[nb0T] == 0); nb0T++) ;\n        storedSkips += (unsigned)(nb0T * sizeof(size_t));\n\n        if (nb0T != seg0SizeT) {   /* not all 0s */\n            size_t const nbNon0ST = seg0SizeT - nb0T;\n            /* skip leading zeros */\n            if (LONG_SEEK(file, storedSkips, SEEK_CUR) != 0)\n                EXM_THROW(92, \"Sparse skip error ; try --no-sparse\");\n            storedSkips = 0;\n            /* write the rest */\n            if (fwrite(ptrT + nb0T, sizeof(size_t), nbNon0ST, file) != nbNon0ST)\n                EXM_THROW(93, \"Write error : cannot write block : %s\",\n                          strerror(errno));\n        }\n        ptrT += seg0SizeT;\n    }\n\n    {   static size_t const maskT = sizeof(size_t)-1;\n        if (bufferSize & maskT) {\n            /* size not multiple of sizeof(size_t) : implies end of block */\n            const char* const restStart = (const char*)bufferTEnd;\n            const char* restPtr = restStart;\n            const char* const restEnd = (const char*)buffer + bufferSize;\n            assert(restEnd > restStart && restEnd < restStart + sizeof(size_t));\n            for ( ; (restPtr < restEnd) && (*restPtr == 0); restPtr++) ;\n            storedSkips += (unsigned) (restPtr - restStart);\n            if (restPtr != restEnd) {\n                /* not all remaining bytes are 0 */\n                size_t const restSize = (size_t)(restEnd - restPtr);\n                if (LONG_SEEK(file, storedSkips, SEEK_CUR) != 0)\n                    EXM_THROW(92, \"Sparse skip error ; try --no-sparse\");\n                if (fwrite(restPtr, 1, restSize, file) != restSize)\n                    EXM_THROW(95, \"Write error : cannot write end of decoded block : %s\",\n                              strerror(errno));\n                storedSkips = 0;\n            }   }   }\n\n    return storedSkips;\n}\n\nstatic void\nAIO_fwriteSparseEnd(const FIO_prefs_t* const prefs, FILE* file, unsigned storedSkips)\n{\n    if (prefs->testMode) assert(storedSkips == 0);\n    if (storedSkips>0) {\n        assert(prefs->sparseFileSupport > 0);  /* storedSkips>0 implies sparse support is enabled */\n        (void)prefs;   /* assert can be disabled, in which case prefs becomes unused */\n        if (LONG_SEEK(file, storedSkips-1, SEEK_CUR) != 0)\n            EXM_THROW(69, \"Final skip error (sparse file support)\");\n        /* last zero must be explicitly written,\n         * so that skipped ones get implicitly translated as zero by FS */\n        {   const char lastZeroByte[1] = { 0 };\n            if (fwrite(lastZeroByte, 1, 1, file) != 1)\n                EXM_THROW(69, \"Write error : cannot write last zero : %s\", strerror(errno));\n        }   }\n}\n\n\n/* **********************************************************************\n *  AsyncIO functionality\n ************************************************************************/\n\n/* AIO_supported:\n * Returns 1 if AsyncIO is supported on the system, 0 otherwise. */\nint AIO_supported(void) {\n#ifdef ZSTD_MULTITHREAD\n    return 1;\n#else\n    return 0;\n#endif\n}\n\n/* ***********************************\n *  Generic IoPool implementation\n *************************************/\n\nstatic IOJob_t *AIO_IOPool_createIoJob(IOPoolCtx_t *ctx, size_t bufferSize) {\n    IOJob_t* const job  = (IOJob_t*) malloc(sizeof(IOJob_t));\n    void* const buffer = malloc(bufferSize);\n    if(!job || !buffer)\n        EXM_THROW(101, \"Allocation error : not enough memory\");\n    job->buffer = buffer;\n    job->bufferSize = bufferSize;\n    job->usedBufferSize = 0;\n    job->file = NULL;\n    job->ctx = ctx;\n    job->offset = 0;\n    return job;\n}\n\n\n/* AIO_IOPool_createThreadPool:\n * Creates a thread pool and a mutex for threaded IO pool.\n * Displays warning if asyncio is requested but MT isn't available. */\nstatic void AIO_IOPool_createThreadPool(IOPoolCtx_t* ctx, const FIO_prefs_t* prefs) {\n    ctx->threadPool = NULL;\n    ctx->threadPoolActive = 0;\n    if(prefs->asyncIO) {\n        if (ZSTD_pthread_mutex_init(&ctx->ioJobsMutex, NULL))\n            EXM_THROW(102,\"Failed creating ioJobsMutex mutex\");\n        /* We want MAX_IO_JOBS-2 queue items because we need to always have 1 free buffer to\n         * decompress into and 1 buffer that's actively written to disk and owned by the writing thread. */\n        assert(MAX_IO_JOBS >= 2);\n        ctx->threadPool = POOL_create(1, MAX_IO_JOBS - 2);\n        ctx->threadPoolActive = 1;\n        if (!ctx->threadPool)\n            EXM_THROW(104, \"Failed creating I/O thread pool\");\n    }\n}\n\n/* AIO_IOPool_init:\n * Allocates and sets and a new I/O thread pool including its included availableJobs. */\nstatic void AIO_IOPool_init(IOPoolCtx_t* ctx, const FIO_prefs_t* prefs, POOL_function poolFunction, size_t bufferSize) {\n    int i;\n    AIO_IOPool_createThreadPool(ctx, prefs);\n    ctx->prefs = prefs;\n    ctx->poolFunction = poolFunction;\n    ctx->totalIoJobs = ctx->threadPool ? MAX_IO_JOBS : 2;\n    ctx->availableJobsCount = ctx->totalIoJobs;\n    for(i=0; i < ctx->availableJobsCount; i++) {\n        ctx->availableJobs[i] = AIO_IOPool_createIoJob(ctx, bufferSize);\n    }\n    ctx->jobBufferSize = bufferSize;\n    ctx->file = NULL;\n}\n\n\n/* AIO_IOPool_threadPoolActive:\n * Check if current operation uses thread pool.\n * Note that in some cases we have a thread pool initialized but choose not to use it. */\nstatic int AIO_IOPool_threadPoolActive(IOPoolCtx_t* ctx) {\n    return ctx->threadPool && ctx->threadPoolActive;\n}\n\n\n/* AIO_IOPool_lockJobsMutex:\n * Locks the IO jobs mutex if threading is active */\nstatic void AIO_IOPool_lockJobsMutex(IOPoolCtx_t* ctx) {\n    if(AIO_IOPool_threadPoolActive(ctx))\n        ZSTD_pthread_mutex_lock(&ctx->ioJobsMutex);\n}\n\n/* AIO_IOPool_unlockJobsMutex:\n * Unlocks the IO jobs mutex if threading is active */\nstatic void AIO_IOPool_unlockJobsMutex(IOPoolCtx_t* ctx) {\n    if(AIO_IOPool_threadPoolActive(ctx))\n        ZSTD_pthread_mutex_unlock(&ctx->ioJobsMutex);\n}\n\n/* AIO_IOPool_releaseIoJob:\n * Releases an acquired job back to the pool. Doesn't execute the job. */\nstatic void AIO_IOPool_releaseIoJob(IOJob_t* job) {\n    IOPoolCtx_t* const ctx = (IOPoolCtx_t *) job->ctx;\n    AIO_IOPool_lockJobsMutex(ctx);\n    assert(ctx->availableJobsCount < ctx->totalIoJobs);\n    ctx->availableJobs[ctx->availableJobsCount++] = job;\n    AIO_IOPool_unlockJobsMutex(ctx);\n}\n\n/* AIO_IOPool_join:\n * Waits for all tasks in the pool to finish executing. */\nstatic void AIO_IOPool_join(IOPoolCtx_t* ctx) {\n    if(AIO_IOPool_threadPoolActive(ctx))\n        POOL_joinJobs(ctx->threadPool);\n}\n\n/* AIO_IOPool_setThreaded:\n * Allows (de)activating threaded mode, to be used when the expected overhead\n * of threading costs more than the expected gains. */\nstatic void AIO_IOPool_setThreaded(IOPoolCtx_t* ctx, int threaded) {\n    assert(threaded == 0 || threaded == 1);\n    assert(ctx != NULL);\n    if(ctx->threadPoolActive != threaded) {\n        AIO_IOPool_join(ctx);\n        ctx->threadPoolActive = threaded;\n    }\n}\n\n/* AIO_IOPool_free:\n * Release a previously allocated IO thread pool. Makes sure all tasks are done and released. */\nstatic void AIO_IOPool_destroy(IOPoolCtx_t* ctx) {\n    int i;\n    if(ctx->threadPool) {\n        /* Make sure we finish all tasks and then free the resources */\n        AIO_IOPool_join(ctx);\n        /* Make sure we are not leaking availableJobs */\n        assert(ctx->availableJobsCount == ctx->totalIoJobs);\n        POOL_free(ctx->threadPool);\n        ZSTD_pthread_mutex_destroy(&ctx->ioJobsMutex);\n    }\n    assert(ctx->file == NULL);\n    for(i=0; i<ctx->availableJobsCount; i++) {\n        IOJob_t* job = (IOJob_t*) ctx->availableJobs[i];\n        free(job->buffer);\n        free(job);\n    }\n}\n\n/* AIO_IOPool_acquireJob:\n * Returns an available io job to be used for a future io. */\nstatic IOJob_t* AIO_IOPool_acquireJob(IOPoolCtx_t* ctx) {\n    IOJob_t* job;\n    assert(ctx->file != NULL || ctx->prefs->testMode);\n    AIO_IOPool_lockJobsMutex(ctx);\n    assert(ctx->availableJobsCount > 0);\n    job = (IOJob_t*) ctx->availableJobs[--ctx->availableJobsCount];\n    AIO_IOPool_unlockJobsMutex(ctx);\n    job->usedBufferSize = 0;\n    job->file = ctx->file;\n    job->offset = 0;\n    return job;\n}\n\n\n/* AIO_IOPool_setFile:\n * Sets the destination file for future files in the pool.\n * Requires completion of all queued jobs and release of all otherwise acquired jobs. */\nstatic void AIO_IOPool_setFile(IOPoolCtx_t* ctx, FILE* file) {\n    assert(ctx!=NULL);\n    AIO_IOPool_join(ctx);\n    assert(ctx->availableJobsCount == ctx->totalIoJobs);\n    ctx->file = file;\n}\n\nstatic FILE* AIO_IOPool_getFile(const IOPoolCtx_t* ctx) {\n    return ctx->file;\n}\n\n/* AIO_IOPool_enqueueJob:\n * Enqueues an io job for execution.\n * The queued job shouldn't be used directly after queueing it. */\nstatic void AIO_IOPool_enqueueJob(IOJob_t* job) {\n    IOPoolCtx_t* const ctx = (IOPoolCtx_t *)job->ctx;\n    if(AIO_IOPool_threadPoolActive(ctx))\n        POOL_add(ctx->threadPool, ctx->poolFunction, job);\n    else\n        ctx->poolFunction(job);\n}\n\n/* ***********************************\n *  WritePool implementation\n *************************************/\n\n/* AIO_WritePool_acquireJob:\n * Returns an available write job to be used for a future write. */\nIOJob_t* AIO_WritePool_acquireJob(WritePoolCtx_t* ctx) {\n    return AIO_IOPool_acquireJob(&ctx->base);\n}\n\n/* AIO_WritePool_enqueueAndReacquireWriteJob:\n * Queues a write job for execution and acquires a new one.\n * After execution `job`'s pointed value would change to the newly acquired job.\n * Make sure to set `usedBufferSize` to the wanted length before call.\n * The queued job shouldn't be used directly after queueing it. */\nvoid AIO_WritePool_enqueueAndReacquireWriteJob(IOJob_t **job) {\n    AIO_IOPool_enqueueJob(*job);\n    *job = AIO_IOPool_acquireJob((IOPoolCtx_t *)(*job)->ctx);\n}\n\n/* AIO_WritePool_sparseWriteEnd:\n * Ends sparse writes to the current file.\n * Blocks on completion of all current write jobs before executing. */\nvoid AIO_WritePool_sparseWriteEnd(WritePoolCtx_t* ctx) {\n    assert(ctx != NULL);\n    AIO_IOPool_join(&ctx->base);\n    AIO_fwriteSparseEnd(ctx->base.prefs, ctx->base.file, ctx->storedSkips);\n    ctx->storedSkips = 0;\n}\n\n/* AIO_WritePool_setFile:\n * Sets the destination file for future writes in the pool.\n * Requires completion of all queues write jobs and release of all otherwise acquired jobs.\n * Also requires ending of sparse write if a previous file was used in sparse mode. */\nvoid AIO_WritePool_setFile(WritePoolCtx_t* ctx, FILE* file) {\n    AIO_IOPool_setFile(&ctx->base, file);\n    assert(ctx->storedSkips == 0);\n}\n\n/* AIO_WritePool_getFile:\n * Returns the file the writePool is currently set to write to. */\nFILE* AIO_WritePool_getFile(const WritePoolCtx_t* ctx) {\n    return AIO_IOPool_getFile(&ctx->base);\n}\n\n/* AIO_WritePool_releaseIoJob:\n * Releases an acquired job back to the pool. Doesn't execute the job. */\nvoid AIO_WritePool_releaseIoJob(IOJob_t* job) {\n    AIO_IOPool_releaseIoJob(job);\n}\n\n/* AIO_WritePool_closeFile:\n * Ends sparse write and closes the writePool's current file and sets the file to NULL.\n * Requires completion of all queues write jobs and release of all otherwise acquired jobs.  */\nint AIO_WritePool_closeFile(WritePoolCtx_t* ctx) {\n    FILE* const dstFile = ctx->base.file;\n    assert(dstFile!=NULL || ctx->base.prefs->testMode!=0);\n    AIO_WritePool_sparseWriteEnd(ctx);\n    AIO_IOPool_setFile(&ctx->base, NULL);\n    return fclose(dstFile);\n}\n\n/* AIO_WritePool_executeWriteJob:\n * Executes a write job synchronously. Can be used as a function for a thread pool. */\nstatic void AIO_WritePool_executeWriteJob(void* opaque){\n    IOJob_t* const job = (IOJob_t*) opaque;\n    WritePoolCtx_t* const ctx = (WritePoolCtx_t*) job->ctx;\n    ctx->storedSkips = AIO_fwriteSparse(job->file, job->buffer, job->usedBufferSize, ctx->base.prefs, ctx->storedSkips);\n    AIO_IOPool_releaseIoJob(job);\n}\n\n/* AIO_WritePool_create:\n * Allocates and sets and a new write pool including its included jobs. */\nWritePoolCtx_t* AIO_WritePool_create(const FIO_prefs_t* prefs, size_t bufferSize) {\n    WritePoolCtx_t* const ctx = (WritePoolCtx_t*) malloc(sizeof(WritePoolCtx_t));\n    if(!ctx) EXM_THROW(100, \"Allocation error : not enough memory\");\n    AIO_IOPool_init(&ctx->base, prefs, AIO_WritePool_executeWriteJob, bufferSize);\n    ctx->storedSkips = 0;\n    return ctx;\n}\n\n/* AIO_WritePool_free:\n * Frees and releases a writePool and its resources. Closes destination file if needs to. */\nvoid AIO_WritePool_free(WritePoolCtx_t* ctx) {\n    /* Make sure we finish all tasks and then free the resources */\n    if(AIO_WritePool_getFile(ctx))\n        AIO_WritePool_closeFile(ctx);\n    AIO_IOPool_destroy(&ctx->base);\n    assert(ctx->storedSkips==0);\n    free(ctx);\n}\n\n/* AIO_WritePool_setAsync:\n * Allows (de)activating async mode, to be used when the expected overhead\n * of asyncio costs more than the expected gains. */\nvoid AIO_WritePool_setAsync(WritePoolCtx_t* ctx, int async) {\n    AIO_IOPool_setThreaded(&ctx->base, async);\n}\n\n\n/* ***********************************\n *  ReadPool implementation\n *************************************/\nstatic void AIO_ReadPool_releaseAllCompletedJobs(ReadPoolCtx_t* ctx) {\n    int i;\n    for(i=0; i<ctx->completedJobsCount; i++) {\n        IOJob_t* job = (IOJob_t*) ctx->completedJobs[i];\n        AIO_IOPool_releaseIoJob(job);\n    }\n    ctx->completedJobsCount = 0;\n}\n\nstatic void AIO_ReadPool_addJobToCompleted(IOJob_t* job) {\n    ReadPoolCtx_t* const ctx = (ReadPoolCtx_t *)job->ctx;\n    AIO_IOPool_lockJobsMutex(&ctx->base);\n    assert(ctx->completedJobsCount < MAX_IO_JOBS);\n    ctx->completedJobs[ctx->completedJobsCount++] = job;\n    if(AIO_IOPool_threadPoolActive(&ctx->base)) {\n        ZSTD_pthread_cond_signal(&ctx->jobCompletedCond);\n    }\n    AIO_IOPool_unlockJobsMutex(&ctx->base);\n}\n\n/* AIO_ReadPool_findNextWaitingOffsetCompletedJob_locked:\n * Looks through the completed jobs for a job matching the waitingOnOffset and returns it,\n * if job wasn't found returns NULL.\n * IMPORTANT: assumes ioJobsMutex is locked. */\nstatic IOJob_t* AIO_ReadPool_findNextWaitingOffsetCompletedJob_locked(ReadPoolCtx_t* ctx) {\n    IOJob_t *job = NULL;\n    int i;\n    /* This implementation goes through all completed jobs and looks for the one matching the next offset.\n     * While not strictly needed for a single threaded reader implementation (as in such a case we could expect\n     * reads to be completed in order) this implementation was chosen as it better fits other asyncio\n     * interfaces (such as io_uring) that do not provide promises regarding order of completion. */\n    for (i=0; i<ctx->completedJobsCount; i++) {\n        job = (IOJob_t *) ctx->completedJobs[i];\n        if (job->offset == ctx->waitingOnOffset) {\n            ctx->completedJobs[i] = ctx->completedJobs[--ctx->completedJobsCount];\n            return job;\n        }\n    }\n    return NULL;\n}\n\n/* AIO_ReadPool_numReadsInFlight:\n * Returns the number of IO read jobs currently in flight. */\nstatic size_t AIO_ReadPool_numReadsInFlight(ReadPoolCtx_t* ctx) {\n    const int jobsHeld = (ctx->currentJobHeld==NULL ? 0 : 1);\n    return (size_t)(ctx->base.totalIoJobs - (ctx->base.availableJobsCount + ctx->completedJobsCount + jobsHeld));\n}\n\n/* AIO_ReadPool_getNextCompletedJob:\n * Returns a completed IOJob_t for the next read in line based on waitingOnOffset and advances waitingOnOffset.\n * Would block. */\nstatic IOJob_t* AIO_ReadPool_getNextCompletedJob(ReadPoolCtx_t* ctx) {\n    IOJob_t *job = NULL;\n    AIO_IOPool_lockJobsMutex(&ctx->base);\n\n    job = AIO_ReadPool_findNextWaitingOffsetCompletedJob_locked(ctx);\n\n    /* As long as we didn't find the job matching the next read, and we have some reads in flight continue waiting */\n    while (!job && (AIO_ReadPool_numReadsInFlight(ctx) > 0)) {\n        assert(ctx->base.threadPool != NULL); /* we shouldn't be here if we work in sync mode */\n        ZSTD_pthread_cond_wait(&ctx->jobCompletedCond, &ctx->base.ioJobsMutex);\n        job = AIO_ReadPool_findNextWaitingOffsetCompletedJob_locked(ctx);\n    }\n\n    if(job) {\n        assert(job->offset == ctx->waitingOnOffset);\n        ctx->waitingOnOffset += job->usedBufferSize;\n    }\n\n    AIO_IOPool_unlockJobsMutex(&ctx->base);\n    return job;\n}\n\n\n/* AIO_ReadPool_executeReadJob:\n * Executes a read job synchronously. Can be used as a function for a thread pool. */\nstatic void AIO_ReadPool_executeReadJob(void* opaque){\n    IOJob_t* const job = (IOJob_t*) opaque;\n    ReadPoolCtx_t* const ctx = (ReadPoolCtx_t *)job->ctx;\n    if(ctx->reachedEof) {\n        job->usedBufferSize = 0;\n        AIO_ReadPool_addJobToCompleted(job);\n        return;\n    }\n    job->usedBufferSize = fread(job->buffer, 1, job->bufferSize, job->file);\n    if(job->usedBufferSize < job->bufferSize) {\n        if(ferror(job->file)) {\n            EXM_THROW(37, \"Read error\");\n        } else if(feof(job->file)) {\n            ctx->reachedEof = 1;\n        } else {\n            EXM_THROW(37, \"Unexpected short read\");\n        }\n    }\n    AIO_ReadPool_addJobToCompleted(job);\n}\n\nstatic void AIO_ReadPool_enqueueRead(ReadPoolCtx_t* ctx) {\n    IOJob_t* const job = AIO_IOPool_acquireJob(&ctx->base);\n    job->offset = ctx->nextReadOffset;\n    ctx->nextReadOffset += job->bufferSize;\n    AIO_IOPool_enqueueJob(job);\n}\n\nstatic void AIO_ReadPool_startReading(ReadPoolCtx_t* ctx) {\n    while(ctx->base.availableJobsCount) {\n        AIO_ReadPool_enqueueRead(ctx);\n    }\n}\n\n/* AIO_ReadPool_setFile:\n * Sets the source file for future read in the pool. Initiates reading immediately if file is not NULL.\n * Waits for all current enqueued tasks to complete if a previous file was set. */\nvoid AIO_ReadPool_setFile(ReadPoolCtx_t* ctx, FILE* file) {\n    assert(ctx!=NULL);\n    AIO_IOPool_join(&ctx->base);\n    AIO_ReadPool_releaseAllCompletedJobs(ctx);\n    if (ctx->currentJobHeld) {\n        AIO_IOPool_releaseIoJob((IOJob_t *)ctx->currentJobHeld);\n        ctx->currentJobHeld = NULL;\n    }\n    AIO_IOPool_setFile(&ctx->base, file);\n    ctx->nextReadOffset = 0;\n    ctx->waitingOnOffset = 0;\n    ctx->srcBuffer = ctx->coalesceBuffer;\n    ctx->srcBufferLoaded = 0;\n    ctx->reachedEof = 0;\n    if(file != NULL)\n        AIO_ReadPool_startReading(ctx);\n}\n\n/* AIO_ReadPool_create:\n * Allocates and sets and a new readPool including its included jobs.\n * bufferSize should be set to the maximal buffer we want to read at a time, will also be used\n * as our basic read size. */\nReadPoolCtx_t* AIO_ReadPool_create(const FIO_prefs_t* prefs, size_t bufferSize) {\n    ReadPoolCtx_t* const ctx = (ReadPoolCtx_t*) malloc(sizeof(ReadPoolCtx_t));\n    if(!ctx) EXM_THROW(100, \"Allocation error : not enough memory\");\n    AIO_IOPool_init(&ctx->base, prefs, AIO_ReadPool_executeReadJob, bufferSize);\n\n    ctx->coalesceBuffer = (U8*) malloc(bufferSize * 2);\n    if(!ctx->coalesceBuffer) EXM_THROW(100, \"Allocation error : not enough memory\");\n    ctx->srcBuffer = ctx->coalesceBuffer;\n    ctx->srcBufferLoaded = 0;\n    ctx->completedJobsCount = 0;\n    ctx->currentJobHeld = NULL;\n\n    if(ctx->base.threadPool)\n        if (ZSTD_pthread_cond_init(&ctx->jobCompletedCond, NULL))\n            EXM_THROW(103,\"Failed creating jobCompletedCond cond\");\n\n    return ctx;\n}\n\n/* AIO_ReadPool_free:\n * Frees and releases a readPool and its resources. Closes source file. */\nvoid AIO_ReadPool_free(ReadPoolCtx_t* ctx) {\n    if(AIO_ReadPool_getFile(ctx))\n        AIO_ReadPool_closeFile(ctx);\n    if(ctx->base.threadPool)\n        ZSTD_pthread_cond_destroy(&ctx->jobCompletedCond);\n    AIO_IOPool_destroy(&ctx->base);\n    free(ctx->coalesceBuffer);\n    free(ctx);\n}\n\n/* AIO_ReadPool_consumeBytes:\n * Consumes byes from srcBuffer's beginning and updates srcBufferLoaded accordingly. */\nvoid AIO_ReadPool_consumeBytes(ReadPoolCtx_t* ctx, size_t n) {\n    assert(n <= ctx->srcBufferLoaded);\n    ctx->srcBufferLoaded -= n;\n    ctx->srcBuffer += n;\n}\n\n/* AIO_ReadPool_releaseCurrentlyHeldAndGetNext:\n * Release the current held job and get the next one, returns NULL if no next job available. */\nstatic IOJob_t* AIO_ReadPool_releaseCurrentHeldAndGetNext(ReadPoolCtx_t* ctx) {\n    if (ctx->currentJobHeld) {\n        AIO_IOPool_releaseIoJob((IOJob_t *)ctx->currentJobHeld);\n        ctx->currentJobHeld = NULL;\n        AIO_ReadPool_enqueueRead(ctx);\n    }\n    ctx->currentJobHeld = AIO_ReadPool_getNextCompletedJob(ctx);\n    return (IOJob_t*) ctx->currentJobHeld;\n}\n\n/* AIO_ReadPool_fillBuffer:\n * Tries to fill the buffer with at least n or jobBufferSize bytes (whichever is smaller).\n * Returns if srcBuffer has at least the expected number of bytes loaded or if we've reached the end of the file.\n * Return value is the number of bytes added to the buffer.\n * Note that srcBuffer might have up to 2 times jobBufferSize bytes. */\nsize_t AIO_ReadPool_fillBuffer(ReadPoolCtx_t* ctx, size_t n) {\n    IOJob_t *job;\n    int useCoalesce = 0;\n    if(n > ctx->base.jobBufferSize)\n        n = ctx->base.jobBufferSize;\n\n    /* We are good, don't read anything */\n    if (ctx->srcBufferLoaded >= n)\n        return 0;\n\n    /* We still have bytes loaded, but not enough to satisfy caller. We need to get the next job\n     * and coalesce the remaining bytes with the next job's buffer */\n    if (ctx->srcBufferLoaded > 0) {\n        useCoalesce = 1;\n        memcpy(ctx->coalesceBuffer, ctx->srcBuffer, ctx->srcBufferLoaded);\n        ctx->srcBuffer = ctx->coalesceBuffer;\n    }\n\n    /* Read the next chunk */\n    job = AIO_ReadPool_releaseCurrentHeldAndGetNext(ctx);\n    if(!job)\n        return 0;\n    if(useCoalesce) {\n        assert(ctx->srcBufferLoaded + job->usedBufferSize <= 2*ctx->base.jobBufferSize);\n        memcpy(ctx->coalesceBuffer + ctx->srcBufferLoaded, job->buffer, job->usedBufferSize);\n        ctx->srcBufferLoaded += job->usedBufferSize;\n    }\n    else {\n        ctx->srcBuffer = (U8 *) job->buffer;\n        ctx->srcBufferLoaded = job->usedBufferSize;\n    }\n    return job->usedBufferSize;\n}\n\n/* AIO_ReadPool_consumeAndRefill:\n * Consumes the current buffer and refills it with bufferSize bytes. */\nsize_t AIO_ReadPool_consumeAndRefill(ReadPoolCtx_t* ctx) {\n    AIO_ReadPool_consumeBytes(ctx, ctx->srcBufferLoaded);\n    return AIO_ReadPool_fillBuffer(ctx, ctx->base.jobBufferSize);\n}\n\n/* AIO_ReadPool_getFile:\n * Returns the current file set for the read pool. */\nFILE* AIO_ReadPool_getFile(const ReadPoolCtx_t* ctx) {\n    return AIO_IOPool_getFile(&ctx->base);\n}\n\n/* AIO_ReadPool_closeFile:\n * Closes the current set file. Waits for all current enqueued tasks to complete and resets state. */\nint AIO_ReadPool_closeFile(ReadPoolCtx_t* ctx) {\n    FILE* const file = AIO_ReadPool_getFile(ctx);\n    AIO_ReadPool_setFile(ctx, NULL);\n    return fclose(file);\n}\n\n/* AIO_ReadPool_setAsync:\n * Allows (de)activating async mode, to be used when the expected overhead\n * of asyncio costs more than the expected gains. */\nvoid AIO_ReadPool_setAsync(ReadPoolCtx_t* ctx, int async) {\n    AIO_IOPool_setThreaded(&ctx->base, async);\n}\n"
  },
  {
    "path": "programs/fileio_asyncio.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n /*\n  * FileIO AsyncIO exposes read/write IO pools that allow doing IO asynchronously.\n  * Current implementation relies on having one thread that reads and one that\n  * writes.\n  * Each IO pool supports up to `MAX_IO_JOBS` that can be enqueued for work, but\n  * are performed serially by the appropriate worker thread.\n  * Most systems exposes better primitives to perform asynchronous IO, such as\n  * io_uring on newer linux systems. The API is built in such a way that in the\n  * future we could replace the threads with better solutions when available.\n  */\n\n#ifndef ZSTD_FILEIO_ASYNCIO_H\n#define ZSTD_FILEIO_ASYNCIO_H\n\n#include \"../lib/common/mem.h\"     /* U32, U64 */\n#include \"fileio_types.h\"\n#include \"platform.h\"\n#include \"util.h\"\n#include \"../lib/common/pool.h\"\n#include \"../lib/common/threading.h\"\n\n#define MAX_IO_JOBS          (10)\n\ntypedef struct {\n    /* These struct fields should be set only on creation and not changed afterwards */\n    POOL_ctx* threadPool;\n    int threadPoolActive;\n    int totalIoJobs;\n    const FIO_prefs_t* prefs;\n    POOL_function poolFunction;\n\n    /* Controls the file we currently write to, make changes only by using provided utility functions */\n    FILE* file;\n\n    /* The jobs and availableJobsCount fields are accessed by both the main and worker threads and should\n     * only be mutated after locking the mutex */\n    ZSTD_pthread_mutex_t ioJobsMutex;\n    void* availableJobs[MAX_IO_JOBS];\n    int availableJobsCount;\n    size_t jobBufferSize;\n} IOPoolCtx_t;\n\ntypedef struct {\n    IOPoolCtx_t base;\n\n    /* State regarding the currently read file */\n    int reachedEof;\n    U64 nextReadOffset;\n    U64 waitingOnOffset;\n\n    /* We may hold an IOJob object as needed if we actively expose its buffer. */\n    void *currentJobHeld;\n\n    /* Coalesce buffer is used to join two buffers in case where we need to read more bytes than left in\n     * the first of them. Shouldn't be accessed from outside ot utility functions. */\n    U8 *coalesceBuffer;\n\n    /* Read buffer can be used by consumer code, take care when copying this pointer aside as it might\n     * change when consuming / refilling buffer. */\n    U8 *srcBuffer;\n    size_t srcBufferLoaded;\n\n    /* We need to know what tasks completed so we can use their buffers when their time comes.\n     * Should only be accessed after locking base.ioJobsMutex . */\n    void* completedJobs[MAX_IO_JOBS];\n    int completedJobsCount;\n    ZSTD_pthread_cond_t jobCompletedCond;\n} ReadPoolCtx_t;\n\ntypedef struct {\n    IOPoolCtx_t base;\n    unsigned storedSkips;\n} WritePoolCtx_t;\n\ntypedef struct {\n    /* These fields are automatically set and shouldn't be changed by non WritePool code. */\n    void *ctx;\n    FILE* file;\n    void *buffer;\n    size_t bufferSize;\n\n    /* This field should be changed before a job is queued for execution and should contain the number\n     * of bytes to write from the buffer. */\n    size_t usedBufferSize;\n    U64 offset;\n} IOJob_t;\n\n/* AIO_supported:\n * Returns 1 if AsyncIO is supported on the system, 0 otherwise. */\nint AIO_supported(void);\n\n\n/* AIO_WritePool_releaseIoJob:\n * Releases an acquired job back to the pool. Doesn't execute the job. */\nvoid AIO_WritePool_releaseIoJob(IOJob_t *job);\n\n/* AIO_WritePool_acquireJob:\n * Returns an available write job to be used for a future write. */\nIOJob_t* AIO_WritePool_acquireJob(WritePoolCtx_t *ctx);\n\n/* AIO_WritePool_enqueueAndReacquireWriteJob:\n * Enqueues a write job for execution and acquires a new one.\n * After execution `job`'s pointed value would change to the newly acquired job.\n * Make sure to set `usedBufferSize` to the wanted length before call.\n * The queued job shouldn't be used directly after queueing it. */\nvoid AIO_WritePool_enqueueAndReacquireWriteJob(IOJob_t **job);\n\n/* AIO_WritePool_sparseWriteEnd:\n * Ends sparse writes to the current file.\n * Blocks on completion of all current write jobs before executing. */\nvoid AIO_WritePool_sparseWriteEnd(WritePoolCtx_t *ctx);\n\n/* AIO_WritePool_setFile:\n * Sets the destination file for future writes in the pool.\n * Requires completion of all queues write jobs and release of all otherwise acquired jobs.\n * Also requires ending of sparse write if a previous file was used in sparse mode. */\nvoid AIO_WritePool_setFile(WritePoolCtx_t *ctx, FILE* file);\n\n/* AIO_WritePool_getFile:\n * Returns the file the writePool is currently set to write to. */\nFILE* AIO_WritePool_getFile(const WritePoolCtx_t* ctx);\n\n/* AIO_WritePool_closeFile:\n * Ends sparse write and closes the writePool's current file and sets the file to NULL.\n * Requires completion of all queues write jobs and release of all otherwise acquired jobs.  */\nint AIO_WritePool_closeFile(WritePoolCtx_t *ctx);\n\n/* AIO_WritePool_create:\n * Allocates and sets and a new write pool including its included jobs.\n * bufferSize should be set to the maximal buffer we want to write to at a time. */\nWritePoolCtx_t* AIO_WritePool_create(const FIO_prefs_t* prefs, size_t bufferSize);\n\n/* AIO_WritePool_free:\n * Frees and releases a writePool and its resources. Closes destination file. */\nvoid AIO_WritePool_free(WritePoolCtx_t* ctx);\n\n/* AIO_WritePool_setAsync:\n * Allows (de)activating async mode, to be used when the expected overhead\n * of asyncio costs more than the expected gains. */\nvoid AIO_WritePool_setAsync(WritePoolCtx_t* ctx, int async);\n\n/* AIO_ReadPool_create:\n * Allocates and sets and a new readPool including its included jobs.\n * bufferSize should be set to the maximal buffer we want to read at a time, will also be used\n * as our basic read size. */\nReadPoolCtx_t* AIO_ReadPool_create(const FIO_prefs_t* prefs, size_t bufferSize);\n\n/* AIO_ReadPool_free:\n * Frees and releases a readPool and its resources. Closes source file. */\nvoid AIO_ReadPool_free(ReadPoolCtx_t* ctx);\n\n/* AIO_ReadPool_setAsync:\n * Allows (de)activating async mode, to be used when the expected overhead\n * of asyncio costs more than the expected gains. */\nvoid AIO_ReadPool_setAsync(ReadPoolCtx_t* ctx, int async);\n\n/* AIO_ReadPool_consumeBytes:\n * Consumes byes from srcBuffer's beginning and updates srcBufferLoaded accordingly. */\nvoid AIO_ReadPool_consumeBytes(ReadPoolCtx_t *ctx, size_t n);\n\n/* AIO_ReadPool_fillBuffer:\n * Makes sure buffer has at least n bytes loaded (as long as n is not bigger than the initialized bufferSize).\n * Returns if srcBuffer has at least n bytes loaded or if we've reached the end of the file.\n * Return value is the number of bytes added to the buffer.\n * Note that srcBuffer might have up to 2 times bufferSize bytes. */\nsize_t AIO_ReadPool_fillBuffer(ReadPoolCtx_t *ctx, size_t n);\n\n/* AIO_ReadPool_consumeAndRefill:\n * Consumes the current buffer and refills it with bufferSize bytes. */\nsize_t AIO_ReadPool_consumeAndRefill(ReadPoolCtx_t *ctx);\n\n/* AIO_ReadPool_setFile:\n * Sets the source file for future read in the pool. Initiates reading immediately if file is not NULL.\n * Waits for all current enqueued tasks to complete if a previous file was set. */\nvoid AIO_ReadPool_setFile(ReadPoolCtx_t *ctx, FILE* file);\n\n/* AIO_ReadPool_getFile:\n * Returns the current file set for the read pool. */\nFILE* AIO_ReadPool_getFile(const ReadPoolCtx_t *ctx);\n\n/* AIO_ReadPool_closeFile:\n * Closes the current set file. Waits for all current enqueued tasks to complete and resets state. */\nint AIO_ReadPool_closeFile(ReadPoolCtx_t *ctx);\n\n#endif /* ZSTD_FILEIO_ASYNCIO_H */\n"
  },
  {
    "path": "programs/fileio_common.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_FILEIO_COMMON_H\n#define ZSTD_FILEIO_COMMON_H\n\n#include \"../lib/common/mem.h\"     /* U32, U64 */\n#include \"fileio_types.h\"\n#include \"platform.h\"\n#include \"timefn.h\"     /* UTIL_getTime, UTIL_clockSpanMicro */\n\n/*-*************************************\n*  Macros\n***************************************/\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n#undef MAX\n#define MAX(a,b) ((a)>(b) ? (a) : (b))\n#undef MIN  /* in case it would be already defined */\n#define MIN(a,b)    ((a) < (b) ? (a) : (b))\n\nextern FIO_display_prefs_t g_display_prefs;\n\n#define DISPLAY_F(f, ...)    fprintf((f), __VA_ARGS__)\n#define DISPLAYOUT(...)      DISPLAY_F(stdout, __VA_ARGS__)\n#define DISPLAY(...)         DISPLAY_F(stderr, __VA_ARGS__)\n#define DISPLAYLEVEL(l, ...) { if (g_display_prefs.displayLevel>=l) { DISPLAY(__VA_ARGS__); } }\n\nextern UTIL_time_t g_displayClock;\n\n#define REFRESH_RATE  ((U64)(SEC_TO_MICRO / 6))\n#define READY_FOR_UPDATE() (UTIL_clockSpanMicro(g_displayClock) > REFRESH_RATE || g_display_prefs.displayLevel >= 4)\n#define DELAY_NEXT_UPDATE() { g_displayClock = UTIL_getTime(); }\n#define DISPLAYUPDATE(l, ...) {                              \\\n        if (g_display_prefs.displayLevel>=l && (g_display_prefs.progressSetting != FIO_ps_never)) { \\\n            if (READY_FOR_UPDATE()) { \\\n                DELAY_NEXT_UPDATE();                         \\\n                DISPLAY(__VA_ARGS__);                        \\\n                if (g_display_prefs.displayLevel>=4) fflush(stderr);       \\\n    }   }   }\n\n#define SHOULD_DISPLAY_SUMMARY() \\\n    (g_display_prefs.displayLevel >= 2 || g_display_prefs.progressSetting == FIO_ps_always)\n#define SHOULD_DISPLAY_PROGRESS()                       \\\n    (g_display_prefs.progressSetting != FIO_ps_never && SHOULD_DISPLAY_SUMMARY())\n#define DISPLAY_PROGRESS(...) { if (SHOULD_DISPLAY_PROGRESS()) { DISPLAYLEVEL(1, __VA_ARGS__); }}\n#define DISPLAYUPDATE_PROGRESS(...) { if (SHOULD_DISPLAY_PROGRESS()) { DISPLAYUPDATE(1, __VA_ARGS__); }}\n#define DISPLAY_SUMMARY(...) { if (SHOULD_DISPLAY_SUMMARY()) { DISPLAYLEVEL(1, __VA_ARGS__); } }\n\n#define EXM_THROW(error, ...)                                             \\\n{                                                                         \\\n    DISPLAYLEVEL(1, \"zstd: \");                                            \\\n    DISPLAYLEVEL(5, \"Error defined at %s, line %i : \\n\", __FILE__, __LINE__); \\\n    DISPLAYLEVEL(1, \"error %i : \", error);                                \\\n    DISPLAYLEVEL(1, __VA_ARGS__);                                         \\\n    DISPLAYLEVEL(1, \" \\n\");                                               \\\n    exit(error);                                                          \\\n}\n\n#define CHECK_V(v, f)                                \\\n    v = f;                                           \\\n    if (ZSTD_isError(v)) {                           \\\n        DISPLAYLEVEL(5, \"%s \\n\", #f);                \\\n        EXM_THROW(11, \"%s\", ZSTD_getErrorName(v));   \\\n    }\n#define CHECK(f) { size_t err; CHECK_V(err, f); }\n\n\n/* Avoid fseek()'s 2GiB barrier with MSVC, macOS, *BSD, MinGW */\n#if defined(LIBC_NO_FSEEKO)\n/* Some older libc implementations don't include these functions (e.g. Bionic < 24) */\n#   define LONG_SEEK fseek\n#   define LONG_TELL ftell\n#elif defined(_MSC_VER) && _MSC_VER >= 1400\n#   define LONG_SEEK _fseeki64\n#   define LONG_TELL _ftelli64\n#elif !defined(__64BIT__) && (PLATFORM_POSIX_VERSION >= 200112L) /* No point defining Large file for 64 bit */\n#   define LONG_SEEK fseeko\n#   define LONG_TELL ftello\n#elif defined(__MINGW32__) && !defined(__STRICT_ANSI__) && !defined(__NO_MINGW_LFS) && defined(__MSVCRT__)\n#   define LONG_SEEK fseeko64\n#   define LONG_TELL ftello64\n#elif defined(_WIN32) && !defined(__DJGPP__)\n#   include <windows.h>\n    static int LONG_SEEK(FILE* file, __int64 offset, int origin) {\n        LARGE_INTEGER off;\n        DWORD method;\n        off.QuadPart = offset;\n        if (origin == SEEK_END)\n            method = FILE_END;\n        else if (origin == SEEK_CUR)\n            method = FILE_CURRENT;\n        else\n            method = FILE_BEGIN;\n\n        if (SetFilePointerEx((HANDLE) _get_osfhandle(_fileno(file)), off, NULL, method))\n            return 0;\n        else\n            return -1;\n    }\n    static __int64 LONG_TELL(FILE* file) {\n        LARGE_INTEGER off, newOff;\n        off.QuadPart = 0;\n        newOff.QuadPart = 0;\n        SetFilePointerEx((HANDLE) _get_osfhandle(_fileno(file)), off, &newOff, FILE_CURRENT);\n        return newOff.QuadPart;\n    }\n#else\n#   define LONG_SEEK fseek\n#   define LONG_TELL ftell\n#endif\n\n#endif /* ZSTD_FILEIO_COMMON_H */\n"
  },
  {
    "path": "programs/fileio_types.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef FILEIO_TYPES_HEADER\n#define FILEIO_TYPES_HEADER\n\n#define ZSTD_STATIC_LINKING_ONLY   /* ZSTD_compressionParameters */\n#include \"../lib/zstd.h\"           /* ZSTD_* */\n\n/*-*************************************\n*  Parameters: FIO_prefs_t\n***************************************/\n\ntypedef struct FIO_display_prefs_s FIO_display_prefs_t;\n\ntypedef enum { FIO_ps_auto, FIO_ps_never, FIO_ps_always } FIO_progressSetting_e;\n\nstruct FIO_display_prefs_s {\n    int displayLevel;   /* 0 : no display;  1: errors;  2: + result + interaction + warnings;  3: + progression;  4: + information */\n    FIO_progressSetting_e progressSetting;\n};\n\n\ntypedef enum { FIO_zstdCompression, FIO_gzipCompression, FIO_xzCompression, FIO_lzmaCompression, FIO_lz4Compression } FIO_compressionType_t;\n\ntypedef struct FIO_prefs_s {\n\n    /* Algorithm preferences */\n    FIO_compressionType_t compressionType;\n    int sparseFileSupport;   /* 0: no sparse allowed; 1: auto (file yes, stdout no); 2: force sparse */\n    int dictIDFlag;\n    int checksumFlag;\n    int jobSize;\n    int overlapLog;\n    int adaptiveMode;\n    int useRowMatchFinder;\n    int rsyncable;\n    int minAdaptLevel;\n    int maxAdaptLevel;\n    int ldmFlag;\n    int ldmHashLog;\n    int ldmMinMatch;\n    int ldmBucketSizeLog;\n    int ldmHashRateLog;\n    size_t streamSrcSize;\n    size_t targetCBlockSize;\n    int srcSizeHint;\n    int testMode;\n    ZSTD_ParamSwitch_e literalCompressionMode;\n\n    /* IO preferences */\n    int removeSrcFile;\n    int overwrite;\n    int asyncIO;\n\n    /* Computation resources preferences */\n    unsigned memLimit;\n    int nbWorkers;\n\n    int excludeCompressedFiles;\n    int patchFromMode;\n    int contentSize;\n    int allowBlockDevices;\n    int passThrough;\n    ZSTD_ParamSwitch_e mmapDict;\n} FIO_prefs_t;\n\ntypedef enum {FIO_mallocDict, FIO_mmapDict} FIO_dictBufferType_t;\n\ntypedef struct {\n    void* dictBuffer;\n    size_t dictBufferSize;\n    FIO_dictBufferType_t dictBufferType;\n#if defined(_MSC_VER) || defined(_WIN32)\n    HANDLE dictHandle;\n#endif\n} FIO_Dict_t;\n\n#endif /* FILEIO_TYPES_HEADER */\n"
  },
  {
    "path": "programs/lorem.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* Implementation notes:\n *\n * This is a very simple lorem ipsum generator\n * which features a static list of words\n * and print them one after another randomly\n * with a fake sentence / paragraph structure.\n *\n * The goal is to generate a printable text\n * that can be used to fake a text compression scenario.\n * The resulting compression / ratio curve of the lorem ipsum generator\n * is more satisfying than the previous statistical generator,\n * which was initially designed for entropy compression,\n * and lacks a regularity more representative of text.\n *\n * The compression ratio achievable on the generated lorem ipsum\n * is still a bit too good, presumably because the dictionary is a bit too\n * small. It would be possible to create some more complex scheme, notably by\n * enlarging the dictionary with a word generator, and adding grammatical rules\n * (composition) and syntax rules. But that's probably overkill for the intended\n * goal.\n */\n\n#include \"lorem.h\"\n#include <assert.h>\n#include <limits.h> /* INT_MAX */\n#include <string.h> /* memcpy */\n\n#define WORD_MAX_SIZE 20\n\n/* Define the word pool */\nstatic const char* kWords[] = {\n    \"lorem\",        \"ipsum\",      \"dolor\",       \"sit\",          \"amet\",\n    \"consectetur\",  \"adipiscing\", \"elit\",        \"sed\",          \"do\",\n    \"eiusmod\",      \"tempor\",     \"incididunt\",  \"ut\",           \"labore\",\n    \"et\",           \"dolore\",     \"magna\",       \"aliqua\",       \"dis\",\n    \"lectus\",       \"vestibulum\", \"mattis\",      \"ullamcorper\",  \"velit\",\n    \"commodo\",      \"a\",          \"lacus\",       \"arcu\",         \"magnis\",\n    \"parturient\",   \"montes\",     \"nascetur\",    \"ridiculus\",    \"mus\",\n    \"mauris\",       \"nulla\",      \"malesuada\",   \"pellentesque\", \"eget\",\n    \"gravida\",      \"in\",         \"dictum\",      \"non\",          \"erat\",\n    \"nam\",          \"voluptat\",   \"maecenas\",    \"blandit\",      \"aliquam\",\n    \"etiam\",        \"enim\",       \"lobortis\",    \"scelerisque\",  \"fermentum\",\n    \"dui\",          \"faucibus\",   \"ornare\",      \"at\",           \"elementum\",\n    \"eu\",           \"facilisis\",  \"odio\",        \"morbi\",        \"quis\",\n    \"eros\",         \"donec\",      \"ac\",          \"orci\",         \"purus\",\n    \"turpis\",       \"cursus\",     \"leo\",         \"vel\",          \"porta\",\n    \"consequat\",    \"interdum\",   \"varius\",      \"vulputate\",    \"aliquet\",\n    \"pharetra\",     \"nunc\",       \"auctor\",      \"urna\",         \"id\",\n    \"metus\",        \"viverra\",    \"nibh\",        \"cras\",         \"mi\",\n    \"unde\",         \"omnis\",      \"iste\",        \"natus\",        \"error\",\n    \"perspiciatis\", \"voluptatem\", \"accusantium\", \"doloremque\",   \"laudantium\",\n    \"totam\",        \"rem\",        \"aperiam\",     \"eaque\",        \"ipsa\",\n    \"quae\",         \"ab\",         \"illo\",        \"inventore\",    \"veritatis\",\n    \"quasi\",        \"architecto\", \"beatae\",      \"vitae\",        \"dicta\",\n    \"sunt\",         \"explicabo\",  \"nemo\",        \"ipsam\",        \"quia\",\n    \"voluptas\",     \"aspernatur\", \"aut\",         \"odit\",         \"fugit\",\n    \"consequuntur\", \"magni\",      \"dolores\",     \"eos\",          \"qui\",\n    \"ratione\",      \"sequi\",      \"nesciunt\",    \"neque\",        \"porro\",\n    \"quisquam\",     \"est\",        \"dolorem\",     \"adipisci\",     \"numquam\",\n    \"eius\",         \"modi\",       \"tempora\",     \"incidunt\",     \"magnam\",\n    \"quaerat\",      \"ad\",         \"minima\",      \"veniam\",       \"nostrum\",\n    \"ullam\",        \"corporis\",   \"suscipit\",    \"laboriosam\",   \"nisi\",\n    \"aliquid\",      \"ex\",         \"ea\",          \"commodi\",      \"consequatur\",\n    \"autem\",        \"eum\",        \"iure\",        \"voluptate\",    \"esse\",\n    \"quam\",         \"nihil\",      \"molestiae\",   \"illum\",        \"fugiat\",\n    \"quo\",          \"pariatur\",   \"vero\",        \"accusamus\",    \"iusto\",\n    \"dignissimos\",  \"ducimus\",    \"blanditiis\",  \"praesentium\",  \"voluptatum\",\n    \"deleniti\",     \"atque\",      \"corrupti\",    \"quos\",         \"quas\",\n    \"molestias\",    \"excepturi\",  \"sint\",        \"occaecati\",    \"cupiditate\",\n    \"provident\",    \"similique\",  \"culpa\",       \"officia\",      \"deserunt\",\n    \"mollitia\",     \"animi\",      \"laborum\",     \"dolorum\",      \"fuga\",\n    \"harum\",        \"quidem\",     \"rerum\",       \"facilis\",      \"expedita\",\n    \"distinctio\",   \"libero\",     \"tempore\",     \"cum\",          \"soluta\",\n    \"nobis\",        \"eligendi\",   \"optio\",       \"cumque\",       \"impedit\",\n    \"minus\",        \"quod\",       \"maxime\",      \"placeat\",      \"facere\",\n    \"possimus\",     \"assumenda\",  \"repellendus\", \"temporibus\",   \"quibusdam\",\n    \"officiis\",     \"debitis\",    \"saepe\",       \"eveniet\",      \"voluptates\",\n    \"repudiandae\",  \"recusandae\", \"itaque\",      \"earum\",        \"hic\",\n    \"tenetur\",      \"sapiente\",   \"delectus\",    \"reiciendis\",   \"cillum\",\n    \"maiores\",      \"alias\",      \"perferendis\", \"doloribus\",    \"asperiores\",\n    \"repellat\",     \"minim\",      \"nostrud\",     \"exercitation\", \"ullamco\",\n    \"laboris\",      \"aliquip\",    \"duis\",        \"aute\",         \"irure\",\n};\nstatic const unsigned kNbWords = sizeof(kWords) / sizeof(kWords[0]);\n\n/* simple 1-dimension distribution, based on word's length, favors small words\n */\nstatic const int kWeights[]    = { 0, 8, 6, 4, 3, 2 };\nstatic const size_t kNbWeights = sizeof(kWeights) / sizeof(kWeights[0]);\n\n#define DISTRIB_SIZE_MAX 650\nstatic int g_distrib[DISTRIB_SIZE_MAX] = { 0 };\nstatic unsigned g_distribCount         = 0;\n\nstatic void countFreqs(\n        const char* words[],\n        size_t nbWords,\n        const int* weights,\n        size_t nbWeights)\n{\n    unsigned total = 0;\n    size_t w;\n    for (w = 0; w < nbWords; w++) {\n        size_t len = strlen(words[w]);\n        int lmax;\n        if (len >= nbWeights)\n            len = nbWeights - 1;\n        lmax = weights[len];\n        total += (unsigned)lmax;\n    }\n    g_distribCount = total;\n    assert(g_distribCount <= DISTRIB_SIZE_MAX);\n}\n\nstatic void init_word_distrib(\n        const char* words[],\n        size_t nbWords,\n        const int* weights,\n        size_t nbWeights)\n{\n    size_t w, d = 0;\n    countFreqs(words, nbWords, weights, nbWeights);\n    for (w = 0; w < nbWords; w++) {\n        size_t len = strlen(words[w]);\n        int l, lmax;\n        if (len >= nbWeights)\n            len = nbWeights - 1;\n        lmax = weights[len];\n        for (l = 0; l < lmax; l++) {\n            g_distrib[d++] = (int)w;\n        }\n    }\n}\n\n/* Note: this unit only works when invoked sequentially.\n * No concurrent access is allowed */\nstatic char* g_ptr         = NULL;\nstatic size_t g_nbChars    = 0;\nstatic size_t g_maxChars   = 10000000;\nstatic unsigned g_randRoot = 0;\n\n#define RDG_rotl32(x, r) ((x << r) | (x >> (32 - r)))\nstatic unsigned LOREM_rand(unsigned range)\n{\n    static const unsigned prime1 = 2654435761U;\n    static const unsigned prime2 = 2246822519U;\n    unsigned rand32              = g_randRoot;\n    rand32 *= prime1;\n    rand32 ^= prime2;\n    rand32     = RDG_rotl32(rand32, 13);\n    g_randRoot = rand32;\n    return (unsigned)(((unsigned long long)rand32 * range) >> 32);\n}\n\nstatic void writeLastCharacters(void)\n{\n    size_t lastChars = g_maxChars - g_nbChars;\n    assert(g_maxChars >= g_nbChars);\n    if (lastChars == 0)\n        return;\n    g_ptr[g_nbChars++] = '.';\n    if (lastChars > 2) {\n        memset(g_ptr + g_nbChars, ' ', lastChars - 2);\n    }\n    if (lastChars > 1) {\n        g_ptr[g_maxChars - 1] = '\\n';\n    }\n    g_nbChars = g_maxChars;\n}\n\nstatic void generateWord(const char* word, const char* separator, int upCase)\n{\n    size_t const len = strlen(word) + strlen(separator);\n    if (g_nbChars + len > g_maxChars) {\n        writeLastCharacters();\n        return;\n    }\n    memcpy(g_ptr + g_nbChars, word, strlen(word));\n    if (upCase) {\n        static const char toUp = 'A' - 'a';\n        g_ptr[g_nbChars]       = (char)(g_ptr[g_nbChars] + toUp);\n    }\n    g_nbChars += strlen(word);\n    memcpy(g_ptr + g_nbChars, separator, strlen(separator));\n    g_nbChars += strlen(separator);\n}\n\nstatic int about(unsigned target)\n{\n    return (int)(LOREM_rand(target) + LOREM_rand(target) + 1);\n}\n\n/* Function to generate a random sentence */\nstatic void generateSentence(int nbWords)\n{\n    int commaPos       = about(9);\n    int comma2         = commaPos + about(7);\n    int qmark          = (LOREM_rand(11) == 7);\n    const char* endSep = qmark ? \"? \" : \". \";\n    int i;\n    for (i = 0; i < nbWords; i++) {\n        int const wordID       = g_distrib[LOREM_rand(g_distribCount)];\n        const char* const word = kWords[wordID];\n        const char* sep        = \" \";\n        if (i == commaPos)\n            sep = \", \";\n        if (i == comma2)\n            sep = \", \";\n        if (i == nbWords - 1)\n            sep = endSep;\n        generateWord(word, sep, i == 0);\n    }\n}\n\nstatic void generateParagraph(int nbSentences)\n{\n    int i;\n    for (i = 0; i < nbSentences; i++) {\n        int wordsPerSentence = about(11);\n        generateSentence(wordsPerSentence);\n    }\n    if (g_nbChars < g_maxChars) {\n        g_ptr[g_nbChars++] = '\\n';\n    }\n    if (g_nbChars < g_maxChars) {\n        g_ptr[g_nbChars++] = '\\n';\n    }\n}\n\n/* It's \"common\" for lorem ipsum generators to start with the same first\n * pre-defined sentence */\nstatic void generateFirstSentence(void)\n{\n    int i;\n    for (i = 0; i < 18; i++) {\n        const char* word      = kWords[i];\n        const char* separator = \" \";\n        if (i == 4)\n            separator = \", \";\n        if (i == 7)\n            separator = \", \";\n        generateWord(word, separator, i == 0);\n    }\n    generateWord(kWords[18], \". \", 0);\n}\n\nsize_t\nLOREM_genBlock(void* buffer, size_t size, unsigned seed, int first, int fill)\n{\n    g_ptr = (char*)buffer;\n    assert(size < INT_MAX);\n    g_maxChars = size;\n    g_nbChars  = 0;\n    g_randRoot = seed;\n    if (g_distribCount == 0) {\n        init_word_distrib(kWords, kNbWords, kWeights, kNbWeights);\n    }\n\n    if (first) {\n        generateFirstSentence();\n    }\n    while (g_nbChars < g_maxChars) {\n        int sentencePerParagraph = about(7);\n        generateParagraph(sentencePerParagraph);\n        if (!fill)\n            break; /* only generate one paragraph in not-fill mode */\n    }\n    g_ptr = NULL;\n    return g_nbChars;\n}\n\nvoid LOREM_genBuffer(void* buffer, size_t size, unsigned seed)\n{\n    LOREM_genBlock(buffer, size, seed, 1, 1);\n}\n"
  },
  {
    "path": "programs/lorem.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* lorem ipsum generator */\n\n#include <stddef.h>   /* size_t */\n\n/*\n * LOREM_genBuffer():\n * Generate @size bytes of compressible data using lorem ipsum generator\n * into provided @buffer.\n */\nvoid LOREM_genBuffer(void* buffer, size_t size, unsigned seed);\n\n/*\n * LOREM_genBlock():\n * Similar to LOREM_genBuffer, with additional controls :\n * - @first : generate the first sentence\n * - @fill : fill the entire @buffer,\n *           if ==0: generate one paragraph at most.\n * @return : nb of bytes generated into @buffer.\n */\nsize_t LOREM_genBlock(void* buffer, size_t size,\n                      unsigned seed,\n                      int first, int fill);\n"
  },
  {
    "path": "programs/platform.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef PLATFORM_H_MODULE\n#define PLATFORM_H_MODULE\n\n/* **************************************\n*  Compiler Options\n****************************************/\n#if defined(_MSC_VER)\n#  define _CRT_SECURE_NO_WARNINGS    /* Disable Visual Studio warning messages for fopen, strncpy, strerror */\n#  define _CRT_NONSTDC_NO_WARNINGS   /* Disable C4996 complaining about posix function names */\n#  if (_MSC_VER <= 1800)             /* 1800 == Visual Studio 2013 */\n#    define _CRT_SECURE_NO_DEPRECATE /* VS2005 - must be declared before <io.h> and <windows.h> */\n#    define snprintf sprintf_s       /* snprintf unsupported by Visual <= 2013 */\n#  endif\n#  pragma warning(disable : 4127)    /* disable: C4127: conditional expression is constant */\n#endif\n\n\n/* **************************************\n*  Detect 64-bit OS\n*  https://nadeausoftware.com/articles/2012/02/c_c_tip_how_detect_processor_type_using_compiler_predefined_macros\n****************************************/\n#if defined __ia64 || defined _M_IA64                                                                               /* Intel Itanium */ \\\n  || defined __powerpc64__ || defined __ppc64__ || defined __PPC64__                                                /* POWER 64-bit */  \\\n  || (defined __sparc && (defined __sparcv9 || defined __sparc_v9__ || defined __arch64__)) || defined __sparc64__  /* SPARC 64-bit */  \\\n  || defined __x86_64__ || defined _M_X64                                                                           /* x86 64-bit */    \\\n  || defined __arm64__ || defined __aarch64__ || defined __ARM64_ARCH_8__                                           /* ARM 64-bit */    \\\n  || (defined __mips  && (__mips == 64 || __mips == 4 || __mips == 3))                                              /* MIPS 64-bit */   \\\n  || (defined(__riscv) && __riscv_xlen == 64)                                                                       /* RISC-V 64-bit */ \\\n  || defined _LP64 || defined __LP64__ /* NetBSD, OpenBSD */ || defined __64BIT__ /* AIX */ || defined _ADDR64 /* Cray */               \\\n  || (defined __SIZEOF_POINTER__ && __SIZEOF_POINTER__ == 8) /* gcc */\n#  if !defined(__64BIT__)\n#    define __64BIT__  1\n#  endif\n#endif\n\n\n/* *********************************************************\n*  Turn on Large Files support (>4GB) for 32-bit Linux/Unix\n***********************************************************/\n#if !defined(__64BIT__) || defined(__MINGW32__)    /* No point defining Large file for 64 bit but MinGW-w64 requires it */\n#  if !defined(_FILE_OFFSET_BITS)\n#    define _FILE_OFFSET_BITS 64                   /* turn off_t into a 64-bit type for ftello, fseeko */\n#  endif\n#  if !defined(_LARGEFILE_SOURCE)                  /* obsolete macro, replaced with _FILE_OFFSET_BITS */\n#    define _LARGEFILE_SOURCE 1                    /* Large File Support extension (LFS) - fseeko, ftello */\n#  endif\n#  if defined(_AIX) || defined(__hpux)\n#    define _LARGE_FILES                           /* Large file support on 32-bits AIX and HP-UX */\n#  endif\n#endif\n\n\n/* ************************************************************\n*  Detect POSIX version\n*  PLATFORM_POSIX_VERSION = 0 for non-Unix e.g. Windows\n*  PLATFORM_POSIX_VERSION = 1 for Unix-like but non-POSIX\n*  PLATFORM_POSIX_VERSION > 1 is equal to found _POSIX_VERSION\n*  Value of PLATFORM_POSIX_VERSION can be forced on command line\n***************************************************************/\n#ifndef PLATFORM_POSIX_VERSION\n\n#  if (defined(__APPLE__) && defined(__MACH__)) || defined(__SVR4) || defined(_AIX) || defined(__hpux) /* POSIX.1-2001 (SUSv3) conformant */\n     /* exception rule : force posix version to 200112L,\n      * note: it's better to use unistd.h's _POSIX_VERSION whenever possible */\n#    define PLATFORM_POSIX_VERSION 200112L\n\n/* try to determine posix version through official unistd.h's _POSIX_VERSION (https://pubs.opengroup.org/onlinepubs/7908799/xsh/unistd.h.html).\n * note : there is no simple way to know in advance if <unistd.h> is present or not on target system,\n * Posix specification mandates its presence and its content, but target system must respect this spec.\n * It's necessary to _not_ #include <unistd.h> whenever target OS is not unix-like\n * otherwise it will block preprocessing stage.\n * The following list of build macros tries to \"guess\" if target OS is likely unix-like, and therefore can #include <unistd.h>\n */\n#  elif !defined(_WIN32) \\\n     && ( defined(__unix__) || defined(__unix) \\\n       || defined(_QNX_SOURCE) || defined(__midipix__) || defined(__VMS) || defined(__HAIKU__) )\n\n#    if defined(__linux__) || defined(__linux) || defined(__CYGWIN__)\n#      ifndef _POSIX_C_SOURCE\n#        define _POSIX_C_SOURCE 200809L  /* feature test macro : https://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html */\n#      endif\n#    endif\n#    include <unistd.h>  /* declares _POSIX_VERSION */\n#    if defined(_POSIX_VERSION)  /* POSIX compliant */\n#      define PLATFORM_POSIX_VERSION _POSIX_VERSION\n#    else\n#      define PLATFORM_POSIX_VERSION 1\n#    endif\n\n#    ifdef __UCLIBC__\n#     ifndef __USE_MISC\n#      define __USE_MISC /* enable st_mtim on uclibc */\n#     endif\n#    endif\n\n#  else  /* non-unix target platform (like Windows) */\n#    define PLATFORM_POSIX_VERSION 0\n#  endif\n\n#endif   /* PLATFORM_POSIX_VERSION */\n\n\n#if PLATFORM_POSIX_VERSION > 1\n   /* glibc < 2.26 may not expose struct timespec def without this.\n    * See issue #1920. */\n#  ifndef _ATFILE_SOURCE\n#    define _ATFILE_SOURCE\n#  endif\n#endif\n\n\n/*-*********************************************\n*  Detect if isatty() and fileno() are available\n*\n*  Note: Use UTIL_isConsole() for the zstd CLI\n*  instead, as it allows faking is console for\n*  testing.\n************************************************/\n#if (defined(__linux__) && (PLATFORM_POSIX_VERSION > 1)) \\\n || (PLATFORM_POSIX_VERSION >= 200112L) \\\n || defined(__DJGPP__)\n#  include <unistd.h>   /* isatty */\n#  include <stdio.h>    /* fileno */\n#  define IS_CONSOLE(stdStream) isatty(fileno(stdStream))\n#elif defined(MSDOS) || defined(OS2)\n#  include <io.h>       /* _isatty */\n#  define IS_CONSOLE(stdStream) _isatty(_fileno(stdStream))\n#elif defined(_WIN32)\n#  include <io.h>      /* _isatty */\n#  include <windows.h> /* DeviceIoControl, HANDLE, FSCTL_SET_SPARSE */\n#  include <stdio.h>   /* FILE */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nstatic __inline int IS_CONSOLE(FILE* stdStream) {\n    DWORD dummy;\n    return _isatty(_fileno(stdStream)) && GetConsoleMode((HANDLE)_get_osfhandle(_fileno(stdStream)), &dummy);\n}\n\n#if defined (__cplusplus)\n}\n#endif\n\n#else\n#  define IS_CONSOLE(stdStream) 0\n#endif\n\n\n/******************************\n*  OS-specific IO behaviors\n******************************/\n#if defined(MSDOS) || defined(OS2) || defined(_WIN32)\n#  include <fcntl.h>   /* _O_BINARY */\n#  include <io.h>      /* _setmode, _fileno, _get_osfhandle */\n#  if !defined(__DJGPP__)\n#    include <windows.h> /* DeviceIoControl, HANDLE, FSCTL_SET_SPARSE */\n#    include <winioctl.h> /* FSCTL_SET_SPARSE */\n#    define SET_BINARY_MODE(file) { int const unused=_setmode(_fileno(file), _O_BINARY); (void)unused; }\n#    define SET_SPARSE_FILE_MODE(file) { DWORD dw; DeviceIoControl((HANDLE) _get_osfhandle(_fileno(file)), FSCTL_SET_SPARSE, 0, 0, 0, 0, &dw, 0); }\n#  else\n#    define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)\n#    define SET_SPARSE_FILE_MODE(file)\n#  endif\n#else\n#  define SET_BINARY_MODE(file)\n#  define SET_SPARSE_FILE_MODE(file)\n#endif\n\n\n#ifndef ZSTD_SPARSE_DEFAULT\n#  if (defined(__APPLE__) && defined(__MACH__))\n#    define ZSTD_SPARSE_DEFAULT 0\n#  else\n#    define ZSTD_SPARSE_DEFAULT 1\n#  endif\n#endif\n\n\n#ifndef ZSTD_START_SYMBOLLIST_FRAME\n#  ifdef __linux__\n#    define ZSTD_START_SYMBOLLIST_FRAME 2\n#  elif defined __APPLE__\n#    define ZSTD_START_SYMBOLLIST_FRAME 4\n#  else\n#    define ZSTD_START_SYMBOLLIST_FRAME 0\n#  endif\n#endif\n\n\n#ifndef ZSTD_SETPRIORITY_SUPPORT\n   /* mandates presence of <sys/resource.h> and support for setpriority() : https://man7.org/linux/man-pages/man2/setpriority.2.html */\n#  define ZSTD_SETPRIORITY_SUPPORT (PLATFORM_POSIX_VERSION >= 200112L)\n#endif\n\n\n#ifndef ZSTD_NANOSLEEP_SUPPORT\n   /* mandates support of nanosleep() within <time.h> : https://man7.org/linux/man-pages/man2/nanosleep.2.html */\n#  if (defined(__linux__) && (PLATFORM_POSIX_VERSION >= 199309L)) \\\n   || (PLATFORM_POSIX_VERSION >= 200112L)\n#     define ZSTD_NANOSLEEP_SUPPORT 1\n#  else\n#     define ZSTD_NANOSLEEP_SUPPORT 0\n#  endif\n#endif\n\n#endif /* PLATFORM_H_MODULE */\n"
  },
  {
    "path": "programs/timefn.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/* ===  Dependencies  === */\n\n#include \"timefn.h\"\n#include \"platform.h\" /* set _POSIX_C_SOURCE */\n#include <time.h>     /* CLOCK_MONOTONIC, TIME_UTC */\n\n/*-****************************************\n*  Time functions\n******************************************/\n\n#if defined(_WIN32)   /* Windows */\n\n#include <windows.h>  /* LARGE_INTEGER */\n#include <stdlib.h>   /* abort */\n#include <stdio.h>    /* perror */\n\nUTIL_time_t UTIL_getTime(void)\n{\n    static LARGE_INTEGER ticksPerSecond;\n    static double nsFactor = 1.0;\n    static int init = 0;\n    if (!init) {\n        if (!QueryPerformanceFrequency(&ticksPerSecond)) {\n            perror(\"timefn::QueryPerformanceFrequency\");\n            abort();\n        }\n        nsFactor = 1000000000.0 / (double)ticksPerSecond.QuadPart;\n        init = 1;\n    }\n    {   UTIL_time_t r;\n        LARGE_INTEGER x;\n        QueryPerformanceCounter(&x);\n        r.t = (PTime)((double)x.QuadPart * nsFactor);\n        return r;\n    }\n}\n\n\n#elif defined(__APPLE__) && defined(__MACH__)\n\n#include <mach/mach_time.h> /* mach_timebase_info_data_t, mach_timebase_info, mach_absolute_time */\n\nUTIL_time_t UTIL_getTime(void)\n{\n    static mach_timebase_info_data_t rate;\n    static int init = 0;\n    if (!init) {\n        mach_timebase_info(&rate);\n        init = 1;\n    }\n    {   UTIL_time_t r;\n        r.t = mach_absolute_time() * (PTime)rate.numer / (PTime)rate.denom;\n        return r;\n    }\n}\n\n/* POSIX.1-2001 (optional) */\n#elif defined(CLOCK_MONOTONIC)\n\n#include <stdlib.h>   /* abort */\n#include <stdio.h>    /* perror */\n\nUTIL_time_t UTIL_getTime(void)\n{\n    /* time must be initialized, othersize it may fail msan test.\n     * No good reason, likely a limitation of timespec_get() for some target */\n    struct timespec time = { 0, 0 };\n    if (clock_gettime(CLOCK_MONOTONIC, &time) != 0) {\n        perror(\"timefn::clock_gettime(CLOCK_MONOTONIC)\");\n        abort();\n    }\n    {   UTIL_time_t r;\n        r.t = (PTime)time.tv_sec * 1000000000ULL + (PTime)time.tv_nsec;\n        return r;\n    }\n}\n\n\n/* C11 requires support of timespec_get().\n * However, FreeBSD 11 claims C11 compliance while lacking timespec_get().\n * Double confirm timespec_get() support by checking the definition of TIME_UTC.\n * However, some versions of Android manage to simultaneously define TIME_UTC\n * and lack timespec_get() support... */\n#elif (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */) \\\n    && defined(TIME_UTC) && !defined(__ANDROID__)\n\n#include <stdlib.h>   /* abort */\n#include <stdio.h>    /* perror */\n\nUTIL_time_t UTIL_getTime(void)\n{\n    /* time must be initialized, othersize it may fail msan test.\n     * No good reason, likely a limitation of timespec_get() for some target */\n    struct timespec time = { 0, 0 };\n    if (timespec_get(&time, TIME_UTC) != TIME_UTC) {\n        perror(\"timefn::timespec_get(TIME_UTC)\");\n        abort();\n    }\n    {   UTIL_time_t r;\n        r.t = (PTime)time.tv_sec * 1000000000ULL + (PTime)time.tv_nsec;\n        return r;\n    }\n}\n\n\n#else   /* relies on standard C90 (note : clock_t produces wrong measurements for multi-threaded workloads) */\n\nUTIL_time_t UTIL_getTime(void)\n{\n    UTIL_time_t r;\n    r.t = (PTime)clock() * 1000000000ULL / CLOCKS_PER_SEC;\n    return r;\n}\n\n#define TIME_MT_MEASUREMENTS_NOT_SUPPORTED\n\n#endif\n\n/* ==== Common functions, valid for all time API ==== */\n\nPTime UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd)\n{\n    return clockEnd.t - clockStart.t;\n}\n\nPTime UTIL_getSpanTimeMicro(UTIL_time_t begin, UTIL_time_t end)\n{\n    return UTIL_getSpanTimeNano(begin, end) / 1000ULL;\n}\n\nPTime UTIL_clockSpanMicro(UTIL_time_t clockStart )\n{\n    UTIL_time_t const clockEnd = UTIL_getTime();\n    return UTIL_getSpanTimeMicro(clockStart, clockEnd);\n}\n\nPTime UTIL_clockSpanNano(UTIL_time_t clockStart )\n{\n    UTIL_time_t const clockEnd = UTIL_getTime();\n    return UTIL_getSpanTimeNano(clockStart, clockEnd);\n}\n\nvoid UTIL_waitForNextTick(void)\n{\n    UTIL_time_t const clockStart = UTIL_getTime();\n    UTIL_time_t clockEnd;\n    do {\n        clockEnd = UTIL_getTime();\n    } while (UTIL_getSpanTimeNano(clockStart, clockEnd) == 0);\n}\n\nint UTIL_support_MT_measurements(void)\n{\n# if defined(TIME_MT_MEASUREMENTS_NOT_SUPPORTED)\n    return 0;\n# else\n    return 1;\n# endif\n}\n"
  },
  {
    "path": "programs/timefn.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef TIME_FN_H_MODULE_287987\n#define TIME_FN_H_MODULE_287987\n\n/*-****************************************\n*  Types\n******************************************/\n\n#if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )\n# if defined(_AIX)\n#  include <inttypes.h>\n# else\n#  include <stdint.h> /* uint64_t */\n# endif\n  typedef uint64_t           PTime;  /* Precise Time */\n#else\n  typedef unsigned long long PTime;  /* does not support compilers without long long support */\n#endif\n\n/* UTIL_time_t contains a nanosecond time counter.\n * The absolute value is not meaningful.\n * It's only valid to compute the difference between 2 measurements. */\ntypedef struct { PTime t; } UTIL_time_t;\n#define UTIL_TIME_INITIALIZER { 0 }\n\n\n/*-****************************************\n*  Time functions\n******************************************/\n\nUTIL_time_t UTIL_getTime(void);\n\n/* Timer resolution can be low on some platforms.\n * To improve accuracy, it's recommended to wait for a new tick\n * before starting benchmark measurements */\nvoid UTIL_waitForNextTick(void);\n/* tells if timefn will return correct time measurements\n * in presence of multi-threaded workload.\n * note : this is not the case if only C90 clock_t measurements are available */\nint UTIL_support_MT_measurements(void);\n\nPTime UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd);\nPTime UTIL_clockSpanNano(UTIL_time_t clockStart);\n\nPTime UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd);\nPTime UTIL_clockSpanMicro(UTIL_time_t clockStart);\n\n#define SEC_TO_MICRO ((PTime)1000000)  /* nb of microseconds in a second */\n\n#endif /* TIME_FN_H_MODULE_287987 */\n"
  },
  {
    "path": "programs/util.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/*-****************************************\n*  Dependencies\n******************************************/\n#include \"util.h\"       /* note : ensure that platform.h is included first ! */\n#include <stdlib.h>     /* malloc, realloc, free */\n#include <stdio.h>      /* fprintf */\n#include <time.h>       /* clock_t, clock, CLOCKS_PER_SEC, nanosleep */\n#include <errno.h>\n#include <assert.h>\n\n#if defined(__FreeBSD__)\n#include <sys/param.h> /* __FreeBSD_version */\n#endif /* #ifdef __FreeBSD__ */\n\n#if defined(_WIN32)\n#  include <sys/utime.h>  /* utime */\n#  include <io.h>         /* _chmod */\n#  define ZSTD_USE_UTIMENSAT 0\n#else\n#  include <unistd.h>     /* chown, stat */\n#  include <sys/stat.h>   /* utimensat, st_mtime */\n#  if (PLATFORM_POSIX_VERSION >= 200809L && defined(st_mtime)) \\\n      || (defined(__FreeBSD__) && __FreeBSD_version >= 1100056)\n#    define ZSTD_USE_UTIMENSAT 1\n#  else\n#    define ZSTD_USE_UTIMENSAT 0\n#  endif\n#  if ZSTD_USE_UTIMENSAT\n#    include <fcntl.h>    /* AT_FDCWD */\n#  else\n#    include <utime.h>    /* utime */\n#  endif\n#endif\n\n#if defined(_MSC_VER) || defined(__MINGW32__) || defined (__MSVCRT__)\n#include <direct.h>     /* needed for _mkdir in windows */\n#endif\n\n#if defined(__linux__) || (PLATFORM_POSIX_VERSION >= 200112L)  /* opendir, readdir require POSIX.1-2001 */\n#  include <dirent.h>       /* opendir, readdir */\n#  include <string.h>       /* strerror, memcpy */\n#endif /* #ifdef _WIN32 */\n\n/*-****************************************\n*  Internal Macros\n******************************************/\n\n/* CONTROL is almost like an assert(), but is never disabled.\n * It's designed for failures that may happen rarely,\n * but we don't want to maintain a specific error code path for them,\n * such as a malloc() returning NULL for example.\n * Since it's always active, this macro can trigger side effects.\n */\n#define CONTROL(c)  {         \\\n    if (!(c)) {               \\\n        UTIL_DISPLAYLEVEL(1, \"Error : %s, %i : %s\",  \\\n                          __FILE__, __LINE__, #c);   \\\n        exit(1);              \\\n}   }\n\n/* console log */\n#define UTIL_DISPLAY(...)         fprintf(stderr, __VA_ARGS__)\n#define UTIL_DISPLAYLEVEL(l, ...) { if (g_utilDisplayLevel>=l) { UTIL_DISPLAY(__VA_ARGS__); } }\n\nstatic int g_traceDepth = 0;\nint g_traceFileStat = 0;\n\n#define UTIL_TRACE_CALL(...)                                         \\\n    {                                                                \\\n        if (g_traceFileStat) {                                       \\\n            UTIL_DISPLAY(\"Trace:FileStat: %*s> \", g_traceDepth, \"\"); \\\n            UTIL_DISPLAY(__VA_ARGS__);                               \\\n            UTIL_DISPLAY(\"\\n\");                                      \\\n            ++g_traceDepth;                                          \\\n        }                                                            \\\n    }\n\n#define UTIL_TRACE_RET(ret)                                                     \\\n    {                                                                           \\\n        if (g_traceFileStat) {                                                  \\\n            --g_traceDepth;                                                     \\\n            UTIL_DISPLAY(\"Trace:FileStat: %*s< %d\\n\", g_traceDepth, \"\", (ret)); \\\n        }                                                                      \\\n    }\n\n/* A modified version of realloc().\n * If UTIL_realloc() fails the original block is freed.\n */\nUTIL_STATIC void* UTIL_realloc(void *ptr, size_t size)\n{\n    void *newptr = realloc(ptr, size);\n    if (newptr) return newptr;\n    free(ptr);\n    return NULL;\n}\n\n#if defined(_MSC_VER)\n    #define chmod _chmod\n#endif\n\n#ifndef ZSTD_HAVE_FCHMOD\n#if PLATFORM_POSIX_VERSION >= 199309L\n#define ZSTD_HAVE_FCHMOD\n#endif\n#endif\n\n#ifndef ZSTD_HAVE_FCHOWN\n#if PLATFORM_POSIX_VERSION >= 200809L\n#define ZSTD_HAVE_FCHOWN\n#endif\n#endif\n\n/*-****************************************\n*  Console log\n******************************************/\nint g_utilDisplayLevel;\n\nint UTIL_requireUserConfirmation(const char* prompt, const char* abortMsg,\n                                 const char* acceptableLetters, int hasStdinInput) {\n    int ch, result;\n\n    if (hasStdinInput) {\n        UTIL_DISPLAY(\"stdin is an input - not proceeding.\\n\");\n        return 1;\n    }\n\n    UTIL_DISPLAY(\"%s\", prompt);\n    ch = getchar();\n    result = 0;\n    if (strchr(acceptableLetters, ch) == NULL) {\n        UTIL_DISPLAY(\"%s \\n\", abortMsg);\n        result = 1;\n    }\n    /* flush the rest */\n    while ((ch!=EOF) && (ch!='\\n'))\n        ch = getchar();\n    return result;\n}\n\n\n/*-*************************************\n*  Constants\n***************************************/\n#define KB * (1 << 10)\n#define LIST_SIZE_INCREASE   (8 KB)\n#define MAX_FILE_OF_FILE_NAMES_SIZE (1<<20)*50\n\n\n/*-*************************************\n*  Functions\n***************************************/\n\nvoid UTIL_traceFileStat(void)\n{\n    g_traceFileStat = 1;\n}\n\nint UTIL_fstat(const int fd, const char* filename, stat_t* statbuf)\n{\n    int ret;\n    UTIL_TRACE_CALL(\"UTIL_stat(%d, %s)\", fd, filename);\n#if defined(_MSC_VER)\n    if (fd >= 0) {\n        ret = !_fstat64(fd, statbuf);\n    } else {\n        ret = !_stat64(filename, statbuf);\n    }\n#elif defined(__MINGW32__) && defined (__MSVCRT__)\n    if (fd >= 0) {\n        ret = !_fstati64(fd, statbuf);\n    } else {\n        ret = !_stati64(filename, statbuf);\n    }\n#else\n    if (fd >= 0) {\n        ret = !fstat(fd, statbuf);\n    } else {\n        ret = !stat(filename, statbuf);\n    }\n#endif\n    UTIL_TRACE_RET(ret);\n    return ret;\n}\n\nint UTIL_stat(const char* filename, stat_t* statbuf)\n{\n    return UTIL_fstat(-1, filename, statbuf);\n}\n\nint UTIL_isFdRegularFile(int fd)\n{\n    stat_t statbuf;\n    int ret;\n    UTIL_TRACE_CALL(\"UTIL_isFdRegularFile(%d)\", fd);\n    ret = fd >= 0 && UTIL_fstat(fd, \"\", &statbuf) && UTIL_isRegularFileStat(&statbuf);\n    UTIL_TRACE_RET(ret);\n    return ret;\n}\n\nint UTIL_isRegularFile(const char* infilename)\n{\n    stat_t statbuf;\n    int ret;\n    UTIL_TRACE_CALL(\"UTIL_isRegularFile(%s)\", infilename);\n    ret = UTIL_stat(infilename, &statbuf) && UTIL_isRegularFileStat(&statbuf);\n    UTIL_TRACE_RET(ret);\n    return ret;\n}\n\nint UTIL_isRegularFileStat(const stat_t* statbuf)\n{\n#if defined(_MSC_VER)\n    return (statbuf->st_mode & S_IFREG) != 0;\n#else\n    return S_ISREG(statbuf->st_mode) != 0;\n#endif\n}\n\n/* like chmod, but avoid changing permission of /dev/null */\nint UTIL_chmod(char const* filename, const stat_t* statbuf, mode_t permissions)\n{\n    return UTIL_fchmod(-1, filename, statbuf, permissions);\n}\n\nint UTIL_fchmod(const int fd, char const* filename, const stat_t* statbuf, mode_t permissions)\n{\n    stat_t localStatBuf;\n    UTIL_TRACE_CALL(\"UTIL_chmod(%s, %#4o)\", filename, (unsigned)permissions);\n    if (statbuf == NULL) {\n        if (!UTIL_fstat(fd, filename, &localStatBuf)) {\n            UTIL_TRACE_RET(0);\n            return 0;\n        }\n        statbuf = &localStatBuf;\n    }\n    if (!UTIL_isRegularFileStat(statbuf)) {\n        UTIL_TRACE_RET(0);\n        return 0; /* pretend success, but don't change anything */\n    }\n#ifdef ZSTD_HAVE_FCHMOD\n    if (fd >= 0) {\n        int ret;\n        UTIL_TRACE_CALL(\"fchmod\");\n        ret = fchmod(fd, permissions);\n        UTIL_TRACE_RET(ret);\n        UTIL_TRACE_RET(ret);\n        return ret;\n    } else\n#endif\n    {\n        int ret;\n        UTIL_TRACE_CALL(\"chmod\");\n        ret = chmod(filename, permissions);\n        UTIL_TRACE_RET(ret);\n        UTIL_TRACE_RET(ret);\n        return ret;\n    }\n}\n\n/* set access and modification times */\nint UTIL_utime(const char* filename, const stat_t *statbuf)\n{\n    int ret;\n    UTIL_TRACE_CALL(\"UTIL_utime(%s)\", filename);\n    /* We check that st_mtime is a macro here in order to give us confidence\n     * that struct stat has a struct timespec st_mtim member. We need this\n     * check because there are some platforms that claim to be POSIX 2008\n     * compliant but which do not have st_mtim... */\n    /* FreeBSD has implemented POSIX 2008 for a long time but still only\n     * advertises support for POSIX 2001. They have a version macro that\n     * lets us safely gate them in.\n     * See https://docs.freebsd.org/en/books/porters-handbook/versions/.\n     */\n#if ZSTD_USE_UTIMENSAT\n    {\n        /* (atime, mtime) */\n        struct timespec timebuf[2] = { {0, UTIME_NOW} };\n        timebuf[1] = statbuf->st_mtim;\n        ret = utimensat(AT_FDCWD, filename, timebuf, 0);\n    }\n#else\n    {\n        struct utimbuf timebuf;\n        timebuf.actime = time(NULL);\n        timebuf.modtime = statbuf->st_mtime;\n        ret = utime(filename, &timebuf);\n    }\n#endif\n    errno = 0;\n    UTIL_TRACE_RET(ret);\n    return ret;\n}\n\nint UTIL_setFileStat(const char *filename, const stat_t *statbuf)\n{\n    return UTIL_setFDStat(-1, filename, statbuf);\n}\n\nint UTIL_setFDStat(const int fd, const char *filename, const stat_t *statbuf)\n{\n    int res = 0;\n    stat_t curStatBuf;\n    UTIL_TRACE_CALL(\"UTIL_setFileStat(%d, %s)\", fd, filename);\n\n    if (!UTIL_fstat(fd, filename, &curStatBuf) || !UTIL_isRegularFileStat(&curStatBuf)) {\n        UTIL_TRACE_RET(-1);\n        return -1;\n    }\n\n    /* Mimic gzip's behavior:\n     *\n     * \"Change the group first, then the permissions, then the owner.\n     * That way, the permissions will be correct on systems that allow\n     * users to give away files, without introducing a security hole.\n     * Security depends on permissions not containing the setuid or\n     * setgid bits.\" */\n\n#if !defined(_WIN32)\n#ifdef ZSTD_HAVE_FCHOWN\n    if (fd >= 0) {\n        res += fchown(fd, -1, statbuf->st_gid);  /* Apply group ownership */\n    } else\n#endif\n    {\n        res += chown(filename, -1, statbuf->st_gid);  /* Apply group ownership */\n    }\n#endif\n\n    res += UTIL_fchmod(fd, filename, &curStatBuf, statbuf->st_mode & 0777);  /* Copy file permissions */\n\n#if !defined(_WIN32)\n#ifdef ZSTD_HAVE_FCHOWN\n    if (fd >= 0) {\n        res += fchown(fd, statbuf->st_uid, -1);  /* Apply user ownership */\n    } else\n#endif\n    {\n        res += chown(filename, statbuf->st_uid, -1);  /* Apply user ownership */\n    }\n#endif\n\n    errno = 0;\n    UTIL_TRACE_RET(-res);\n    return -res; /* number of errors is returned */\n}\n\nint UTIL_isDirectory(const char* infilename)\n{\n    stat_t statbuf;\n    int ret;\n    UTIL_TRACE_CALL(\"UTIL_isDirectory(%s)\", infilename);\n    ret = UTIL_stat(infilename, &statbuf) && UTIL_isDirectoryStat(&statbuf);\n    UTIL_TRACE_RET(ret);\n    return ret;\n}\n\nint UTIL_isDirectoryStat(const stat_t* statbuf)\n{\n    int ret;\n    UTIL_TRACE_CALL(\"UTIL_isDirectoryStat()\");\n#if defined(_MSC_VER)\n    ret = (statbuf->st_mode & _S_IFDIR) != 0;\n#else\n    ret = S_ISDIR(statbuf->st_mode) != 0;\n#endif\n    UTIL_TRACE_RET(ret);\n    return ret;\n}\n\nint UTIL_compareStr(const void *p1, const void *p2) {\n    return strcmp(* (char * const *) p1, * (char * const *) p2);\n}\n\nint UTIL_isSameFile(const char* fName1, const char* fName2)\n{\n    int ret;\n    assert(fName1 != NULL); assert(fName2 != NULL);\n    UTIL_TRACE_CALL(\"UTIL_isSameFile(%s, %s)\", fName1, fName2);\n#if defined(_MSC_VER) || defined(_WIN32)\n    /* note : Visual does not support file identification by inode.\n     *        inode does not work on Windows, even with a posix layer, like msys2.\n     *        The following work-around is limited to detecting exact name repetition only,\n     *        aka `filename` is considered different from `subdir/../filename` */\n    ret = !strcmp(fName1, fName2);\n#else\n    {   stat_t file1Stat;\n        stat_t file2Stat;\n        ret =  UTIL_stat(fName1, &file1Stat)\n            && UTIL_stat(fName2, &file2Stat)\n            && UTIL_isSameFileStat(fName1, fName2, &file1Stat, &file2Stat);\n    }\n#endif\n    UTIL_TRACE_RET(ret);\n    return ret;\n}\n\nint UTIL_isSameFileStat(\n        const char* fName1, const char* fName2,\n        const stat_t* file1Stat, const stat_t* file2Stat)\n{\n    int ret;\n    assert(fName1 != NULL); assert(fName2 != NULL);\n    UTIL_TRACE_CALL(\"UTIL_isSameFileStat(%s, %s)\", fName1, fName2);\n#if defined(_MSC_VER) || defined(_WIN32)\n    /* note : Visual does not support file identification by inode.\n     *        inode does not work on Windows, even with a posix layer, like msys2.\n     *        The following work-around is limited to detecting exact name repetition only,\n     *        aka `filename` is considered different from `subdir/../filename` */\n    (void)file1Stat;\n    (void)file2Stat;\n    ret = !strcmp(fName1, fName2);\n#else\n    {\n        ret =  (file1Stat->st_dev == file2Stat->st_dev)\n            && (file1Stat->st_ino == file2Stat->st_ino);\n    }\n#endif\n    UTIL_TRACE_RET(ret);\n    return ret;\n}\n\n/* UTIL_isFIFO : distinguish named pipes */\nint UTIL_isFIFO(const char* infilename)\n{\n    UTIL_TRACE_CALL(\"UTIL_isFIFO(%s)\", infilename);\n/* macro guards, as defined in : https://linux.die.net/man/2/lstat */\n#if PLATFORM_POSIX_VERSION >= 200112L\n    {\n        stat_t statbuf;\n        if (UTIL_stat(infilename, &statbuf) && UTIL_isFIFOStat(&statbuf)) {\n            UTIL_TRACE_RET(1);\n            return 1;\n        }\n    }\n#endif\n    (void)infilename;\n    UTIL_TRACE_RET(0);\n    return 0;\n}\n\n/* UTIL_isFIFO : distinguish named pipes */\nint UTIL_isFIFOStat(const stat_t* statbuf)\n{\n/* macro guards, as defined in : https://linux.die.net/man/2/lstat */\n#if PLATFORM_POSIX_VERSION >= 200112L\n    if (S_ISFIFO(statbuf->st_mode)) return 1;\n#endif\n    (void)statbuf;\n    return 0;\n}\n\n/* process substitution */\nint UTIL_isFileDescriptorPipe(const char* filename)\n{\n    UTIL_TRACE_CALL(\"UTIL_isFileDescriptorPipe(%s)\", filename);\n    /* Check if the filename is a /dev/fd/ path which indicates a file descriptor */\n    if (filename[0] == '/' && strncmp(filename, \"/dev/fd/\", 8) == 0) {\n        UTIL_TRACE_RET(1);\n        return 1;\n    }\n\n    /* Check for alternative process substitution formats on different systems */\n    if (filename[0] == '/' && strncmp(filename, \"/proc/self/fd/\", 14) == 0) {\n        UTIL_TRACE_RET(1);\n        return 1;\n    }\n\n    UTIL_TRACE_RET(0);\n    return 0; /* Not recognized as a file descriptor pipe */\n}\n\n/* UTIL_isBlockDevStat : distinguish named pipes */\nint UTIL_isBlockDevStat(const stat_t* statbuf)\n{\n/* macro guards, as defined in : https://linux.die.net/man/2/lstat */\n#if PLATFORM_POSIX_VERSION >= 200112L\n    if (S_ISBLK(statbuf->st_mode)) return 1;\n#endif\n    (void)statbuf;\n    return 0;\n}\n\nint UTIL_isLink(const char* infilename)\n{\n    UTIL_TRACE_CALL(\"UTIL_isLink(%s)\", infilename);\n/* macro guards, as defined in : https://linux.die.net/man/2/lstat */\n#if PLATFORM_POSIX_VERSION >= 200112L\n    {\n        stat_t statbuf;\n        int const r = lstat(infilename, &statbuf);\n        if (!r && S_ISLNK(statbuf.st_mode)) {\n            UTIL_TRACE_RET(1);\n            return 1;\n        }\n    }\n#endif\n    (void)infilename;\n    UTIL_TRACE_RET(0);\n    return 0;\n}\n\nstatic int g_fakeStdinIsConsole = 0;\nstatic int g_fakeStderrIsConsole = 0;\nstatic int g_fakeStdoutIsConsole = 0;\n\nint UTIL_isConsole(FILE* file)\n{\n    int ret;\n    UTIL_TRACE_CALL(\"UTIL_isConsole(%d)\", fileno(file));\n    if (file == stdin && g_fakeStdinIsConsole)\n        ret = 1;\n    else if (file == stderr && g_fakeStderrIsConsole)\n        ret = 1;\n    else if (file == stdout && g_fakeStdoutIsConsole)\n        ret = 1;\n    else\n        ret = IS_CONSOLE(file);\n    UTIL_TRACE_RET(ret);\n    return ret;\n}\n\nvoid UTIL_fakeStdinIsConsole(void)\n{\n    g_fakeStdinIsConsole = 1;\n}\nvoid UTIL_fakeStdoutIsConsole(void)\n{\n    g_fakeStdoutIsConsole = 1;\n}\nvoid UTIL_fakeStderrIsConsole(void)\n{\n    g_fakeStderrIsConsole = 1;\n}\n\nU64 UTIL_getFileSize(const char* infilename)\n{\n    stat_t statbuf;\n    UTIL_TRACE_CALL(\"UTIL_getFileSize(%s)\", infilename);\n    if (!UTIL_stat(infilename, &statbuf)) {\n        UTIL_TRACE_RET(-1);\n        return UTIL_FILESIZE_UNKNOWN;\n    }\n    {\n        U64 const size = UTIL_getFileSizeStat(&statbuf);\n        UTIL_TRACE_RET((int)size);\n        return size;\n    }\n}\n\nU64 UTIL_getFileSizeStat(const stat_t* statbuf)\n{\n    if (!UTIL_isRegularFileStat(statbuf)) return UTIL_FILESIZE_UNKNOWN;\n#if defined(_MSC_VER)\n    if (!(statbuf->st_mode & S_IFREG)) return UTIL_FILESIZE_UNKNOWN;\n#elif defined(__MINGW32__) && defined (__MSVCRT__)\n    if (!(statbuf->st_mode & S_IFREG)) return UTIL_FILESIZE_UNKNOWN;\n#else\n    if (!S_ISREG(statbuf->st_mode)) return UTIL_FILESIZE_UNKNOWN;\n#endif\n    return (U64)statbuf->st_size;\n}\n\nUTIL_HumanReadableSize_t UTIL_makeHumanReadableSize(U64 size)\n{\n    UTIL_HumanReadableSize_t hrs;\n\n    if (g_utilDisplayLevel > 3) {\n        /* In verbose mode, do not scale sizes down, except in the case of\n         * values that exceed the integral precision of a double. */\n        if (size >= (1ull << 53)) {\n            hrs.value = (double)size / (1ull << 20);\n            hrs.suffix = \" MiB\";\n            /* At worst, a double representation of a maximal size will be\n             * accurate to better than tens of kilobytes. */\n            hrs.precision = 2;\n        } else {\n            hrs.value = (double)size;\n            hrs.suffix = \" B\";\n            hrs.precision = 0;\n        }\n    } else {\n        /* In regular mode, scale sizes down and use suffixes. */\n        if (size >= (1ull << 60)) {\n            hrs.value = (double)size / (1ull << 60);\n            hrs.suffix = \" EiB\";\n        } else if (size >= (1ull << 50)) {\n            hrs.value = (double)size / (1ull << 50);\n            hrs.suffix = \" PiB\";\n        } else if (size >= (1ull << 40)) {\n            hrs.value = (double)size / (1ull << 40);\n            hrs.suffix = \" TiB\";\n        } else if (size >= (1ull << 30)) {\n            hrs.value = (double)size / (1ull << 30);\n            hrs.suffix = \" GiB\";\n        } else if (size >= (1ull << 20)) {\n            hrs.value = (double)size / (1ull << 20);\n            hrs.suffix = \" MiB\";\n        } else if (size >= (1ull << 10)) {\n            hrs.value = (double)size / (1ull << 10);\n            hrs.suffix = \" KiB\";\n        } else {\n            hrs.value = (double)size;\n            hrs.suffix = \" B\";\n        }\n\n        if (hrs.value >= 100 || (U64)hrs.value == size) {\n            hrs.precision = 0;\n        } else if (hrs.value >= 10) {\n            hrs.precision = 1;\n        } else if (hrs.value > 1) {\n            hrs.precision = 2;\n        } else {\n            hrs.precision = 3;\n        }\n    }\n\n    return hrs;\n}\n\nU64 UTIL_getTotalFileSize(const char* const * fileNamesTable, unsigned nbFiles)\n{\n    U64 total = 0;\n    unsigned n;\n    UTIL_TRACE_CALL(\"UTIL_getTotalFileSize(%u)\", nbFiles);\n    for (n=0; n<nbFiles; n++) {\n        U64 const size = UTIL_getFileSize(fileNamesTable[n]);\n        if (size == UTIL_FILESIZE_UNKNOWN) {\n            UTIL_TRACE_RET(-1);\n            return UTIL_FILESIZE_UNKNOWN;\n        }\n        total += size;\n    }\n    UTIL_TRACE_RET((int)total);\n    return total;\n}\n\n\n/* Read the entire content of a file into a buffer with progressive resizing */\nstatic char* UTIL_readFileContent(FILE* inFile, size_t* totalReadPtr)\n{\n    size_t bufSize = 64 KB;  /* Start with a reasonable buffer size */\n    size_t totalRead = 0;\n    size_t bytesRead = 0;\n    char* buf = (char*)malloc(bufSize);\n    if (buf == NULL) return NULL;\n\n\n    /* Read the file incrementally */\n    while ((bytesRead = fread(buf + totalRead, 1, bufSize - totalRead - 1, inFile)) > 0) {\n        totalRead += bytesRead;\n\n        /* If buffer is nearly full, expand it */\n        if (bufSize - totalRead < 1 KB) {\n            if (bufSize >= MAX_FILE_OF_FILE_NAMES_SIZE) {\n                /* Too large, abort */\n                free(buf);\n                return NULL;\n            }\n\n            {   size_t newBufSize = bufSize * 2;\n                if (newBufSize > MAX_FILE_OF_FILE_NAMES_SIZE)\n                    newBufSize = MAX_FILE_OF_FILE_NAMES_SIZE;\n\n                {   char* newBuf = (char*)realloc(buf, newBufSize);\n                    if (newBuf == NULL) {\n                        free(buf);\n                        return NULL;\n                    }\n\n                    buf = newBuf;\n                    bufSize = newBufSize;\n        }   }   }\n    }\n\n    /* Add null terminator to the end */\n    buf[totalRead] = '\\0';\n    *totalReadPtr = totalRead;\n\n    return buf;\n}\n\n/* Process a buffer containing multiple lines and count the number of lines */\nstatic size_t UTIL_processLines(char* buffer, size_t bufferSize)\n{\n    size_t lineCount = 0;\n    size_t i = 0;\n\n    /* Convert newlines to null terminators and count lines */\n    while (i < bufferSize) {\n        if (buffer[i] == '\\n') {\n            buffer[i] = '\\0';  /* Replace newlines with null terminators */\n            lineCount++;\n        }\n        i++;\n    }\n\n    /* Count the last line if it doesn't end with a newline */\n    if (bufferSize > 0 && (i == 0 || buffer[i-1] != '\\0')) {\n        lineCount++;\n    }\n\n    return lineCount;\n}\n\n/* Create an array of pointers to the lines in a buffer */\nstatic const char** UTIL_createLinePointers(char* buffer, size_t numLines, size_t bufferSize)\n{\n    size_t lineIndex = 0;\n    size_t pos = 0;\n    void* const bufferPtrs = malloc(numLines * sizeof(const char**));\n    const char** const linePointers = (const char**)bufferPtrs;\n    if (bufferPtrs == NULL) return NULL;\n\n    while (lineIndex < numLines && pos < bufferSize) {\n        size_t len = 0;\n        linePointers[lineIndex++] = buffer+pos;\n\n        /* Find the next null terminator, being careful not to go past the buffer */\n        while ((pos + len < bufferSize) && buffer[pos + len] != '\\0') {\n            len++;\n        }\n\n        /* Move past this string and its null terminator */\n        pos += len;\n        if (pos < bufferSize) pos++;  /* Skip the null terminator if we're not at buffer end */\n    }\n\n    /* Verify we processed the expected number of lines */\n    if (lineIndex != numLines) {\n        /* Something went wrong - we didn't find as many lines as expected */\n        free(bufferPtrs);\n        return NULL;\n    }\n\n    return linePointers;\n}\n\nFileNamesTable*\nUTIL_createFileNamesTable_fromFileList(const char* fileList)\n{\n    stat_t statbuf;\n    char* buffer = NULL;\n    size_t numLines = 0;\n    size_t bufferSize = 0;\n\n    /* Check if the input is a valid file */\n    if (!UTIL_stat(fileList, &statbuf)) {\n        return NULL;\n    }\n\n    /* Check if the input is a supported type */\n    if (!UTIL_isRegularFileStat(&statbuf) &&\n        !UTIL_isFIFOStat(&statbuf) &&\n        !UTIL_isFileDescriptorPipe(fileList)) {\n        return NULL;\n    }\n\n    /* Open the input file */\n    {   FILE* const inFile = fopen(fileList, \"rb\");\n        if (inFile == NULL) return NULL;\n\n        /* Read the file content */\n        buffer = UTIL_readFileContent(inFile, &bufferSize);\n        fclose(inFile);\n    }\n\n    if (buffer == NULL) return NULL;\n\n    /* Process lines */\n    numLines = UTIL_processLines(buffer, bufferSize);\n    if (numLines == 0) {\n        free(buffer);\n        return NULL;\n    }\n\n    /* Create line pointers */\n    {   const char** linePointers = UTIL_createLinePointers(buffer, numLines, bufferSize);\n        if (linePointers == NULL) {\n            free(buffer);\n            return NULL;\n        }\n\n        /* Create the final table */\n        return UTIL_assembleFileNamesTable(linePointers, numLines, buffer);\n    }\n}\n\n\nstatic FileNamesTable*\nUTIL_assembleFileNamesTable2(const char** filenames, size_t tableSize, size_t tableCapacity, char* buf)\n{\n    FileNamesTable* const table = (FileNamesTable*) malloc(sizeof(*table));\n    CONTROL(table != NULL);\n    table->fileNames = filenames;\n    table->buf = buf;\n    table->tableSize = tableSize;\n    table->tableCapacity = tableCapacity;\n    return table;\n}\n\nFileNamesTable*\nUTIL_assembleFileNamesTable(const char** filenames, size_t tableSize, char* buf)\n{\n    return UTIL_assembleFileNamesTable2(filenames, tableSize, tableSize, buf);\n}\n\nvoid UTIL_freeFileNamesTable(FileNamesTable* table)\n{\n    if (table==NULL) return;\n    free((void*)table->fileNames);\n    free(table->buf);\n    free(table);\n}\n\nFileNamesTable* UTIL_allocateFileNamesTable(size_t tableSize)\n{\n    const char** const fnTable = (const char**)malloc(tableSize * sizeof(*fnTable));\n    FileNamesTable* fnt;\n    if (fnTable==NULL) return NULL;\n    fnt = UTIL_assembleFileNamesTable(fnTable, tableSize, NULL);\n    fnt->tableSize = 0;   /* the table is empty */\n    return fnt;\n}\n\nint UTIL_searchFileNamesTable(FileNamesTable* table, char const* name) {\n    size_t i;\n    for(i=0 ;i < table->tableSize; i++) {\n        if(!strcmp(table->fileNames[i], name)) {\n            return (int)i;\n        }\n    }\n    return -1;\n}\n\nvoid UTIL_refFilename(FileNamesTable* fnt, const char* filename)\n{\n    assert(fnt->tableSize < fnt->tableCapacity);\n    fnt->fileNames[fnt->tableSize] = filename;\n    fnt->tableSize++;\n}\n\nstatic size_t getTotalTableSize(FileNamesTable* table)\n{\n    size_t fnb, totalSize = 0;\n    for(fnb = 0 ; fnb < table->tableSize && table->fileNames[fnb] ; ++fnb) {\n        totalSize += strlen(table->fileNames[fnb]) + 1; /* +1 to add '\\0' at the end of each fileName */\n    }\n    return totalSize;\n}\n\nFileNamesTable*\nUTIL_mergeFileNamesTable(FileNamesTable* table1, FileNamesTable* table2)\n{\n    unsigned newTableIdx = 0;\n    size_t pos = 0;\n    size_t newTotalTableSize;\n    char* buf;\n\n    FileNamesTable* const newTable = UTIL_assembleFileNamesTable(NULL, 0, NULL);\n    CONTROL( newTable != NULL );\n\n    newTotalTableSize = getTotalTableSize(table1) + getTotalTableSize(table2);\n\n    buf = (char*) calloc(newTotalTableSize, sizeof(*buf));\n    CONTROL ( buf != NULL );\n\n    newTable->buf = buf;\n    newTable->tableSize = table1->tableSize + table2->tableSize;\n    newTable->fileNames = (const char **) calloc(newTable->tableSize, sizeof(*(newTable->fileNames)));\n    CONTROL ( newTable->fileNames != NULL );\n\n    {   unsigned idx1;\n        for( idx1=0 ; (idx1 < table1->tableSize) && table1->fileNames[idx1] && (pos < newTotalTableSize); ++idx1, ++newTableIdx) {\n            size_t const curLen = strlen(table1->fileNames[idx1]);\n            memcpy(buf+pos, table1->fileNames[idx1], curLen);\n            assert(newTableIdx <= newTable->tableSize);\n            newTable->fileNames[newTableIdx] = buf+pos;\n            pos += curLen+1;\n    }   }\n\n    {   unsigned idx2;\n        for( idx2=0 ; (idx2 < table2->tableSize) && table2->fileNames[idx2] && (pos < newTotalTableSize) ; ++idx2, ++newTableIdx) {\n            size_t const curLen = strlen(table2->fileNames[idx2]);\n            memcpy(buf+pos, table2->fileNames[idx2], curLen);\n            assert(newTableIdx < newTable->tableSize);\n            newTable->fileNames[newTableIdx] = buf+pos;\n            pos += curLen+1;\n    }   }\n    assert(pos <= newTotalTableSize);\n    newTable->tableSize = newTableIdx;\n\n    UTIL_freeFileNamesTable(table1);\n    UTIL_freeFileNamesTable(table2);\n\n    return newTable;\n}\n\n#ifdef _WIN32\nstatic int UTIL_prepareFileList(const char* dirName,\n                                char** bufStart, size_t* pos,\n                                char** bufEnd, int followLinks)\n{\n    char* path;\n    size_t dirLength, pathLength;\n    int nbFiles = 0;\n    WIN32_FIND_DATAA cFile;\n    HANDLE hFile;\n\n    dirLength = strlen(dirName);\n    path = (char*) malloc(dirLength + 3);\n    if (!path) return 0;\n\n    memcpy(path, dirName, dirLength);\n    path[dirLength] = '\\\\';\n    path[dirLength+1] = '*';\n    path[dirLength+2] = 0;\n\n    hFile=FindFirstFileA(path, &cFile);\n    if (hFile == INVALID_HANDLE_VALUE) {\n        UTIL_DISPLAYLEVEL(1, \"Cannot open directory '%s'\\n\", dirName);\n        free(path);\n        return 0;\n    }\n    free(path);\n\n    do {\n        size_t const fnameLength = strlen(cFile.cFileName);\n        path = (char*) malloc(dirLength + fnameLength + 2);\n        if (!path) { FindClose(hFile); return 0; }\n        memcpy(path, dirName, dirLength);\n        path[dirLength] = '\\\\';\n        memcpy(path+dirLength+1, cFile.cFileName, fnameLength);\n        pathLength = dirLength+1+fnameLength;\n        path[pathLength] = 0;\n        if (cFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {\n            if ( strcmp (cFile.cFileName, \"..\") == 0\n              || strcmp (cFile.cFileName, \".\") == 0 )\n                continue;\n            /* Recursively call \"UTIL_prepareFileList\" with the new path. */\n            nbFiles += UTIL_prepareFileList(path, bufStart, pos, bufEnd, followLinks);\n            if (*bufStart == NULL) { free(path); FindClose(hFile); return 0; }\n        } else if ( (cFile.dwFileAttributes & FILE_ATTRIBUTE_NORMAL)\n                 || (cFile.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)\n                 || (cFile.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) ) {\n            if (*bufStart + *pos + pathLength >= *bufEnd) {\n                ptrdiff_t const newListSize = (*bufEnd - *bufStart) + LIST_SIZE_INCREASE;\n                *bufStart = (char*)UTIL_realloc(*bufStart, newListSize);\n                if (*bufStart == NULL) { free(path); FindClose(hFile); return 0; }\n                *bufEnd = *bufStart + newListSize;\n            }\n            if (*bufStart + *pos + pathLength < *bufEnd) {\n                memcpy(*bufStart + *pos, path, pathLength+1 /* include final \\0 */);\n                *pos += pathLength + 1;\n                nbFiles++;\n        }   }\n        free(path);\n    } while (FindNextFileA(hFile, &cFile));\n\n    FindClose(hFile);\n    return nbFiles;\n}\n\n#elif defined(__linux__) || (PLATFORM_POSIX_VERSION >= 200112L)  /* opendir, readdir require POSIX.1-2001 */\n\nstatic int UTIL_prepareFileList(const char *dirName,\n                                char** bufStart, size_t* pos,\n                                char** bufEnd, int followLinks)\n{\n    DIR* dir;\n    struct dirent * entry;\n    size_t dirLength;\n    int nbFiles = 0;\n\n    if (!(dir = opendir(dirName))) {\n        UTIL_DISPLAYLEVEL(1, \"Cannot open directory '%s': %s\\n\", dirName, strerror(errno));\n        return 0;\n    }\n\n    dirLength = strlen(dirName);\n    errno = 0;\n    while ((entry = readdir(dir)) != NULL) {\n        char* path;\n        size_t fnameLength, pathLength;\n        if (strcmp (entry->d_name, \"..\") == 0 ||\n            strcmp (entry->d_name, \".\") == 0) continue;\n        fnameLength = strlen(entry->d_name);\n        path = (char*) malloc(dirLength + fnameLength + 2);\n        if (!path) { closedir(dir); return 0; }\n        memcpy(path, dirName, dirLength);\n\n        path[dirLength] = '/';\n        memcpy(path+dirLength+1, entry->d_name, fnameLength);\n        pathLength = dirLength+1+fnameLength;\n        path[pathLength] = 0;\n\n        if (!followLinks && UTIL_isLink(path)) {\n            UTIL_DISPLAYLEVEL(2, \"Warning : %s is a symbolic link, ignoring\\n\", path);\n            free(path);\n            continue;\n        }\n\n        if (UTIL_isDirectory(path)) {\n            nbFiles += UTIL_prepareFileList(path, bufStart, pos, bufEnd, followLinks);  /* Recursively call \"UTIL_prepareFileList\" with the new path. */\n            if (*bufStart == NULL) { free(path); closedir(dir); return 0; }\n        } else {\n            if (*bufStart + *pos + pathLength >= *bufEnd) {\n                ptrdiff_t newListSize = (*bufEnd - *bufStart) + LIST_SIZE_INCREASE;\n                assert(newListSize >= 0);\n                *bufStart = (char*)UTIL_realloc(*bufStart, (size_t)newListSize);\n                if (*bufStart != NULL) {\n                    *bufEnd = *bufStart + newListSize;\n                } else {\n                    free(path); closedir(dir); return 0;\n                }\n            }\n            if (*bufStart + *pos + pathLength < *bufEnd) {\n                memcpy(*bufStart + *pos, path, pathLength + 1);  /* with final \\0 */\n                *pos += pathLength + 1;\n                nbFiles++;\n        }   }\n        free(path);\n        errno = 0; /* clear errno after UTIL_isDirectory, UTIL_prepareFileList */\n    }\n\n    if (errno != 0) {\n        UTIL_DISPLAYLEVEL(1, \"readdir(%s) error: %s \\n\", dirName, strerror(errno));\n        free(*bufStart);\n        *bufStart = NULL;\n    }\n    closedir(dir);\n    return nbFiles;\n}\n\n#else\n\nstatic int UTIL_prepareFileList(const char *dirName,\n                                char** bufStart, size_t* pos,\n                                char** bufEnd, int followLinks)\n{\n    (void)bufStart; (void)bufEnd; (void)pos; (void)followLinks;\n    UTIL_DISPLAYLEVEL(1, \"Directory %s ignored (compiled without _WIN32 or _POSIX_C_SOURCE) \\n\", dirName);\n    return 0;\n}\n\n#endif /* #ifdef _WIN32 */\n\nint UTIL_isCompressedFile(const char *inputName, const char *extensionList[])\n{\n  const char* ext = UTIL_getFileExtension(inputName);\n  while(*extensionList!=NULL)\n  {\n    const int isCompressedExtension = strcmp(ext,*extensionList);\n    if(isCompressedExtension==0)\n      return 1;\n    ++extensionList;\n  }\n   return 0;\n}\n\n/*Utility function to get file extension from file */\nconst char* UTIL_getFileExtension(const char* infilename)\n{\n   const char* extension = strrchr(infilename, '.');\n   if(!extension || extension==infilename) return \"\";\n   return extension;\n}\n\nstatic int pathnameHas2Dots(const char *pathname)\n{\n    /* We need to figure out whether any \"..\" present in the path is a whole\n     * path token, which is the case if it is bordered on both sides by either\n     * the beginning/end of the path or by a directory separator.\n     */\n    const char *needle = pathname;\n    while (1) {\n        needle = strstr(needle, \"..\");\n\n        if (needle == NULL) {\n            return 0;\n        }\n\n        if ((needle == pathname || needle[-1] == PATH_SEP)\n         && (needle[2] == '\\0' || needle[2] == PATH_SEP)) {\n            return 1;\n        }\n\n        /* increment so we search for the next match */\n        needle++;\n    };\n    return 0;\n}\n\nstatic int isFileNameValidForMirroredOutput(const char *filename)\n{\n    return !pathnameHas2Dots(filename);\n}\n\n\n#define DIR_DEFAULT_MODE 0755\nstatic mode_t getDirMode(const char *dirName)\n{\n    stat_t st;\n    if (!UTIL_stat(dirName, &st)) {\n        UTIL_DISPLAY(\"zstd: failed to get DIR stats %s: %s\\n\", dirName, strerror(errno));\n        return DIR_DEFAULT_MODE;\n    }\n    if (!UTIL_isDirectoryStat(&st)) {\n        UTIL_DISPLAY(\"zstd: expected directory: %s\\n\", dirName);\n        return DIR_DEFAULT_MODE;\n    }\n    return st.st_mode;\n}\n\nstatic int makeDir(const char *dir, mode_t mode)\n{\n#if defined(_MSC_VER) || defined(__MINGW32__) || defined (__MSVCRT__)\n    int ret = _mkdir(dir);\n    (void) mode;\n#else\n    int ret = mkdir(dir, mode);\n#endif\n    if (ret != 0) {\n        if (errno == EEXIST)\n            return 0;\n        UTIL_DISPLAY(\"zstd: failed to create DIR %s: %s\\n\", dir, strerror(errno));\n    }\n    return ret;\n}\n\n/* this function requires a mutable input string */\nstatic void convertPathnameToDirName(char *pathname)\n{\n    size_t len = 0;\n    char* pos = NULL;\n    /* get dir name from pathname similar to 'dirname()' */\n    assert(pathname != NULL);\n\n    /* remove trailing '/' chars */\n    len = strlen(pathname);\n    assert(len > 0);\n    while (pathname[len] == PATH_SEP) {\n        pathname[len] = '\\0';\n        len--;\n    }\n    if (len == 0) return;\n\n    /* if input is a single file, return '.' instead. i.e.\n     * \"xyz/abc/file.txt\" => \"xyz/abc\"\n       \"./file.txt\"       => \".\"\n       \"file.txt\"         => \".\"\n     */\n    pos = strrchr(pathname, PATH_SEP);\n    if (pos == NULL) {\n        pathname[0] = '.';\n        pathname[1] = '\\0';\n    } else {\n        *pos = '\\0';\n    }\n}\n\n/* pathname must be valid */\nstatic const char* trimLeadingRootChar(const char *pathname)\n{\n    assert(pathname != NULL);\n    if (pathname[0] == PATH_SEP)\n        return pathname + 1;\n    return pathname;\n}\n\n/* pathname must be valid */\nstatic const char* trimLeadingCurrentDirConst(const char *pathname)\n{\n    assert(pathname != NULL);\n    if ((pathname[0] == '.') && (pathname[1] == PATH_SEP))\n        return pathname + 2;\n    return pathname;\n}\n\nstatic char*\ntrimLeadingCurrentDir(char *pathname)\n{\n    /* 'union charunion' can do const-cast without compiler warning */\n    union charunion {\n        char *chr;\n        const char* cchr;\n    } ptr;\n    ptr.cchr = trimLeadingCurrentDirConst(pathname);\n    return ptr.chr;\n}\n\n/* remove leading './' or '/' chars here */\nstatic const char * trimPath(const char *pathname)\n{\n    return trimLeadingRootChar(\n            trimLeadingCurrentDirConst(pathname));\n}\n\nstatic char* mallocAndJoin2Dir(const char *dir1, const char *dir2)\n{\n    assert(dir1 != NULL && dir2 != NULL);\n    {   const size_t dir1Size = strlen(dir1);\n        const size_t dir2Size = strlen(dir2);\n        char *outDirBuffer, *buffer;\n\n        outDirBuffer = (char *) malloc(dir1Size + dir2Size + 2);\n        CONTROL(outDirBuffer != NULL);\n\n        memcpy(outDirBuffer, dir1, dir1Size);\n        outDirBuffer[dir1Size] = '\\0';\n\n        buffer = outDirBuffer + dir1Size;\n        if (dir1Size > 0 && *(buffer - 1) != PATH_SEP) {\n            *buffer = PATH_SEP;\n            buffer++;\n        }\n        memcpy(buffer, dir2, dir2Size);\n        buffer[dir2Size] = '\\0';\n\n        return outDirBuffer;\n    }\n}\n\n/* this function will return NULL if input srcFileName is not valid name for mirrored output path */\nchar* UTIL_createMirroredDestDirName(const char* srcFileName, const char* outDirRootName)\n{\n    char* pathname = NULL;\n    if (!isFileNameValidForMirroredOutput(srcFileName))\n        return NULL;\n\n    pathname = mallocAndJoin2Dir(outDirRootName, trimPath(srcFileName));\n\n    convertPathnameToDirName(pathname);\n    return pathname;\n}\n\nstatic int\nmirrorSrcDir(char* srcDirName, const char* outDirName)\n{\n    mode_t srcMode;\n    int status = 0;\n    char* newDir = mallocAndJoin2Dir(outDirName, trimPath(srcDirName));\n    if (!newDir)\n        return -ENOMEM;\n\n    srcMode = getDirMode(srcDirName);\n    status = makeDir(newDir, srcMode);\n    free(newDir);\n    return status;\n}\n\nstatic int\nmirrorSrcDirRecursive(char* srcDirName, const char* outDirName)\n{\n    int status = 0;\n    char* pp = trimLeadingCurrentDir(srcDirName);\n    char* sp = NULL;\n\n    while ((sp = strchr(pp, PATH_SEP)) != NULL) {\n        if (sp != pp) {\n            *sp = '\\0';\n            status = mirrorSrcDir(srcDirName, outDirName);\n            if (status != 0)\n                return status;\n            *sp = PATH_SEP;\n        }\n        pp = sp + 1;\n    }\n    status = mirrorSrcDir(srcDirName, outDirName);\n    return status;\n}\n\nstatic void\nmakeMirroredDestDirsWithSameSrcDirMode(char** srcDirNames, unsigned nbFile, const char* outDirName)\n{\n    unsigned int i = 0;\n    for (i = 0; i < nbFile; i++)\n        mirrorSrcDirRecursive(srcDirNames[i], outDirName);\n}\n\nstatic int\nfirstIsParentOrSameDirOfSecond(const char* firstDir, const char* secondDir)\n{\n    size_t firstDirLen  = strlen(firstDir),\n           secondDirLen = strlen(secondDir);\n    return firstDirLen <= secondDirLen &&\n           (secondDir[firstDirLen] == PATH_SEP || secondDir[firstDirLen] == '\\0') &&\n           0 == strncmp(firstDir, secondDir, firstDirLen);\n}\n\nstatic int compareDir(const void* pathname1, const void* pathname2) {\n    /* sort it after remove the leading '/'  or './'*/\n    const char* s1 = trimPath(*(char * const *) pathname1);\n    const char* s2 = trimPath(*(char * const *) pathname2);\n    return strcmp(s1, s2);\n}\n\nstatic void\nmakeUniqueMirroredDestDirs(char** srcDirNames, unsigned nbFile, const char* outDirName)\n{\n    unsigned int i = 0, uniqueDirNr = 0;\n    char** uniqueDirNames = NULL;\n\n    if (nbFile == 0)\n        return;\n\n    uniqueDirNames = (char** ) malloc(nbFile * sizeof (char *));\n    CONTROL(uniqueDirNames != NULL);\n\n    /* if dirs is \"a/b/c\" and \"a/b/c/d\", we only need call:\n     * we just need \"a/b/c/d\" */\n    qsort((void *)srcDirNames, nbFile, sizeof(char*), compareDir);\n\n    uniqueDirNr = 1;\n    uniqueDirNames[uniqueDirNr - 1] = srcDirNames[0];\n    for (i = 1; i < nbFile; i++) {\n        char* prevDirName = srcDirNames[i - 1];\n        char* currDirName = srcDirNames[i];\n\n        /* note: we always compare trimmed path, i.e.:\n         * src dir of \"./foo\" and \"/foo\" will be both saved into:\n         * \"outDirName/foo/\" */\n        if (!firstIsParentOrSameDirOfSecond(trimPath(prevDirName),\n                                            trimPath(currDirName)))\n            uniqueDirNr++;\n\n        /* we need to maintain original src dir name instead of trimmed\n         * dir, so we can retrieve the original src dir's mode_t */\n        uniqueDirNames[uniqueDirNr - 1] = currDirName;\n    }\n\n    makeMirroredDestDirsWithSameSrcDirMode(uniqueDirNames, uniqueDirNr, outDirName);\n\n    free(uniqueDirNames);\n}\n\nstatic void\nmakeMirroredDestDirs(char** srcFileNames, unsigned nbFile, const char* outDirName)\n{\n    unsigned int i = 0;\n    for (i = 0; i < nbFile; ++i)\n        convertPathnameToDirName(srcFileNames[i]);\n    makeUniqueMirroredDestDirs(srcFileNames, nbFile, outDirName);\n}\n\nvoid UTIL_mirrorSourceFilesDirectories(const char** inFileNames, unsigned int nbFile, const char* outDirName)\n{\n    unsigned int i = 0, validFilenamesNr = 0;\n    char** srcFileNames = (char **) malloc(nbFile * sizeof (char *));\n    CONTROL(srcFileNames != NULL);\n\n    /* check input filenames is valid */\n    for (i = 0; i < nbFile; ++i) {\n        if (isFileNameValidForMirroredOutput(inFileNames[i])) {\n            char* fname = STRDUP(inFileNames[i]);\n            CONTROL(fname != NULL);\n            srcFileNames[validFilenamesNr++] = fname;\n        }\n    }\n\n    if (validFilenamesNr > 0) {\n        makeDir(outDirName, DIR_DEFAULT_MODE);\n        makeMirroredDestDirs(srcFileNames, validFilenamesNr, outDirName);\n    }\n\n    for (i = 0; i < validFilenamesNr; i++)\n        free(srcFileNames[i]);\n    free(srcFileNames);\n}\n\nFileNamesTable*\nUTIL_createExpandedFNT(const char* const* inputNames, size_t nbIfns, int followLinks)\n{\n    unsigned nbFiles;\n    char* buf = (char*)malloc(LIST_SIZE_INCREASE);\n    char* bufend = buf + LIST_SIZE_INCREASE;\n\n    if (!buf) return NULL;\n\n    {   size_t ifnNb, pos;\n        for (ifnNb=0, pos=0, nbFiles=0; ifnNb<nbIfns; ifnNb++) {\n            if (!UTIL_isDirectory(inputNames[ifnNb])) {\n                size_t const len = strlen(inputNames[ifnNb]);\n                if (buf + pos + len >= bufend) {\n                    ptrdiff_t newListSize = (bufend - buf) + LIST_SIZE_INCREASE;\n                    assert(newListSize >= 0);\n                    buf = (char*)UTIL_realloc(buf, (size_t)newListSize);\n                    if (!buf) return NULL;\n                    bufend = buf + newListSize;\n                }\n                if (buf + pos + len < bufend) {\n                    memcpy(buf+pos, inputNames[ifnNb], len+1);  /* including final \\0 */\n                    pos += len + 1;\n                    nbFiles++;\n                }\n            } else {\n                nbFiles += (unsigned)UTIL_prepareFileList(inputNames[ifnNb], &buf, &pos, &bufend, followLinks);\n                if (buf == NULL) return NULL;\n    }   }   }\n\n    /* note : even if nbFiles==0, function returns a valid, though empty, FileNamesTable* object */\n\n    {   size_t ifnNb, pos;\n        size_t const fntCapacity = nbFiles + 1;  /* minimum 1, allows adding one reference, typically stdin */\n        const char** const fileNamesTable = (const char**)malloc(fntCapacity * sizeof(*fileNamesTable));\n        if (!fileNamesTable) { free(buf); return NULL; }\n\n        for (ifnNb = 0, pos = 0; ifnNb < nbFiles; ifnNb++) {\n            fileNamesTable[ifnNb] = buf + pos;\n            if (buf + pos > bufend) { free(buf); free((void*)fileNamesTable); return NULL; }\n            pos += strlen(fileNamesTable[ifnNb]) + 1;\n        }\n        return UTIL_assembleFileNamesTable2(fileNamesTable, nbFiles, fntCapacity, buf);\n    }\n}\n\n\nvoid UTIL_expandFNT(FileNamesTable** fnt, int followLinks)\n{\n    FileNamesTable* const newFNT = UTIL_createExpandedFNT((*fnt)->fileNames, (*fnt)->tableSize, followLinks);\n    CONTROL(newFNT != NULL);\n    UTIL_freeFileNamesTable(*fnt);\n    *fnt = newFNT;\n}\n\nFileNamesTable* UTIL_createFNT_fromROTable(const char** filenames, size_t nbFilenames)\n{\n    size_t const sizeof_FNTable = nbFilenames * sizeof(*filenames);\n    const char** const newFNTable = (const char**)malloc(sizeof_FNTable);\n    if (newFNTable==NULL) return NULL;\n    memcpy((void*)newFNTable, filenames, sizeof_FNTable);  /* void* : mitigate a Visual compiler bug or limitation */\n    return UTIL_assembleFileNamesTable(newFNTable, nbFilenames, NULL);\n}\n\n\n/*-****************************************\n*  count the number of cores\n******************************************/\n\n#if defined(_WIN32) || defined(WIN32)\n\n#include <windows.h>\n\ntypedef BOOL(WINAPI* LPFN_GLPI)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);\n\nDWORD CountSetBits(ULONG_PTR bitMask)\n{\n    DWORD LSHIFT = sizeof(ULONG_PTR)*8 - 1;\n    DWORD bitSetCount = 0;\n    ULONG_PTR bitTest = (ULONG_PTR)1 << LSHIFT;\n    DWORD i;\n\n    for (i = 0; i <= LSHIFT; ++i)\n    {\n        bitSetCount += ((bitMask & bitTest)?1:0);\n        bitTest/=2;\n    }\n\n    return bitSetCount;\n}\n\nint UTIL_countCores(int logical)\n{\n    static int numCores = 0;\n    if (numCores != 0) return numCores;\n\n    {   LPFN_GLPI glpi;\n        BOOL done = FALSE;\n        PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL;\n        PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL;\n        DWORD returnLength = 0;\n        size_t byteOffset = 0;\n\n#if defined(_MSC_VER)\n/* Visual Studio does not like the following cast */\n#   pragma warning( disable : 4054 )  /* conversion from function ptr to data ptr */\n#   pragma warning( disable : 4055 )  /* conversion from data ptr to function ptr */\n#endif\n        glpi = (LPFN_GLPI)(void*)GetProcAddress(GetModuleHandle(TEXT(\"kernel32\")),\n                                               \"GetLogicalProcessorInformation\");\n\n        if (glpi == NULL) {\n            goto failed;\n        }\n\n        while(!done) {\n            DWORD rc = glpi(buffer, &returnLength);\n            if (FALSE == rc) {\n                if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {\n                    if (buffer)\n                        free(buffer);\n                    buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(returnLength);\n\n                    if (buffer == NULL) {\n                        perror(\"zstd\");\n                        exit(1);\n                    }\n                } else {\n                    /* some other error */\n                    goto failed;\n                }\n            } else {\n                done = TRUE;\n        }   }\n\n        ptr = buffer;\n\n        while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength) {\n\n            if (ptr->Relationship == RelationProcessorCore) {\n                if (logical)\n                    numCores += CountSetBits(ptr->ProcessorMask);\n                else\n                    numCores++;\n            }\n\n            ptr++;\n            byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);\n        }\n\n        free(buffer);\n\n        return numCores;\n    }\n\nfailed:\n    /* try to fall back on GetSystemInfo */\n    {   SYSTEM_INFO sysinfo;\n        GetSystemInfo(&sysinfo);\n        numCores = sysinfo.dwNumberOfProcessors;\n        if (numCores == 0) numCores = 1; /* just in case */\n    }\n    return numCores;\n}\n\n#elif defined(__APPLE__)\n\n#include <sys/sysctl.h>\n\n/* Use apple-provided syscall\n * see: man 3 sysctl */\nint UTIL_countCores(int logical)\n{\n    static S32 numCores = 0; /* apple specifies int32_t */\n    if (numCores != 0) return numCores;\n\n    {   size_t size = sizeof(S32);\n        int const ret = sysctlbyname(logical ? \"hw.logicalcpu\" : \"hw.physicalcpu\", &numCores, &size, NULL, 0);\n        if (ret != 0) {\n            if (errno == ENOENT) {\n                /* entry not present, fall back on 1 */\n                numCores = 1;\n            } else {\n                perror(\"zstd: can't get number of cpus\");\n                exit(1);\n            }\n        }\n\n        return numCores;\n    }\n}\n\n#elif defined(__linux__)\n\n/* parse /proc/cpuinfo\n * siblings / cpu cores should give hyperthreading ratio\n * otherwise fall back on sysconf */\nint UTIL_countCores(int logical)\n{\n    static int numCores = 0;\n\n    if (numCores != 0) return numCores;\n\n    numCores = (int)sysconf(_SC_NPROCESSORS_ONLN);\n    if (numCores == -1) {\n        /* value not queryable, fall back on 1 */\n        return numCores = 1;\n    }\n\n    /* try to determine if there's hyperthreading */\n    {   FILE* const cpuinfo = fopen(\"/proc/cpuinfo\", \"r\");\n#define BUF_SIZE 80\n        char buff[BUF_SIZE];\n\n        int siblings = 0;\n        int cpu_cores = 0;\n        int ratio = 1;\n\n        if (cpuinfo == NULL) {\n            /* fall back on the sysconf value */\n            return numCores;\n        }\n\n        /* assume the cpu cores/siblings values will be constant across all\n         * present processors */\n        while (!feof(cpuinfo)) {\n            if (fgets(buff, BUF_SIZE, cpuinfo) != NULL) {\n                if (strncmp(buff, \"siblings\", 8) == 0) {\n                    const char* const sep = strchr(buff, ':');\n                    if (sep == NULL || *sep == '\\0') {\n                        /* formatting was broken? */\n                        goto failed;\n                    }\n\n                    siblings = atoi(sep + 1);\n                }\n                if (strncmp(buff, \"cpu cores\", 9) == 0) {\n                    const char* const sep = strchr(buff, ':');\n                    if (sep == NULL || *sep == '\\0') {\n                        /* formatting was broken? */\n                        goto failed;\n                    }\n\n                    cpu_cores = atoi(sep + 1);\n                }\n            } else if (ferror(cpuinfo)) {\n                /* fall back on the sysconf value */\n                goto failed;\n        }   }\n        if (siblings && cpu_cores && siblings > cpu_cores) {\n            ratio = siblings / cpu_cores;\n        }\n\n        if (ratio && numCores > ratio && !logical) {\n            numCores = numCores / ratio;\n        }\n\nfailed:\n        fclose(cpuinfo);\n        return numCores;\n    }\n}\n\n#elif defined(__FreeBSD__)\n\n#include <sys/sysctl.h>\n\n/* Use physical core sysctl when available\n * see: man 4 smp, man 3 sysctl */\nint UTIL_countCores(int logical)\n{\n    static int numCores = 0; /* freebsd sysctl is native int sized */\n#if __FreeBSD_version >= 1300008\n    static int perCore = 1;\n#endif\n    if (numCores != 0) return numCores;\n\n#if __FreeBSD_version >= 1300008\n    {   size_t size = sizeof(numCores);\n        int ret = sysctlbyname(\"kern.smp.cores\", &numCores, &size, NULL, 0);\n        if (ret == 0) {\n            if (logical) {\n                ret = sysctlbyname(\"kern.smp.threads_per_core\", &perCore, &size, NULL, 0);\n                /* default to physical cores if logical cannot be read */\n                if (ret == 0)\n                    numCores *= perCore;\n            }\n\n            return numCores;\n        }\n        if (errno != ENOENT) {\n            perror(\"zstd: can't get number of cpus\");\n            exit(1);\n        }\n        /* sysctl not present, fall through to older sysconf method */\n    }\n#else\n    /* suppress unused parameter warning */\n    (void) logical;\n#endif\n\n    numCores = (int)sysconf(_SC_NPROCESSORS_ONLN);\n    if (numCores == -1) {\n        /* value not queryable, fall back on 1 */\n        numCores = 1;\n    }\n    return numCores;\n}\n\n#elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__CYGWIN__)\n\n/* Use POSIX sysconf\n * see: man 3 sysconf */\nint UTIL_countCores(int logical)\n{\n    static int numCores = 0;\n\n    /* suppress unused parameter warning */\n    (void)logical;\n\n    if (numCores != 0) return numCores;\n\n    numCores = (int)sysconf(_SC_NPROCESSORS_ONLN);\n    if (numCores == -1) {\n        /* value not queryable, fall back on 1 */\n        return numCores = 1;\n    }\n    return numCores;\n}\n\n#else\n\nint UTIL_countCores(int logical)\n{\n    /* suppress unused parameter warning */\n    (void)logical;\n\n    /* assume 1 */\n    return 1;\n}\n\n#endif\n\nint UTIL_countPhysicalCores(void)\n{\n    return UTIL_countCores(0);\n}\n\nint UTIL_countLogicalCores(void)\n{\n    return UTIL_countCores(1);\n}\n"
  },
  {
    "path": "programs/util.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef UTIL_H_MODULE\n#define UTIL_H_MODULE\n\n/*-****************************************\n*  Dependencies\n******************************************/\n#include \"platform.h\"     /* PLATFORM_POSIX_VERSION, ZSTD_NANOSLEEP_SUPPORT, ZSTD_SETPRIORITY_SUPPORT */\n#include <stddef.h>       /* size_t, ptrdiff_t */\n#include <stdio.h>        /* FILE */\n#include <sys/types.h>    /* stat, utime */\n#include <sys/stat.h>     /* stat, chmod */\n#include \"../lib/common/mem.h\"          /* U64 */\n#if !(defined(_MSC_VER) || defined(__MINGW32__) || defined (__MSVCRT__))\n#include <libgen.h>\n#endif\n\n/*-************************************************************\n*  Fix fseek()'s 2GiB barrier with MSVC, macOS, *BSD, MinGW\n***************************************************************/\n#if defined(LIBC_NO_FSEEKO)\n/* Some older libc implementations don't include these functions (e.g. Bionic < 24) */\n#  define UTIL_fseek fseek\n#elif defined(_MSC_VER) && (_MSC_VER >= 1400)\n#  define UTIL_fseek _fseeki64\n#elif !defined(__64BIT__) && (PLATFORM_POSIX_VERSION >= 200112L) /* No point defining Large file for 64 bit */\n#  define UTIL_fseek fseeko\n#elif defined(__MINGW32__) && defined(__MSVCRT__) && !defined(__STRICT_ANSI__) && !defined(__NO_MINGW_LFS)\n#  define UTIL_fseek fseeko64\n#else\n#  define UTIL_fseek fseek\n#endif\n\n/*-*************************************************\n*  Sleep & priority functions: Windows - Posix - others\n***************************************************/\n#if defined(_WIN32)\n#  include <windows.h>\n#  define SET_REALTIME_PRIORITY SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS)\n#  define UTIL_sleep(s) Sleep(1000*s)\n#  define UTIL_sleepMilli(milli) Sleep(milli)\n\n#elif PLATFORM_POSIX_VERSION > 0 /* Unix-like operating system */\n#  include <unistd.h>   /* sleep */\n#  define UTIL_sleep(s) sleep(s)\n#  if ZSTD_NANOSLEEP_SUPPORT   /* necessarily defined in platform.h */\n#      define UTIL_sleepMilli(milli) { struct timespec t; t.tv_sec=0; t.tv_nsec=milli*1000000ULL; nanosleep(&t, NULL); }\n#  else\n#      define UTIL_sleepMilli(milli) /* disabled */\n#  endif\n#  if ZSTD_SETPRIORITY_SUPPORT\n#    include <sys/resource.h> /* setpriority */\n#    define SET_REALTIME_PRIORITY setpriority(PRIO_PROCESS, 0, -20)\n#  else\n#    define SET_REALTIME_PRIORITY /* disabled */\n#  endif\n\n#else  /* unknown non-unix operating system */\n#  define UTIL_sleep(s)          /* disabled */\n#  define UTIL_sleepMilli(milli) /* disabled */\n#  define SET_REALTIME_PRIORITY  /* disabled */\n#endif\n\n\n/*-****************************************\n*  Compiler specifics\n******************************************/\n#if defined(__INTEL_COMPILER)\n#  pragma warning(disable : 177)    /* disable: message #177: function was declared but never referenced, useful with UTIL_STATIC */\n#endif\n#if defined(__GNUC__)\n#  define UTIL_STATIC static __attribute__((unused))\n#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n#  define UTIL_STATIC static inline\n#elif defined(_MSC_VER)\n#  define UTIL_STATIC static __inline\n#else\n#  define UTIL_STATIC static  /* this version may generate warnings for unused static functions; disable the relevant warning */\n#endif\n\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/*-****************************************\n*  Console log\n******************************************/\nextern int g_utilDisplayLevel;\n\n/**\n * Displays a message prompt and returns success (0) if first character from stdin\n * matches any from acceptableLetters. Otherwise, returns failure (1) and displays abortMsg.\n * If any of the inputs are stdin itself, then automatically return failure (1).\n */\nint UTIL_requireUserConfirmation(const char* prompt, const char* abortMsg, const char* acceptableLetters, int hasStdinInput);\n\n\n/*-****************************************\n*  File functions\n******************************************/\n#if defined(_MSC_VER)\n    typedef struct __stat64 stat_t;\n    typedef int mode_t;\n#elif defined(__MINGW32__) && defined (__MSVCRT__)\n    typedef struct _stati64 stat_t;\n#else\n    typedef struct stat stat_t;\n#endif\n\n#if defined(_MSC_VER) || defined(__MINGW32__) || defined (__MSVCRT__) /* windows support */\n#define PATH_SEP '\\\\'\n#define STRDUP(s) _strdup(s)\n#else\n#define PATH_SEP '/'\n#define STRDUP(s) strdup(s)\n#endif\n\n\n/**\n * Calls platform's equivalent of stat() on filename and writes info to statbuf.\n * Returns success (1) or failure (0).\n *\n * UTIL_fstat() is like UTIL_stat() but takes an optional fd that refers to the\n * file in question. It turns out that this can be meaningfully faster. If fd is\n * -1, behaves just like UTIL_stat() (i.e., falls back to using the filename).\n */\nint UTIL_stat(const char* filename, stat_t* statbuf);\nint UTIL_fstat(const int fd, const char* filename, stat_t* statbuf);\n\n/**\n * Instead of getting a file's stats, this updates them with the info in the\n * provided stat_t. Currently sets owner, group, atime, and mtime. Will only\n * update this info for regular files.\n *\n * UTIL_setFDStat() also takes an fd, and will preferentially use that to\n * indicate which file to modify, If fd is -1, it will fall back to using the\n * filename.\n */\nint UTIL_setFileStat(const char* filename, const stat_t* statbuf);\nint UTIL_setFDStat(const int fd, const char* filename, const stat_t* statbuf);\n\n/**\n * Set atime to now and mtime to the st_mtim in statbuf.\n *\n * Directly wraps utime() or utimensat(). Returns -1 on error.\n * Does not validate filename is valid.\n */\nint UTIL_utime(const char* filename, const stat_t *statbuf);\n\n/*\n * These helpers operate on a pre-populated stat_t, i.e., the result of\n * calling one of the above functions.\n */\n\nint UTIL_isRegularFileStat(const stat_t* statbuf);\nint UTIL_isDirectoryStat(const stat_t* statbuf);\nint UTIL_isFIFOStat(const stat_t* statbuf);\nint UTIL_isBlockDevStat(const stat_t* statbuf);\nU64 UTIL_getFileSizeStat(const stat_t* statbuf);\n\n/**\n * Like chmod(), but only modifies regular files. Provided statbuf may be NULL,\n * in which case this function will stat() the file internally, in order to\n * check whether it should be modified.\n *\n * If fd is -1, fd is ignored and the filename is used.\n */\nint UTIL_chmod(char const* filename, const stat_t* statbuf, mode_t permissions);\nint UTIL_fchmod(const int fd, char const* filename, const stat_t* statbuf, mode_t permissions);\n\n/*\n * In the absence of a pre-existing stat result on the file in question, these\n * functions will do a stat() call internally and then use that result to\n * compute the needed information.\n */\n\nint UTIL_isFdRegularFile(int fd);\nint UTIL_isRegularFile(const char* infilename);\nint UTIL_isDirectory(const char* infilename);\nint UTIL_isSameFile(const char* file1, const char* file2);\nint UTIL_isSameFileStat(const char* file1, const char* file2, const stat_t* file1Stat, const stat_t* file2Stat);\nint UTIL_isCompressedFile(const char* infilename, const char *extensionList[]);\nint UTIL_isLink(const char* infilename);\nint UTIL_isFIFO(const char* infilename);\nint UTIL_isFileDescriptorPipe(const char* filename);\n\n/**\n * Returns with the given file descriptor is a console.\n * Allows faking whether stdin/stdout/stderr is a console\n * using UTIL_fake*IsConsole().\n */\nint UTIL_isConsole(FILE* file);\n\n/**\n * Pretends that stdin/stdout/stderr is a console for testing.\n */\nvoid UTIL_fakeStdinIsConsole(void);\nvoid UTIL_fakeStdoutIsConsole(void);\nvoid UTIL_fakeStderrIsConsole(void);\n\n/**\n * Emit traces for functions that read, or modify file metadata.\n */\nvoid UTIL_traceFileStat(void);\n\n#define UTIL_FILESIZE_UNKNOWN  ((U64)(-1))\nU64 UTIL_getFileSize(const char* infilename);\nU64 UTIL_getTotalFileSize(const char* const * fileNamesTable, unsigned nbFiles);\n\n/**\n * Take @size in bytes,\n * prepare the components to pretty-print it in a scaled way.\n * The components in the returned struct should be passed in\n * precision, value, suffix order to a \"%.*f%s\" format string.\n * Output policy is sensible to @g_utilDisplayLevel,\n * for verbose mode (@g_utilDisplayLevel >= 4),\n * does not scale down.\n */\ntypedef struct {\n  double value;\n  int precision;\n  const char* suffix;\n} UTIL_HumanReadableSize_t;\n\nUTIL_HumanReadableSize_t UTIL_makeHumanReadableSize(U64 size);\n\nint UTIL_compareStr(const void *p1, const void *p2);\nconst char* UTIL_getFileExtension(const char* infilename);\nvoid  UTIL_mirrorSourceFilesDirectories(const char** fileNamesTable, unsigned int nbFiles, const char *outDirName);\nchar* UTIL_createMirroredDestDirName(const char* srcFileName, const char* outDirRootName);\n\n\n\n/*-****************************************\n *  Lists of Filenames\n ******************************************/\n\ntypedef struct\n{   const char** fileNames;\n    char* buf;            /* fileNames are stored in this buffer (or are read-only) */\n    size_t tableSize;     /* nb of fileNames */\n    size_t tableCapacity;\n} FileNamesTable;\n\n/*! UTIL_createFileNamesTable_fromFileList() :\n *  read filenames from @inputFileName, and store them into returned object.\n * @return : a FileNamesTable*, or NULL in case of error (ex: @inputFileName doesn't exist).\n *  Note: inputFileSize must be less than 50MB\n */\nFileNamesTable*\nUTIL_createFileNamesTable_fromFileList(const char* inputFileName);\n\n/*! UTIL_assembleFileNamesTable() :\n *  This function takes ownership of its arguments, @filenames and @buf,\n *  and store them inside the created object.\n *  note : this function never fails,\n *         it will rather exit() the program if internal allocation fails.\n * @return : resulting FileNamesTable* object.\n */\nFileNamesTable*\nUTIL_assembleFileNamesTable(const char** filenames, size_t tableSize, char* buf);\n\n/*! UTIL_freeFileNamesTable() :\n *  This function is compatible with NULL argument and never fails.\n */\nvoid UTIL_freeFileNamesTable(FileNamesTable* table);\n\n/*! UTIL_mergeFileNamesTable():\n * @return : FileNamesTable*, concatenation of @table1 and @table2\n *  note: @table1 and @table2 are consumed (freed) by this operation\n */\nFileNamesTable*\nUTIL_mergeFileNamesTable(FileNamesTable* table1, FileNamesTable* table2);\n\n\n/*! UTIL_expandFNT() :\n *  read names from @fnt, and expand those corresponding to directories\n *  update @fnt, now containing only file names,\n *  note : in case of error, @fnt[0] is NULL\n */\nvoid UTIL_expandFNT(FileNamesTable** fnt, int followLinks);\n\n/*! UTIL_createFNT_fromROTable() :\n *  copy the @filenames pointer table inside the returned object.\n *  The names themselves are still stored in their original buffer, which must outlive the object.\n * @return : a FileNamesTable* object,\n *        or NULL in case of error\n */\nFileNamesTable*\nUTIL_createFNT_fromROTable(const char** filenames, size_t nbFilenames);\n\n/*! UTIL_allocateFileNamesTable() :\n *  Allocates a table of const char*, to insert read-only names later on.\n *  The created FileNamesTable* doesn't hold a buffer.\n * @return : FileNamesTable*, or NULL, if allocation fails.\n */\nFileNamesTable* UTIL_allocateFileNamesTable(size_t tableSize);\n\n/*! UTIL_searchFileNamesTable() :\n *  Searched through entries in FileNamesTable for a specific name.\n * @return : index of entry if found or -1 if not found\n */\nint UTIL_searchFileNamesTable(FileNamesTable* table, char const* name);\n\n/*! UTIL_refFilename() :\n *  Add a reference to read-only name into @fnt table.\n *  As @filename is only referenced, its lifetime must outlive @fnt.\n *  Internal table must be large enough to reference a new member,\n *  otherwise its UB (protected by an `assert()`).\n */\nvoid UTIL_refFilename(FileNamesTable* fnt, const char* filename);\n\n\n/* UTIL_createExpandedFNT() is only active if UTIL_HAS_CREATEFILELIST is defined.\n * Otherwise, UTIL_createExpandedFNT() is a shell function which does nothing\n * apart from displaying a warning message.\n */\n#ifdef _WIN32\n#  define UTIL_HAS_CREATEFILELIST\n#elif defined(__linux__) || (PLATFORM_POSIX_VERSION >= 200112L)  /* opendir, readdir require POSIX.1-2001 */\n#  define UTIL_HAS_CREATEFILELIST\n#  define UTIL_HAS_MIRRORFILELIST\n#else\n   /* do not define UTIL_HAS_CREATEFILELIST */\n#endif\n\n/*! UTIL_createExpandedFNT() :\n *  read names from @filenames, and expand those corresponding to directories.\n *  links are followed or not depending on @followLinks directive.\n * @return : an expanded FileNamesTable*, where each name is a file\n *        or NULL in case of error\n */\nFileNamesTable*\nUTIL_createExpandedFNT(const char* const* filenames, size_t nbFilenames, int followLinks);\n\n#if defined(_WIN32)\nDWORD CountSetBits(ULONG_PTR bitMask);\n#endif\n\n/*-****************************************\n *  System\n ******************************************/\n\nint UTIL_countCores(int logical);\n\nint UTIL_countPhysicalCores(void);\n\nint UTIL_countLogicalCores(void);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* UTIL_H_MODULE */\n"
  },
  {
    "path": "programs/windres/verrsrc.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n/* minimal set of defines required to generate zstd.res from zstd.rc */\n\n#define VS_VERSION_INFO         1\n\n#define VS_FFI_FILEFLAGSMASK    0x0000003FL\n#define VOS_NT_WINDOWS32        0x00040004L\n#define VFT_DLL                 0x00000002L\n#define VFT2_UNKNOWN            0x00000000L\n"
  },
  {
    "path": "programs/windres/zstd.rc",
    "content": "// Microsoft Visual C++ generated resource script.\r\n//\r\n\r\n#include \"zstd.h\" /* ZSTD_VERSION_STRING */\r\n#define APSTUDIO_READONLY_SYMBOLS\r\n#include \"verrsrc.h\"\r\n#undef APSTUDIO_READONLY_SYMBOLS\r\n\r\n\r\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\nLANGUAGE 9, 1\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Version\r\n//\r\n\r\nVS_VERSION_INFO     VERSIONINFO\r\n  FILEVERSION       ZSTD_VERSION_MAJOR,ZSTD_VERSION_MINOR,ZSTD_VERSION_RELEASE,0\r\n  PRODUCTVERSION    ZSTD_VERSION_MAJOR,ZSTD_VERSION_MINOR,ZSTD_VERSION_RELEASE,0\r\n FILEFLAGSMASK VS_FFI_FILEFLAGSMASK\r\n#ifdef _DEBUG\r\n FILEFLAGS VS_FF_DEBUG\r\n#else\r\n FILEFLAGS 0x0L\r\n#endif\r\n FILEOS VOS_NT_WINDOWS32\r\n FILETYPE VFT_DLL\r\n FILESUBTYPE VFT2_UNKNOWN\r\nBEGIN\r\n    BLOCK \"StringFileInfo\"\r\n    BEGIN\r\n        BLOCK \"040904B0\"\r\n        BEGIN\r\n            VALUE \"CompanyName\", \"Meta Platforms, Inc.\"\r\n            VALUE \"FileDescription\", \"Zstandard - Fast and efficient compression algorithm\"\r\n            VALUE \"FileVersion\", ZSTD_VERSION_STRING\r\n            VALUE \"InternalName\", \"zstd.exe\"\r\n            VALUE \"LegalCopyright\", \"Copyright (c) Meta Platforms, Inc. and affiliates.\"\r\n            VALUE \"OriginalFilename\", \"zstd.exe\"\r\n            VALUE \"ProductName\", \"Zstandard\"\r\n            VALUE \"ProductVersion\", ZSTD_VERSION_STRING\r\n        END\r\n    END\r\n    BLOCK \"VarFileInfo\"\r\n    BEGIN\r\n        VALUE \"Translation\", 0x0409, 1200\r\n    END\r\nEND\r\n\r\n#endif\r\n"
  },
  {
    "path": "programs/zstd.1",
    "content": ".\n.TH \"ZSTD\" \"1\" \"February 2025\" \"zstd 1.5.7\" \"User Commands\"\n.\n.SH \"NAME\"\n\\fBzstd\\fR \\- zstd, zstdmt, unzstd, zstdcat \\- Compress or decompress \\.zst files\n.\n.SH \"SYNOPSIS\"\n\\fBzstd\\fR [\\fIOPTIONS\\fR] [\\-|\\fIINPUT\\-FILE\\fR] [\\-o \\fIOUTPUT\\-FILE\\fR]\n.\n.P\n\\fBzstdmt\\fR is equivalent to \\fBzstd \\-T0\\fR\n.\n.P\n\\fBunzstd\\fR is equivalent to \\fBzstd \\-d\\fR\n.\n.P\n\\fBzstdcat\\fR is equivalent to \\fBzstd \\-dcf\\fR\n.\n.SH \"DESCRIPTION\"\n\\fBzstd\\fR is a fast lossless compression algorithm and data compression tool, with command line syntax similar to \\fBgzip\\fR(1) and \\fBxz\\fR(1)\\. It is based on the \\fBLZ77\\fR family, with further FSE & huff0 entropy stages\\. \\fBzstd\\fR offers highly configurable compression speed, from fast modes at > 200 MB/s per core, to strong modes with excellent compression ratios\\. It also features a very fast decoder, with speeds > 500 MB/s per core, which remains roughly stable at all compression settings\\.\n.\n.P\n\\fBzstd\\fR command line syntax is generally similar to gzip, but features the following few differences:\n.\n.IP \"\\(bu\" 4\nSource files are preserved by default\\. It\\'s possible to remove them automatically by using the \\fB\\-\\-rm\\fR command\\.\n.\n.IP \"\\(bu\" 4\nWhen compressing a single file, \\fBzstd\\fR displays progress notifications and result summary by default\\. Use \\fB\\-q\\fR to turn them off\\.\n.\n.IP \"\\(bu\" 4\n\\fBzstd\\fR displays a short help page when command line is an error\\. Use \\fB\\-q\\fR to turn it off\\.\n.\n.IP \"\\(bu\" 4\n\\fBzstd\\fR does not accept input from console, though it does accept \\fBstdin\\fR when it\\'s not the console\\.\n.\n.IP \"\\(bu\" 4\n\\fBzstd\\fR does not store the input\\'s filename or attributes, only its contents\\.\n.\n.IP \"\" 0\n.\n.P\n\\fBzstd\\fR processes each \\fIfile\\fR according to the selected operation mode\\. If no \\fIfiles\\fR are given or \\fIfile\\fR is \\fB\\-\\fR, \\fBzstd\\fR reads from standard input and writes the processed data to standard output\\. \\fBzstd\\fR will refuse to write compressed data to standard output if it is a terminal: it will display an error message and skip the file\\. Similarly, \\fBzstd\\fR will refuse to read compressed data from standard input if it is a terminal\\.\n.\n.P\nUnless \\fB\\-\\-stdout\\fR or \\fB\\-o\\fR is specified, \\fIfiles\\fR are written to a new file whose name is derived from the source \\fIfile\\fR name:\n.\n.IP \"\\(bu\" 4\nWhen compressing, the suffix \\fB\\.zst\\fR is appended to the source filename to get the target filename\\.\n.\n.IP \"\\(bu\" 4\nWhen decompressing, the \\fB\\.zst\\fR suffix is removed from the source filename to get the target filename\n.\n.IP \"\" 0\n.\n.SS \"Concatenation with \\.zst Files\"\nIt is possible to concatenate multiple \\fB\\.zst\\fR files\\. \\fBzstd\\fR will decompress such agglomerated file as if it was a single \\fB\\.zst\\fR file\\.\n.\n.SH \"OPTIONS\"\n.\n.SS \"Integer Suffixes and Special Values\"\nIn most places where an integer argument is expected, an optional suffix is supported to easily indicate large integers\\. There must be no space between the integer and the suffix\\.\n.\n.TP\n\\fBKiB\\fR\nMultiply the integer by 1,024 (2^10)\\. \\fBKi\\fR, \\fBK\\fR, and \\fBKB\\fR are accepted as synonyms for \\fBKiB\\fR\\.\n.\n.TP\n\\fBMiB\\fR\nMultiply the integer by 1,048,576 (2^20)\\. \\fBMi\\fR, \\fBM\\fR, and \\fBMB\\fR are accepted as synonyms for \\fBMiB\\fR\\.\n.\n.SS \"Operation Mode\"\nIf multiple operation mode options are given, the last one takes effect\\.\n.\n.TP\n\\fB\\-z\\fR, \\fB\\-\\-compress\\fR\nCompress\\. This is the default operation mode when no operation mode option is specified and no other operation mode is implied from the command name (for example, \\fBunzstd\\fR implies \\fB\\-\\-decompress\\fR)\\.\n.\n.TP\n\\fB\\-d\\fR, \\fB\\-\\-decompress\\fR, \\fB\\-\\-uncompress\\fR\nDecompress\\.\n.\n.TP\n\\fB\\-t\\fR, \\fB\\-\\-test\\fR\nTest the integrity of compressed \\fIfiles\\fR\\. This option is equivalent to \\fB\\-\\-decompress \\-\\-stdout > /dev/null\\fR, decompressed data is discarded and checksummed for errors\\. No files are created or removed\\.\n.\n.TP\n\\fB\\-b#\\fR\nBenchmark file(s) using compression level \\fI#\\fR\\. See \\fIBENCHMARK\\fR below for a description of this operation\\.\n.\n.TP\n\\fB\\-\\-train FILES\\fR\nUse \\fIFILES\\fR as a training set to create a dictionary\\. The training set should contain a lot of small files (> 100)\\. See \\fIDICTIONARY BUILDER\\fR below for a description of this operation\\.\n.\n.TP\n\\fB\\-l\\fR, \\fB\\-\\-list\\fR\nDisplay information related to a zstd compressed file, such as size, ratio, and checksum\\. Some of these fields may not be available\\. This command\\'s output can be augmented with the \\fB\\-v\\fR modifier\\.\n.\n.SS \"Operation Modifiers\"\n.\n.IP \"\\(bu\" 4\n\\fB\\-#\\fR: selects \\fB#\\fR compression level [1\\-19] (default: 3)\\. Higher compression levels \\fIgenerally\\fR produce higher compression ratio at the expense of speed and memory\\. A rough rule of thumb is that compression speed is expected to be divided by 2 every 2 levels\\. Technically, each level is mapped to a set of advanced parameters (that can also be modified individually, see below)\\. Because the compressor\\'s behavior highly depends on the content to compress, there\\'s no guarantee of a smooth progression from one level to another\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-ultra\\fR: unlocks high compression levels 20+ (maximum 22), using a lot more memory\\. Note that decompression will also require more memory when using these levels\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-fast[=#]\\fR: switch to ultra\\-fast compression levels\\. If \\fB=#\\fR is not present, it defaults to \\fB1\\fR\\. The higher the value, the faster the compression speed, at the cost of some compression ratio\\. This setting overwrites compression level if one was set previously\\. Similarly, if a compression level is set after \\fB\\-\\-fast\\fR, it overrides it\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-T#\\fR, \\fB\\-\\-threads=#\\fR: Compress using \\fB#\\fR working threads (default: between 1 and 4 depending on physical CPU cores; see \\fBZSTD_NBTHREADS\\fR below)\\. If \\fB#\\fR is 0, attempt to detect and use the number of physical CPU cores\\. In all cases, the nb of threads is capped to \\fBZSTDMT_NBWORKERS_MAX\\fR, which is either 64 in 32\\-bit mode, or 256 for 64\\-bit environments\\. This modifier does nothing if \\fBzstd\\fR is compiled without multithread support\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-single\\-thread\\fR: Use a single thread for both I/O and compression\\. As compression is serialized with I/O, this can be slightly slower\\. Single\\-thread mode features significantly lower memory usage, which can be useful for systems with limited amount of memory, such as 32\\-bit systems\\.\n.\n.IP\nNote 1: this mode is the only available one when multithread support is disabled\\.\n.\n.IP\nNote 2: this mode is different from \\fB\\-T1\\fR, which spawns 1 compression thread in parallel with I/O\\. Final compressed result is also slightly different from \\fB\\-T1\\fR\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-auto\\-threads={physical,logical} (default: physical)\\fR: When using a default amount of threads via \\fB\\-T0\\fR, choose the default based on the number of detected physical or logical cores\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-adapt[=min=#,max=#]\\fR: \\fBzstd\\fR will dynamically adapt compression level to perceived I/O conditions\\. Compression level adaptation can be observed live by using command \\fB\\-v\\fR\\. Adaptation can be constrained between supplied \\fBmin\\fR and \\fBmax\\fR levels\\. The feature works when combined with multi\\-threading and \\fB\\-\\-long\\fR mode\\. It does not work with \\fB\\-\\-single\\-thread\\fR\\. It sets window size to 8 MiB by default (can be changed manually, see \\fBwlog\\fR)\\. Due to the chaotic nature of dynamic adaptation, compressed result is not reproducible\\.\n.\n.IP\n\\fINote\\fR: at the time of this writing, \\fB\\-\\-adapt\\fR can remain stuck at low speed when combined with multiple worker threads (>=2)\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-long[=#]\\fR: enables long distance matching with \\fB#\\fR \\fBwindowLog\\fR, if \\fB#\\fR is not present it defaults to \\fB27\\fR\\. This increases the window size (\\fBwindowLog\\fR) and memory usage for both the compressor and decompressor\\. This setting is designed to improve the compression ratio for files with long matches at a large distance\\.\n.\n.IP\nNote: If \\fBwindowLog\\fR is set to larger than 27, \\fB\\-\\-long=windowLog\\fR or \\fB\\-\\-memory=windowSize\\fR needs to be passed to the decompressor\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-max\\fR: set advanced parameters to maximum compression\\. warning: this setting is very slow and uses a lot of resources\\. It\\'s inappropriate for 32\\-bit mode and therefore disabled in this mode\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-D DICT\\fR: use \\fBDICT\\fR as Dictionary to compress or decompress FILE(s)\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-patch\\-from FILE\\fR: Specify the file to be used as a reference point for zstd\\'s diff engine\\. This is effectively dictionary compression with some convenient parameter selection, namely that \\fIwindowSize\\fR > \\fIsrcSize\\fR\\.\n.\n.IP\nNote: cannot use both this and \\fB\\-D\\fR together\\.\n.\n.IP\nNote: \\fB\\-\\-long\\fR mode will be automatically activated if \\fIchainLog\\fR < \\fIfileLog\\fR (\\fIfileLog\\fR being the \\fIwindowLog\\fR required to cover the whole file)\\. You can also manually force it\\.\n.\n.IP\nNote: up to level 15, you can use \\fB\\-\\-patch\\-from\\fR in \\fB\\-\\-single\\-thread\\fR mode to improve compression ratio marginally at the cost of speed\\. Using \\'\\-\\-single\\-thread\\' above level 15 will lead to lower compression ratios\\.\n.\n.IP\nNote: for level 19, you can get increased compression ratio at the cost of speed by specifying \\fB\\-\\-zstd=targetLength=\\fR to be something large (i\\.e\\. 4096), and by setting a large \\fB\\-\\-zstd=chainLog=\\fR\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-rsyncable\\fR: \\fBzstd\\fR will periodically synchronize the compression state to make the compressed file more rsync\\-friendly\\. There is a negligible impact to compression ratio, and a potential impact to compression speed, perceptible at higher speeds, for example when combining \\fB\\-\\-rsyncable\\fR with many parallel worker threads\\. This feature does not work with \\fB\\-\\-single\\-thread\\fR\\. You probably don\\'t want to use it with long range mode, since it will decrease the effectiveness of the synchronization points, but your mileage may vary\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-C\\fR, \\fB\\-\\-[no\\-]check\\fR: add integrity check computed from uncompressed data (default: enabled)\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-[no\\-]content\\-size\\fR: enable / disable whether or not the original size of the file is placed in the header of the compressed file\\. The default option is \\fB\\-\\-content\\-size\\fR (meaning that the original size will be placed in the header)\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-no\\-dictID\\fR: do not store dictionary ID within frame header (dictionary compression)\\. The decoder will have to rely on implicit knowledge about which dictionary to use, it won\\'t be able to check if it\\'s correct\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-M#\\fR, \\fB\\-\\-memory=#\\fR: Set a memory usage limit\\. By default, \\fBzstd\\fR uses 128 MiB for decompression as the maximum amount of memory the decompressor is allowed to use, but you can override this manually if need be in either direction (i\\.e\\. you can increase or decrease it)\\.\n.\n.IP\nThis is also used during compression when using with \\fB\\-\\-patch\\-from=\\fR\\. In this case, this parameter overrides that maximum size allowed for a dictionary\\. (128 MiB)\\.\n.\n.IP\nAdditionally, this can be used to limit memory for dictionary training\\. This parameter overrides the default limit of 2 GiB\\. zstd will load training samples up to the memory limit and ignore the rest\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-stream\\-size=#\\fR: Sets the pledged source size of input coming from a stream\\. This value must be exact, as it will be included in the produced frame header\\. Incorrect stream sizes will cause an error\\. This information will be used to better optimize compression parameters, resulting in better and potentially faster compression, especially for smaller source sizes\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-size\\-hint=#\\fR: When handling input from a stream, \\fBzstd\\fR must guess how large the source size will be when optimizing compression parameters\\. If the stream size is relatively small, this guess may be a poor one, resulting in a higher compression ratio than expected\\. This feature allows for controlling the guess when needed\\. Exact guesses result in better compression ratios\\. Overestimates result in slightly degraded compression ratios, while underestimates may result in significant degradation\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-target\\-compressed\\-block\\-size=#\\fR: Attempt to produce compressed blocks of approximately this size\\. This will split larger blocks in order to approach this target\\. This feature is notably useful for improved latency, when the receiver can leverage receiving early incomplete data\\. This parameter defines a loose target: compressed blocks will target this size \"on average\", but individual blocks can still be larger or smaller\\. Enabling this feature can decrease compression speed by up to ~10% at level 1\\. Higher levels will see smaller relative speed regression, becoming invisible at higher settings\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-f\\fR, \\fB\\-\\-force\\fR: disable input and output checks\\. Allows overwriting existing files, input from console, output to stdout, operating on links, block devices, etc\\. During decompression and when the output destination is stdout, pass\\-through unrecognized formats as\\-is\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-c\\fR, \\fB\\-\\-stdout\\fR: write to standard output (even if it is the console); keep original files (disable \\fB\\-\\-rm\\fR)\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-o FILE\\fR: save result into \\fBFILE\\fR\\. Note that this operation is in conflict with \\fB\\-c\\fR\\. If both operations are present on the command line, the last expressed one wins\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-[no\\-]sparse\\fR: enable / disable sparse FS support, to make files with many zeroes smaller on disk\\. Creating sparse files may save disk space and speed up decompression by reducing the amount of disk I/O\\. default: enabled when output is into a file, and disabled when output is stdout\\. This setting overrides default and can force sparse mode over stdout\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-[no\\-]pass\\-through\\fR enable / disable passing through uncompressed files as\\-is\\. During decompression when pass\\-through is enabled, unrecognized formats will be copied as\\-is from the input to the output\\. By default, pass\\-through will occur when the output destination is stdout and the force (\\fB\\-f\\fR) option is set\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-rm\\fR: remove source file(s) after successful compression or decompression\\. This command is silently ignored if output is \\fBstdout\\fR\\. If used in combination with \\fB\\-o\\fR, triggers a confirmation prompt (which can be silenced with \\fB\\-f\\fR), as this is a destructive operation\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-k\\fR, \\fB\\-\\-keep\\fR: keep source file(s) after successful compression or decompression\\. This is the default behavior\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-r\\fR: operate recursively on directories\\. It selects all files in the named directory and all its subdirectories\\. This can be useful both to reduce command line typing, and to circumvent shell expansion limitations, when there are a lot of files and naming breaks the maximum size of a command line\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-filelist FILE\\fR read a list of files to process as content from \\fBFILE\\fR\\. Format is compatible with \\fBls\\fR output, with one file per line\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-output\\-dir\\-flat DIR\\fR: resulting files are stored into target \\fBDIR\\fR directory, instead of same directory as origin file\\. Be aware that this command can introduce name collision issues, if multiple files, from different directories, end up having the same name\\. Collision resolution ensures first file with a given name will be present in \\fBDIR\\fR, while in combination with \\fB\\-f\\fR, the last file will be present instead\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-output\\-dir\\-mirror DIR\\fR: similar to \\fB\\-\\-output\\-dir\\-flat\\fR, the output files are stored underneath target \\fBDIR\\fR directory, but this option will replicate input directory hierarchy into output \\fBDIR\\fR\\.\n.\n.IP\nIf input directory contains \"\\.\\.\", the files in this directory will be ignored\\. If input directory is an absolute directory (i\\.e\\. \"/var/tmp/abc\"), it will be stored into the \"output\\-dir/var/tmp/abc\"\\. If there are multiple input files or directories, name collision resolution will follow the same rules as \\fB\\-\\-output\\-dir\\-flat\\fR\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-format=FORMAT\\fR: compress and decompress in other formats\\. If compiled with support, zstd can compress to or decompress from other compression algorithm formats\\. Possibly available options are \\fBzstd\\fR, \\fBgzip\\fR, \\fBxz\\fR, \\fBlzma\\fR, and \\fBlz4\\fR\\. If no such format is provided, \\fBzstd\\fR is the default\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-h\\fR/\\fB\\-H\\fR, \\fB\\-\\-help\\fR: display help/long help and exit\n.\n.IP \"\\(bu\" 4\n\\fB\\-V\\fR, \\fB\\-\\-version\\fR: display version number and immediately exit\\. note that, since it exits, flags specified after \\fB\\-V\\fR are effectively ignored\\. Advanced: \\fB\\-vV\\fR also displays supported formats\\. \\fB\\-vvV\\fR also displays POSIX support\\. \\fB\\-qV\\fR will only display the version number, suitable for machine reading\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-v\\fR, \\fB\\-\\-verbose\\fR: verbose mode, display more information\n.\n.IP \"\\(bu\" 4\n\\fB\\-q\\fR, \\fB\\-\\-quiet\\fR: suppress warnings, interactivity, and notifications\\. specify twice to suppress errors too\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-no\\-progress\\fR: do not display the progress bar, but keep all other messages\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-show\\-default\\-cparams\\fR: shows the default compression parameters that will be used for a particular input file, based on the provided compression level and the input size\\. If the provided file is not a regular file (e\\.g\\. a pipe), this flag will output the parameters used for inputs of unknown size\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-exclude\\-compressed\\fR: only compress files that are not already compressed\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-\\fR: All arguments after \\fB\\-\\-\\fR are treated as files\n.\n.IP \"\" 0\n.\n.SS \"gzip Operation Modifiers\"\nWhen invoked via a \\fBgzip\\fR symlink, \\fBzstd\\fR will support further options that intend to mimic the \\fBgzip\\fR behavior:\n.\n.TP\n\\fB\\-n\\fR, \\fB\\-\\-no\\-name\\fR\ndo not store the original filename and timestamps when compressing a file\\. This is the default behavior and hence a no\\-op\\.\n.\n.TP\n\\fB\\-\\-best\\fR\nalias to the option \\fB\\-9\\fR\\.\n.\n.SS \"Environment Variables\"\nEmploying environment variables to set parameters has security implications\\. Therefore, this avenue is intentionally limited\\. Only \\fBZSTD_CLEVEL\\fR and \\fBZSTD_NBTHREADS\\fR are currently supported\\. They set the default compression level and number of threads to use during compression, respectively\\.\n.\n.P\n\\fBZSTD_CLEVEL\\fR can be used to set the level between 1 and 19 (the \"normal\" range)\\. If the value of \\fBZSTD_CLEVEL\\fR is not a valid integer, it will be ignored with a warning message\\. \\fBZSTD_CLEVEL\\fR just replaces the default compression level (\\fB3\\fR)\\.\n.\n.P\n\\fBZSTD_NBTHREADS\\fR can be used to set the number of threads \\fBzstd\\fR will attempt to use during compression\\. If the value of \\fBZSTD_NBTHREADS\\fR is not a valid unsigned integer, it will be ignored with a warning message\\. \\fBZSTD_NBTHREADS\\fR has a default value of \\fBmax(1, min(4, nbCores/4))\\fR, and is capped at ZSTDMT_NBWORKERS_MAX==200\\. \\fBzstd\\fR must be compiled with multithread support for this variable to have any effect\\.\n.\n.P\nThey can both be overridden by corresponding command line arguments: \\fB\\-#\\fR for compression level and \\fB\\-T#\\fR for number of compression threads\\.\n.\n.SH \"ADVANCED COMPRESSION OPTIONS\"\n\\fBzstd\\fR provides 22 predefined regular compression levels plus the fast levels\\. A compression level is translated internally into multiple advanced parameters that control the behavior of the compressor (one can observe the result of this translation with \\fB\\-\\-show\\-default\\-cparams\\fR)\\. These advanced parameters can be overridden using advanced compression options\\.\n.\n.SS \"\\-\\-zstd[=options]:\"\nThe \\fIoptions\\fR are provided as a comma\\-separated list\\. You may specify only the options you want to change and the rest will be taken from the selected or default compression level\\. The list of available \\fIoptions\\fR:\n.\n.TP\n\\fBstrategy\\fR=\\fIstrat\\fR, \\fBstrat\\fR=\\fIstrat\\fR\nSpecify a strategy used by a match finder\\.\n.\n.IP\nThere are 9 strategies numbered from 1 to 9, from fastest to strongest: 1=\\fBZSTD_fast\\fR, 2=\\fBZSTD_dfast\\fR, 3=\\fBZSTD_greedy\\fR, 4=\\fBZSTD_lazy\\fR, 5=\\fBZSTD_lazy2\\fR, 6=\\fBZSTD_btlazy2\\fR, 7=\\fBZSTD_btopt\\fR, 8=\\fBZSTD_btultra\\fR, 9=\\fBZSTD_btultra2\\fR\\.\n.\n.TP\n\\fBwindowLog\\fR=\\fIwlog\\fR, \\fBwlog\\fR=\\fIwlog\\fR\nSpecify the maximum number of bits for a match distance\\.\n.\n.IP\nThe higher number of increases the chance to find a match which usually improves compression ratio\\. It also increases memory requirements for the compressor and decompressor\\. The minimum \\fIwlog\\fR is 10 (1 KiB) and the maximum is 30 (1 GiB) on 32\\-bit platforms and 31 (2 GiB) on 64\\-bit platforms\\.\n.\n.IP\nNote: If \\fBwindowLog\\fR is set to larger than 27, \\fB\\-\\-long=windowLog\\fR or \\fB\\-\\-memory=windowSize\\fR needs to be passed to the decompressor\\.\n.\n.TP\n\\fBhashLog\\fR=\\fIhlog\\fR, \\fBhlog\\fR=\\fIhlog\\fR\nSpecify the maximum number of bits for a hash table\\.\n.\n.IP\nBigger hash tables cause fewer collisions which usually makes compression faster, but requires more memory during compression\\.\n.\n.IP\nThe minimum \\fIhlog\\fR is 6 (64 entries / 256 B) and the maximum is 30 (1B entries / 4 GiB)\\.\n.\n.TP\n\\fBchainLog\\fR=\\fIclog\\fR, \\fBclog\\fR=\\fIclog\\fR\nSpecify the maximum number of bits for the secondary search structure, whose form depends on the selected \\fBstrategy\\fR\\.\n.\n.IP\nHigher numbers of bits increases the chance to find a match which usually improves compression ratio\\. It also slows down compression speed and increases memory requirements for compression\\. This option is ignored for the \\fBZSTD_fast\\fR \\fBstrategy\\fR, which only has the primary hash table\\.\n.\n.IP\nThe minimum \\fIclog\\fR is 6 (64 entries / 256 B) and the maximum is 29 (512M entries / 2 GiB) on 32\\-bit platforms and 30 (1B entries / 4 GiB) on 64\\-bit platforms\\.\n.\n.TP\n\\fBsearchLog\\fR=\\fIslog\\fR, \\fBslog\\fR=\\fIslog\\fR\nSpecify the maximum number of searches in a hash chain or a binary tree using logarithmic scale\\.\n.\n.IP\nMore searches increases the chance to find a match which usually increases compression ratio but decreases compression speed\\.\n.\n.IP\nThe minimum \\fIslog\\fR is 1 and the maximum is \\'windowLog\\' \\- 1\\.\n.\n.TP\n\\fBminMatch\\fR=\\fImml\\fR, \\fBmml\\fR=\\fImml\\fR\nSpecify the minimum searched length of a match in a hash table\\.\n.\n.IP\nLarger search lengths usually decrease compression ratio but improve decompression speed\\.\n.\n.IP\nThe minimum \\fImml\\fR is 3 and the maximum is 7\\.\n.\n.TP\n\\fBtargetLength\\fR=\\fItlen\\fR, \\fBtlen\\fR=\\fItlen\\fR\nThe impact of this field vary depending on selected strategy\\.\n.\n.IP\nFor \\fBZSTD_btopt\\fR, \\fBZSTD_btultra\\fR and \\fBZSTD_btultra2\\fR, it specifies the minimum match length that causes match finder to stop searching\\. A larger \\fBtargetLength\\fR usually improves compression ratio but decreases compression speed\\.\n.\n.IP\nFor \\fBZSTD_fast\\fR, it triggers ultra\\-fast mode when > 0\\. The value represents the amount of data skipped between match sampling\\. Impact is reversed: a larger \\fBtargetLength\\fR increases compression speed but decreases compression ratio\\.\n.\n.IP\nFor all other strategies, this field has no impact\\.\n.\n.IP\nThe minimum \\fItlen\\fR is 0 and the maximum is 128 KiB\\.\n.\n.TP\n\\fBoverlapLog\\fR=\\fIovlog\\fR, \\fBovlog\\fR=\\fIovlog\\fR\nDetermine \\fBoverlapSize\\fR, amount of data reloaded from previous job\\. This parameter is only available when multithreading is enabled\\. Reloading more data improves compression ratio, but decreases speed\\.\n.\n.IP\nThe minimum \\fIovlog\\fR is 0, and the maximum is 9\\. 1 means \"no overlap\", hence completely independent jobs\\. 9 means \"full overlap\", meaning up to \\fBwindowSize\\fR is reloaded from previous job\\. Reducing \\fIovlog\\fR by 1 reduces the reloaded amount by a factor 2\\. For example, 8 means \"windowSize/2\", and 6 means \"windowSize/8\"\\. Value 0 is special and means \"default\": \\fIovlog\\fR is automatically determined by \\fBzstd\\fR\\. In which case, \\fIovlog\\fR will range from 6 to 9, depending on selected \\fIstrat\\fR\\.\n.\n.TP\n\\fBldmHashRateLog\\fR=\\fIlhrlog\\fR, \\fBlhrlog\\fR=\\fIlhrlog\\fR\nSpecify the frequency of inserting entries into the long distance matching hash table\\.\n.\n.IP\nThis option is ignored unless long distance matching is enabled\\.\n.\n.IP\nLarger values will improve compression speed\\. Deviating far from the default value will likely result in a decrease in compression ratio\\.\n.\n.IP\nThe default value varies between 4 and 7, depending on \\fBstrategy\\fR\\.\n.\n.TP\n\\fBldmHashLog\\fR=\\fIlhlog\\fR, \\fBlhlog\\fR=\\fIlhlog\\fR\nSpecify the maximum size for a hash table used for long distance matching\\.\n.\n.IP\nThis option is ignored unless long distance matching is enabled\\.\n.\n.IP\nBigger hash tables usually improve compression ratio at the expense of more memory during compression and a decrease in compression speed\\.\n.\n.IP\nThe minimum \\fIlhlog\\fR is 6 and the maximum is 30 (default: \\fBwindowLog \\- ldmHashRateLog\\fR)\\.\n.\n.TP\n\\fBldmMinMatch\\fR=\\fIlmml\\fR, \\fBlmml\\fR=\\fIlmml\\fR\nSpecify the minimum searched length of a match for long distance matching\\.\n.\n.IP\nThis option is ignored unless long distance matching is enabled\\.\n.\n.IP\nLarger/very small values usually decrease compression ratio\\.\n.\n.IP\nThe minimum \\fIlmml\\fR is 4 and the maximum is 4096 (default: 32 to 64, depending on \\fBstrategy\\fR)\\.\n.\n.TP\n\\fBldmBucketSizeLog\\fR=\\fIlblog\\fR, \\fBlblog\\fR=\\fIlblog\\fR\nSpecify the size of each bucket for the hash table used for long distance matching\\.\n.\n.IP\nThis option is ignored unless long distance matching is enabled\\.\n.\n.IP\nLarger bucket sizes improve collision resolution but decrease compression speed\\.\n.\n.IP\nThe minimum \\fIlblog\\fR is 1 and the maximum is 8 (default: 4 to 8, depending on \\fBstrategy\\fR)\\.\n.\n.SS \"Example\"\nThe following parameters sets advanced compression options to something similar to predefined level 19 for files bigger than 256 KB:\n.\n.P\n\\fB\\-\\-zstd\\fR=wlog=23,clog=23,hlog=22,slog=6,mml=3,tlen=48,strat=6\n.\n.SS \"\\-B#:\"\nSpecify the size of each compression job\\. This parameter is only available when multi\\-threading is enabled\\. Each compression job is run in parallel, so this value indirectly impacts the nb of active threads\\. Default job size varies depending on compression level (generally \\fB4 * windowSize\\fR)\\. \\fB\\-B#\\fR makes it possible to manually select a custom size\\. Note that job size must respect a minimum value which is enforced transparently\\. This minimum is either 512 KB, or \\fBoverlapSize\\fR, whichever is largest\\. Different job sizes will lead to non\\-identical compressed frames\\.\n.\n.SH \"DICTIONARY BUILDER\"\n\\fBzstd\\fR offers \\fIdictionary\\fR compression, which greatly improves efficiency on small files and messages\\. It\\'s possible to train \\fBzstd\\fR with a set of samples, the result of which is saved into a file called a \\fBdictionary\\fR\\. Then, during compression and decompression, reference the same dictionary, using command \\fB\\-D dictionaryFileName\\fR\\. Compression of small files similar to the sample set will be greatly improved\\.\n.\n.TP\n\\fB\\-\\-train FILEs\\fR\nUse FILEs as training set to create a dictionary\\. The training set should ideally contain a lot of samples (> 100), and weight typically 100x the target dictionary size (for example, ~10 MB for a 100 KB dictionary)\\. \\fB\\-\\-train\\fR can be combined with \\fB\\-r\\fR to indicate a directory rather than listing all the files, which can be useful to circumvent shell expansion limits\\.\n.\n.IP\nSince dictionary compression is mostly effective for small files, the expectation is that the training set will only contain small files\\. In the case where some samples happen to be large, only the first 128 KiB of these samples will be used for training\\.\n.\n.IP\n\\fB\\-\\-train\\fR supports multithreading if \\fBzstd\\fR is compiled with threading support (default)\\. Additional advanced parameters can be specified with \\fB\\-\\-train\\-fastcover\\fR\\. The legacy dictionary builder can be accessed with \\fB\\-\\-train\\-legacy\\fR\\. The slower cover dictionary builder can be accessed with \\fB\\-\\-train\\-cover\\fR\\. Default \\fB\\-\\-train\\fR is equivalent to \\fB\\-\\-train\\-fastcover=d=8,steps=4\\fR\\.\n.\n.TP\n\\fB\\-o FILE\\fR\nDictionary saved into \\fBFILE\\fR (default name: dictionary)\\.\n.\n.TP\n\\fB\\-\\-maxdict=#\\fR\nLimit dictionary to specified size (default: 112640 bytes)\\. As usual, quantities are expressed in bytes by default, and it\\'s possible to employ suffixes (like \\fBKB\\fR or \\fBMB\\fR) to specify larger values\\.\n.\n.TP\n\\fB\\-#\\fR\nUse \\fB#\\fR compression level during training (optional)\\. Will generate statistics more tuned for selected compression level, resulting in a \\fIsmall\\fR compression ratio improvement for this level\\.\n.\n.TP\n\\fB\\-B#\\fR\nSplit input files into blocks of size # (default: no split)\n.\n.TP\n\\fB\\-M#\\fR, \\fB\\-\\-memory=#\\fR\nLimit the amount of sample data loaded for training (default: 2 GB)\\. Note that the default (2 GB) is also the maximum\\. This parameter can be useful in situations where the training set size is not well controlled and could be potentially very large\\. Since speed of the training process is directly correlated to the size of the training sample set, a smaller sample set leads to faster training\\.\n.\n.IP\nIn situations where the training set is larger than maximum memory, the CLI will randomly select samples among the available ones, up to the maximum allowed memory budget\\. This is meant to improve dictionary relevance by mitigating the potential impact of clustering, such as selecting only files from the beginning of a list sorted by modification date, or sorted by alphabetical order\\. The randomization process is deterministic, so training of the same list of files with the same parameters will lead to the creation of the same dictionary\\.\n.\n.TP\n\\fB\\-\\-dictID=#\\fR\nA dictionary ID is a locally unique ID\\. The decoder will use this value to verify it is using the right dictionary\\. By default, zstd will create a 4\\-bytes random number ID\\. It\\'s possible to provide an explicit number ID instead\\. It\\'s up to the dictionary manager to not assign twice the same ID to 2 different dictionaries\\. Note that short numbers have an advantage: an ID < 256 will only need 1 byte in the compressed frame header, and an ID < 65536 will only need 2 bytes\\. This compares favorably to 4 bytes default\\.\n.\n.IP\nNote that RFC8878 reserves IDs less than 32768 and greater than or equal to 2^31, so they should not be used in public\\.\n.\n.TP\n\\fB\\-\\-train\\-cover[=k#,d=#,steps=#,split=#,shrink[=#]]\\fR\nSelect parameters for the default dictionary builder algorithm named cover\\. If \\fId\\fR is not specified, then it tries \\fId\\fR = 6 and \\fId\\fR = 8\\. If \\fIk\\fR is not specified, then it tries \\fIsteps\\fR values in the range [50, 2000]\\. If \\fIsteps\\fR is not specified, then the default value of 40 is used\\. If \\fIsplit\\fR is not specified or split <= 0, then the default value of 100 is used\\. Requires that \\fId\\fR <= \\fIk\\fR\\. If \\fIshrink\\fR flag is not used, then the default value for \\fIshrinkDict\\fR of 0 is used\\. If \\fIshrink\\fR is not specified, then the default value for \\fIshrinkDictMaxRegression\\fR of 1 is used\\.\n.\n.IP\nSelects segments of size \\fIk\\fR with highest score to put in the dictionary\\. The score of a segment is computed by the sum of the frequencies of all the subsegments of size \\fId\\fR\\. Generally \\fId\\fR should be in the range [6, 8], occasionally up to 16, but the algorithm will run faster with d <= \\fI8\\fR\\. Good values for \\fIk\\fR vary widely based on the input data, but a safe range is [2 * \\fId\\fR, 2000]\\. If \\fIsplit\\fR is 100, all input samples are used for both training and testing to find optimal \\fId\\fR and \\fIk\\fR to build dictionary\\. Supports multithreading if \\fBzstd\\fR is compiled with threading support\\. Having \\fIshrink\\fR enabled takes a truncated dictionary of minimum size and doubles in size until compression ratio of the truncated dictionary is at most \\fIshrinkDictMaxRegression%\\fR worse than the compression ratio of the largest dictionary\\.\n.\n.IP\nExamples:\n.\n.IP\n\\fBzstd \\-\\-train\\-cover FILEs\\fR\n.\n.IP\n\\fBzstd \\-\\-train\\-cover=k=50,d=8 FILEs\\fR\n.\n.IP\n\\fBzstd \\-\\-train\\-cover=d=8,steps=500 FILEs\\fR\n.\n.IP\n\\fBzstd \\-\\-train\\-cover=k=50 FILEs\\fR\n.\n.IP\n\\fBzstd \\-\\-train\\-cover=k=50,split=60 FILEs\\fR\n.\n.IP\n\\fBzstd \\-\\-train\\-cover=shrink FILEs\\fR\n.\n.IP\n\\fBzstd \\-\\-train\\-cover=shrink=2 FILEs\\fR\n.\n.TP\n\\fB\\-\\-train\\-fastcover[=k#,d=#,f=#,steps=#,split=#,accel=#]\\fR\nSame as cover but with extra parameters \\fIf\\fR and \\fIaccel\\fR and different default value of split If \\fIsplit\\fR is not specified, then it tries \\fIsplit\\fR = 75\\. If \\fIf\\fR is not specified, then it tries \\fIf\\fR = 20\\. Requires that 0 < \\fIf\\fR < 32\\. If \\fIaccel\\fR is not specified, then it tries \\fIaccel\\fR = 1\\. Requires that 0 < \\fIaccel\\fR <= 10\\. Requires that \\fId\\fR = 6 or \\fId\\fR = 8\\.\n.\n.IP\n\\fIf\\fR is log of size of array that keeps track of frequency of subsegments of size \\fId\\fR\\. The subsegment is hashed to an index in the range [0,2^\\fIf\\fR \\- 1]\\. It is possible that 2 different subsegments are hashed to the same index, and they are considered as the same subsegment when computing frequency\\. Using a higher \\fIf\\fR reduces collision but takes longer\\.\n.\n.IP\nExamples:\n.\n.IP\n\\fBzstd \\-\\-train\\-fastcover FILEs\\fR\n.\n.IP\n\\fBzstd \\-\\-train\\-fastcover=d=8,f=15,accel=2 FILEs\\fR\n.\n.TP\n\\fB\\-\\-train\\-legacy[=selectivity=#]\\fR\nUse legacy dictionary builder algorithm with the given dictionary \\fIselectivity\\fR (default: 9)\\. The smaller the \\fIselectivity\\fR value, the denser the dictionary, improving its efficiency but reducing its achievable maximum size\\. \\fB\\-\\-train\\-legacy=s=#\\fR is also accepted\\.\n.\n.IP\nExamples:\n.\n.IP\n\\fBzstd \\-\\-train\\-legacy FILEs\\fR\n.\n.IP\n\\fBzstd \\-\\-train\\-legacy=selectivity=8 FILEs\\fR\n.\n.SH \"BENCHMARK\"\nThe \\fBzstd\\fR CLI provides a benchmarking mode that can be used to easily find suitable compression parameters, or alternatively to benchmark a computer\\'s performance\\. \\fBzstd \\-b [FILE(s)]\\fR will benchmark \\fBzstd\\fR for both compression and decompression using default compression level\\. Note that results are very dependent on the content being compressed\\.\n.\n.P\nIt\\'s possible to pass multiple files to the benchmark, and even a directory with \\fB\\-r DIRECTORY\\fR\\. When no \\fBFILE\\fR is provided, the benchmark will use a procedurally generated \\fBlorem ipsum\\fR text\\.\n.\n.P\nBenchmarking will employ \\fBmax(1, min(4, nbCores/4))\\fR worker threads by default in order to match the behavior of the normal CLI I/O\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-b#\\fR: benchmark file(s) using compression level #\n.\n.IP \"\\(bu\" 4\n\\fB\\-e#\\fR: benchmark file(s) using multiple compression levels, from \\fB\\-b#\\fR to \\fB\\-e#\\fR (inclusive)\n.\n.IP \"\\(bu\" 4\n\\fB\\-d\\fR: benchmark decompression speed only (requires providing a zstd\\-compressed content)\n.\n.IP \"\\(bu\" 4\n\\fB\\-i#\\fR: minimum evaluation time, in seconds (default: 3s), benchmark mode only\n.\n.IP \"\\(bu\" 4\n\\fB\\-B#\\fR, \\fB\\-\\-block\\-size=#\\fR: cut file(s) into independent chunks of size # (default: no chunking)\n.\n.IP \"\\(bu\" 4\n\\fB\\-S\\fR: output one benchmark result per input file (default: consolidated result)\n.\n.IP \"\\(bu\" 4\n\\fB\\-D dictionary\\fR benchmark using dictionary\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-priority=rt\\fR: set process priority to real\\-time (Windows)\n.\n.IP \"\" 0\n.\n.P\nBeyond compression levels, benchmarking is also compatible with other parameters, such as number of threads (\\fB\\-T#\\fR), advanced compression parameters (\\fB\\-\\-zstd=###\\fR), dictionary compression (\\fB\\-D dictionary\\fR), or even disabling checksum verification for example\\.\n.\n.P\n\\fBOutput Format:\\fR CompressionLevel#Filename: InputSize \\-> OutputSize (CompressionRatio), CompressionSpeed, DecompressionSpeed\n.\n.P\n\\fBMethodology:\\fR For speed measurement, the entire input is compressed/decompressed in\\-memory to measure speed\\. A run lasts at least 1 sec, so when files are small, they are compressed/decompressed several times per run, in order to improve measurement accuracy\\.\n.\n.SH \"SEE ALSO\"\n\\fBzstdgrep\\fR(1), \\fBzstdless\\fR(1), \\fBgzip\\fR(1), \\fBxz\\fR(1)\n.\n.P\nThe \\fIzstandard\\fR format is specified in Y\\. Collet, \"Zstandard Compression and the \\'application/zstd\\' Media Type\", https://www\\.ietf\\.org/rfc/rfc8878\\.txt, Internet RFC 8878 (February 2021)\\.\n.\n.SH \"BUGS\"\nReport bugs at: https://github\\.com/facebook/zstd/issues\n.\n.SH \"AUTHOR\"\nYann Collet\n"
  },
  {
    "path": "programs/zstd.1.md",
    "content": "zstd(1) -- zstd, zstdmt, unzstd, zstdcat - Compress or decompress .zst files\n============================================================================\n\nSYNOPSIS\n--------\n\n`zstd` [<OPTIONS>] [-|<INPUT-FILE>] [-o <OUTPUT-FILE>]\n\n`zstdmt` is equivalent to `zstd -T0`\n\n`unzstd` is equivalent to `zstd -d`\n\n`zstdcat` is equivalent to `zstd -dcf`\n\n\nDESCRIPTION\n-----------\n`zstd` is a fast lossless compression algorithm and data compression tool,\nwith command line syntax similar to `gzip`(1) and `xz`(1).\nIt is based on the **LZ77** family, with further FSE & huff0 entropy stages.\n`zstd` offers highly configurable compression speed,\nfrom fast modes at > 200 MB/s per core,\nto strong modes with excellent compression ratios.\nIt also features a very fast decoder, with speeds > 500 MB/s per core,\nwhich remains roughly stable at all compression settings.\n\n`zstd` command line syntax is generally similar to gzip,\nbut features the following few differences:\n\n  - Source files are preserved by default.\n    It's possible to remove them automatically by using the `--rm` command.\n  - When compressing a single file, `zstd` displays progress notifications\n    and result summary by default.\n    Use `-q` to turn them off.\n  - `zstd` displays a short help page when command line is an error.\n    Use `-q` to turn it off.\n  - `zstd` does not accept input from console,\n    though it does accept `stdin` when it's not the console.\n  - `zstd` does not store the input's filename or attributes, only its contents.\n\n`zstd` processes each _file_ according to the selected operation mode.\nIf no _files_ are given or _file_ is `-`, `zstd` reads from standard input\nand writes the processed data to standard output.\n`zstd` will refuse to write compressed data to standard output\nif it is a terminal: it will display an error message and skip the file.\nSimilarly, `zstd` will refuse to read compressed data from standard input\nif it is a terminal.\n\nUnless `--stdout` or `-o` is specified, _files_ are written to a new file\nwhose name is derived from the source _file_ name:\n\n* When compressing, the suffix `.zst` is appended to the source filename to\n  get the target filename.\n* When decompressing, the `.zst` suffix is removed from the source filename to\n  get the target filename\n\n### Concatenation with .zst Files\nIt is possible to concatenate multiple `.zst` files. `zstd` will decompress\nsuch agglomerated file as if it was a single `.zst` file.\n\nOPTIONS\n-------\n\n### Integer Suffixes and Special Values\n\nIn most places where an integer argument is expected,\nan optional suffix is supported to easily indicate large integers.\nThere must be no space between the integer and the suffix.\n\n* `KiB`:\n    Multiply the integer by 1,024 (2\\^10).\n    `Ki`, `K`, and `KB` are accepted as synonyms for `KiB`.\n* `MiB`:\n    Multiply the integer by 1,048,576 (2\\^20).\n    `Mi`, `M`, and `MB` are accepted as synonyms for `MiB`.\n\n### Operation Mode\n\nIf multiple operation mode options are given,\nthe last one takes effect.\n\n* `-z`, `--compress`:\n    Compress.\n    This is the default operation mode when no operation mode option is specified\n    and no other operation mode is implied from the command name\n    (for example, `unzstd` implies `--decompress`).\n* `-d`, `--decompress`, `--uncompress`:\n    Decompress.\n* `-t`, `--test`:\n    Test the integrity of compressed _files_.\n    This option is equivalent to `--decompress --stdout > /dev/null`,\n    decompressed data is discarded and checksummed for errors.\n    No files are created or removed.\n* `-b#`:\n    Benchmark file(s) using compression level _#_.\n    See _BENCHMARK_ below for a description of this operation.\n* `--train FILES`:\n    Use _FILES_ as a training set to create a dictionary.\n    The training set should contain a lot of small files (> 100).\n    See _DICTIONARY BUILDER_ below for a description of this operation.\n* `-l`, `--list`:\n    Display information related to a zstd compressed file, such as size, ratio, and checksum.\n    Some of these fields may not be available.\n    This command's output can be augmented with the `-v` modifier.\n\n### Operation Modifiers\n\n* `-#`:\n    selects `#` compression level \\[1-19\\] (default: 3).\n    Higher compression levels *generally* produce higher compression ratio at the expense of speed and memory.\n    A rough rule of thumb is that compression speed is expected to be divided by 2 every 2 levels.\n    Technically, each level is mapped to a set of advanced parameters (that can also be modified individually, see below).\n    Because the compressor's behavior highly depends on the content to compress, there's no guarantee of a smooth progression from one level to another.\n* `--ultra`:\n    unlocks high compression levels 20+ (maximum 22), using a lot more memory.\n    Decompression will also need more memory when using these levels.\n* `--max`:\n    set advanced parameters to reach maximum compression.\n    warning: this setting is very slow and uses a lot of resources.\n    It's inappropriate for 32-bit mode and therefore disabled in this mode.\n* `--fast[=#]`:\n    switch to ultra-fast compression levels.\n    If `=#` is not present, it defaults to `1`.\n    The higher the value, the faster the compression speed,\n    at the cost of some compression ratio.\n    This setting overwrites compression level if one was set previously.\n    Similarly, if a compression level is set after `--fast`, it overrides it.\n* `-T#`, `--threads=#`:\n    Compress using `#` working threads (default: between 1 and 4 depending on physical CPU cores; see `ZSTD_NBTHREADS` below).\n    If `#` is 0, attempt to detect and use the number of physical CPU cores.\n    In all cases, the nb of threads is capped to `ZSTDMT_NBWORKERS_MAX`,\n    which is either 64 in 32-bit mode, or 256 for 64-bit environments.\n    This modifier does nothing if `zstd` is compiled without multithread support.\n    Note that memory usage increases with each thread.\n* `--single-thread`:\n    Use a single thread for both I/O and compression.\n    As compression is serialized with I/O, this can be slightly slower.\n    Single-thread mode features significantly lower memory usage,\n    which can be useful for systems with limited amount of memory, such as 32-bit systems.\n\n    Note 1: this mode is the only available one when multithread support is disabled.\n\n    Note 2: this mode is different from `-T1`, which spawns 1 compression thread in parallel with I/O.\n    Final compressed result is also slightly different from `-T1`.\n* `--auto-threads={physical,logical} (default: physical)`:\n    When using a default amount of threads via `-T0`, choose the default based on the number\n    of detected physical or logical cores.\n* `--adapt[=min=#,max=#]`:\n    `zstd` will dynamically adapt compression level to perceived I/O conditions.\n    Compression level adaptation can be observed live by using command `-v`.\n    Adaptation can be constrained between supplied `min` and `max` levels.\n    The feature works when combined with multi-threading and `--long` mode.\n    It does not work with `--single-thread`.\n    It sets window size to 8 MiB by default (can be changed manually, see `wlog`).\n    Due to the chaotic nature of dynamic adaptation, compressed result is not reproducible.\n\n    _Note_: at the time of this writing, `--adapt` can remain stuck at low speed\n    when combined with multiple worker threads (>=2).\n* `--long[=#]`:\n    enables long distance matching with `#` `windowLog`, if `#` is not\n    present it defaults to `27`. The highest possible value is 31.\n    This increases the window size (`windowLog`) and memory usage for both the\n    compressor and decompressor.\n    This setting is designed to improve the compression ratio for files with\n    long matches at a large distance.\n\n    Note: If `windowLog` is set to larger than 27, `--long=windowLog` or\n    `--memory=windowSize` needs to be passed to the decompressor.\n* `-D DICT`:\n    use `DICT` as Dictionary to compress or decompress FILE(s)\n* `--patch-from FILE`:\n    Specify the file to be used as a reference point for zstd's diff engine.\n    This is effectively dictionary compression with some convenient parameter\n    selection, namely that _windowSize_ > _srcSize_.\n\n    Note: cannot use both this and `-D` together.\n\n    Note: `--long` mode will be automatically activated if _chainLog_ < _fileLog_\n        (_fileLog_ being the _windowLog_ required to cover the whole file). You\n        can also manually force it.\n\n    Note: up to level 15, you can use `--patch-from` in `--single-thread` mode\n        to improve compression ratio marginally at the cost of speed. Using\n        '--single-thread' above level 15  will lead to lower compression\n        ratios.\n\n    Note: for level 19, you can get increased compression ratio at the cost\n        of speed by specifying `--zstd=targetLength=` to be something large\n        (i.e. 4096), and by setting a large `--zstd=chainLog=`.\n* `--rsyncable`:\n    `zstd` will periodically synchronize the compression state to make the\n    compressed file more rsync-friendly.\n    There is a negligible impact to compression ratio,\n    and a potential impact to compression speed, perceptible at higher speeds,\n    for example when combining `--rsyncable` with many parallel worker threads.\n    This feature does not work with `--single-thread`. You probably don't want\n    to use it with long range mode, since it will decrease the effectiveness of\n    the synchronization points, but your mileage may vary.\n* `-C`, `--[no-]check`:\n    add integrity check computed from uncompressed data (default: enabled)\n* `--[no-]content-size`:\n    enable / disable whether or not the original size of the file is placed in\n    the header of the compressed file. The default option is\n    `--content-size` (meaning that the original size will be placed in the header).\n* `--no-dictID`:\n    do not store dictionary ID within frame header (dictionary compression).\n    The decoder will have to rely on implicit knowledge about which dictionary to use,\n    it won't be able to check if it's correct.\n* `-M#`, `--memory=#`:\n    Set a memory usage limit. By default, `zstd` uses 128 MiB for decompression\n    as the maximum amount of memory the decompressor is allowed to use, but you can\n    override this manually if need be in either direction (i.e. you can increase or\n    decrease it).\n\n    This is also used during compression when using with `--patch-from=`. In this case,\n    this parameter overrides that maximum size allowed for a dictionary. (128 MiB).\n\n    Additionally, this can be used to limit memory for dictionary training. This parameter\n    overrides the default limit of 2 GiB. zstd will load training samples up to the memory limit\n    and ignore the rest.\n* `--stream-size=#`:\n    Sets the pledged source size of input coming from a stream. This value must be exact, as it\n    will be included in the produced frame header. Incorrect stream sizes will cause an error.\n    This information will be used to better optimize compression parameters, resulting in\n    better and potentially faster compression, especially for smaller source sizes.\n* `--size-hint=#`:\n    When handling input from a stream, `zstd` must guess how large the source size\n    will be when optimizing compression parameters. If the stream size is relatively\n    small, this guess may be a poor one, resulting in a higher compression ratio than\n    expected. This feature allows for controlling the guess when needed.\n    Exact guesses result in better compression ratios. Overestimates result in slightly\n    degraded compression ratios, while underestimates may result in significant degradation.\n* `--target-compressed-block-size=#`:\n    Attempt to produce compressed blocks of approximately this size.\n    This will split larger blocks in order to approach this target.\n    This feature is notably useful for improved latency, when the receiver can leverage receiving early incomplete data.\n    This parameter defines a loose target: compressed blocks will target this size \"on average\", but individual blocks can still be larger or smaller.\n    Enabling this feature can decrease compression speed by up to ~10% at level 1.\n    Higher levels will see smaller relative speed regression, becoming invisible at higher settings.\n* `-f`, `--force`:\n    disable input and output checks. Allows overwriting existing files, input\n    from console, output to stdout, operating on links, block devices, etc.\n    During decompression and when the output destination is stdout, pass-through\n    unrecognized formats as-is.\n* `-c`, `--stdout`:\n    write to standard output (even if it is the console); keep original files (disable `--rm`).\n* `-o FILE`:\n    save result into `FILE`.\n    Note that this operation is in conflict with `-c`.\n    If both operations are present on the command line, the last expressed one wins.\n* `--[no-]sparse`:\n    enable / disable sparse FS support,\n    to make files with many zeroes smaller on disk.\n    Creating sparse files may save disk space and speed up decompression by\n    reducing the amount of disk I/O.\n    default: enabled when output is into a file,\n    and disabled when output is stdout.\n    This setting overrides default and can force sparse mode over stdout.\n* `--[no-]pass-through`\n    enable / disable passing through uncompressed files as-is. During\n    decompression when pass-through is enabled, unrecognized formats will be\n    copied as-is from the input to the output. By default, pass-through will\n    occur when the output destination is stdout and the force (`-f`) option is\n    set.\n* `--rm`:\n    remove source file(s) after successful compression or decompression.\n    This command is silently ignored if output is `stdout`.\n    If used in combination with `-o`,\n    triggers a confirmation prompt (which can be silenced with `-f`), as this is a destructive operation.\n* `-k`, `--keep`:\n    keep source file(s) after successful compression or decompression.\n    This is the default behavior.\n* `-r`:\n    operate recursively on directories.\n    It selects all files in the named directory and all its subdirectories.\n    This can be useful both to reduce command line typing,\n    and to circumvent shell expansion limitations,\n    when there are a lot of files and naming breaks the maximum size of a command line.\n* `--filelist FILE`\n    read a list of files to process as content from `FILE`.\n    Format is compatible with `ls` output, with one file per line.\n* `--output-dir-flat DIR`:\n    resulting files are stored into target `DIR` directory,\n    instead of same directory as origin file.\n    Be aware that this command can introduce name collision issues,\n    if multiple files, from different directories, end up having the same name.\n    Collision resolution ensures first file with a given name will be present in `DIR`,\n    while in combination with `-f`, the last file will be present instead.\n* `--output-dir-mirror DIR`:\n    similar to `--output-dir-flat`,\n    the output files are stored underneath target `DIR` directory,\n    but this option will replicate input directory hierarchy into output `DIR`.\n\n    If input directory contains \"..\", the files in this directory will be ignored.\n    If input directory is an absolute directory (i.e. \"/var/tmp/abc\"),\n    it will be stored into the \"output-dir/var/tmp/abc\".\n    If there are multiple input files or directories,\n    name collision resolution will follow the same rules as `--output-dir-flat`.\n* `--format=FORMAT`:\n    compress and decompress in other formats. If compiled with\n    support, zstd can compress to or decompress from other compression algorithm\n    formats. Possibly available options are `zstd`, `gzip`, `xz`, `lzma`, and `lz4`.\n    If no such format is provided, `zstd` is the default.\n* `-h`/`-H`, `--help`:\n    display help/long help and exit\n* `-V`, `--version`:\n    display version number and immediately exit.\n    note that, since it exits, flags specified after `-V` are effectively ignored.\n    Advanced: `-vV` also displays supported formats.\n    `-vvV` also displays POSIX support.\n    `-qV` will only display the version number, suitable for machine reading.\n* `-v`, `--verbose`:\n    verbose mode, display more information\n* `-q`, `--quiet`:\n    suppress warnings, interactivity, and notifications.\n    specify twice to suppress errors too.\n* `--no-progress`:\n    do not display the progress bar, but keep all other messages.\n* `--show-default-cparams`:\n    shows the default compression parameters that will be used for a particular input file, based on the provided compression level and the input size.\n    If the provided file is not a regular file (e.g. a pipe), this flag will output the parameters used for inputs of unknown size.\n* `--exclude-compressed`:\n    only compress files that are not already compressed.\n* `--`:\n    All arguments after `--` are treated as files\n\n\n### gzip Operation Modifiers\nWhen invoked via a `gzip` symlink, `zstd` will support further\noptions that intend to mimic the `gzip` behavior:\n\n* `-n`, `--no-name`:\n    do not store the original filename and timestamps when compressing\n    a file. This is the default behavior and hence a no-op.\n* `--best`:\n    alias to the option `-9`.\n\n\n### Environment Variables\nEmploying environment variables to set parameters has security implications.\nTherefore, this avenue is intentionally limited.\nOnly `ZSTD_CLEVEL` and `ZSTD_NBTHREADS` are currently supported.\nThey set the default compression level and number of threads to use during compression, respectively.\n\n`ZSTD_CLEVEL` can be used to set the level between 1 and 19 (the \"normal\" range).\nIf the value of `ZSTD_CLEVEL` is not a valid integer, it will be ignored with a warning message.\n`ZSTD_CLEVEL` just replaces the default compression level (`3`).\n\n`ZSTD_NBTHREADS` can be used to set the number of threads `zstd` will attempt to use during compression.\nIf the value of `ZSTD_NBTHREADS` is not a valid unsigned integer, it will be ignored with a warning message.\n`ZSTD_NBTHREADS` has a default value of `max(1, min(4, nbCores/4))`, and is capped at ZSTDMT_NBWORKERS_MAX==200.\n`zstd` must be compiled with multithread support for this variable to have any effect.\n\nThey can both be overridden by corresponding command line arguments:\n`-#` for compression level and `-T#` for number of compression threads.\n\n\nADVANCED COMPRESSION OPTIONS\n----------------------------\n`zstd` provides 22 predefined regular compression levels plus the fast levels.\nA compression level is translated internally into multiple advanced parameters that control the behavior of the compressor\n(one can observe the result of this translation with `--show-default-cparams`).\nThese advanced parameters can be overridden using advanced compression options.\n\n### --zstd[=options]:\nThe _options_ are provided as a comma-separated list.\nYou may specify only the options you want to change and the rest will be\ntaken from the selected or default compression level.\nThe list of available _options_:\n\n- `strategy`=_strat_, `strat`=_strat_:\n    Specify a strategy used by a match finder.\n\n    There are 9 strategies numbered from 1 to 9, from fastest to strongest:\n    1=`ZSTD_fast`, 2=`ZSTD_dfast`, 3=`ZSTD_greedy`,\n    4=`ZSTD_lazy`, 5=`ZSTD_lazy2`, 6=`ZSTD_btlazy2`,\n    7=`ZSTD_btopt`, 8=`ZSTD_btultra`, 9=`ZSTD_btultra2`.\n\n- `windowLog`=_wlog_, `wlog`=_wlog_:\n    Specify the maximum number of bits for a match distance.\n\n    The higher number of increases the chance to find a match which usually\n    improves compression ratio.\n    It also increases memory requirements for the compressor and decompressor.\n    The minimum _wlog_ is 10 (1 KiB) and the maximum is 30 (1 GiB) on 32-bit\n    platforms and 31 (2 GiB) on 64-bit platforms.\n\n    Note: If `windowLog` is set to larger than 27, `--long=windowLog` or\n    `--memory=windowSize` needs to be passed to the decompressor.\n\n- `hashLog`=_hlog_, `hlog`=_hlog_:\n    Specify the maximum number of bits for a hash table.\n\n    Bigger hash tables cause fewer collisions which usually makes compression\n    faster, but requires more memory during compression.\n\n    The minimum _hlog_ is 6 (64 entries / 256 B) and the maximum is 30 (1B entries / 4 GiB).\n\n- `chainLog`=_clog_, `clog`=_clog_:\n    Specify the maximum number of bits for the secondary search structure,\n    whose form depends on the selected `strategy`.\n\n    Higher numbers of bits increases the chance to find a match which usually\n    improves compression ratio.\n    It also slows down compression speed and increases memory requirements for\n    compression.\n    This option is ignored for the `ZSTD_fast` `strategy`, which only has the primary hash table.\n\n    The minimum _clog_ is 6 (64 entries / 256 B) and the maximum is 29 (512M entries / 2 GiB) on 32-bit platforms\n    and 30 (1B entries / 4 GiB) on 64-bit platforms.\n\n- `searchLog`=_slog_, `slog`=_slog_:\n    Specify the maximum number of searches in a hash chain or a binary tree\n    using logarithmic scale.\n\n    More searches increases the chance to find a match which usually increases\n    compression ratio but decreases compression speed.\n\n    The minimum _slog_ is 1 and the maximum is 'windowLog' - 1.\n\n- `minMatch`=_mml_, `mml`=_mml_:\n    Specify the minimum searched length of a match in a hash table.\n\n    Larger search lengths usually decrease compression ratio but improve\n    decompression speed.\n\n    The minimum _mml_ is 3 and the maximum is 7.\n\n- `targetLength`=_tlen_, `tlen`=_tlen_:\n    The impact of this field vary depending on selected strategy.\n\n    For `ZSTD_btopt`, `ZSTD_btultra` and `ZSTD_btultra2`, it specifies\n    the minimum match length that causes match finder to stop searching.\n    A larger `targetLength` usually improves compression ratio\n    but decreases compression speed.\n\n    For `ZSTD_fast`, it triggers ultra-fast mode when > 0.\n    The value represents the amount of data skipped between match sampling.\n    Impact is reversed: a larger `targetLength` increases compression speed\n    but decreases compression ratio.\n\n    For all other strategies, this field has no impact.\n\n    The minimum _tlen_ is 0 and the maximum is 128 KiB.\n\n- `overlapLog`=_ovlog_,  `ovlog`=_ovlog_:\n    Determine `overlapSize`, amount of data reloaded from previous job.\n    This parameter is only available when multithreading is enabled.\n    Reloading more data improves compression ratio, but decreases speed.\n\n    The minimum _ovlog_ is 0, and the maximum is 9.\n    1 means \"no overlap\", hence completely independent jobs.\n    9 means \"full overlap\", meaning up to `windowSize` is reloaded from previous job.\n    Reducing _ovlog_ by 1 reduces the reloaded amount by a factor 2.\n    For example, 8 means \"windowSize/2\", and 6 means \"windowSize/8\".\n    Value 0 is special and means \"default\": _ovlog_ is automatically determined by `zstd`.\n    In which case, _ovlog_ will range from 6 to 9, depending on selected _strat_.\n\n- `ldmHashRateLog`=_lhrlog_, `lhrlog`=_lhrlog_:\n    Specify the frequency of inserting entries into the long distance matching\n    hash table.\n\n    This option is ignored unless long distance matching is enabled.\n\n    Larger values will improve compression speed. Deviating far from the\n    default value will likely result in a decrease in compression ratio.\n\n    The default value varies between 4 and 7, depending on `strategy`.\n\n- `ldmHashLog`=_lhlog_, `lhlog`=_lhlog_:\n    Specify the maximum size for a hash table used for long distance matching.\n\n    This option is ignored unless long distance matching is enabled.\n\n    Bigger hash tables usually improve compression ratio at the expense of more\n    memory during compression and a decrease in compression speed.\n\n    The minimum _lhlog_ is 6 and the maximum is 30 (default: `windowLog - ldmHashRateLog`).\n\n- `ldmMinMatch`=_lmml_, `lmml`=_lmml_:\n    Specify the minimum searched length of a match for long distance matching.\n\n    This option is ignored unless long distance matching is enabled.\n\n    Larger/very small values usually decrease compression ratio.\n\n    The minimum _lmml_ is 4 and the maximum is 4096 (default: 32 to 64, depending on `strategy`).\n\n- `ldmBucketSizeLog`=_lblog_, `lblog`=_lblog_:\n    Specify the size of each bucket for the hash table used for long distance\n    matching.\n\n    This option is ignored unless long distance matching is enabled.\n\n    Larger bucket sizes improve collision resolution but decrease compression\n    speed.\n\n    The minimum _lblog_ is 1 and the maximum is 8 (default: 4 to 8, depending on `strategy`).\n\n\n### Example\nThe following parameters sets advanced compression options to something\nsimilar to predefined level 19 for files bigger than 256 KB:\n\n`--zstd`=wlog=23,clog=23,hlog=22,slog=6,mml=3,tlen=48,strat=6\n\n### --jobsize=#:\nSpecify the size of each compression job.\nThis parameter is only meaningful when multi-threading is enabled.\nEach compression job is run in parallel, so this value can indirectly impact the nb of active threads.\nDefault job size varies depending on compression level (generally  `4 * windowSize`).\n`--jobsize=#` makes it possible to manually select a custom size.\nNote that job size must respect a minimum value which is enforced transparently.\nThis minimum is either 512 KB, or `overlapSize`, whichever is largest.\nDifferent job sizes will lead to non-identical compressed frames.\n\n\nDICTIONARY BUILDER\n------------------\n`zstd` offers _dictionary_ compression,\nwhich greatly improves efficiency on small files and messages.\nIt's possible to train `zstd` with a set of samples,\nthe result of which is saved into a file called a `dictionary`.\nThen, during compression and decompression, reference the same dictionary,\nusing command `-D dictionaryFileName`.\nCompression of small files similar to the sample set will be greatly improved.\n\n* `--train FILEs`:\n    Use FILEs as training set to create a dictionary.\n    The training set should ideally contain a lot of samples (> 100),\n    and weight typically 100x the target dictionary size\n    (for example, ~10 MB for a 100 KB dictionary).\n    `--train` can be combined with `-r` to indicate a directory rather than listing all the files,\n    which can be useful to circumvent shell expansion limits.\n\n    Since dictionary compression is mostly effective for small files,\n    the expectation is that the training set will only contain small files.\n    In the case where some samples happen to be large,\n    only the first 128 KiB of these samples will be used for training.\n\n    `--train` supports multithreading if `zstd` is compiled with threading support (default).\n    Additional advanced parameters can be specified with `--train-fastcover`.\n    The legacy dictionary builder can be accessed with `--train-legacy`.\n    The slower cover dictionary builder can be accessed with `--train-cover`.\n    Default `--train` is equivalent to `--train-fastcover=d=8,steps=4`.\n\n* `-o FILE`:\n    Dictionary saved into `FILE` (default name: dictionary).\n* `--maxdict=#`:\n    Limit dictionary to specified size (default: 112640 bytes).\n    As usual, quantities are expressed in bytes by default,\n    and it's possible to employ suffixes (like `KB` or `MB`)\n    to specify larger values.\n* `-#`:\n    Use `#` compression level during training (optional).\n    Will generate statistics more tuned for selected compression level,\n    resulting in a _small_ compression ratio improvement for this level.\n* `--split=#`:\n    Split input files into independent chunks of size # (default: no split)\n* `-M#`, `--memory=#`:\n    Limit the amount of sample data loaded for training (default: 2 GB).\n    Note that the default (2 GB) is also the maximum.\n    This parameter can be useful in situations where the training set size\n    is not well controlled and could be potentially very large.\n    Since speed of the training process is directly correlated to\n    the size of the training sample set,\n    a smaller sample set leads to faster training.\n\n    In situations where the training set is larger than maximum memory,\n    the CLI will randomly select samples among the available ones,\n    up to the maximum allowed memory budget.\n    This is meant to improve dictionary relevance\n    by mitigating the potential impact of clustering,\n    such as selecting only files from the beginning of a list\n    sorted by modification date, or sorted by alphabetical order.\n    The randomization process is deterministic, so\n    training of the same list of files with the same parameters\n    will lead to the creation of the same dictionary.\n\n* `--dictID=#`:\n    A dictionary ID is a locally unique ID.\n    The decoder will use this value to verify it is using the right dictionary.\n    By default, zstd will create a 4-bytes random number ID.\n    It's possible to provide an explicit number ID instead.\n    It's up to the dictionary manager to not assign twice the same ID to\n    2 different dictionaries.\n    Note that short numbers have an advantage:\n    an ID < 256 will only need 1 byte in the compressed frame header,\n    and an ID < 65536 will only need 2 bytes.\n    This compares favorably to 4 bytes default.\n\n    Note that RFC8878 reserves IDs less than 32768 and greater than or equal to 2\\^31, so they should not be used in public.\n\n* `--train-cover[=k#,d=#,steps=#,split=#,shrink[=#]]`:\n    Select parameters for the default dictionary builder algorithm named cover.\n    If _d_ is not specified, then it tries _d_ = 6 and _d_ = 8.\n    If _k_ is not specified, then it tries _steps_ values in the range [50, 2000].\n    If _steps_ is not specified, then the default value of 40 is used.\n    If _split_ is not specified or split <= 0, then the default value of 100 is used.\n    Requires that _d_ <= _k_.\n    If _shrink_ flag is not used, then the default value for _shrinkDict_ of 0 is used.\n    If _shrink_ is not specified, then the default value for _shrinkDictMaxRegression_ of 1 is used.\n\n    Selects segments of size _k_ with highest score to put in the dictionary.\n    The score of a segment is computed by the sum of the frequencies of all the\n    subsegments of size _d_.\n    Generally _d_ should be in the range [6, 8], occasionally up to 16, but the\n    algorithm will run faster with d <= _8_.\n    Good values for _k_ vary widely based on the input data, but a safe range is\n    [2 * _d_, 2000].\n    If _split_ is 100, all input samples are used for both training and testing\n    to find optimal _d_ and _k_ to build dictionary.\n    Supports multithreading if `zstd` is compiled with threading support.\n    Having _shrink_ enabled takes a truncated dictionary of minimum size and doubles\n    in size until compression ratio of the truncated dictionary is at most\n    _shrinkDictMaxRegression%_ worse than the compression ratio of the largest dictionary.\n\n    Examples:\n\n    `zstd --train-cover FILEs`\n\n    `zstd --train-cover=k=50,d=8 FILEs`\n\n    `zstd --train-cover=d=8,steps=500 FILEs`\n\n    `zstd --train-cover=k=50 FILEs`\n\n    `zstd --train-cover=k=50,split=60 FILEs`\n\n    `zstd --train-cover=shrink FILEs`\n\n    `zstd --train-cover=shrink=2 FILEs`\n\n* `--train-fastcover[=k#,d=#,f=#,steps=#,split=#,accel=#]`:\n    Same as cover but with extra parameters _f_ and _accel_ and different default value of split\n    If _split_ is not specified, then it tries _split_ = 75.\n    If _f_ is not specified, then it tries _f_ = 20.\n    Requires that 0 < _f_ < 32.\n    If _accel_ is not specified, then it tries _accel_ = 1.\n    Requires that 0 < _accel_ <= 10.\n    Requires that _d_ = 6 or _d_ = 8.\n\n    _f_ is log of size of array that keeps track of frequency of subsegments of size _d_.\n    The subsegment is hashed to an index in the range [0,2^_f_ - 1].\n    It is possible that 2 different subsegments are hashed to the same index, and they are considered as the same subsegment when computing frequency.\n    Using a higher _f_ reduces collision but takes longer.\n\n    Examples:\n\n    `zstd --train-fastcover FILEs`\n\n    `zstd --train-fastcover=d=8,f=15,accel=2 FILEs`\n\n* `--train-legacy[=selectivity=#]`:\n    Use legacy dictionary builder algorithm with the given dictionary\n    _selectivity_ (default: 9).\n    The smaller the _selectivity_ value, the denser the dictionary,\n    improving its efficiency but reducing its achievable maximum size.\n    `--train-legacy=s=#` is also accepted.\n\n    Examples:\n\n    `zstd --train-legacy FILEs`\n\n    `zstd --train-legacy=selectivity=8 FILEs`\n\n\nBENCHMARK\n---------\nThe `zstd` CLI provides a benchmarking mode that can be used to easily find suitable compression parameters, or alternatively to benchmark a computer's performance.\n`zstd -b [FILE(s)]` will benchmark `zstd` for both compression and decompression using default compression level.\nNote that results are very dependent on the content being compressed.\n\nIt's possible to pass multiple files to the benchmark, and even a directory with `-r DIRECTORY`.\nWhen no `FILE` is provided, the benchmark will use a procedurally generated `lorem ipsum` text.\n\nBenchmarking will employ `max(1, min(4, nbCores/4))` worker threads by default in order to match the behavior of the normal CLI I/O.\n\n* `-b#`:\n    benchmark file(s) using compression level #\n* `-e#`:\n    benchmark file(s) using multiple compression levels, from `-b#` to `-e#` (inclusive)\n* `-d`:\n    benchmark decompression speed only (requires providing a zstd-compressed content)\n* `-i#`:\n    minimum evaluation time, in seconds (default: 3s), benchmark mode only\n* `--split=#`:\n    split input file(s) into independent chunks of size # (default: no chunking)\n* `-S`:\n    output one benchmark result per input file (default: consolidated result)\n* `-D dictionary`\n    benchmark using dictionary\n* `--priority=rt`:\n    set process priority to real-time (Windows)\n\nBeyond compression levels, benchmarking is also compatible with other parameters, such as number of threads (`-T#`), advanced compression parameters (`--zstd=###`), dictionary compression (`-D dictionary`), or even disabling checksum verification for example.\n\n**Output Format:** CompressionLevel#Filename: InputSize -> OutputSize (CompressionRatio), CompressionSpeed, DecompressionSpeed\n\n**Methodology:** For speed measurement, the entire input is compressed/decompressed in-memory to measure speed. A run lasts at least 1 sec, so when files are small, they are compressed/decompressed several times per run, in order to improve measurement accuracy.\n\n\nSEE ALSO\n--------\n`zstdgrep`(1), `zstdless`(1), `gzip`(1), `xz`(1)\n\nThe <zstandard> format is specified in Y. Collet, \"Zstandard Compression and the 'application/zstd' Media Type\", https://www.ietf.org/rfc/rfc8878.txt, Internet RFC 8878 (February 2021).\n\nBUGS\n----\nReport bugs at: https://github.com/facebook/zstd/issues\n\nAUTHOR\n------\nYann Collet\n"
  },
  {
    "path": "programs/zstdcli.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/*-************************************\n*  Dependencies\n**************************************/\n#include \"platform.h\" /* PLATFORM_POSIX_VERSION */\n#include \"util.h\"     /* UTIL_HAS_CREATEFILELIST, UTIL_createFileList, UTIL_isConsole */\n#include <stdlib.h>   /* getenv */\n#include <string.h>   /* strcmp, strlen */\n#include <stdio.h>    /* fprintf(), stdin, stdout, stderr */\n#include <assert.h>   /* assert */\n\n#include \"fileio.h\"   /* stdinmark, stdoutmark, ZSTD_EXTENSION */\n#ifndef ZSTD_NOBENCH\n#  include \"benchzstd.h\"  /* BMK_benchFilesAdvanced */\n#endif\n#ifndef ZSTD_NODICT\n#  include \"dibio.h\"  /* ZDICT_cover_params_t, DiB_trainFromFiles() */\n#endif\n#ifndef ZSTD_NOTRACE\n#  include \"zstdcli_trace.h\"\n#endif\n#include \"../lib/zstd.h\"  /* ZSTD_VERSION_STRING, ZSTD_minCLevel, ZSTD_maxCLevel */\n#include \"fileio_asyncio.h\"\n#include \"fileio_common.h\"\n\n/*-************************************\n*  Tuning parameters\n**************************************/\n#ifndef ZSTDCLI_CLEVEL_DEFAULT\n#  define ZSTDCLI_CLEVEL_DEFAULT 3\n#endif\n\n#ifndef ZSTDCLI_CLEVEL_MAX\n#  define ZSTDCLI_CLEVEL_MAX 19   /* without using --ultra */\n#endif\n\n#ifndef ZSTDCLI_NBTHREADS_DEFAULT\n#define ZSTDCLI_NBTHREADS_DEFAULT (unsigned)(MAX(1, MIN(4, UTIL_countLogicalCores() / 4)))\n#endif\n\nstatic unsigned init_nbWorkers(unsigned defaultNbWorkers);\n\n/*-************************************\n*  Constants\n**************************************/\n#define COMPRESSOR_NAME \"Zstandard CLI\"\n#ifndef ZSTD_VERSION\n#  define ZSTD_VERSION \"v\" ZSTD_VERSION_STRING\n#endif\n#define AUTHOR \"Yann Collet\"\n#define WELCOME_MESSAGE \"*** %s (%i-bit) %s, by %s ***\\n\", COMPRESSOR_NAME, (int)(sizeof(size_t)*8), ZSTD_VERSION, AUTHOR\n\n#define ZSTD_ZSTDMT \"zstdmt\"\n#define ZSTD_UNZSTD \"unzstd\"\n#define ZSTD_CAT \"zstdcat\"\n#define ZSTD_ZCAT \"zcat\"\n#define ZSTD_GZ \"gzip\"\n#define ZSTD_GUNZIP \"gunzip\"\n#define ZSTD_GZCAT \"gzcat\"\n#define ZSTD_LZMA \"lzma\"\n#define ZSTD_UNLZMA \"unlzma\"\n#define ZSTD_XZ \"xz\"\n#define ZSTD_UNXZ \"unxz\"\n#define ZSTD_LZ4 \"lz4\"\n#define ZSTD_UNLZ4 \"unlz4\"\n\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\n#ifndef ZSTD_DISPLAY_LEVEL_DEFAULT\n# define ZSTD_DISPLAY_LEVEL_DEFAULT 2\n#endif\n\nstatic const char*    g_defaultDictName = \"dictionary\";\nstatic const unsigned g_defaultMaxDictSize = 110 KB;\nstatic const int      g_defaultDictCLevel = 3;\nstatic const unsigned g_defaultSelectivityLevel = 9;\nstatic const unsigned g_defaultMaxWindowLog = 27;\n#define OVERLAP_LOG_DEFAULT 9999\n#define LDM_PARAM_DEFAULT 9999  /* Default for parameters where 0 is valid */\nstatic U32 g_overlapLog = OVERLAP_LOG_DEFAULT;\nstatic U32 g_ldmHashLog = 0;\nstatic U32 g_ldmMinMatch = 0;\nstatic U32 g_ldmHashRateLog = LDM_PARAM_DEFAULT;\nstatic U32 g_ldmBucketSizeLog = LDM_PARAM_DEFAULT;\n\n\n#define DEFAULT_ACCEL 1\n#define NBWORKERS_AUTOCPU 0\n#define NBWORKERS_UNSET UINT_MAX\n\ntypedef enum { cover, fastCover, legacy } dictType;\n\n/*-************************************\n*  Display Macros\n**************************************/\n#undef DISPLAYLEVEL\n#define DISPLAYLEVEL(l, ...) { if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); } }\nstatic int g_displayLevel = ZSTD_DISPLAY_LEVEL_DEFAULT;   /* 0 : no display,  1: errors,  2 : + result + interaction + warnings,  3 : + progression,  4 : + information */\n\n\n/*-************************************\n*  Check Version (when CLI linked to dynamic library)\n**************************************/\n\n/* Due to usage of experimental symbols and capabilities by the CLI,\n * the CLI must be linked against a dynamic library of same version */\nstatic void checkLibVersion(void)\n{\n    if (strcmp(ZSTD_VERSION_STRING, ZSTD_versionString())) {\n        DISPLAYLEVEL(1, \"Error : incorrect library version (expecting : %s ; actual : %s ) \\n\",\n                    ZSTD_VERSION_STRING, ZSTD_versionString());\n        DISPLAYLEVEL(1, \"Please update library to version %s, or use stand-alone zstd binary \\n\",\n                    ZSTD_VERSION_STRING);\n        exit(1);\n    }\n}\n\n\n/*! exeNameMatch() :\n    @return : a non-zero value if exeName matches test, excluding the extension\n   */\nstatic int exeNameMatch(const char* exeName, const char* test)\n{\n    return !strncmp(exeName, test, strlen(test)) &&\n        (exeName[strlen(test)] == '\\0' || exeName[strlen(test)] == '.');\n}\n\n/*-************************************\n*  Command Line\n**************************************/\n/* print help either in `stderr` or `stdout` depending on originating request\n * error (badUsage) => stderr\n * help (usageAdvanced) => stdout\n */\nstatic void usage(FILE* f, const char* programName)\n{\n    DISPLAY_F(f, \"Compress or decompress the INPUT file(s); reads from STDIN if INPUT is `-` or not provided.\\n\\n\");\n    DISPLAY_F(f, \"Usage: %s [OPTIONS...] [INPUT... | -] [-o OUTPUT]\\n\\n\", programName);\n    DISPLAY_F(f, \"Options:\\n\");\n    DISPLAY_F(f, \"  -o OUTPUT                     Write output to a single file, OUTPUT.\\n\");\n    DISPLAY_F(f, \"  -c, --stdout                  Write to STDOUT (even if it is a console) and keep the INPUT file(s).\\n\");\n    DISPLAY_F(f, \"  -k, --keep                    Preserve INPUT file(s). [Default] \\n\");\n    DISPLAY_F(f, \"  --rm                          Remove INPUT file(s) after successful (de)compression to file.\\n\");\n#ifdef ZSTD_GZCOMPRESS\n    if (exeNameMatch(programName, ZSTD_GZ)) {     /* behave like gzip */\n        DISPLAY_F(f, \"  -n, --no-name                 Do not store original filename when compressing.\\n\\n\");\n    }\n#endif\n    DISPLAY_F(f, \"\\n\");\n#ifndef ZSTD_NOCOMPRESS\n    DISPLAY_F(f, \"  -#                            Desired compression level, where `#` is a number between 1 and %d;\\n\", ZSTDCLI_CLEVEL_MAX);\n    DISPLAY_F(f, \"                                lower numbers provide faster compression, higher numbers yield\\n\");\n    DISPLAY_F(f, \"                                better compression ratios. [Default: %d]\\n\\n\", ZSTDCLI_CLEVEL_DEFAULT);\n#endif\n#ifndef ZSTD_NODECOMPRESS\n    DISPLAY_F(f, \"  -d, --decompress              Perform decompression.\\n\");\n#endif\n    DISPLAY_F(f, \"  -D DICT                       Use DICT as the dictionary for compression or decompression.\\n\\n\");\n    DISPLAY_F(f, \"  -f, --force                   Disable input and output checks. Allows overwriting existing files,\\n\");\n    DISPLAY_F(f, \"                                receiving input from the console, printing output to STDOUT, and\\n\");\n    DISPLAY_F(f, \"                                operating on links, block devices, etc. Unrecognized formats will be\\n\");\n    DISPLAY_F(f, \"                                passed-through through as-is.\\n\\n\");\n\n    DISPLAY_F(f, \"  -h                            Display short usage and exit.\\n\");\n    DISPLAY_F(f, \"  -H, --help                    Display full help and exit.\\n\");\n    DISPLAY_F(f, \"  -V, --version                 Display the program version and exit.\\n\");\n    DISPLAY_F(f, \"\\n\");\n}\n\nstatic void usageAdvanced(const char* programName)\n{\n    DISPLAYOUT(WELCOME_MESSAGE);\n    DISPLAYOUT(\"\\n\");\n    usage(stdout, programName);\n    DISPLAYOUT(\"Advanced options:\\n\");\n\n    DISPLAYOUT(\"  -v, --verbose                 Enable verbose output; pass multiple times to increase verbosity.\\n\");\n    DISPLAYOUT(\"  -q, --quiet                   Suppress warnings; pass twice to suppress errors.\\n\");\n#ifndef ZSTD_NOTRACE\n    DISPLAYOUT(\"  --trace LOG                   Log tracing information to LOG.\\n\");\n#endif\n    DISPLAYOUT(\"\\n\");\n    DISPLAYOUT(\"  --[no-]progress               Forcibly show/hide the progress counter. NOTE: Any (de)compressed\\n\");\n    DISPLAYOUT(\"                                output to terminal will mix with progress counter text.\\n\\n\");\n\n#ifdef UTIL_HAS_CREATEFILELIST\n    DISPLAYOUT(\"  -r                            Operate recursively on directories.\\n\");\n    DISPLAYOUT(\"  --filelist LIST               Read a list of files to operate on from LIST.\\n\");\n    DISPLAYOUT(\"  --output-dir-flat DIR         Store processed files in DIR.\\n\");\n#endif\n\n#ifdef UTIL_HAS_MIRRORFILELIST\n    DISPLAYOUT(\"  --output-dir-mirror DIR       Store processed files in DIR, respecting original directory structure.\\n\");\n#endif\n    if (AIO_supported())\n        DISPLAYOUT(\"  --[no-]asyncio                Use asynchronous IO. [Default: Enabled]\\n\");\n\n    DISPLAYOUT(\"\\n\");\n#ifndef ZSTD_NOCOMPRESS\n    DISPLAYOUT(\"  --[no-]check                  Add XXH64 integrity checksums during compression. [Default: Add, Validate]\\n\");\n#ifndef ZSTD_NODECOMPRESS\n    DISPLAYOUT(\"                                If `-d` is present, ignore/validate checksums during decompression.\\n\");\n#endif\n#else\n#ifdef ZSTD_NOCOMPRESS\n    DISPLAYOUT(\"  --[no-]check                  Ignore/validate checksums during decompression. [Default: Validate]\");\n#endif\n#endif /* ZSTD_NOCOMPRESS */\n\n    DISPLAYOUT(\"\\n\");\n    DISPLAYOUT(\"  --                            Treat remaining arguments after `--` as files.\\n\");\n\n#ifndef ZSTD_NOCOMPRESS\n    DISPLAYOUT(\"\\n\");\n    DISPLAYOUT(\"Advanced compression options:\\n\");\n    DISPLAYOUT(\"  --ultra                       Enable levels beyond %i, up to %i; requires more memory.\\n\", ZSTDCLI_CLEVEL_MAX, ZSTD_maxCLevel());\n    DISPLAYOUT(\"  --fast[=#]                    Use to very fast compression levels. [Default: %u]\\n\", 1);\n#ifdef ZSTD_GZCOMPRESS\n    if (exeNameMatch(programName, ZSTD_GZ)) {     /* behave like gzip */\n        DISPLAYOUT(\"  --best                        Compatibility alias for `-9`.\\n\");\n    }\n#endif\n    DISPLAYOUT(\"  --adapt                       Dynamically adapt compression level to I/O conditions.\\n\");\n    DISPLAYOUT(\"  --long[=#]                    Enable long distance matching with window log #. [Default: %u]\\n\", g_defaultMaxWindowLog);\n    DISPLAYOUT(\"  --patch-from=REF              Use REF as the reference point for Zstandard's diff engine. \\n\");\n    DISPLAYOUT(\"  --patch-apply                 Equivalent for `-d --patch-from` \\n\\n\");\n# ifdef ZSTD_MULTITHREAD\n    DISPLAYOUT(\"  -T#                           Spawn # compression threads. [Default: %u; pass 0 for core count.]\\n\", init_nbWorkers(ZSTDCLI_NBTHREADS_DEFAULT));\n    DISPLAYOUT(\"  --single-thread               Share a single thread for I/O and compression (slightly different than `-T1`).\\n\");\n    DISPLAYOUT(\"  --auto-threads={physical|logical}\\n\");\n    DISPLAYOUT(\"                                Use physical/logical cores when using `-T0`. [Default: Physical]\\n\\n\");\n    DISPLAYOUT(\"  --jobsize=#                   Set job size to #. [Default: 0 (automatic)]\\n\");\n    DISPLAYOUT(\"  --rsyncable                   Compress using a rsync-friendly method (`--jobsize=#` sets unit size). \\n\");\n    DISPLAYOUT(\"\\n\");\n# endif\n    DISPLAYOUT(\"  --exclude-compressed          Only compress files that are not already compressed.\\n\\n\");\n\n    DISPLAYOUT(\"  --stream-size=#               Specify size of streaming input from STDIN.\\n\");\n    DISPLAYOUT(\"  --size-hint=#                 Optimize compression parameters for streaming input of approximately size #.\\n\");\n    DISPLAYOUT(\"  --target-compressed-block-size=#\\n\");\n    DISPLAYOUT(\"                                Generate compressed blocks of approximately # size.\\n\\n\");\n    DISPLAYOUT(\"  --no-dictID                   Don't write `dictID` into the header (dictionary compression only).\\n\");\n    DISPLAYOUT(\"  --[no-]compress-literals      Force (un)compressed literals.\\n\");\n    DISPLAYOUT(\"  --[no-]row-match-finder       Explicitly enable/disable the fast, row-based matchfinder for\\n\");\n    DISPLAYOUT(\"                                the 'greedy', 'lazy', and 'lazy2' strategies.\\n\");\n\n    DISPLAYOUT(\"\\n\");\n    DISPLAYOUT(\"  --format=zstd                 Compress files to the `.zst` format. [Default]\\n\");\n    DISPLAYOUT(\"  --[no-]mmap-dict              Memory-map dictionary file rather than mallocing and loading all at once\\n\");\n#ifdef ZSTD_GZCOMPRESS\n    DISPLAYOUT(\"  --format=gzip                 Compress files to the `.gz` format.\\n\");\n#endif\n#ifdef ZSTD_LZMACOMPRESS\n    DISPLAYOUT(\"  --format=xz                   Compress files to the `.xz` format.\\n\");\n    DISPLAYOUT(\"  --format=lzma                 Compress files to the `.lzma` format.\\n\");\n#endif\n#ifdef ZSTD_LZ4COMPRESS\n    DISPLAYOUT( \"  --format=lz4                  Compress files to the `.lz4` format.\\n\");\n#endif\n#endif  /* !ZSTD_NOCOMPRESS */\n\n#ifndef ZSTD_NODECOMPRESS\n    DISPLAYOUT(\"\\n\");\n    DISPLAYOUT(\"Advanced decompression options:\\n\");\n    DISPLAYOUT(\"  -l                            Print information about Zstandard-compressed files.\\n\");\n    DISPLAYOUT(\"  --test                        Test compressed file integrity.\\n\");\n    DISPLAYOUT(\"  -M#                           Set the memory usage limit to # megabytes.\\n\");\n# if ZSTD_SPARSE_DEFAULT\n    DISPLAYOUT(\"  --[no-]sparse                 Enable sparse mode. [Default: Enabled for files, disabled for STDOUT.]\\n\");\n# else\n    DISPLAYOUT(\"  --[no-]sparse                 Enable sparse mode. [Default: Disabled]\\n\");\n# endif\n    {\n        char const* passThroughDefault = \"Disabled\";\n        if (exeNameMatch(programName, ZSTD_CAT) ||\n            exeNameMatch(programName, ZSTD_ZCAT) ||\n            exeNameMatch(programName, ZSTD_GZCAT)) {\n            passThroughDefault = \"Enabled\";\n        }\n        DISPLAYOUT(\"  --[no-]pass-through           Pass through uncompressed files as-is. [Default: %s]\\n\", passThroughDefault);\n    }\n#endif  /* ZSTD_NODECOMPRESS */\n\n#ifndef ZSTD_NODICT\n    DISPLAYOUT(\"\\n\");\n    DISPLAYOUT(\"Dictionary builder:\\n\");\n    DISPLAYOUT(\"  --train                       Create a dictionary from a training set of files.\\n\\n\");\n    DISPLAYOUT(\"  --train-cover[=k=#,d=#,steps=#,split=#,shrink[=#]]\\n\");\n    DISPLAYOUT(\"                                Use the cover algorithm (with optional arguments).\\n\");\n    DISPLAYOUT(\"  --train-fastcover[=k=#,d=#,f=#,steps=#,split=#,accel=#,shrink[=#]]\\n\");\n    DISPLAYOUT(\"                                Use the fast cover algorithm (with optional arguments).\\n\\n\");\n    DISPLAYOUT(\"  --train-legacy[=s=#]          Use the legacy algorithm with selectivity #. [Default: %u]\\n\", g_defaultSelectivityLevel);\n    DISPLAYOUT(\"  -o NAME                       Use NAME as dictionary name. [Default: %s]\\n\", g_defaultDictName);\n    DISPLAYOUT(\"  --maxdict=#                   Limit dictionary to specified size #. [Default: %u]\\n\", g_defaultMaxDictSize);\n    DISPLAYOUT(\"  --dictID=#                    Force dictionary ID to #. [Default: Random]\\n\");\n#endif\n\n#ifndef ZSTD_NOBENCH\n    DISPLAYOUT(\"\\n\");\n    DISPLAYOUT(\"Benchmark options:\\n\");\n    DISPLAYOUT(\"  -b#                           Perform benchmarking with compression level #. [Default: %d]\\n\", ZSTDCLI_CLEVEL_DEFAULT);\n    DISPLAYOUT(\"  -e#                           Test all compression levels up to #; starting level is `-b#`. [Default: 1]\\n\");\n    DISPLAYOUT(\"  -i#                           Set the minimum evaluation to time # seconds. [Default: 3]\\n\");\n    DISPLAYOUT(\"  --split=#                     Split input into independent chunks of size #. [Default: No chunking]\\n\");\n    DISPLAYOUT(\"  -S                            Output one benchmark result per input file. [Default: Consolidated result]\\n\");\n    DISPLAYOUT(\"  -D dictionary                 Benchmark using dictionary \\n\");\n    DISPLAYOUT(\"  --priority=rt                 Set process priority to real-time.\\n\");\n#endif\n\n}\n\nstatic void badUsage(const char* programName, const char* parameter)\n{\n    DISPLAYLEVEL(1, \"Incorrect parameter: %s \\n\", parameter);\n    if (g_displayLevel >= 2) usage(stderr, programName);\n}\n\nstatic void waitEnter(void)\n{\n    int unused;\n    DISPLAY(\"Press enter to continue... \\n\");\n    unused = getchar();\n    (void)unused;\n}\n\nstatic const char* lastNameFromPath(const char* path)\n{\n    const char* name = path;\n    if (strrchr(name, '/')) name = strrchr(name, '/') + 1;\n    if (strrchr(name, '\\\\')) name = strrchr(name, '\\\\') + 1; /* windows */\n    return name;\n}\n\nstatic void errorOut(const char* msg)\n{\n    DISPLAYLEVEL(1, \"%s \\n\", msg); exit(1);\n}\n\n/*! readU32FromCharChecked() :\n * @return 0 if success, and store the result in *value.\n *  allows and interprets K, KB, KiB, M, MB, MiB, G, GB and GiB suffix.\n *  Will also modify `*stringPtr`, advancing it to position where it stopped reading.\n * @return 1 if an overflow error occurs */\nstatic int readU32FromCharChecked(const char** stringPtr, unsigned* value)\n{\n    unsigned result = 0;\n    while ((**stringPtr >='0') && (**stringPtr <='9')) {\n        unsigned const max = ((unsigned)(-1)) / 10;\n        unsigned last = result;\n        if (result > max) return 1; /* overflow error */\n        result *= 10;\n        result += (unsigned)(**stringPtr - '0');\n        if (result < last) return 1; /* overflow error */\n        (*stringPtr)++ ;\n    }\n    if ((**stringPtr=='K') || (**stringPtr=='M') || (**stringPtr=='G')) {\n        switch (**stringPtr) {\n            case 'K':\n                if (result > (((unsigned)-1) >> 10)) return 1; /* overflow error */\n                result <<= 10;\n                break;\n            case 'M':\n                if (result > (((unsigned)-1) >> 20)) return 1; /* overflow error */\n                result <<= 20;\n                break;\n            case 'G':\n                if (result > (((unsigned)-1) >> 30)) return 1; /* overflow error */\n                result <<= 30;\n                break;\n        }\n        (*stringPtr)++;  /* skip `K`, `M` or `G` */\n        if (**stringPtr=='i') (*stringPtr)++;\n        if (**stringPtr=='B') (*stringPtr)++;\n    }\n    *value = result;\n    return 0;\n}\n\n/*! readU32FromChar() :\n * @return : unsigned integer value read from input in `char` format.\n *  allows and interprets K, KB, KiB, M, MB, MiB, G, GB and GiB suffix.\n *  Will also modify `*stringPtr`, advancing it to position where it stopped reading.\n *  Note : function will exit() program if digit sequence overflows */\nstatic unsigned readU32FromChar(const char** stringPtr) {\n    static const char errorMsg[] = \"error: numeric value overflows 32-bit unsigned int\";\n    unsigned result;\n    if (readU32FromCharChecked(stringPtr, &result)) { errorOut(errorMsg); }\n    return result;\n}\n\n/*! readIntFromChar() :\n * @return : signed integer value read from input in `char` format.\n *  allows and interprets K, KB, KiB, M, MB, MiB, G, GB and GiB suffix.\n *  Will also modify `*stringPtr`, advancing it to position where it stopped reading.\n *  Note : function will exit() program if digit sequence overflows */\nstatic int readIntFromChar(const char** stringPtr) {\n    static const char errorMsg[] = \"error: numeric value overflows 32-bit int\";\n    int sign = 1;\n    unsigned result;\n    if (**stringPtr=='-') {\n        (*stringPtr)++;\n        sign = -1;\n    }\n    if (readU32FromCharChecked(stringPtr, &result)) { errorOut(errorMsg); }\n    return (int) result * sign;\n}\n\n/*! readSizeTFromCharChecked() :\n * @return 0 if success, and store the result in *value.\n *  allows and interprets K, KB, KiB, M, MB, MiB, G, GB and GiB suffix.\n *  Will also modify `*stringPtr`, advancing it to position where it stopped reading.\n * @return 1 if an overflow error occurs */\nstatic int readSizeTFromCharChecked(const char** stringPtr, size_t* value)\n{\n    size_t result = 0;\n    while ((**stringPtr >='0') && (**stringPtr <='9')) {\n        size_t const max = ((size_t)(-1)) / 10;\n        size_t last = result;\n        if (result > max) return 1; /* overflow error */\n        result *= 10;\n        result += (size_t)(**stringPtr - '0');\n        if (result < last) return 1; /* overflow error */\n        (*stringPtr)++ ;\n    }\n    if ((**stringPtr=='K') || (**stringPtr=='M') || (**stringPtr=='G')) {\n        switch (**stringPtr) {\n            case 'K':\n                if (result > (((size_t)-1) >> 10)) return 1; /* overflow error */\n                result <<= 10;\n                break;\n            case 'M':\n                if (result > (((size_t)-1) >> 20)) return 1; /* overflow error */\n                result <<= 20;\n                break;\n            case 'G':\n                if (result > (((size_t)-1) >> 30)) return 1; /* overflow error */\n                result <<= 30;\n                break;\n        }\n        (*stringPtr)++;  /* skip `K`, `M` or `G` */\n        if (**stringPtr=='i') (*stringPtr)++;\n        if (**stringPtr=='B') (*stringPtr)++;\n    }\n    *value = result;\n    return 0;\n}\n\n/*! readSizeTFromChar() :\n * @return : size_t value read from input in `char` format.\n *  allows and interprets K, KB, KiB, M, MB, MiB, G, GB and GiB suffix.\n *  Will also modify `*stringPtr`, advancing it to position where it stopped reading.\n *  Note : function will exit() program if digit sequence overflows */\nstatic size_t readSizeTFromChar(const char** stringPtr) {\n    static const char errorMsg[] = \"error: numeric value overflows size_t\";\n    size_t result;\n    if (readSizeTFromCharChecked(stringPtr, &result)) { errorOut(errorMsg); }\n    return result;\n}\n\n/** longCommandWArg() :\n *  check if *stringPtr is the same as longCommand.\n *  If yes, @return 1 and advances *stringPtr to the position which immediately follows longCommand.\n * @return 0 and doesn't modify *stringPtr otherwise.\n */\nstatic int longCommandWArg(const char** stringPtr, const char* longCommand)\n{\n    size_t const comSize = strlen(longCommand);\n    int const result = !strncmp(*stringPtr, longCommand, comSize);\n    if (result) *stringPtr += comSize;\n    return result;\n}\n\n\n#ifndef ZSTD_NODICT\n\nstatic const unsigned kDefaultRegression = 1;\n/**\n * parseCoverParameters() :\n * reads cover parameters from *stringPtr (e.g. \"--train-cover=k=48,d=8,steps=32\") into *params\n * @return 1 means that cover parameters were correct\n * @return 0 in case of malformed parameters\n */\nstatic unsigned parseCoverParameters(const char* stringPtr, ZDICT_cover_params_t* params)\n{\n    memset(params, 0, sizeof(*params));\n    for (; ;) {\n        if (longCommandWArg(&stringPtr, \"k=\")) { params->k = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }\n        if (longCommandWArg(&stringPtr, \"d=\")) { params->d = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }\n        if (longCommandWArg(&stringPtr, \"steps=\")) { params->steps = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }\n        if (longCommandWArg(&stringPtr, \"split=\")) {\n          unsigned splitPercentage = readU32FromChar(&stringPtr);\n          params->splitPoint = (double)splitPercentage / 100.0;\n          if (stringPtr[0]==',') { stringPtr++; continue; } else break;\n        }\n        if (longCommandWArg(&stringPtr, \"shrink\")) {\n          params->shrinkDictMaxRegression = kDefaultRegression;\n          params->shrinkDict = 1;\n          if (stringPtr[0]=='=') {\n            stringPtr++;\n            params->shrinkDictMaxRegression = readU32FromChar(&stringPtr);\n          }\n          if (stringPtr[0]==',') {\n            stringPtr++;\n            continue;\n          }\n          else break;\n        }\n        return 0;\n    }\n    if (stringPtr[0] != 0) return 0;\n    DISPLAYLEVEL(4, \"cover: k=%u\\nd=%u\\nsteps=%u\\nsplit=%u\\nshrink%u\\n\", params->k, params->d, params->steps, (unsigned)(params->splitPoint * 100), params->shrinkDictMaxRegression);\n    return 1;\n}\n\n/**\n * parseFastCoverParameters() :\n * reads fastcover parameters from *stringPtr (e.g. \"--train-fastcover=k=48,d=8,f=20,steps=32,accel=2\") into *params\n * @return 1 means that fastcover parameters were correct\n * @return 0 in case of malformed parameters\n */\nstatic unsigned parseFastCoverParameters(const char* stringPtr, ZDICT_fastCover_params_t* params)\n{\n    memset(params, 0, sizeof(*params));\n    for (; ;) {\n        if (longCommandWArg(&stringPtr, \"k=\")) { params->k = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }\n        if (longCommandWArg(&stringPtr, \"d=\")) { params->d = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }\n        if (longCommandWArg(&stringPtr, \"f=\")) { params->f = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }\n        if (longCommandWArg(&stringPtr, \"steps=\")) { params->steps = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }\n        if (longCommandWArg(&stringPtr, \"accel=\")) { params->accel = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }\n        if (longCommandWArg(&stringPtr, \"split=\")) {\n          unsigned splitPercentage = readU32FromChar(&stringPtr);\n          params->splitPoint = (double)splitPercentage / 100.0;\n          if (stringPtr[0]==',') { stringPtr++; continue; } else break;\n        }\n        if (longCommandWArg(&stringPtr, \"shrink\")) {\n          params->shrinkDictMaxRegression = kDefaultRegression;\n          params->shrinkDict = 1;\n          if (stringPtr[0]=='=') {\n            stringPtr++;\n            params->shrinkDictMaxRegression = readU32FromChar(&stringPtr);\n          }\n          if (stringPtr[0]==',') {\n            stringPtr++;\n            continue;\n          }\n          else break;\n        }\n        return 0;\n    }\n    if (stringPtr[0] != 0) return 0;\n    DISPLAYLEVEL(4, \"cover: k=%u\\nd=%u\\nf=%u\\nsteps=%u\\nsplit=%u\\naccel=%u\\nshrink=%u\\n\", params->k, params->d, params->f, params->steps, (unsigned)(params->splitPoint * 100), params->accel, params->shrinkDictMaxRegression);\n    return 1;\n}\n\n/**\n * parseLegacyParameters() :\n * reads legacy dictionary builder parameters from *stringPtr (e.g. \"--train-legacy=selectivity=8\") into *selectivity\n * @return 1 means that legacy dictionary builder parameters were correct\n * @return 0 in case of malformed parameters\n */\nstatic unsigned parseLegacyParameters(const char* stringPtr, unsigned* selectivity)\n{\n    if (!longCommandWArg(&stringPtr, \"s=\") && !longCommandWArg(&stringPtr, \"selectivity=\")) { return 0; }\n    *selectivity = readU32FromChar(&stringPtr);\n    if (stringPtr[0] != 0) return 0;\n    DISPLAYLEVEL(4, \"legacy: selectivity=%u\\n\", *selectivity);\n    return 1;\n}\n\nstatic ZDICT_cover_params_t defaultCoverParams(void)\n{\n    ZDICT_cover_params_t params;\n    memset(&params, 0, sizeof(params));\n    params.d = 8;\n    params.steps = 4;\n    params.splitPoint = 1.0;\n    params.shrinkDict = 0;\n    params.shrinkDictMaxRegression = kDefaultRegression;\n    return params;\n}\n\nstatic ZDICT_fastCover_params_t defaultFastCoverParams(void)\n{\n    ZDICT_fastCover_params_t params;\n    memset(&params, 0, sizeof(params));\n    params.d = 8;\n    params.f = 20;\n    params.steps = 4;\n    params.splitPoint = 0.75; /* different from default splitPoint of cover */\n    params.accel = DEFAULT_ACCEL;\n    params.shrinkDict = 0;\n    params.shrinkDictMaxRegression = kDefaultRegression;\n    return params;\n}\n#endif\n\n\n/** parseAdaptParameters() :\n *  reads adapt parameters from *stringPtr (e.g. \"--adapt=min=1,max=19) and store them into adaptMinPtr and adaptMaxPtr.\n *  Both adaptMinPtr and adaptMaxPtr must be already allocated and correctly initialized.\n *  There is no guarantee that any of these values will be updated.\n *  @return 1 means that parsing was successful,\n *  @return 0 in case of malformed parameters\n */\nstatic unsigned parseAdaptParameters(const char* stringPtr, int* adaptMinPtr, int* adaptMaxPtr)\n{\n    for ( ; ;) {\n        if (longCommandWArg(&stringPtr, \"min=\")) { *adaptMinPtr = readIntFromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }\n        if (longCommandWArg(&stringPtr, \"max=\")) { *adaptMaxPtr = readIntFromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }\n        DISPLAYLEVEL(4, \"invalid compression parameter \\n\");\n        return 0;\n    }\n    if (stringPtr[0] != 0) return 0; /* check the end of string */\n    if (*adaptMinPtr > *adaptMaxPtr) {\n        DISPLAYLEVEL(4, \"incoherent adaptation limits \\n\");\n        return 0;\n    }\n    return 1;\n}\n\n\n/** parseCompressionParameters() :\n *  reads compression parameters from *stringPtr (e.g. \"--zstd=wlog=23,clog=23,hlog=22,slog=6,mml=3,tlen=48,strat=6\") into *params\n *  @return 1 means that compression parameters were correct\n *  @return 0 in case of malformed parameters\n */\nstatic unsigned parseCompressionParameters(const char* stringPtr, ZSTD_compressionParameters* params)\n{\n    for ( ; ;) {\n        if (longCommandWArg(&stringPtr, \"windowLog=\") || longCommandWArg(&stringPtr, \"wlog=\")) { params->windowLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }\n        if (longCommandWArg(&stringPtr, \"chainLog=\") || longCommandWArg(&stringPtr, \"clog=\")) { params->chainLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }\n        if (longCommandWArg(&stringPtr, \"hashLog=\") || longCommandWArg(&stringPtr, \"hlog=\")) { params->hashLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }\n        if (longCommandWArg(&stringPtr, \"searchLog=\") || longCommandWArg(&stringPtr, \"slog=\")) { params->searchLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }\n        if (longCommandWArg(&stringPtr, \"minMatch=\") || longCommandWArg(&stringPtr, \"mml=\")) { params->minMatch = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }\n        if (longCommandWArg(&stringPtr, \"targetLength=\") || longCommandWArg(&stringPtr, \"tlen=\")) { params->targetLength = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }\n        if (longCommandWArg(&stringPtr, \"strategy=\") || longCommandWArg(&stringPtr, \"strat=\")) { params->strategy = (ZSTD_strategy)(readU32FromChar(&stringPtr)); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }\n        if (longCommandWArg(&stringPtr, \"overlapLog=\") || longCommandWArg(&stringPtr, \"ovlog=\")) { g_overlapLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }\n        if (longCommandWArg(&stringPtr, \"ldmHashLog=\") || longCommandWArg(&stringPtr, \"lhlog=\")) { g_ldmHashLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }\n        if (longCommandWArg(&stringPtr, \"ldmMinMatch=\") || longCommandWArg(&stringPtr, \"lmml=\")) { g_ldmMinMatch = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }\n        if (longCommandWArg(&stringPtr, \"ldmBucketSizeLog=\") || longCommandWArg(&stringPtr, \"lblog=\")) { g_ldmBucketSizeLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }\n        if (longCommandWArg(&stringPtr, \"ldmHashRateLog=\") || longCommandWArg(&stringPtr, \"lhrlog=\")) { g_ldmHashRateLog = readU32FromChar(&stringPtr); if (stringPtr[0]==',') { stringPtr++; continue; } else break; }\n        DISPLAYLEVEL(4, \"invalid compression parameter \\n\");\n        return 0;\n    }\n\n    if (stringPtr[0] != 0) return 0; /* check the end of string */\n    return 1;\n}\n\nstatic void setMaxCompression(ZSTD_compressionParameters* params)\n{\n    params->windowLog = ZSTD_WINDOWLOG_MAX;\n    params->chainLog = ZSTD_CHAINLOG_MAX;\n    params->hashLog = ZSTD_HASHLOG_MAX;\n    params->searchLog = ZSTD_SEARCHLOG_MAX;\n    params->minMatch = ZSTD_MINMATCH_MIN;\n    params->targetLength = ZSTD_TARGETLENGTH_MAX;\n    params->strategy = ZSTD_STRATEGY_MAX;\n    g_overlapLog = ZSTD_OVERLAPLOG_MAX;\n    g_ldmHashLog = ZSTD_LDM_HASHLOG_MAX;\n    g_ldmHashRateLog = 0; /* automatically derived */\n    g_ldmMinMatch = 16; /* heuristic */\n    g_ldmBucketSizeLog = ZSTD_LDM_BUCKETSIZELOG_MAX;\n}\n\nstatic void printVersion(void)\n{\n    if (g_displayLevel < ZSTD_DISPLAY_LEVEL_DEFAULT) {\n        DISPLAYOUT(\"%s\\n\", ZSTD_VERSION_STRING);\n        return;\n    }\n\n    DISPLAYOUT(WELCOME_MESSAGE);\n    if (g_displayLevel >= 3) {\n    /* format support */\n        DISPLAYOUT(\"*** supports: zstd\");\n    #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>0) && (ZSTD_LEGACY_SUPPORT<8)\n        DISPLAYOUT(\", zstd legacy v0.%d+\", ZSTD_LEGACY_SUPPORT);\n    #endif\n    #ifdef ZSTD_GZCOMPRESS\n        DISPLAYOUT(\", gzip\");\n    #endif\n    #ifdef ZSTD_LZ4COMPRESS\n        DISPLAYOUT(\", lz4\");\n    #endif\n    #ifdef ZSTD_LZMACOMPRESS\n        DISPLAYOUT(\", lzma, xz \");\n    #endif\n        DISPLAYOUT(\"\\n\");\n        if (g_displayLevel >= 4) {\n            /* library versions */\n            DISPLAYOUT(\"zlib version %s\\n\", FIO_zlibVersion());\n            DISPLAYOUT(\"lz4 version %s\\n\", FIO_lz4Version());\n            DISPLAYOUT(\"lzma version %s\\n\", FIO_lzmaVersion());\n\n        #ifdef ZSTD_MULTITHREAD\n            DISPLAYOUT(\"supports Multithreading \\n\");\n        #else\n            DISPLAYOUT(\"single-thread operations only \\n\");\n        #endif\n\n            /* posix support */\n        #ifdef _POSIX_C_SOURCE\n            DISPLAYOUT(\"_POSIX_C_SOURCE defined: %ldL\\n\", (long) _POSIX_C_SOURCE);\n        #endif\n        #ifdef _POSIX_VERSION\n            DISPLAYOUT(\"_POSIX_VERSION defined: %ldL \\n\", (long) _POSIX_VERSION);\n        #endif\n        #ifdef PLATFORM_POSIX_VERSION\n            DISPLAYOUT(\"PLATFORM_POSIX_VERSION defined: %ldL\\n\", (long) PLATFORM_POSIX_VERSION);\n        #endif\n\n            if (!ZSTD_isDeterministicBuild()) {\n                DISPLAYOUT(\"non-deterministic build\\n\");\n    }   }   }\n}\n\n#define ZSTD_NB_STRATEGIES 9\nstatic const char* ZSTD_strategyMap[ZSTD_NB_STRATEGIES + 1] = { \"\", \"ZSTD_fast\",\n                \"ZSTD_dfast\", \"ZSTD_greedy\", \"ZSTD_lazy\", \"ZSTD_lazy2\", \"ZSTD_btlazy2\",\n                \"ZSTD_btopt\", \"ZSTD_btultra\", \"ZSTD_btultra2\"};\n\n#ifndef ZSTD_NOCOMPRESS\n\nstatic void printDefaultCParams(const char* filename, const char* dictFileName, int cLevel) {\n    unsigned long long fileSize = UTIL_getFileSize(filename);\n    const size_t dictSize = dictFileName != NULL ? (size_t)UTIL_getFileSize(dictFileName) : 0;\n    const ZSTD_compressionParameters cParams = ZSTD_getCParams(cLevel, fileSize, dictSize);\n    if (fileSize != UTIL_FILESIZE_UNKNOWN) DISPLAY(\"%s (%llu bytes)\\n\", filename, fileSize);\n    else DISPLAY(\"%s (src size unknown)\\n\", filename);\n    DISPLAY(\" - windowLog     : %u\\n\", cParams.windowLog);\n    DISPLAY(\" - chainLog      : %u\\n\", cParams.chainLog);\n    DISPLAY(\" - hashLog       : %u\\n\", cParams.hashLog);\n    DISPLAY(\" - searchLog     : %u\\n\", cParams.searchLog);\n    DISPLAY(\" - minMatch      : %u\\n\", cParams.minMatch);\n    DISPLAY(\" - targetLength  : %u\\n\", cParams.targetLength);\n    assert(cParams.strategy < ZSTD_NB_STRATEGIES + 1);\n    DISPLAY(\" - strategy      : %s (%u)\\n\", ZSTD_strategyMap[(int)cParams.strategy], (unsigned)cParams.strategy);\n}\n\nstatic void printActualCParams(const char* filename, const char* dictFileName, int cLevel, const ZSTD_compressionParameters* cParams) {\n    unsigned long long fileSize = UTIL_getFileSize(filename);\n    const size_t dictSize = dictFileName != NULL ? (size_t)UTIL_getFileSize(dictFileName) : 0;\n    ZSTD_compressionParameters actualCParams = ZSTD_getCParams(cLevel, fileSize, dictSize);\n    assert(g_displayLevel >= 4);\n    actualCParams.windowLog = cParams->windowLog == 0 ? actualCParams.windowLog : cParams->windowLog;\n    actualCParams.chainLog = cParams->chainLog == 0 ? actualCParams.chainLog : cParams->chainLog;\n    actualCParams.hashLog = cParams->hashLog == 0 ? actualCParams.hashLog : cParams->hashLog;\n    actualCParams.searchLog = cParams->searchLog == 0 ? actualCParams.searchLog : cParams->searchLog;\n    actualCParams.minMatch = cParams->minMatch == 0 ? actualCParams.minMatch : cParams->minMatch;\n    actualCParams.targetLength = cParams->targetLength == 0 ? actualCParams.targetLength : cParams->targetLength;\n    actualCParams.strategy = cParams->strategy == 0 ? actualCParams.strategy : cParams->strategy;\n    DISPLAY(\"--zstd=wlog=%d,clog=%d,hlog=%d,slog=%d,mml=%d,tlen=%d,strat=%d\\n\",\n            actualCParams.windowLog, actualCParams.chainLog, actualCParams.hashLog, actualCParams.searchLog,\n            actualCParams.minMatch, actualCParams.targetLength, actualCParams.strategy);\n}\n\n#endif\n\n/* Environment variables for parameter setting */\n#define ENV_CLEVEL \"ZSTD_CLEVEL\"\n#define ENV_NBWORKERS \"ZSTD_NBTHREADS\"    /* takes lower precedence than directly specifying -T# in the CLI */\n\n/* pick up environment variable */\nstatic int init_cLevel(void) {\n    const char* const env = getenv(ENV_CLEVEL);\n    if (env != NULL) {\n        const char* ptr = env;\n        int sign = 1;\n        if (*ptr == '-') {\n            sign = -1;\n            ptr++;\n        } else if (*ptr == '+') {\n            ptr++;\n        }\n\n        if ((*ptr>='0') && (*ptr<='9')) {\n            unsigned absLevel;\n            if (readU32FromCharChecked(&ptr, &absLevel)) {\n                DISPLAYLEVEL(2, \"Ignore environment variable setting %s=%s: numeric value too large \\n\", ENV_CLEVEL, env);\n                return ZSTDCLI_CLEVEL_DEFAULT;\n            } else if (*ptr == 0) {\n                return sign * (int)absLevel;\n        }   }\n\n        DISPLAYLEVEL(2, \"Ignore environment variable setting %s=%s: not a valid integer value \\n\", ENV_CLEVEL, env);\n    }\n\n    return ZSTDCLI_CLEVEL_DEFAULT;\n}\n\nstatic unsigned init_nbWorkers(unsigned defaultNbWorkers) {\n#ifdef ZSTD_MULTITHREAD\n    const char* const env = getenv(ENV_NBWORKERS);\n    if (env != NULL) {\n        const char* ptr = env;\n        if ((*ptr>='0') && (*ptr<='9')) {\n            unsigned nbThreads;\n            if (readU32FromCharChecked(&ptr, &nbThreads)) {\n                DISPLAYLEVEL(2, \"Ignore environment variable setting %s=%s: numeric value too large \\n\", ENV_NBWORKERS, env);\n                return defaultNbWorkers;\n            } else if (*ptr == 0) {\n                return nbThreads;\n            }\n        }\n        DISPLAYLEVEL(2, \"Ignore environment variable setting %s=%s: not a valid unsigned value \\n\", ENV_NBWORKERS, env);\n    }\n\n    return defaultNbWorkers;\n#else\n    (void)defaultNbWorkers;\n    return 1;\n#endif\n}\n\n#define NEXT_FIELD(ptr) {         \\\n    if (*argument == '=') {       \\\n        ptr = ++argument;         \\\n        argument += strlen(ptr);  \\\n    } else {                      \\\n        argNb++;                  \\\n        if (argNb >= argCount) {  \\\n            DISPLAYLEVEL(1, \"error: missing command argument \\n\"); \\\n            CLEAN_RETURN(1);      \\\n        }                         \\\n        ptr = argv[argNb];        \\\n        assert(ptr != NULL);      \\\n        if (ptr[0]=='-') {        \\\n            DISPLAYLEVEL(1, \"error: command cannot be separated from its argument by another command \\n\"); \\\n            CLEAN_RETURN(1);      \\\n}   }   }\n\n#define NEXT_UINT32(_varu32) {        \\\n    const char* __nb;                 \\\n    NEXT_FIELD(__nb);                 \\\n    _varu32 = readU32FromChar(&__nb); \\\n    if(*__nb != 0) {                  \\\n        errorOut(\"error: only numeric values with optional suffixes K, KB, KiB, M, MB, MiB, G, GB, GiB are allowed\"); \\\n    }                                 \\\n}\n\n#define NEXT_TSIZE(_varTsize) {           \\\n    const char* __nb;                     \\\n    NEXT_FIELD(__nb);                     \\\n    _varTsize = readSizeTFromChar(&__nb); \\\n    if(*__nb != 0) {                      \\\n        errorOut(\"error: only numeric values with optional suffixes K, KB, KiB, M, MB, MiB, G, GB, GiB are allowed\"); \\\n    }                                     \\\n}\n\ntypedef enum { zom_compress, zom_decompress, zom_test, zom_bench, zom_train, zom_list } zstd_operation_mode;\n\n#define CLEAN_RETURN(i) { operationResult = (i); goto _end; }\n\n#ifdef ZSTD_NOCOMPRESS\n/* symbols from compression library are not defined and should not be invoked */\n# define MINCLEVEL  -99\n# define MAXCLEVEL   22\n#else\n# define MINCLEVEL  ZSTD_minCLevel()\n# define MAXCLEVEL  ZSTD_maxCLevel()\n#endif\n\nint main(int argCount, const char* argv[])\n{\n    int argNb,\n        followLinks = 0,\n        allowBlockDevices = 0,\n        forceStdin = 0,\n        forceStdout = 0,\n        hasStdout = 0,\n        ldmFlag = 0,\n        main_pause = 0,\n        adapt = 0,\n        adaptMin = MINCLEVEL,\n        adaptMax = MAXCLEVEL,\n        rsyncable = 0,\n        nextArgumentsAreFiles = 0,\n        operationResult = 0,\n        separateFiles = 0,\n        setRealTimePrio = 0,\n        singleThread = 0,\n        defaultLogicalCores = 0,\n        showDefaultCParams = 0,\n        contentSize = 1,\n        removeSrcFile = 0,\n        cLevel = init_cLevel(),\n        ultra = 0,\n        cLevelLast = MINCLEVEL - 1, /* for benchmark range */\n        setThreads_non1 = 0;\n    unsigned nbWorkers = init_nbWorkers(NBWORKERS_UNSET);\n    ZSTD_ParamSwitch_e mmapDict = ZSTD_ps_auto;\n    ZSTD_ParamSwitch_e useRowMatchFinder = ZSTD_ps_auto;\n    FIO_compressionType_t cType = FIO_zstdCompression;\n    double compressibility = -1.0;  /* lorem ipsum generator */\n    unsigned bench_nbSeconds = 3;   /* would be better if this value was synchronized from bench */\n    size_t chunkSize = 0;\n\n    FIO_prefs_t* const prefs = FIO_createPreferences();\n    FIO_ctx_t* const fCtx = FIO_createContext();\n    FIO_progressSetting_e progress = FIO_ps_auto;\n    zstd_operation_mode operation = zom_compress;\n    ZSTD_compressionParameters compressionParams;\n    unsigned recursive = 0;\n    unsigned memLimit = 0;\n    FileNamesTable* filenames = UTIL_allocateFileNamesTable((size_t)argCount);  /* argCount >= 1 */\n    FileNamesTable* file_of_names = UTIL_allocateFileNamesTable((size_t)argCount);  /* argCount >= 1 */\n    const char* programName = argv[0];\n    const char* outFileName = NULL;\n    const char* outDirName = NULL;\n    const char* outMirroredDirName = NULL;\n    const char* dictFileName = NULL;\n    const char* patchFromDictFileName = NULL;\n    const char* suffix = ZSTD_EXTENSION;\n    unsigned maxDictSize = g_defaultMaxDictSize;\n    unsigned dictID = 0;\n    size_t streamSrcSize = 0;\n    size_t targetCBlockSize = 0;\n    size_t srcSizeHint = 0;\n    size_t nbInputFileNames = 0;\n    int dictCLevel = g_defaultDictCLevel;\n    unsigned dictSelect = g_defaultSelectivityLevel;\n#ifndef ZSTD_NODICT\n    ZDICT_cover_params_t coverParams = defaultCoverParams();\n    ZDICT_fastCover_params_t fastCoverParams = defaultFastCoverParams();\n    dictType dict = fastCover;\n#endif\n#ifndef ZSTD_NOBENCH\n    BMK_advancedParams_t benchParams = BMK_initAdvancedParams();\n#endif\n    ZSTD_ParamSwitch_e literalCompressionMode = ZSTD_ps_auto;\n\n    /* init */\n    checkLibVersion();\n    (void)recursive; (void)cLevelLast;    /* not used when ZSTD_NOBENCH set */\n    (void)memLimit;\n    assert(argCount >= 1);\n    if ((filenames==NULL) || (file_of_names==NULL)) { DISPLAYLEVEL(1, \"zstd: allocation error \\n\"); exit(1); }\n    programName = lastNameFromPath(programName);\n\n    /* preset behaviors */\n    if (exeNameMatch(programName, ZSTD_ZSTDMT)) nbWorkers=NBWORKERS_AUTOCPU, singleThread=0;\n    if (exeNameMatch(programName, ZSTD_UNZSTD)) operation=zom_decompress;\n    if (exeNameMatch(programName, ZSTD_CAT)) { operation=zom_decompress; FIO_overwriteMode(prefs); forceStdout=1; followLinks=1; FIO_setPassThroughFlag(prefs, 1); outFileName=stdoutmark; g_displayLevel=1; }     /* supports multiple formats */\n    if (exeNameMatch(programName, ZSTD_ZCAT)) { operation=zom_decompress; FIO_overwriteMode(prefs); forceStdout=1; followLinks=1; FIO_setPassThroughFlag(prefs, 1); outFileName=stdoutmark; g_displayLevel=1; }    /* behave like zcat, also supports multiple formats */\n    if (exeNameMatch(programName, ZSTD_GZ)) {   /* behave like gzip */\n        suffix = GZ_EXTENSION; cType = FIO_gzipCompression; removeSrcFile=1;\n        dictCLevel = cLevel = 6;  /* gzip default is -6 */\n    }\n    if (exeNameMatch(programName, ZSTD_GUNZIP)) { operation=zom_decompress; removeSrcFile=1; }                              /* behave like gunzip, also supports multiple formats */\n    if (exeNameMatch(programName, ZSTD_GZCAT)) { operation=zom_decompress; FIO_overwriteMode(prefs); forceStdout=1; followLinks=1; FIO_setPassThroughFlag(prefs, 1); outFileName=stdoutmark; g_displayLevel=1; }   /* behave like gzcat, also supports multiple formats */\n    if (exeNameMatch(programName, ZSTD_LZMA)) { suffix = LZMA_EXTENSION; cType = FIO_lzmaCompression; removeSrcFile=1; }    /* behave like lzma */\n    if (exeNameMatch(programName, ZSTD_UNLZMA)) { operation=zom_decompress; cType = FIO_lzmaCompression; removeSrcFile=1; } /* behave like unlzma, also supports multiple formats */\n    if (exeNameMatch(programName, ZSTD_XZ)) { suffix = XZ_EXTENSION; cType = FIO_xzCompression; removeSrcFile=1; }          /* behave like xz */\n    if (exeNameMatch(programName, ZSTD_UNXZ)) { operation=zom_decompress; cType = FIO_xzCompression; removeSrcFile=1; }     /* behave like unxz, also supports multiple formats */\n    if (exeNameMatch(programName, ZSTD_LZ4)) { suffix = LZ4_EXTENSION; cType = FIO_lz4Compression; }                        /* behave like lz4 */\n    if (exeNameMatch(programName, ZSTD_UNLZ4)) { operation=zom_decompress; cType = FIO_lz4Compression; }                    /* behave like unlz4, also supports multiple formats */\n    memset(&compressionParams, 0, sizeof(compressionParams));\n\n    /* init crash handler */\n    FIO_addAbortHandler();\n\n    /* command switches */\n    for (argNb=1; argNb<argCount; argNb++) {\n        const char* argument = argv[argNb];\n        const char* const originalArgument = argument;\n        if (!argument) continue;   /* Protection if argument empty */\n\n        if (nextArgumentsAreFiles) {\n            UTIL_refFilename(filenames, argument);\n            continue;\n        }\n\n        /* \"-\" means stdin/stdout */\n        if (!strcmp(argument, \"-\")){\n            UTIL_refFilename(filenames, stdinmark);\n            continue;\n        }\n\n        /* Decode commands (note : aggregated commands are allowed) */\n        if (argument[0]=='-') {\n\n            if (argument[1]=='-') {\n                /* long commands (--long-word) */\n                if (!strcmp(argument, \"--\")) { nextArgumentsAreFiles=1; continue; }   /* only file names allowed from now on */\n                if (!strcmp(argument, \"--list\")) { operation=zom_list; continue; }\n                if (!strcmp(argument, \"--compress\")) { operation=zom_compress; continue; }\n                if (!strcmp(argument, \"--decompress\")) { operation=zom_decompress; continue; }\n                if (!strcmp(argument, \"--uncompress\")) { operation=zom_decompress; continue; }\n                if (!strcmp(argument, \"--force\")) { FIO_overwriteMode(prefs); forceStdin=1; forceStdout=1; followLinks=1; allowBlockDevices=1; continue; }\n                if (!strcmp(argument, \"--version\")) { printVersion(); CLEAN_RETURN(0); }\n                if (!strcmp(argument, \"--help\")) { usageAdvanced(programName); CLEAN_RETURN(0); }\n                if (!strcmp(argument, \"--verbose\")) { g_displayLevel++; continue; }\n                if (!strcmp(argument, \"--quiet\")) { g_displayLevel--; continue; }\n                if (!strcmp(argument, \"--stdout\")) { forceStdout=1; outFileName=stdoutmark; continue; }\n                if (!strcmp(argument, \"--ultra\")) { ultra=1; continue; }\n                if (!strcmp(argument, \"--check\")) { FIO_setChecksumFlag(prefs, 2); continue; }\n                if (!strcmp(argument, \"--no-check\")) { FIO_setChecksumFlag(prefs, 0); continue; }\n                if (!strcmp(argument, \"--sparse\")) { FIO_setSparseWrite(prefs, 2); continue; }\n                if (!strcmp(argument, \"--no-sparse\")) { FIO_setSparseWrite(prefs, 0); continue; }\n                if (!strcmp(argument, \"--pass-through\")) { FIO_setPassThroughFlag(prefs, 1); continue; }\n                if (!strcmp(argument, \"--no-pass-through\")) { FIO_setPassThroughFlag(prefs, 0); continue; }\n                if (!strcmp(argument, \"--test\")) { operation=zom_test; continue; }\n                if (!strcmp(argument, \"--asyncio\")) { FIO_setAsyncIOFlag(prefs, 1); continue;}\n                if (!strcmp(argument, \"--no-asyncio\")) { FIO_setAsyncIOFlag(prefs, 0); continue;}\n                if (!strcmp(argument, \"--train\")) { operation=zom_train; if (outFileName==NULL) outFileName=g_defaultDictName; continue; }\n                if (!strcmp(argument, \"--no-dictID\")) { FIO_setDictIDFlag(prefs, 0); continue; }\n                if (!strcmp(argument, \"--keep\")) { removeSrcFile=0; continue; }\n                if (!strcmp(argument, \"--rm\")) { removeSrcFile=1; continue; }\n                if (!strcmp(argument, \"--priority=rt\")) { setRealTimePrio = 1; continue; }\n                if (!strcmp(argument, \"--show-default-cparams\")) { showDefaultCParams = 1; continue; }\n                if (!strcmp(argument, \"--content-size\")) { contentSize = 1; continue; }\n                if (!strcmp(argument, \"--no-content-size\")) { contentSize = 0; continue; }\n                if (!strcmp(argument, \"--adapt\")) { adapt = 1; continue; }\n                if (!strcmp(argument, \"--no-row-match-finder\")) { useRowMatchFinder = ZSTD_ps_disable; continue; }\n                if (!strcmp(argument, \"--row-match-finder\")) { useRowMatchFinder = ZSTD_ps_enable; continue; }\n                if (longCommandWArg(&argument, \"--adapt=\")) { adapt = 1; if (!parseAdaptParameters(argument, &adaptMin, &adaptMax)) { badUsage(programName, originalArgument); CLEAN_RETURN(1); } continue; }\n                if (!strcmp(argument, \"--single-thread\")) { nbWorkers = 0; singleThread = 1; continue; }\n                if (!strcmp(argument, \"--format=zstd\")) { suffix = ZSTD_EXTENSION; cType = FIO_zstdCompression; continue; }\n                if (!strcmp(argument, \"--mmap-dict\")) { mmapDict = ZSTD_ps_enable; continue; }\n                if (!strcmp(argument, \"--no-mmap-dict\")) { mmapDict = ZSTD_ps_disable; continue; }\n#ifdef ZSTD_GZCOMPRESS\n                if (!strcmp(argument, \"--format=gzip\")) { suffix = GZ_EXTENSION; cType = FIO_gzipCompression; continue; }\n                if (exeNameMatch(programName, ZSTD_GZ)) {     /* behave like gzip */\n                    if (!strcmp(argument, \"--best\")) { dictCLevel = cLevel = 9; continue; }\n                    if (!strcmp(argument, \"--no-name\")) { /* ignore for now */; continue; }\n                }\n#endif\n#ifdef ZSTD_LZMACOMPRESS\n                if (!strcmp(argument, \"--format=lzma\")) { suffix = LZMA_EXTENSION; cType = FIO_lzmaCompression; continue; }\n                if (!strcmp(argument, \"--format=xz\")) { suffix = XZ_EXTENSION; cType = FIO_xzCompression; continue; }\n#endif\n#ifdef ZSTD_LZ4COMPRESS\n                if (!strcmp(argument, \"--format=lz4\")) { suffix = LZ4_EXTENSION; cType = FIO_lz4Compression; continue; }\n#endif\n                if (!strcmp(argument, \"--rsyncable\")) { rsyncable = 1; continue; }\n                if (!strcmp(argument, \"--compress-literals\")) { literalCompressionMode = ZSTD_ps_enable; continue; }\n                if (!strcmp(argument, \"--no-compress-literals\")) { literalCompressionMode = ZSTD_ps_disable; continue; }\n                if (!strcmp(argument, \"--no-progress\")) { progress = FIO_ps_never; continue; }\n                if (!strcmp(argument, \"--progress\")) { progress = FIO_ps_always; continue; }\n                if (!strcmp(argument, \"--exclude-compressed\")) { FIO_setExcludeCompressedFile(prefs, 1); continue; }\n                if (!strcmp(argument, \"--fake-stdin-is-console\")) { UTIL_fakeStdinIsConsole(); continue; }\n                if (!strcmp(argument, \"--fake-stdout-is-console\")) { UTIL_fakeStdoutIsConsole(); continue; }\n                if (!strcmp(argument, \"--fake-stderr-is-console\")) { UTIL_fakeStderrIsConsole(); continue; }\n                if (!strcmp(argument, \"--trace-file-stat\")) { UTIL_traceFileStat(); continue; }\n\n                if (!strcmp(argument, \"--max\")) {\n                    if (sizeof(void*)==4) {\n                        DISPLAYLEVEL(2, \"--max is incompatible with 32-bit mode \\n\");\n                        badUsage(programName, originalArgument);\n                        CLEAN_RETURN(1);\n                    }\n                    ultra=1; ldmFlag = 1; setMaxCompression(&compressionParams);\n                    continue;\n                }\n\n                /* long commands with arguments */\n#ifndef ZSTD_NODICT\n                if (longCommandWArg(&argument, \"--train-cover\")) {\n                  operation = zom_train;\n                  if (outFileName == NULL)\n                      outFileName = g_defaultDictName;\n                  dict = cover;\n                  /* Allow optional arguments following an = */\n                  if (*argument == 0) { memset(&coverParams, 0, sizeof(coverParams)); }\n                  else if (*argument++ != '=') { badUsage(programName, originalArgument); CLEAN_RETURN(1); }\n                  else if (!parseCoverParameters(argument, &coverParams)) { badUsage(programName, originalArgument); CLEAN_RETURN(1); }\n                  continue;\n                }\n                if (longCommandWArg(&argument, \"--train-fastcover\")) {\n                  operation = zom_train;\n                  if (outFileName == NULL)\n                      outFileName = g_defaultDictName;\n                  dict = fastCover;\n                  /* Allow optional arguments following an = */\n                  if (*argument == 0) { memset(&fastCoverParams, 0, sizeof(fastCoverParams)); }\n                  else if (*argument++ != '=') { badUsage(programName, originalArgument); CLEAN_RETURN(1); }\n                  else if (!parseFastCoverParameters(argument, &fastCoverParams)) { badUsage(programName, originalArgument); CLEAN_RETURN(1); }\n                  continue;\n                }\n                if (longCommandWArg(&argument, \"--train-legacy\")) {\n                  operation = zom_train;\n                  if (outFileName == NULL)\n                      outFileName = g_defaultDictName;\n                  dict = legacy;\n                  /* Allow optional arguments following an = */\n                  if (*argument == 0) { continue; }\n                  else if (*argument++ != '=') { badUsage(programName, originalArgument); CLEAN_RETURN(1); }\n                  else if (!parseLegacyParameters(argument, &dictSelect)) { badUsage(programName, originalArgument); CLEAN_RETURN(1); }\n                  continue;\n                }\n#endif\n                if (longCommandWArg(&argument, \"--threads\")) { NEXT_UINT32(nbWorkers); setThreads_non1 = (nbWorkers != 1); continue; }\n                if (longCommandWArg(&argument, \"--memlimit\")) { NEXT_UINT32(memLimit); continue; }\n                if (longCommandWArg(&argument, \"--memory\")) { NEXT_UINT32(memLimit); continue; }\n                if (longCommandWArg(&argument, \"--memlimit-decompress\")) { NEXT_UINT32(memLimit); continue; }\n                if (longCommandWArg(&argument, \"--block-size\")) { NEXT_TSIZE(chunkSize); continue; } /* hidden command, prefer --split below */\n                if (longCommandWArg(&argument, \"--split\")) { NEXT_TSIZE(chunkSize); continue; }\n                if (longCommandWArg(&argument, \"--jobsize\")) { NEXT_TSIZE(chunkSize); continue; } /* note: overloaded variable */\n                if (longCommandWArg(&argument, \"--maxdict\")) { NEXT_UINT32(maxDictSize); continue; }\n                if (longCommandWArg(&argument, \"--dictID\")) { NEXT_UINT32(dictID); continue; }\n                if (longCommandWArg(&argument, \"--zstd=\")) { if (!parseCompressionParameters(argument, &compressionParams)) { badUsage(programName, originalArgument); CLEAN_RETURN(1); } ; cType = FIO_zstdCompression; continue; }\n                if (longCommandWArg(&argument, \"--stream-size\")) { NEXT_TSIZE(streamSrcSize); continue; }\n                if (longCommandWArg(&argument, \"--target-compressed-block-size\")) { NEXT_TSIZE(targetCBlockSize); continue; }\n                if (longCommandWArg(&argument, \"--size-hint\")) { NEXT_TSIZE(srcSizeHint); continue; }\n                if (longCommandWArg(&argument, \"--output-dir-flat\")) {\n                    NEXT_FIELD(outDirName);\n                    if (strlen(outDirName) == 0) {\n                        DISPLAYLEVEL(1, \"error: output dir cannot be empty string (did you mean to pass '.' instead?)\\n\");\n                        CLEAN_RETURN(1);\n                    }\n                    continue;\n                }\n                if (longCommandWArg(&argument, \"--auto-threads\")) {\n                    const char* threadDefault = NULL;\n                    NEXT_FIELD(threadDefault);\n                    if (strcmp(threadDefault, \"logical\") == 0)\n                        defaultLogicalCores = 1;\n                    continue;\n                }\n#ifdef UTIL_HAS_MIRRORFILELIST\n                if (longCommandWArg(&argument, \"--output-dir-mirror\")) {\n                    NEXT_FIELD(outMirroredDirName);\n                    if (strlen(outMirroredDirName) == 0) {\n                        DISPLAYLEVEL(1, \"error: output dir cannot be empty string (did you mean to pass '.' instead?)\\n\");\n                        CLEAN_RETURN(1);\n                    }\n                    continue;\n                }\n#endif\n#ifndef ZSTD_NOTRACE\n                if (longCommandWArg(&argument, \"--trace\")) { char const* traceFile; NEXT_FIELD(traceFile); TRACE_enable(traceFile); continue; }\n#endif\n                if (longCommandWArg(&argument, \"--patch-from\")) { NEXT_FIELD(patchFromDictFileName); ultra = 1; continue; }\n                if (longCommandWArg(&argument, \"--patch-apply\")) { operation=zom_decompress; NEXT_FIELD(patchFromDictFileName); memLimit= 1U << ZSTD_WINDOWLOG_MAX; continue; }\n                if (longCommandWArg(&argument, \"--long\")) {\n                    unsigned ldmWindowLog = 0;\n                    ldmFlag = 1;\n                    ultra = 1;\n                    /* Parse optional window log */\n                    if (*argument == '=') {\n                        ++argument;\n                        ldmWindowLog = readU32FromChar(&argument);\n                    } else if (*argument != 0) {\n                        /* Invalid character following --long */\n                        badUsage(programName, originalArgument);\n                        CLEAN_RETURN(1);\n                    } else {\n                        ldmWindowLog = g_defaultMaxWindowLog;\n                    }\n                    /* Only set windowLog if not already set by --zstd */\n                    if (compressionParams.windowLog == 0)\n                        compressionParams.windowLog = ldmWindowLog;\n                    continue;\n                }\n#ifndef ZSTD_NOCOMPRESS   /* linking ZSTD_minCLevel() requires compression support */\n                if (longCommandWArg(&argument, \"--fast\")) {\n                    /* Parse optional acceleration factor */\n                    if (*argument == '=') {\n                        U32 const maxFast = (U32)-ZSTD_minCLevel();\n                        U32 fastLevel;\n                        ++argument;\n                        fastLevel = readU32FromChar(&argument);\n                        if (fastLevel > maxFast) fastLevel = maxFast;\n                        if (fastLevel) {\n                            dictCLevel = cLevel = -(int)fastLevel;\n                        } else {\n                            badUsage(programName, originalArgument);\n                            CLEAN_RETURN(1);\n                        }\n                    } else if (*argument != 0) {\n                        /* Invalid character following --fast */\n                        badUsage(programName, originalArgument);\n                        CLEAN_RETURN(1);\n                    } else {\n                        cLevel = -1;  /* default for --fast */\n                    }\n                    continue;\n                }\n#endif\n\n                if (longCommandWArg(&argument, \"--filelist\")) {\n                    const char* listName;\n                    NEXT_FIELD(listName);\n                    UTIL_refFilename(file_of_names, listName);\n                    continue;\n                }\n\n                badUsage(programName, originalArgument);\n                CLEAN_RETURN(1);\n            }\n\n            argument++;\n            while (argument[0]!=0) {\n\n#ifndef ZSTD_NOCOMPRESS\n                /* compression Level */\n                if ((*argument>='0') && (*argument<='9')) {\n                    dictCLevel = cLevel = (int)readU32FromChar(&argument);\n                    continue;\n                }\n#endif\n\n                switch(argument[0])\n                {\n                    /* Display help */\n                case 'V': printVersion(); CLEAN_RETURN(0);   /* Version Only */\n                case 'H': usageAdvanced(programName); CLEAN_RETURN(0);\n                case 'h': usage(stdout, programName); CLEAN_RETURN(0);\n\n                     /* Compress */\n                case 'z': operation=zom_compress; argument++; break;\n\n                     /* Decoding */\n                case 'd':\n#ifndef ZSTD_NOBENCH\n                        benchParams.mode = BMK_decodeOnly;\n                        if (operation==zom_bench) { argument++; break; }  /* benchmark decode (hidden option) */\n#endif\n                        operation=zom_decompress; argument++; break;\n\n                    /* Force stdout, even if stdout==console */\n                case 'c': forceStdout=1; outFileName=stdoutmark; argument++; break;\n\n                    /* destination file name */\n                case 'o': argument++; NEXT_FIELD(outFileName); break;\n\n                    /* do not store filename - gzip compatibility - nothing to do */\n                case 'n': argument++; break;\n\n                    /* Use file content as dictionary */\n                case 'D': argument++; NEXT_FIELD(dictFileName); break;\n\n                    /* Overwrite */\n                case 'f': FIO_overwriteMode(prefs); forceStdin=1; forceStdout=1; followLinks=1; allowBlockDevices=1; argument++; break;\n\n                    /* Verbose mode */\n                case 'v': g_displayLevel++; argument++; break;\n\n                    /* Quiet mode */\n                case 'q': g_displayLevel--; argument++; break;\n\n                    /* keep source file (default) */\n                case 'k': removeSrcFile=0; argument++; break;\n\n                    /* Checksum */\n                case 'C': FIO_setChecksumFlag(prefs, 2); argument++; break;\n\n                    /* test compressed file */\n                case 't': operation=zom_test; argument++; break;\n\n                    /* limit memory */\n                case 'M':\n                    argument++;\n                    memLimit = readU32FromChar(&argument);\n                    break;\n                case 'l': operation=zom_list; argument++; break;\n#ifdef UTIL_HAS_CREATEFILELIST\n                    /* recursive */\n                case 'r': recursive=1; argument++; break;\n#endif\n\n#ifndef ZSTD_NOBENCH\n                    /* Benchmark */\n                case 'b':\n                    operation=zom_bench;\n                    argument++;\n                    break;\n\n                    /* range bench (benchmark only) */\n                case 'e':\n                    /* compression Level */\n                    argument++;\n                    cLevelLast = (int)readU32FromChar(&argument);\n                    break;\n\n                    /* Modify Nb Iterations (benchmark only) */\n                case 'i':\n                    argument++;\n                    bench_nbSeconds = readU32FromChar(&argument);\n                    break;\n\n                    /* hidden shortcut for --split=# and --jobsize=# */\n                case 'B':\n                    argument++;\n                    chunkSize = readU32FromChar(&argument);\n                    break;\n\n                    /* benchmark files separately (hidden option) */\n                case 'S':\n                    argument++;\n                    separateFiles = 1;\n                    break;\n\n#endif   /* ZSTD_NOBENCH */\n\n                    /* nb of threads (hidden option) */\n                case 'T':\n                    argument++;\n                    nbWorkers = readU32FromChar(&argument);\n                    setThreads_non1 = (nbWorkers != 1);\n                    break;\n\n                    /* Dictionary Selection level */\n                case 's':\n                    argument++;\n                    dictSelect = readU32FromChar(&argument);\n                    break;\n\n                    /* Pause at the end (-p) or set an additional param (-p#) (hidden option) */\n                case 'p': argument++;\n#ifndef ZSTD_NOBENCH\n                    if ((*argument>='0') && (*argument<='9')) {\n                        benchParams.additionalParam = (int)readU32FromChar(&argument);\n                    } else\n#endif\n                        main_pause=1;\n                    break;\n\n                    /* Select compressibility of synthetic sample */\n                case 'P':\n                    argument++;\n                    compressibility = (double)readU32FromChar(&argument) / 100;\n                    break;\n\n                    /* unknown command */\n                default :\n                    {   char shortArgument[3] = {'-', 0, 0};\n                        shortArgument[1] = argument[0];\n                        badUsage(programName, shortArgument);\n                        CLEAN_RETURN(1);\n                    }\n                }\n            }\n            continue;\n        }   /* if (argument[0]=='-') */\n\n        /* none of the above : add filename to list */\n        UTIL_refFilename(filenames, argument);\n    }\n\n    /* Welcome message (if verbose) */\n    DISPLAYLEVEL(3, WELCOME_MESSAGE);\n\n#ifdef ZSTD_MULTITHREAD\n    if ((operation==zom_decompress) && (setThreads_non1)) {\n        DISPLAYLEVEL(2, \"Warning : decompression does not support multi-threading\\n\");\n    }\n    if ((nbWorkers==NBWORKERS_AUTOCPU) && (!singleThread)) {\n        /* automatically set # workers based on # of reported cpu cores */\n        if (defaultLogicalCores) {\n            nbWorkers = (unsigned)UTIL_countLogicalCores();\n            DISPLAYLEVEL(3, \"Note: %d logical core(s) detected \\n\", nbWorkers);\n        } else {\n            nbWorkers = (unsigned)UTIL_countPhysicalCores();\n            DISPLAYLEVEL(3, \"Note: %d physical core(s) detected \\n\", nbWorkers);\n        }\n    }\n    if (operation == zom_compress)\n        DISPLAYLEVEL(4, \"Compressing with %u worker threads \\n\", nbWorkers);\n#else\n    (void)singleThread; (void)nbWorkers; (void)defaultLogicalCores; (void)setThreads_non1;\n#endif\n\n    g_utilDisplayLevel = g_displayLevel;\n\n#ifdef UTIL_HAS_CREATEFILELIST\n    if (!followLinks) {\n        unsigned u, fileNamesNb;\n        unsigned const nbFilenames = (unsigned)filenames->tableSize;\n        for (u=0, fileNamesNb=0; u<nbFilenames; u++) {\n            if ( UTIL_isLink(filenames->fileNames[u])\n             && !UTIL_isFIFO(filenames->fileNames[u])\n            ) {\n                DISPLAYLEVEL(2, \"Warning : %s is a symbolic link, ignoring \\n\", filenames->fileNames[u]);\n            } else {\n                filenames->fileNames[fileNamesNb++] = filenames->fileNames[u];\n        }   }\n        if (fileNamesNb == 0 && nbFilenames > 0)  /* all names are eliminated */\n            CLEAN_RETURN(1);\n        filenames->tableSize = fileNamesNb;\n    }   /* if (!followLinks) */\n\n    /* read names from a file */\n    if (file_of_names->tableSize) {\n        size_t const nbFileLists = file_of_names->tableSize;\n        size_t flNb;\n        for (flNb=0; flNb < nbFileLists; flNb++) {\n            FileNamesTable* const fnt = UTIL_createFileNamesTable_fromFileList(file_of_names->fileNames[flNb]);\n            if (fnt==NULL) {\n                DISPLAYLEVEL(1, \"zstd: error reading %s \\n\", file_of_names->fileNames[flNb]);\n                CLEAN_RETURN(1);\n            }\n            filenames = UTIL_mergeFileNamesTable(filenames, fnt);\n        }\n    }\n\n    nbInputFileNames = filenames->tableSize; /* saving number of input files */\n\n    if (recursive) {  /* at this stage, filenameTable is a list of paths, which can contain both files and directories */\n        UTIL_expandFNT(&filenames, followLinks);\n    }\n#else\n    (void)followLinks;\n#endif\n\n    if (operation == zom_list) {\n#ifndef ZSTD_NODECOMPRESS\n        int const ret = FIO_listMultipleFiles((unsigned)filenames->tableSize, filenames->fileNames, g_displayLevel);\n        CLEAN_RETURN(ret);\n#else\n        DISPLAYLEVEL(1, \"file information is not supported \\n\");\n        CLEAN_RETURN(1);\n#endif\n    }\n\n    /* Check if benchmark is selected */\n    if (operation==zom_bench) {\n#ifndef ZSTD_NOBENCH\n        int benchThreadsMsgLevel = 2;\n        if (nbWorkers == NBWORKERS_UNSET) nbWorkers = 1;\n        if (nbWorkers <= 1) benchThreadsMsgLevel = 3;\n        if (cType != FIO_zstdCompression) {\n            DISPLAYLEVEL(1, \"benchmark mode is only compatible with zstd format \\n\");\n            CLEAN_RETURN(1);\n        }\n        benchParams.chunkSizeMax = chunkSize;\n        benchParams.targetCBlockSize = targetCBlockSize;\n        benchParams.nbWorkers = (int)nbWorkers;\n        benchParams.realTime = (unsigned)setRealTimePrio;\n        benchParams.nbSeconds = bench_nbSeconds;\n        benchParams.ldmFlag = ldmFlag;\n        benchParams.ldmMinMatch = (int)g_ldmMinMatch;\n        benchParams.ldmHashLog = (int)g_ldmHashLog;\n        benchParams.useRowMatchFinder = (int)useRowMatchFinder;\n        if (g_ldmBucketSizeLog != LDM_PARAM_DEFAULT) {\n            benchParams.ldmBucketSizeLog = (int)g_ldmBucketSizeLog;\n        }\n        if (g_ldmHashRateLog != LDM_PARAM_DEFAULT) {\n            benchParams.ldmHashRateLog = (int)g_ldmHashRateLog;\n        }\n        benchParams.literalCompressionMode = literalCompressionMode;\n\n        if (benchParams.mode == BMK_decodeOnly) cLevel = cLevelLast = 0;\n        if (cLevel > ZSTD_maxCLevel()) cLevel = ZSTD_maxCLevel();\n        if (cLevelLast > ZSTD_maxCLevel()) cLevelLast = ZSTD_maxCLevel();\n        if (cLevelLast < cLevel) cLevelLast = cLevel;\n        DISPLAYLEVEL(benchThreadsMsgLevel, \"Benchmarking \");\n        if (filenames->tableSize > 1)\n            DISPLAYLEVEL(3, \"%u files \", (unsigned)filenames->tableSize);\n        if (cLevelLast > cLevel) {\n            DISPLAYLEVEL(3, \"from level %d to %d \", cLevel, cLevelLast);\n        } else {\n            DISPLAYLEVEL(3, \"at level %d \", cLevel);\n        }\n        DISPLAYLEVEL(benchThreadsMsgLevel, \"using %i threads \\n\", nbWorkers);\n        if (filenames->tableSize > 0) {\n            if(separateFiles) {\n                unsigned i;\n                for(i = 0; i < filenames->tableSize; i++) {\n                    operationResult = BMK_benchFilesAdvanced(&filenames->fileNames[i], 1, dictFileName, cLevel, cLevelLast, &compressionParams, g_displayLevel, &benchParams);\n                }\n            } else {\n                operationResult = BMK_benchFilesAdvanced(filenames->fileNames, (unsigned)filenames->tableSize, dictFileName, cLevel, cLevelLast, &compressionParams, g_displayLevel, &benchParams);\n            }\n        } else {\n            operationResult = BMK_syntheticTest(compressibility, cLevel, cLevelLast, &compressionParams, g_displayLevel, &benchParams);\n        }\n\n#else\n        (void)bench_nbSeconds; (void)chunkSize; (void)setRealTimePrio; (void)separateFiles; (void)compressibility;\n#endif\n        goto _end;\n    }\n\n    /* Check if dictionary builder is selected */\n    if (operation==zom_train) {\n#ifndef ZSTD_NODICT\n        ZDICT_params_t zParams;\n        zParams.compressionLevel = dictCLevel;\n        zParams.notificationLevel = (unsigned)g_displayLevel;\n        zParams.dictID = dictID;\n        if (nbWorkers == NBWORKERS_UNSET) nbWorkers = init_nbWorkers(ZSTDCLI_NBTHREADS_DEFAULT);\n        if (dict == cover) {\n            int const optimize = !coverParams.k || !coverParams.d;\n            coverParams.nbThreads = (unsigned)nbWorkers;\n            coverParams.zParams = zParams;\n            operationResult = DiB_trainFromFiles(outFileName, maxDictSize, filenames->fileNames, (int)filenames->tableSize, chunkSize, NULL, &coverParams, NULL, optimize, memLimit);\n        } else if (dict == fastCover) {\n            int const optimize = !fastCoverParams.k || !fastCoverParams.d;\n            fastCoverParams.nbThreads = (unsigned)nbWorkers;\n            fastCoverParams.zParams = zParams;\n            operationResult = DiB_trainFromFiles(outFileName, maxDictSize, filenames->fileNames, (int)filenames->tableSize, chunkSize, NULL, NULL, &fastCoverParams, optimize, memLimit);\n        } else {\n            ZDICT_legacy_params_t dictParams;\n            memset(&dictParams, 0, sizeof(dictParams));\n            dictParams.selectivityLevel = dictSelect;\n            dictParams.zParams = zParams;\n            operationResult = DiB_trainFromFiles(outFileName, maxDictSize, filenames->fileNames, (int)filenames->tableSize, chunkSize, &dictParams, NULL, NULL, 0, memLimit);\n        }\n#else\n        (void)dictCLevel; (void)dictSelect; (void)dictID;  (void)maxDictSize; /* not used when ZSTD_NODICT set */\n        DISPLAYLEVEL(1, \"training mode not available \\n\");\n        operationResult = 1;\n#endif\n        goto _end;\n    }\n\n#ifndef ZSTD_NODECOMPRESS\n    if (operation==zom_test) { FIO_setTestMode(prefs, 1); outFileName=nulmark; removeSrcFile=0; }  /* test mode */\n#endif\n\n    /* No input filename ==> use stdin and stdout */\n    if (filenames->tableSize == 0) {\n      /* It is possible that the input\n       was a number of empty directories. In this case\n       stdin and stdout should not be used */\n       if (nbInputFileNames > 0 ){\n        DISPLAYLEVEL(1, \"please provide correct input file(s) or non-empty directories -- ignored \\n\");\n        CLEAN_RETURN(0);\n       }\n       UTIL_refFilename(filenames, stdinmark);\n    }\n\n    if (filenames->tableSize == 1 && !strcmp(filenames->fileNames[0], stdinmark) && !outFileName)\n        outFileName = stdoutmark;  /* when input is stdin, default output is stdout */\n\n    /* Check if input/output defined as console; trigger an error in this case */\n    if (!forceStdin\n     && (UTIL_searchFileNamesTable(filenames, stdinmark) != -1)\n     && UTIL_isConsole(stdin) ) {\n        DISPLAYLEVEL(1, \"stdin is a console, aborting\\n\");\n        CLEAN_RETURN(1);\n    }\n    if ( (!outFileName || !strcmp(outFileName, stdoutmark))\n      && UTIL_isConsole(stdout)\n      && (UTIL_searchFileNamesTable(filenames, stdinmark) != -1)\n      && !forceStdout\n      && operation!=zom_decompress ) {\n        DISPLAYLEVEL(1, \"stdout is a console, aborting\\n\");\n        CLEAN_RETURN(1);\n    }\n\n#ifndef ZSTD_NOCOMPRESS\n    /* check compression level limits */\n    {   int const maxCLevel = ultra ? ZSTD_maxCLevel() : ZSTDCLI_CLEVEL_MAX;\n        if (cLevel > maxCLevel) {\n            DISPLAYLEVEL(2, \"Warning : compression level higher than max, reduced to %i. \", maxCLevel);\n            DISPLAYLEVEL(2, \"Specify --ultra to raise the limit to 22 and use \"\n                            \"--long=31 for maximum compression. Note that this \"\n                            \"requires high amounts of memory, and the resulting data \"\n                            \"might be rejected by third-party decoders and is \"\n                            \"therefore only recommended for archival purposes. \\n\");            \n            cLevel = maxCLevel;\n    }   }\n#endif\n\n    if (showDefaultCParams) {\n        if (operation == zom_decompress) {\n            DISPLAYLEVEL(1, \"error : can't use --show-default-cparams in decompression mode \\n\");\n            CLEAN_RETURN(1);\n        }\n    }\n\n    if (dictFileName != NULL && patchFromDictFileName != NULL) {\n        DISPLAYLEVEL(1, \"error : can't use -D and --patch-from=# at the same time \\n\");\n        CLEAN_RETURN(1);\n    }\n\n    if (patchFromDictFileName != NULL && filenames->tableSize > 1) {\n        DISPLAYLEVEL(1, \"error : can't use --patch-from=# on multiple files \\n\");\n        CLEAN_RETURN(1);\n    }\n\n    /* No status message by default when output is stdout */\n    hasStdout = outFileName && !strcmp(outFileName,stdoutmark);\n    if (hasStdout && (g_displayLevel==2)) g_displayLevel=1;\n\n    /* when stderr is not the console, do not pollute it with progress updates (unless requested) */\n    if (!UTIL_isConsole(stderr) && (progress!=FIO_ps_always)) progress=FIO_ps_never;\n    FIO_setProgressSetting(progress);\n\n    /* don't remove source files when output is stdout */;\n    if (hasStdout && removeSrcFile) {\n        DISPLAYLEVEL(3, \"Note: src files are not removed when output is stdout \\n\");\n        removeSrcFile = 0;\n    }\n    FIO_setRemoveSrcFile(prefs, removeSrcFile);\n\n    /* IO Stream/File */\n    FIO_setHasStdoutOutput(fCtx, hasStdout);\n    FIO_setNbFilesTotal(fCtx, (int)filenames->tableSize);\n    FIO_determineHasStdinInput(fCtx, filenames);\n    FIO_setNotificationLevel(g_displayLevel);\n    FIO_setAllowBlockDevices(prefs, allowBlockDevices);\n    FIO_setPatchFromMode(prefs, patchFromDictFileName != NULL);\n    FIO_setMMapDict(prefs, mmapDict);\n    if (memLimit == 0) {\n        if (compressionParams.windowLog == 0) {\n            memLimit = (U32)1 << g_defaultMaxWindowLog;\n        } else {\n            memLimit = (U32)1 << (compressionParams.windowLog & 31);\n    }   }\n    if (patchFromDictFileName != NULL)\n        dictFileName = patchFromDictFileName;\n    FIO_setMemLimit(prefs, memLimit);\n    if (operation==zom_compress) {\n#ifndef ZSTD_NOCOMPRESS\n        FIO_setCompressionType(prefs, cType);\n        FIO_setContentSize(prefs, contentSize);\n        if (nbWorkers == NBWORKERS_UNSET) nbWorkers = init_nbWorkers(ZSTDCLI_NBTHREADS_DEFAULT);\n        FIO_setNbWorkers(prefs, (int)nbWorkers);\n        FIO_setJobSize(prefs, (int)chunkSize);\n        if (g_overlapLog!=OVERLAP_LOG_DEFAULT) FIO_setOverlapLog(prefs, (int)g_overlapLog);\n        FIO_setLdmFlag(prefs, (unsigned)ldmFlag);\n        FIO_setLdmHashLog(prefs, (int)g_ldmHashLog);\n        FIO_setLdmMinMatch(prefs, (int)g_ldmMinMatch);\n        if (g_ldmBucketSizeLog != LDM_PARAM_DEFAULT) FIO_setLdmBucketSizeLog(prefs, (int)g_ldmBucketSizeLog);\n        if (g_ldmHashRateLog != LDM_PARAM_DEFAULT) FIO_setLdmHashRateLog(prefs, (int)g_ldmHashRateLog);\n        FIO_setAdaptiveMode(prefs, adapt);\n        FIO_setUseRowMatchFinder(prefs, (int)useRowMatchFinder);\n        FIO_setAdaptMin(prefs, adaptMin);\n        FIO_setAdaptMax(prefs, adaptMax);\n        FIO_setRsyncable(prefs, rsyncable);\n        FIO_setStreamSrcSize(prefs, streamSrcSize);\n        FIO_setTargetCBlockSize(prefs, targetCBlockSize);\n        FIO_setSrcSizeHint(prefs, srcSizeHint);\n        FIO_setLiteralCompressionMode(prefs, literalCompressionMode);\n        FIO_setSparseWrite(prefs, 0);\n        if (adaptMin > cLevel) cLevel = adaptMin;\n        if (adaptMax < cLevel) cLevel = adaptMax;\n\n        /* Compare strategies constant with the ground truth */\n        { ZSTD_bounds strategyBounds = ZSTD_cParam_getBounds(ZSTD_c_strategy);\n          assert(ZSTD_NB_STRATEGIES == strategyBounds.upperBound);\n          (void)strategyBounds; }\n\n        if (showDefaultCParams || g_displayLevel >= 4) {\n            size_t fileNb;\n            for (fileNb = 0; fileNb < (size_t)filenames->tableSize; fileNb++) {\n                if (showDefaultCParams)\n                    printDefaultCParams(filenames->fileNames[fileNb], dictFileName, cLevel);\n                if (g_displayLevel >= 4)\n                    printActualCParams(filenames->fileNames[fileNb], dictFileName, cLevel, &compressionParams);\n            }\n        }\n\n        if (g_displayLevel >= 4)\n            FIO_displayCompressionParameters(prefs);\n        if ((filenames->tableSize==1) && outFileName)\n            operationResult = FIO_compressFilename(fCtx, prefs, outFileName, filenames->fileNames[0], dictFileName, cLevel, compressionParams);\n        else\n            operationResult = FIO_compressMultipleFilenames(fCtx, prefs, filenames->fileNames, outMirroredDirName, outDirName, outFileName, suffix, dictFileName, cLevel, compressionParams);\n#else\n        /* these variables are only used when compression mode is enabled */\n        (void)contentSize; (void)suffix; (void)adapt; (void)rsyncable;\n        (void)ultra; (void)cLevel; (void)ldmFlag; (void)literalCompressionMode;\n        (void)targetCBlockSize; (void)streamSrcSize; (void)srcSizeHint;\n        (void)ZSTD_strategyMap; (void)useRowMatchFinder; (void)cType;\n        DISPLAYLEVEL(1, \"Compression not supported \\n\");\n#endif\n    } else {  /* decompression or test */\n#ifndef ZSTD_NODECOMPRESS\n        if (filenames->tableSize == 1 && outFileName) {\n            operationResult = FIO_decompressFilename(fCtx, prefs, outFileName, filenames->fileNames[0], dictFileName);\n        } else {\n            operationResult = FIO_decompressMultipleFilenames(fCtx, prefs, filenames->fileNames, outMirroredDirName, outDirName, outFileName, dictFileName);\n        }\n#else\n        DISPLAYLEVEL(1, \"Decompression not supported \\n\");\n#endif\n    }\n\n_end:\n    FIO_freePreferences(prefs);\n    FIO_freeContext(fCtx);\n    if (main_pause) waitEnter();\n    UTIL_freeFileNamesTable(filenames);\n    UTIL_freeFileNamesTable(file_of_names);\n#ifndef ZSTD_NOTRACE\n    TRACE_finish();\n#endif\n\n    return operationResult;\n}\n"
  },
  {
    "path": "programs/zstdcli_trace.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"zstdcli_trace.h\"\n\n#include <stdio.h>\n#include <stdlib.h>\n\n#include \"timefn.h\"\n#include \"util.h\"\n\n#define ZSTD_STATIC_LINKING_ONLY\n#include \"../lib/zstd.h\"\n/* We depend on the trace header to avoid duplicating the ZSTD_trace struct.\n * But, we check the version so it is compatible with dynamic linking.\n */\n#include \"../lib/common/zstd_trace.h\"\n/* We only use macros from threading.h so it is compatible with dynamic linking */\n#include \"../lib/common/threading.h\"\n\n#if ZSTD_TRACE\n\nstatic FILE* g_traceFile = NULL;\nstatic int g_mutexInit = 0;\nstatic ZSTD_pthread_mutex_t g_mutex;\nstatic UTIL_time_t g_enableTime = UTIL_TIME_INITIALIZER;\n\nvoid TRACE_enable(char const* filename)\n{\n    int const writeHeader = !UTIL_isRegularFile(filename);\n    if (g_traceFile)\n        fclose(g_traceFile);\n    g_traceFile = fopen(filename, \"a\");\n    if (g_traceFile && writeHeader) {\n        /* Fields:\n        * algorithm\n        * version\n        * method\n        * streaming\n        * level\n        * workers\n        * dictionary size\n        * uncompressed size\n        * compressed size\n        * duration nanos\n        * compression ratio\n        * speed MB/s\n        */\n        fprintf(g_traceFile, \"Algorithm, Version, Method, Mode, Level, Workers, Dictionary Size, Uncompressed Size, Compressed Size, Duration Nanos, Compression Ratio, Speed MB/s\\n\");\n    }\n    g_enableTime = UTIL_getTime();\n    if (!g_mutexInit) {\n        if (!ZSTD_pthread_mutex_init(&g_mutex, NULL)) {\n            g_mutexInit = 1;\n        } else {\n            TRACE_finish();\n        }\n    }\n}\n\nvoid TRACE_finish(void)\n{\n    if (g_traceFile) {\n        fclose(g_traceFile);\n    }\n    g_traceFile = NULL;\n    if (g_mutexInit) {\n        ZSTD_pthread_mutex_destroy(&g_mutex);\n        g_mutexInit = 0;\n    }\n}\n\nstatic void TRACE_log(char const* method, PTime duration, ZSTD_Trace const* trace)\n{\n    int level = 0;\n    int workers = 0;\n    double const durationAsDouble = duration ? (double)duration : .1;\n    double const ratio = (double)trace->uncompressedSize / (double)trace->compressedSize;\n    double const speed = ((double)trace->uncompressedSize * 1000) / durationAsDouble;\n    if (trace->params) {\n        ZSTD_CCtxParams_getParameter(trace->params, ZSTD_c_compressionLevel, &level);\n        ZSTD_CCtxParams_getParameter(trace->params, ZSTD_c_nbWorkers, &workers);\n    }\n    assert(g_traceFile != NULL);\n\n    ZSTD_pthread_mutex_lock(&g_mutex);\n    /* Fields:\n     * algorithm\n     * version\n     * method\n     * streaming\n     * level\n     * workers\n     * dictionary size\n     * uncompressed size\n     * compressed size\n     * duration nanos\n     * compression ratio\n     * speed MB/s\n     */\n    fprintf(g_traceFile,\n        \"zstd, %u, %s, %s, %d, %d, %llu, %llu, %llu, %llu, %.2f, %.2f\\n\",\n        trace->version,\n        method,\n        trace->streaming ? \"streaming\" : \"single-pass\",\n        level,\n        workers,\n        (unsigned long long)trace->dictionarySize,\n        (unsigned long long)trace->uncompressedSize,\n        (unsigned long long)trace->compressedSize,\n        (unsigned long long)duration,\n        ratio,\n        speed);\n    ZSTD_pthread_mutex_unlock(&g_mutex);\n}\n\n/**\n * These symbols override the weak symbols provided by the library.\n */\n\nZSTD_TraceCtx ZSTD_trace_compress_begin(ZSTD_CCtx const* cctx)\n{\n    (void)cctx;\n    if (g_traceFile == NULL)\n        return 0;\n    return (ZSTD_TraceCtx)UTIL_clockSpanNano(g_enableTime);\n}\n\nvoid ZSTD_trace_compress_end(ZSTD_TraceCtx ctx, ZSTD_Trace const* trace)\n{\n    PTime const beginNanos = (PTime)ctx;\n    PTime const endNanos = UTIL_clockSpanNano(g_enableTime);\n    PTime const durationNanos = endNanos > beginNanos ? endNanos - beginNanos : 0;\n    assert(g_traceFile != NULL);\n    assert(trace->version == ZSTD_VERSION_NUMBER); /* CLI version must match. */\n    TRACE_log(\"compress\", durationNanos, trace);\n}\n\nZSTD_TraceCtx ZSTD_trace_decompress_begin(ZSTD_DCtx const* dctx)\n{\n    (void)dctx;\n    if (g_traceFile == NULL)\n        return 0;\n    return (ZSTD_TraceCtx)UTIL_clockSpanNano(g_enableTime);\n}\n\nvoid ZSTD_trace_decompress_end(ZSTD_TraceCtx ctx, ZSTD_Trace const* trace)\n{\n    PTime const beginNanos = (PTime)ctx;\n    PTime const endNanos = UTIL_clockSpanNano(g_enableTime);\n    PTime const durationNanos = endNanos > beginNanos ? endNanos - beginNanos : 0;\n    assert(g_traceFile != NULL);\n    assert(trace->version == ZSTD_VERSION_NUMBER); /* CLI version must match. */\n    TRACE_log(\"decompress\", durationNanos, trace);\n}\n\n#else /* ZSTD_TRACE */\n\nvoid TRACE_enable(char const* filename)\n{\n    (void)filename;\n}\n\nvoid TRACE_finish(void) {}\n\n#endif /* ZSTD_TRACE */\n"
  },
  {
    "path": "programs/zstdcli_trace.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTDCLI_TRACE_H\n#define ZSTDCLI_TRACE_H\n\n/**\n * Enable tracing - log to filename.\n */\nvoid TRACE_enable(char const* filename);\n\n/**\n * Shut down the tracing library.\n */\nvoid TRACE_finish(void);\n\n#endif /* ZSTDCLI_TRACE_H */\n"
  },
  {
    "path": "programs/zstdgrep",
    "content": "#!/bin/sh\n#\n# Copyright (c) 2003 Thomas Klausner.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n# 1. Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n# 2. Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#\n# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\ngrep=${GREP:-grep}\nzcat=${ZCAT:-zstdcat}\n\nendofopts=0\npattern_found=0\ngrep_args=\"\"\nhyphen=0\nsilent=0\n\nprog=${0##*/}\n\n# handle being called 'zegrep' or 'zfgrep'\ncase $prog in\n    *egrep*) prog=zegrep; grep_args='-E';;\n    *fgrep*) prog=zfgrep; grep_args='-F';;\n    *)       prog=zstdgrep;;\nesac\n\n# skip all options and pass them on to grep taking care of options\n# with arguments, and if -e was supplied\n\nwhile [ \"$#\" -gt 0 ] && [ \"${endofopts}\" -eq 0 ]; do\n    case \"$1\" in\n    # from GNU grep-2.5.1 -- keep in sync!\n        -[ABCDXdefm])\n            if [ \"$#\" -lt 2 ]; then\n                printf '%s: missing argument for %s flag\\n' \"${prog}\" \"$1\" >&2\n                exit 1\n            fi\n            case \"$1\" in\n                -e)\n                    pattern=\"$2\"\n                    pattern_found=1\n                    shift 2\n                    break\n                    ;;\n                -f)\n                    pattern_found=2\n                    ;;\n                *)\n                    ;;\n            esac\n            grep_args=\"${grep_args} $1 $2\"\n            shift 2\n            ;;\n        --)\n            shift\n            endofopts=1\n            ;;\n        -)\n            hyphen=1\n            shift\n            ;;\n        -h)\n            silent=1\n            shift\n            ;;\n        -*)\n            grep_args=\"${grep_args} $1\"\n            shift\n            ;;\n        *)\n            # pattern to grep for\n            endofopts=1\n            ;;\n    esac\ndone\n\n# if no -e option was found, take next argument as grep-pattern\nif [ \"${pattern_found}\" -lt 1 ]; then\n    if [ \"$#\" -ge 1 ]; then\n        pattern=\"$1\"\n        shift\n    elif [ \"${hyphen}\" -gt 0 ]; then\n        pattern=\"-\"\n    else\n        printf '%s: missing pattern\\n' \"${prog}\" >&2\n        exit 1\n    fi\nfi\n\nEXIT_CODE=0\n# call grep ...\nif [ \"$#\" -lt 1 ]; then\n    # ... on stdin\n    set -f # Disable file name generation (globbing).\n    # shellcheck disable=SC2086\n    \"${zcat}\" - | \"${grep}\" ${grep_args} -- \"${pattern}\" -\n    EXIT_CODE=$?\n    set +f\nelse\n    # ... on all files given on the command line\n    if [ \"${silent}\" -lt 1 ] && [ \"$#\" -gt 1 ]; then\n        grep_args=\"-H ${grep_args}\"\n    fi\n    set -f\n    while [ \"$#\" -gt 0 ]; do\n        # shellcheck disable=SC2086\n        if [ $pattern_found -eq 2 ]; then\n            \"${zcat}\" -- \"$1\" | \"${grep}\" --label=\"${1}\" ${grep_args} -- -\n        else\n            \"${zcat}\" -- \"$1\" | \"${grep}\" --label=\"${1}\" ${grep_args} -- \"${pattern}\" -\n        fi\n        [ \"$?\" -ne 0 ] && EXIT_CODE=1\n        shift\n    done\n    set +f\nfi\n\nexit \"${EXIT_CODE}\"\n"
  },
  {
    "path": "programs/zstdgrep.1",
    "content": ".\n.TH \"ZSTDGREP\" \"1\" \"February 2025\" \"zstd 1.5.7\" \"User Commands\"\n.\n.SH \"NAME\"\n\\fBzstdgrep\\fR \\- print lines matching a pattern in zstandard\\-compressed files\n.\n.SH \"SYNOPSIS\"\n\\fBzstdgrep\\fR [\\fIgrep\\-flags\\fR] [\\-\\-] \\fIpattern\\fR [\\fIfiles\\fR \\.\\.\\.]\n.\n.SH \"DESCRIPTION\"\n\\fBzstdgrep\\fR runs \\fBgrep\\fR(1) on files, or \\fBstdin\\fR if no files argument is given, after decompressing them with \\fBzstdcat\\fR(1)\\.\n.\n.P\nThe \\fIgrep\\-flags\\fR and \\fIpattern\\fR arguments are passed on to \\fBgrep\\fR(1)\\. If an \\fB\\-e\\fR flag is found in the \\fIgrep\\-flags\\fR, \\fBzstdgrep\\fR will not look for a \\fIpattern\\fR argument\\.\n.\n.P\nNote that modern \\fBgrep\\fR alternatives such as \\fBripgrep\\fR (\\fBrg\\fR(1)) support \\fBzstd\\fR\\-compressed files out of the box, and can prove better alternatives than \\fBzstdgrep\\fR notably for unsupported complex pattern searches\\. Note though that such alternatives may also feature some minor command line differences\\.\n.\n.SH \"EXIT STATUS\"\nIn case of missing arguments or missing pattern, 1 will be returned, otherwise 0\\.\n.\n.SH \"SEE ALSO\"\n\\fBzstd\\fR(1)\n.\n.SH \"AUTHORS\"\nThomas Klausner \\fIwiz@NetBSD\\.org\\fR\n"
  },
  {
    "path": "programs/zstdgrep.1.md",
    "content": "zstdgrep(1) -- print lines matching a pattern in zstandard-compressed files\n============================================================================\n\nSYNOPSIS\n--------\n\n`zstdgrep` [<grep-flags>] [--] <pattern> [<files> ...]\n\n\nDESCRIPTION\n-----------\n`zstdgrep` runs `grep`(1) on files, or `stdin` if no files argument is given, after decompressing them with `zstdcat`(1).\n\nThe <grep-flags> and <pattern> arguments are passed on to `grep`(1).  If an `-e` flag is found in the <grep-flags>, `zstdgrep` will not look for a <pattern> argument.\n\nNote that modern `grep` alternatives such as `ripgrep` (`rg`(1)) support `zstd`-compressed files out of the box,\nand can prove better alternatives than `zstdgrep` notably for unsupported complex pattern searches.\nNote though that such alternatives may also feature some minor command line differences.\n\nEXIT STATUS\n-----------\nIn case of missing arguments or missing pattern, 1 will be returned, otherwise 0.\n\nSEE ALSO\n--------\n`zstd`(1)\n\nAUTHORS\n-------\nThomas Klausner <wiz@NetBSD.org>\n"
  },
  {
    "path": "programs/zstdless",
    "content": "#!/bin/sh\n\nzstd=${ZSTD:-zstd}\n\n# TODO: Address quirks and bugs tied to old versions of less, provide a mechanism to pass flags directly to zstd\n\nexport LESSOPEN=\"|-${zstd} -cdfq %s\"\nexec less \"$@\"\n"
  },
  {
    "path": "programs/zstdless.1",
    "content": ".\n.TH \"ZSTDLESS\" \"1\" \"February 2025\" \"zstd 1.5.7\" \"User Commands\"\n.\n.SH \"NAME\"\n\\fBzstdless\\fR \\- view zstandard\\-compressed files\n.\n.SH \"SYNOPSIS\"\n\\fBzstdless\\fR [\\fIflags\\fR] [\\fIfile\\fR \\.\\.\\.]\n.\n.SH \"DESCRIPTION\"\n\\fBzstdless\\fR runs \\fBless\\fR(1) on files or stdin, if no \\fIfile\\fR argument is given, after decompressing them with \\fBzstdcat\\fR(1)\\.\n.\n.SH \"SEE ALSO\"\n\\fBzstd\\fR(1)\n"
  },
  {
    "path": "programs/zstdless.1.md",
    "content": "zstdless(1) -- view zstandard-compressed files\n============================================================================\n\nSYNOPSIS\n--------\n\n`zstdless` [<flags>] [<file> ...]\n\n\nDESCRIPTION\n-----------\n`zstdless` runs `less`(1) on files or stdin, if no <file> argument is given, after decompressing them with `zstdcat`(1).\n\nSEE ALSO\n--------\n`zstd`(1)\n"
  },
  {
    "path": "tests/.gitignore",
    "content": "# local binary (Makefile)\nfullbench\nfullbench32\nfullbench-lib\nfuzzer\nfuzzer32\nfuzzer-dll\nlargeDictionary\nzbufftest\nzbufftest32\nzbufftest-dll\nzstreamtest\nzstreamtest32\nzstreamtest_asan\nzstreamtest_tsan\nzstreamtest_ubsan\nzstreamtest-dll\ndatagen\nparamgrill\nparamgrill32\nroundTripCrash\nlongmatch\nsymbols\nlegacy\ndecodecorpus\npool\npoolTests\ninvalidDictionaries\ncheckTag\nzcat\nzstdcat\ntm\n\n# test artifacts\ndictionary\ngrillResults.txt\n_*\ntmp*\n*.zst\n*.gz\n!gzip/hufts-segv.gz\nresult\nout\n*.zstd\nhello*\nworld\n\n# Tmp test directory\nzstdtest\nspeedTest\nversionsTest\nnamespaceTest\ndirTest*\n\n# fuzzer\nafl\n\n# Local script\nstartSpeedTest\nspeedTest.pid\n*.bat\n\n# Generic Object files\n*.o\n*.ko\n\n# Generic Executables\n*.exe\n*.out\n*.app\n\n# Specific exclusions\n!golden-decompression/*.zst\n"
  },
  {
    "path": "tests/DEPRECATED-test-zstd-speed.py",
    "content": "#! /usr/bin/env python3\n# THIS BENCHMARK IS BEING REPLACED BY automated-bencmarking.py\n\n# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ##########################################################################\n\n# Limitations:\n# - doesn't support filenames with spaces\n# - dir1/zstd and dir2/zstd will be merged in a single results file\n\nimport argparse\nimport os           # getloadavg\nimport string\nimport subprocess\nimport time         # strftime\nimport traceback\nimport hashlib\nimport platform     # system\n\nscript_version = 'v1.1.2 (2017-03-26)'\ndefault_repo_url = 'https://github.com/facebook/zstd.git'\nworking_dir_name = 'speedTest'\nworking_path = os.getcwd() + '/' + working_dir_name     # /path/to/zstd/tests/speedTest\nclone_path = working_path + '/' + 'zstd'                # /path/to/zstd/tests/speedTest/zstd\nemail_header = 'ZSTD_speedTest'\npid = str(os.getpid())\nverbose = False\nclang_version = \"unknown\"\ngcc_version = \"unknown\"\nargs = None\n\n\ndef hashfile(hasher, fname, blocksize=65536):\n    with open(fname, \"rb\") as f:\n        for chunk in iter(lambda: f.read(blocksize), b\"\"):\n            hasher.update(chunk)\n    return hasher.hexdigest()\n\n\ndef log(text):\n    print(time.strftime(\"%Y/%m/%d %H:%M:%S\") + ' - ' + text)\n\n\ndef execute(command, print_command=True, print_output=False, print_error=True, param_shell=True):\n    if print_command:\n        log(\"> \" + command)\n    popen = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=param_shell, cwd=execute.cwd)\n    stdout_lines, stderr_lines = popen.communicate(timeout=args.timeout)\n    stderr_lines = stderr_lines.decode(\"utf-8\")\n    stdout_lines = stdout_lines.decode(\"utf-8\")\n    if print_output:\n        if stdout_lines:\n            print(stdout_lines)\n        if stderr_lines:\n            print(stderr_lines)\n    if popen.returncode is not None and popen.returncode != 0:\n        if stderr_lines and not print_output and print_error:\n            print(stderr_lines)\n        raise RuntimeError(stdout_lines + stderr_lines)\n    return (stdout_lines + stderr_lines).splitlines()\nexecute.cwd = None\n\n\ndef does_command_exist(command):\n    try:\n        execute(command, verbose, False, False)\n    except Exception:\n        return False\n    return True\n\n\ndef send_email(emails, topic, text, have_mutt, have_mail):\n    logFileName = working_path + '/' + 'tmpEmailContent'\n    with open(logFileName, \"w\") as myfile:\n        myfile.writelines(text)\n        myfile.close()\n        if have_mutt:\n            execute('mutt -s \"' + topic + '\" ' + emails + ' < ' + logFileName, verbose)\n        elif have_mail:\n            execute('mail -s \"' + topic + '\" ' + emails + ' < ' + logFileName, verbose)\n        else:\n            log(\"e-mail cannot be sent (mail or mutt not found)\")\n\n\ndef send_email_with_attachments(branch, commit, last_commit, args, text, results_files,\n                                logFileName, have_mutt, have_mail):\n    with open(logFileName, \"w\") as myfile:\n        myfile.writelines(text)\n        myfile.close()\n        email_topic = '[%s:%s] Warning for %s:%s last_commit=%s speed<%s ratio<%s' \\\n                      % (email_header, pid, branch, commit, last_commit,\n                         args.lowerLimit, args.ratioLimit)\n        if have_mutt:\n            execute('mutt -s \"' + email_topic + '\" ' + args.emails + ' -a ' + results_files\n                    + ' < ' + logFileName)\n        elif have_mail:\n            execute('mail -s \"' + email_topic + '\" ' + args.emails + ' < ' + logFileName)\n        else:\n            log(\"e-mail cannot be sent (mail or mutt not found)\")\n\n\ndef git_get_branches():\n    execute('git fetch -p', verbose)\n    branches = execute('git branch -rl', verbose)\n    output = []\n    for line in branches:\n        if (\"HEAD\" not in line) and (\"coverity_scan\" not in line) and (\"gh-pages\" not in line):\n            output.append(line.strip())\n    return output\n\n\ndef git_get_changes(branch, commit, last_commit):\n    fmt = '--format=\"%h: (%an) %s, %ar\"'\n    if last_commit is None:\n        commits = execute('git log -n 10 %s %s' % (fmt, commit))\n    else:\n        commits = execute('git --no-pager log %s %s..%s' % (fmt, last_commit, commit))\n    return str('Changes in %s since %s:\\n' % (branch, last_commit)) + '\\n'.join(commits)\n\n\ndef get_last_results(resultsFileName):\n    if not os.path.isfile(resultsFileName):\n        return None, None, None, None\n    commit = None\n    csize = []\n    cspeed = []\n    dspeed = []\n    with open(resultsFileName, 'r') as f:\n        for line in f:\n            words = line.split()\n            if len(words) <= 4:   # branch + commit + compilerVer + md5\n                commit = words[1]\n                csize = []\n                cspeed = []\n                dspeed = []\n            if (len(words) == 8) or (len(words) == 9):  # results: \"filename\" or \"XX files\"\n                csize.append(int(words[1]))\n                cspeed.append(float(words[3]))\n                dspeed.append(float(words[5]))\n    return commit, csize, cspeed, dspeed\n\n\ndef benchmark_and_compare(branch, commit, last_commit, args, executableName, md5sum, compilerVersion, resultsFileName,\n                          testFilePath, fileName, last_csize, last_cspeed, last_dspeed):\n    sleepTime = 30\n    while os.getloadavg()[0] > args.maxLoadAvg:\n        log(\"WARNING: bench loadavg=%.2f is higher than %s, sleeping for %s seconds\"\n            % (os.getloadavg()[0], args.maxLoadAvg, sleepTime))\n        time.sleep(sleepTime)\n    start_load = str(os.getloadavg())\n    osType = platform.system()\n    if osType == 'Linux':\n        cpuSelector = \"taskset --cpu-list 0\"\n    else:\n        cpuSelector = \"\"\n    if args.dictionary:\n        result = execute('%s programs/%s -rqi5b1e%s -D %s %s' % (cpuSelector, executableName, args.lastCLevel, args.dictionary, testFilePath), print_output=True)\n    else:\n        result = execute('%s programs/%s -rqi5b1e%s %s' % (cpuSelector, executableName, args.lastCLevel, testFilePath), print_output=True)\n    end_load = str(os.getloadavg())\n    linesExpected = args.lastCLevel + 1\n    if len(result) != linesExpected:\n        raise RuntimeError(\"ERROR: number of result lines=%d is different that expected %d\\n%s\" % (len(result), linesExpected, '\\n'.join(result)))\n    with open(resultsFileName, \"a\") as myfile:\n        myfile.write('%s %s %s md5=%s\\n' % (branch, commit, compilerVersion, md5sum))\n        myfile.write('\\n'.join(result) + '\\n')\n        myfile.close()\n        if (last_cspeed == None):\n            log(\"WARNING: No data for comparison for branch=%s file=%s \" % (branch, fileName))\n            return \"\"\n        commit, csize, cspeed, dspeed = get_last_results(resultsFileName)\n        text = \"\"\n        for i in range(0, min(len(cspeed), len(last_cspeed))):\n            print(\"%s:%s -%d cSpeed=%6.2f cLast=%6.2f cDiff=%1.4f dSpeed=%6.2f dLast=%6.2f dDiff=%1.4f ratioDiff=%1.4f %s\" % (branch, commit, i+1, cspeed[i], last_cspeed[i], cspeed[i]/last_cspeed[i], dspeed[i], last_dspeed[i], dspeed[i]/last_dspeed[i], float(last_csize[i])/csize[i], fileName))\n            if (cspeed[i]/last_cspeed[i] < args.lowerLimit):\n                text += \"WARNING: %s -%d cSpeed=%.2f cLast=%.2f cDiff=%.4f %s\\n\" % (executableName, i+1, cspeed[i], last_cspeed[i], cspeed[i]/last_cspeed[i], fileName)\n            if (dspeed[i]/last_dspeed[i] < args.lowerLimit):\n                text += \"WARNING: %s -%d dSpeed=%.2f dLast=%.2f dDiff=%.4f %s\\n\" % (executableName, i+1, dspeed[i], last_dspeed[i], dspeed[i]/last_dspeed[i], fileName)\n            if (float(last_csize[i])/csize[i] < args.ratioLimit):\n                text += \"WARNING: %s -%d cSize=%d last_cSize=%d diff=%.4f %s\\n\" % (executableName, i+1, csize[i], last_csize[i], float(last_csize[i])/csize[i], fileName)\n        if text:\n            text = args.message + (\"\\nmaxLoadAvg=%s  load average at start=%s end=%s\\n%s  last_commit=%s  md5=%s\\n\" % (args.maxLoadAvg, start_load, end_load, compilerVersion, last_commit, md5sum)) + text\n        return text\n\n\ndef update_config_file(branch, commit):\n    last_commit = None\n    commitFileName = working_path + \"/commit_\" + branch.replace(\"/\", \"_\") + \".txt\"\n    if os.path.isfile(commitFileName):\n        with open(commitFileName, 'r') as infile:\n            last_commit = infile.read()\n    with open(commitFileName, 'w') as outfile:\n        outfile.write(commit)\n    return last_commit\n\n\ndef double_check(branch, commit, args, executableName, md5sum, compilerVersion, resultsFileName, filePath, fileName):\n    last_commit, csize, cspeed, dspeed = get_last_results(resultsFileName)\n    if not args.dry_run:\n        text = benchmark_and_compare(branch, commit, last_commit, args, executableName, md5sum, compilerVersion, resultsFileName, filePath, fileName, csize, cspeed, dspeed)\n        if text:\n            log(\"WARNING: redoing tests for branch %s: commit %s\" % (branch, commit))\n            text = benchmark_and_compare(branch, commit, last_commit, args, executableName, md5sum, compilerVersion, resultsFileName, filePath, fileName, csize, cspeed, dspeed)\n    return text\n\n\ndef test_commit(branch, commit, last_commit, args, testFilePaths, have_mutt, have_mail):\n    local_branch = branch.split('/')[1]\n    version = local_branch.rpartition('-')[2] + '_' + commit\n    if not args.dry_run:\n        execute('make -C programs clean zstd CC=clang MOREFLAGS=\"-Werror -Wconversion -Wno-sign-conversion -DZSTD_GIT_COMMIT=%s\" && ' % version +\n                'mv programs/zstd programs/zstd_clang && ' +\n                'make -C programs clean zstd zstd32 MOREFLAGS=\"-DZSTD_GIT_COMMIT=%s\"' % version)\n    md5_zstd = hashfile(hashlib.md5(), clone_path + '/programs/zstd')\n    md5_zstd32 = hashfile(hashlib.md5(), clone_path + '/programs/zstd32')\n    md5_zstd_clang = hashfile(hashlib.md5(), clone_path + '/programs/zstd_clang')\n    print(\"md5(zstd)=%s\\nmd5(zstd32)=%s\\nmd5(zstd_clang)=%s\" % (md5_zstd, md5_zstd32, md5_zstd_clang))\n    print(\"gcc_version=%s clang_version=%s\" % (gcc_version, clang_version))\n\n    logFileName = working_path + \"/log_\" + branch.replace(\"/\", \"_\") + \".txt\"\n    text_to_send = []\n    results_files = \"\"\n    if args.dictionary:\n        dictName = args.dictionary.rpartition('/')[2]\n    else:\n        dictName = None\n\n    for filePath in testFilePaths:\n        fileName = filePath.rpartition('/')[2]\n        if dictName:\n            resultsFileName = working_path + \"/\" + dictName.replace(\".\", \"_\") + \"_\" + branch.replace(\"/\", \"_\") + \"_\" + fileName.replace(\".\", \"_\") + \".txt\"\n        else:\n            resultsFileName = working_path + \"/results_\" + branch.replace(\"/\", \"_\") + \"_\" + fileName.replace(\".\", \"_\") + \".txt\"\n        text = double_check(branch, commit, args, 'zstd', md5_zstd, 'gcc_version='+gcc_version, resultsFileName, filePath, fileName)\n        if text:\n            text_to_send.append(text)\n            results_files += resultsFileName + \" \"\n        resultsFileName = working_path + \"/results32_\" + branch.replace(\"/\", \"_\") + \"_\" + fileName.replace(\".\", \"_\") + \".txt\"\n        text = double_check(branch, commit, args, 'zstd32', md5_zstd32, 'gcc_version='+gcc_version, resultsFileName, filePath, fileName)\n        if text:\n            text_to_send.append(text)\n            results_files += resultsFileName + \" \"\n        resultsFileName = working_path + \"/resultsClang_\" + branch.replace(\"/\", \"_\") + \"_\" + fileName.replace(\".\", \"_\") + \".txt\"\n        text = double_check(branch, commit, args, 'zstd_clang', md5_zstd_clang, 'clang_version='+clang_version, resultsFileName, filePath, fileName)\n        if text:\n            text_to_send.append(text)\n            results_files += resultsFileName + \" \"\n    if text_to_send:\n        send_email_with_attachments(branch, commit, last_commit, args, text_to_send, results_files, logFileName, have_mutt, have_mail)\n\n\nif __name__ == '__main__':\n    parser = argparse.ArgumentParser()\n    parser.add_argument('testFileNames', help='file or directory names list for speed benchmark')\n    parser.add_argument('emails', help='list of e-mail addresses to send warnings')\n    parser.add_argument('--dictionary', '-D', help='path to the dictionary')\n    parser.add_argument('--message', '-m', help='attach an additional message to e-mail', default=\"\")\n    parser.add_argument('--repoURL', help='changes default repository URL', default=default_repo_url)\n    parser.add_argument('--lowerLimit', '-l', type=float, help='send email if speed is lower than given limit', default=0.98)\n    parser.add_argument('--ratioLimit', '-r', type=float, help='send email if ratio is lower than given limit', default=0.999)\n    parser.add_argument('--maxLoadAvg', type=float, help='maximum load average to start testing', default=0.75)\n    parser.add_argument('--lastCLevel', type=int, help='last compression level for testing', default=5)\n    parser.add_argument('--sleepTime', '-s', type=int, help='frequency of repository checking in seconds', default=300)\n    parser.add_argument('--timeout', '-t', type=int, help='timeout for executing shell commands', default=1800)\n    parser.add_argument('--dry-run', dest='dry_run', action='store_true', help='not build', default=False)\n    parser.add_argument('--verbose', '-v', action='store_true', help='more verbose logs', default=False)\n    args = parser.parse_args()\n    verbose = args.verbose\n\n    # check if test files are accessible\n    testFileNames = args.testFileNames.split()\n    testFilePaths = []\n    for fileName in testFileNames:\n        fileName = os.path.expanduser(fileName)\n        if os.path.isfile(fileName) or os.path.isdir(fileName):\n            testFilePaths.append(os.path.abspath(fileName))\n        else:\n            log(\"ERROR: File/directory not found: \" + fileName)\n            exit(1)\n\n    # check if dictionary is accessible\n    if args.dictionary:\n        args.dictionary = os.path.abspath(os.path.expanduser(args.dictionary))\n        if not os.path.isfile(args.dictionary):\n            log(\"ERROR: Dictionary not found: \" + args.dictionary)\n            exit(1)\n\n    # check availability of e-mail senders\n    have_mutt = does_command_exist(\"mutt -h\")\n    have_mail = does_command_exist(\"mail -V\")\n    if not have_mutt and not have_mail:\n        log(\"ERROR: e-mail senders 'mail' or 'mutt' not found\")\n        exit(1)\n\n    clang_version = execute(\"clang -v 2>&1 | grep ' version ' | sed -e 's:.*version \\\\([0-9.]*\\\\).*:\\\\1:' -e 's:\\\\.\\\\([0-9][0-9]\\\\):\\\\1:g'\", verbose)[0];\n    gcc_version = execute(\"gcc -dumpversion\", verbose)[0];\n\n    if verbose:\n        print(\"PARAMETERS:\\nrepoURL=%s\" % args.repoURL)\n        print(\"working_path=%s\" % working_path)\n        print(\"clone_path=%s\" % clone_path)\n        print(\"testFilePath(%s)=%s\" % (len(testFilePaths), testFilePaths))\n        print(\"message=%s\" % args.message)\n        print(\"emails=%s\" % args.emails)\n        print(\"dictionary=%s\" % args.dictionary)\n        print(\"maxLoadAvg=%s\" % args.maxLoadAvg)\n        print(\"lowerLimit=%s\" % args.lowerLimit)\n        print(\"ratioLimit=%s\" % args.ratioLimit)\n        print(\"lastCLevel=%s\" % args.lastCLevel)\n        print(\"sleepTime=%s\" % args.sleepTime)\n        print(\"timeout=%s\" % args.timeout)\n        print(\"dry_run=%s\" % args.dry_run)\n        print(\"verbose=%s\" % args.verbose)\n        print(\"have_mutt=%s have_mail=%s\" % (have_mutt, have_mail))\n\n    # clone ZSTD repo if needed\n    if not os.path.isdir(working_path):\n        os.mkdir(working_path)\n    if not os.path.isdir(clone_path):\n        execute.cwd = working_path\n        execute('git clone ' + args.repoURL)\n    if not os.path.isdir(clone_path):\n        log(\"ERROR: ZSTD clone not found: \" + clone_path)\n        exit(1)\n    execute.cwd = clone_path\n\n    # check if speedTest.pid already exists\n    pidfile = \"./speedTest.pid\"\n    if os.path.isfile(pidfile):\n        log(\"ERROR: %s already exists, exiting\" % pidfile)\n        exit(1)\n\n    send_email(args.emails, '[%s:%s] test-zstd-speed.py %s has been started' % (email_header, pid, script_version), args.message, have_mutt, have_mail)\n    with open(pidfile, 'w') as the_file:\n        the_file.write(pid)\n\n    branch = \"\"\n    commit = \"\"\n    first_time = True\n    while True:\n        try:\n            if first_time:\n                first_time = False\n            else:\n                time.sleep(args.sleepTime)\n            loadavg = os.getloadavg()[0]\n            if (loadavg <= args.maxLoadAvg):\n                branches = git_get_branches()\n                for branch in branches:\n                    commit = execute('git show -s --format=%h ' + branch, verbose)[0]\n                    last_commit = update_config_file(branch, commit)\n                    if commit == last_commit:\n                        log(\"skipping branch %s: head %s already processed\" % (branch, commit))\n                    else:\n                        log(\"build branch %s: head %s is different from prev %s\" % (branch, commit, last_commit))\n                        execute('git checkout -- . && git checkout ' + branch)\n                        print(git_get_changes(branch, commit, last_commit))\n                        test_commit(branch, commit, last_commit, args, testFilePaths, have_mutt, have_mail)\n            else:\n                log(\"WARNING: main loadavg=%.2f is higher than %s\" % (loadavg, args.maxLoadAvg))\n            if verbose:\n                log(\"sleep for %s seconds\" % args.sleepTime)\n        except Exception as e:\n            stack = traceback.format_exc()\n            email_topic = '[%s:%s] ERROR in %s:%s' % (email_header, pid, branch, commit)\n            send_email(args.emails, email_topic, stack, have_mutt, have_mail)\n            print(stack)\n        except KeyboardInterrupt:\n            os.unlink(pidfile)\n            send_email(args.emails, '[%s:%s] test-zstd-speed.py %s has been stopped' % (email_header, pid, script_version), args.message, have_mutt, have_mail)\n            exit(0)\n"
  },
  {
    "path": "tests/Makefile",
    "content": "\n# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ################################################################\n# datagen : Synthetic and parametrable data generator, for tests\n# fullbench  : Precisely measure speed for each zstd inner functions\n# fullbench32: Same as fullbench, but forced to compile in 32-bits mode\n# fuzzer  : Test tool, to check zstd integrity on target platform\n# fuzzer32: Same as fuzzer, but forced to compile in 32-bits mode\n# paramgrill : parameter tester for zstd\n# test-zstd-speed.py : script for testing zstd speed difference between commits\n# versionsTest : compatibility test between zstd versions stored on Github (v0.1+)\n# zstreamtest : Fuzzer test tool for zstd streaming API\n# zstreamtest32: Same as zstreamtest, but forced to compile in 32-bits mode\n# ##########################################################################\n\nZSTD_LEGACY_SUPPORT ?= 0\nexport ZSTD_LEGACY_SUPPORT\n\nDEBUGLEVEL ?= 2\nexport DEBUGLEVEL  # transmit value to sub-makefiles\n\n.PHONY: default\ndefault: fullbench\n\nLIBZSTD_MK_DIR := ../lib\ninclude $(LIBZSTD_MK_DIR)/libzstd.mk\n\nPRGDIR  = ../programs\nPYTHON ?= python3\nTESTARTEFACT := versionsTest\n\nDEBUGFLAGS += -g -Wno-c++-compat\nCPPFLAGS   += -I$(LIB_SRCDIR) -I$(LIB_SRCDIR)/common -I$(LIB_SRCDIR)/compress -I$(LIB_SRCDIR)/legacy \\\n              -I$(LIB_SRCDIR)/dictBuilder -I$(LIB_SRCDIR)/deprecated -I$(PRGDIR) \\\n              -DZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY=1\n\nZSTDCOMMON_FILES := $(sort $(ZSTD_COMMON_FILES))\nZSTDCOMP_FILES   := $(sort $(ZSTD_COMPRESS_FILES))\nZSTDDECOMP_FILES := $(sort $(ZSTD_DECOMPRESS_FILES))\nZSTDLEGACY_FILES := $(sort $(wildcard $(LIB_SRCDIR)/legacy/*.c))\nZSTD_FILES  := $(ZSTDDECOMP_FILES) $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES) $(ZSTDLEGACY_FILES)\nZDICT_FILES := $(sort $(ZSTD_DICTBUILDER_FILES))\n\nZSTD_F1 := $(sort $(wildcard $(ZSTD_FILES)))\nZSTD_OBJ1 := $(subst $(LIB_SRCDIR)/common/,zstdm_,$(ZSTD_F1))\nZSTD_OBJ2 := $(subst $(LIB_SRCDIR)/compress/,zstdc_,$(ZSTD_OBJ1))\nZSTD_OBJ3 := $(subst $(LIB_SRCDIR)/decompress/,zstdd_,$(ZSTD_OBJ2))\nZSTD_OBJ4 := $(subst $(LIB_SRCDIR)/legacy/,zstdl_,$(ZSTD_OBJ3))\nZSTD_OBJ5 := $(ZSTD_OBJ4:.c=.o)\nZSTD_OBJECTS := $(ZSTD_OBJ5:.S=.o)\n\nZSTDMT_OBJ1 := $(subst $(LIB_SRCDIR)/common/,zstdmt_m_,$(ZSTD_F1))\nZSTDMT_OBJ2 := $(subst $(LIB_SRCDIR)/compress/,zstdmt_c_,$(ZSTDMT_OBJ1))\nZSTDMT_OBJ3 := $(subst $(LIB_SRCDIR)/decompress/,zstdmt_d_,$(ZSTDMT_OBJ2))\nZSTDMT_OBJ4 := $(subst $(LIB_SRCDIR)/legacy/,zstdmt_l_,$(ZSTDMT_OBJ3))\nZSTDMT_OBJ5 := $(ZSTDMT_OBJ4:.c=.o)\nZSTDMT_OBJECTS := $(ZSTDMT_OBJ5:.S=.o)\n\n# Define *.exe as extension for Windows systems\nifneq (,$(filter Windows%,$(OS)))\nEXT =.exe\nMULTITHREAD_CPP = -DZSTD_MULTITHREAD\nMULTITHREAD_LD  =\nelse\nEXT =\nMULTITHREAD_CPP = -DZSTD_MULTITHREAD\nMULTITHREAD_LD  = -pthread\nendif\nMULTITHREAD = $(MULTITHREAD_CPP) $(MULTITHREAD_LD)\n\nVOID = /dev/null\nZSTREAM_TESTTIME ?= -T90s\nFUZZERTEST ?= -T200s\nZSTDRTTEST = --test-large-data\nDECODECORPUS_TESTTIME ?= -T30\n\n.PHONY: all\nall: fullbench fuzzer zstreamtest paramgrill datagen decodecorpus roundTripCrash poolTests\n\n.PHONY: all32\nall32: fullbench32 fuzzer32 zstreamtest32\n\n.PHONY: allnothread\nallnothread: MULTITHREAD_CPP=\nallnothread: MULTITHREAD_LD=\nallnothread: fullbench fuzzer paramgrill datagen decodecorpus\n\n# note : broken : requires symbols unavailable from dynamic library\n.PHONY: dll\ndll: fuzzer-dll zstreamtest-dll\n\n.PHONY: zstd zstd32 zstd-nolegacy  # only external makefile knows how to build or update them\nzstd zstd32 zstd-nolegacy zstd-dll:\n\t$(MAKE) -C $(PRGDIR) $@ MOREFLAGS+=\"$(DEBUGFLAGS)\"\n\n.PHONY: libzstd\nlibzstd :\n\t$(MAKE) -C $(LIB_SRCDIR) libzstd MOREFLAGS+=\"$(DEBUGFLAGS)\"\n\n%-dll : libzstd\n%-dll : LDFLAGS += -L$(LIB_BINDIR) -lzstd\n\n$(LIB_BINDIR)/libzstd.a :\n\t$(MAKE) -C $(LIB_SRCDIR) libzstd.a\n\nzstdm_%.o : $(LIB_SRCDIR)/common/%.c\n\t$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@\n\nzstdc_%.o : $(LIB_SRCDIR)/compress/%.c\n\t$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@\n\nzstdd_%.o : $(LIB_SRCDIR)/decompress/%.c\n\t$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@\n\nzstdd_%.o : $(LIB_SRCDIR)/decompress/%.S\n\t$(CC) -c $(CPPFLAGS) $(ASFLAGS) $< -o $@\n\nzstdl_%.o : $(LIB_SRCDIR)/legacy/%.c\n\t$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@\n\nzstdmt%.o : CPPFLAGS += $(MULTITHREAD_CPP)\n\nzstdmt_m_%.o : $(LIB_SRCDIR)/common/%.c\n\t$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@\n\nzstdmt_c_%.o : $(LIB_SRCDIR)/compress/%.c\n\t$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@\n\nzstdmt_d_%.o : $(LIB_SRCDIR)/decompress/%.c\n\t$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@\n\nzstdmt_d_%.o : $(LIB_SRCDIR)/decompress/%.S\n\t$(CC) -c $(CPPFLAGS) $(ASFLAGS) $< -o $@\n\nzstdmt_l_%.o : $(LIB_SRCDIR)/legacy/%.c\n\t$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@\n\nFULLBENCHS := fullbench fullbench32\nCLEAN += $(FULLBENCHS)\nfullbench32: CPPFLAGS += -m32\n$(FULLBENCHS) : CPPFLAGS += $(MULTITHREAD_CPP) -Wno-deprecated-declarations\n$(FULLBENCHS) : LDFLAGS += $(MULTITHREAD_LD)\n$(FULLBENCHS) : DEBUGFLAGS = -DNDEBUG  # turn off assert() for speed measurements\n$(FULLBENCHS) : DEBUGLEVEL = 0  # turn off assert() for speed measurements\n$(FULLBENCHS) : $(ZSTD_FILES)\n$(FULLBENCHS) : $(PRGDIR)/datagen.c $(PRGDIR)/lorem.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/benchfn.c fullbench.c\n\t$(LINK.c) $^ -o $@$(EXT)\n\nCLEAN += fullbench-lib\nfullbench-lib : CPPFLAGS += -DXXH_NAMESPACE=ZSTD_\nfullbench-lib : $(PRGDIR)/datagen.c $(PRGDIR)/lorem.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/benchfn.c $(LIB_SRCDIR)/libzstd.a fullbench.c\n\t$(LINK.c) $^ -o $@$(EXT)\n\n# note : broken : requires symbols unavailable from dynamic library\nfullbench-dll: $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/benchfn.c $(PRGDIR)/timefn.c fullbench.c\n#\t$(CC) $(FLAGS) $(filter %.c,$^) -o $@$(EXT) -DZSTD_DLL_IMPORT=1 $(LIB_SRCDIR)/dll/libzstd.dll\n\t$(LINK.c) $^ $(LDLIBS) -o $@$(EXT)\n\nCLEAN += fuzzer fuzzer32\nfuzzer : CPPFLAGS += $(MULTITHREAD_CPP) -Wno-deprecated-declarations\nfuzzer : LDFLAGS += $(MULTITHREAD_LD)\nfuzzer : $(ZSTDMT_OBJECTS)\nfuzzer fuzzer32 : $(ZDICT_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/datagen.c fuzzer.c\n\nfuzzer32 : CFLAGS += -m32 $(MULTITHREAD)\nfuzzer32 : $(ZSTD_FILES)\n\t$(LINK.c) $^ -o $@$(EXT)\n\n# note : broken : requires symbols unavailable from dynamic library\nfuzzer-dll : $(LIB_SRCDIR)/common/xxhash.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/datagen.c fuzzer.c\n\t$(CC) $(CPPFLAGS) $(CFLAGS) $(filter %.c,$^) $(LDFLAGS) -o $@$(EXT)\n\nCLEAN += zstreamtest zstreamtest32\nZSTREAM_LOCAL_FILES := $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c seqgen.c zstreamtest.c external_matchfinder.c\nZSTREAM_PROPER_FILES := $(ZDICT_FILES) $(ZSTREAM_LOCAL_FILES)\nZSTREAMFILES := $(ZSTD_FILES) $(ZSTREAM_PROPER_FILES)\nzstreamtest32 : CFLAGS += -m32\nzstreamtest zstreamtest32 : CPPFLAGS += $(MULTITHREAD_CPP)\nzstreamtest zstreamtest32 : LDFLAGS += $(MULTITHREAD_LD)\nzstreamtest : $(ZSTDMT_OBJECTS) $(ZSTREAM_PROPER_FILES)\nzstreamtest32 : $(ZSTREAMFILES)\nzstreamtest zstreamtest32 :\n\t$(LINK.c) $^ -o $@$(EXT)\n\nCLEAN += zstreamtest_asan\nzstreamtest_asan : CFLAGS += -fsanitize=address\nzstreamtest_asan : $(ZSTREAMFILES)\n\t$(LINK.c) $(MULTITHREAD) $^ -o $@$(EXT)\n\nCLEAN += zstreamtest_tsan\nzstreamtest_tsan : CFLAGS += -fsanitize=thread\nzstreamtest_tsan : $(ZSTREAMFILES)\n\t$(LINK.c) $(MULTITHREAD) $^ -o $@$(EXT)\n\nCLEAN += zstreamtest_ubsan\nzstreamtest_ubsan : CFLAGS += -fsanitize=undefined\nzstreamtest_ubsan : $(ZSTREAMFILES)\n\t$(LINK.c) $(MULTITHREAD) $^ -o $@$(EXT)\n\n# note : broken : requires symbols unavailable from dynamic library\nzstreamtest-dll : $(LIB_SRCDIR)/common/xxhash.c  # xxh symbols not exposed from dll\nzstreamtest-dll : $(ZSTREAM_LOCAL_FILES)\n\t$(CC) $(CPPFLAGS) $(CFLAGS) $(filter %.c,$^) $(LDFLAGS) -o $@$(EXT)\n\nCLEAN += paramgrill\nparamgrill : DEBUGFLAGS =   # turn off debug for speed measurements\nparamgrill : LDLIBS += -lm\nparamgrill : $(ZSTD_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/benchfn.c $(PRGDIR)/benchzstd.c $(PRGDIR)/datagen.c $(PRGDIR)/lorem.c paramgrill.c\n\nCLEAN += datagen\ndatagen : $(PRGDIR)/datagen.c $(PRGDIR)/lorem.c loremOut.c datagencli.c\n\t$(LINK.c) $^ -o $@$(EXT)\n\nCLEAN += roundTripCrash\nroundTripCrash: CFLAGS += $(MULTITHREAD)\nroundTripCrash : $(ZSTD_OBJECTS) roundTripCrash.c\n\nCLEAN += longmatch\nlongmatch : $(ZSTD_OBJECTS) longmatch.c\n\nCLEAN += largeDictionary\nlargeDictionary: CFLAGS += $(MULTITHREAD)\nlargeDictionary: $(ZSTDMT_OBJECTS) $(PRGDIR)/datagen.c largeDictionary.c\n\nCLEAN += invalidDictionaries\ninvalidDictionaries : $(ZSTD_OBJECTS) invalidDictionaries.c\n\nCLEAN += legacy\nlegacy : CPPFLAGS += -UZSTD_LEGACY_SUPPORT -DZSTD_LEGACY_SUPPORT=4\nlegacy : $(ZSTD_FILES) legacy.c\n\nCLEAN += decodecorpus\ndecodecorpus : LDLIBS += -lm\ndecodecorpus : $(filter-out zstdc_zstd_compress.o, $(ZSTD_OBJECTS)) $(ZDICT_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c decodecorpus.c\n\nCLEAN += poolTests\npoolTests : $(PRGDIR)/util.c $(PRGDIR)/timefn.c poolTests.c $(LIB_SRCDIR)/common/pool.c $(LIB_SRCDIR)/common/threading.c $(LIB_SRCDIR)/common/zstd_common.c $(LIB_SRCDIR)/common/error_private.c\n\t$(LINK.c) $(MULTITHREAD) $^ -o $@$(EXT)\n\n.PHONY: versionsTest\nversionsTest: clean\n\t$(PYTHON) test-zstd-versions.py\n\n.PHONY: automated_benchmarking\nautomated_benchmarking: clean\n\t$(PYTHON) automated_benchmarking.py\n\n# make checkTag : check that release tag corresponds to release version\nCLEAN += checkTag\ncheckTag.o : $(LIB_SRCDIR)/zstd.h\n\n.PHONY: clean\nclean:\n\t$(MAKE) -C $(LIB_SRCDIR) clean\n\t$(MAKE) -C $(PRGDIR) clean\n\t$(MAKE) -C fuzz clean\n\t$(RM) -R $(TESTARTEFACT)\n\t$(RM) -r tmp*  # some test directories are named tmp*\n\t$(RM) $(CLEAN) core *.o *.tmp result* *.gcda dictionary *.zst \\\n        $(PRGDIR)/zstd$(EXT) $(PRGDIR)/zstd32$(EXT) \\\n        fullbench-dll$(EXT) fuzzer-dll$(EXT) zstreamtest-dll$(EXT)\n\t@echo Cleaning completed\n\n\n#----------------------------------------------------------------------------------\n# valgrind tests validated only for some posix platforms\n#----------------------------------------------------------------------------------\nUNAME := $(shell sh -c 'MSYSTEM=\"MSYS\" uname')\nifneq (,$(filter Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS AIX CYGWIN_NT%,$(UNAME)))\nHOST_OS = POSIX\n\n.PHONY: test-valgrind\ntest-valgrind: VALGRIND = valgrind --leak-check=full --show-leak-kinds=all --error-exitcode=1\ntest-valgrind: zstd datagen fuzzer fullbench\n\t@echo \"\\n ---- valgrind tests : memory analyzer ----\"\n\t$(VALGRIND) ./datagen -g50M > $(VOID)\n\t$(VALGRIND) $(PRGDIR)/zstd ; if [ $$? -eq 0 ] ; then echo \"zstd without argument should have failed\"; false; fi\n\t./datagen -g80 | $(VALGRIND) $(PRGDIR)/zstd - -c > $(VOID)\n\t./datagen -g16KB | $(VALGRIND) $(PRGDIR)/zstd -vf - -c > $(VOID)\n\t./datagen -g2930KB | $(VALGRIND) $(PRGDIR)/zstd -5 -vf - -o tmp\n\t$(VALGRIND) $(PRGDIR)/zstd -vdf tmp -c > $(VOID)\n\t./datagen -g64MB | $(VALGRIND) $(PRGDIR)/zstd -vf - -c > $(VOID)\n\t$(RM) tmp\n\t$(VALGRIND) ./fuzzer -T1mn -t1\n\t$(VALGRIND) ./fullbench -i1\n\nendif\n\nifneq (,$(filter MINGW% MSYS%,$(UNAME)))\n  HOST_OS = MSYS\nendif\n\n\n#-----------------------------------------------------------------------------\n# make tests validated only for below targets\n#-----------------------------------------------------------------------------\nifneq (,$(filter MSYS POSIX,$(HOST_OS)))\n\nDIFF:=diff\nifneq (,$(filter SunOS,$(UNAME)))\n  DIFF:=gdiff\nendif\n\n.PHONY: list\nlist:\n\t@$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ \"^[#.]\") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' | xargs\n\n.PHONY: check\ncheck: ZSTDRTTEST=  # remove long tests\ncheck: test-zstd\n\t@echo \"\\n******************************\"\n\t@echo \"All tests completed successfully\"\n\t@echo \"******************************\"\n\n.PHONY: fuzztest\nfuzztest: test-fuzzer test-zstream test-decodecorpus\n\n.PHONY: test\ntest: test-zstd test-cli-tests test-fullbench test-fuzzer test-zstream test-invalidDictionaries test-legacy test-decodecorpus\nifeq ($(QEMU_SYS),)\ntest: test-pool\nendif\n\t@echo \"\\n******************************\"\n\t@echo \"All tests completed successfully\"\n\t@echo \"******************************\"\n\n.PHONY: test32\ntest32: test-zstd32 test-fullbench32 test-fuzzer32 test-zstream32\n\n.PHONY: test-all\ntest-all: test test32 test-decodecorpus-cli\n\n.PHONY: test-zstd test-zstd32 test-zstd-nolegacy\ntest-zstd: ZSTD = $(PRGDIR)/zstd\ntest-zstd: zstd\n\n.PHONY: test-zstd-dll\ntest-zstd-dll: ZSTD = $(PRGDIR)/zstd\ntest-zstd-dll: zstd-dll\n\ntest-zstd32: ZSTD = $(PRGDIR)/zstd32\ntest-zstd32: zstd32\n\ntest-zstd-nolegacy: ZSTD = $(PRGDIR)/zstd-nolegacy\ntest-zstd-nolegacy: zstd-nolegacy\n\ntest-zstd test-zstd32 test-zstd-nolegacy test-zstd-dll: datagen\n\tfile $(ZSTD)\n\tEXE_PREFIX=\"$(QEMU_SYS)\" ZSTD_BIN=\"$(ZSTD)\" DATAGEN_BIN=./datagen ./playTests.sh $(ZSTDRTTEST)\n\n.PHONY: test-cli-tests\ntest-cli-tests: ZSTD = $(PRGDIR)/zstd\ntest-cli-tests: zstd datagen\n\tfile $(ZSTD)\n\t./cli-tests/run.py --exec-prefix=\"$(QEMU_SYS)\" --zstd=\"$(ZSTD)\" --datagen=./datagen $(CLI_TEST_ARGS)\n\n.PHONY: update-cli-tests\nupdate-cli-tests: CLI_TEST_ARGS = --set-exact-output\nupdate-cli-tests: test-cli-tests\n\n.PHONY: test-fullbench\ntest-fullbench: fullbench datagen\n\t$(QEMU_SYS) ./fullbench -i1\n\t$(QEMU_SYS) ./fullbench -i1 -P0\n\n.PHONY: test-fullbench32\ntest-fullbench32: fullbench32 datagen\n\t$(QEMU_SYS) ./fullbench32 -i1\n\t$(QEMU_SYS) ./fullbench32 -i1 -P0\n\n.PHONY: test-fuzzer\ntest-fuzzer: fuzzer\n\t$(QEMU_SYS) ./fuzzer -v $(FUZZERTEST) $(FUZZER_FLAGS)\n\n# Note : this test presumes `fuzzer` will be built\n.PHONY: test-fuzzer-stackmode\ntest-fuzzer-stackmode: MOREFLAGS += -DZSTD_HEAPMODE=0\ntest-fuzzer-stackmode: test-fuzzer\n\n.PHONY: test-fuzzer32\ntest-fuzzer32: fuzzer32\n\t$(QEMU_SYS) ./fuzzer32 -v $(FUZZERTEST) $(FUZZER_FLAGS)\n\n.PHONY: test-zstream\ntest-zstream: zstreamtest\n\t$(QEMU_SYS) ./zstreamtest -v $(ZSTREAM_TESTTIME) $(FUZZER_FLAGS)\n\t$(QEMU_SYS) ./zstreamtest --newapi -t1 $(ZSTREAM_TESTTIME) $(FUZZER_FLAGS)\n\ntest-zstream32: zstreamtest32\n\t$(QEMU_SYS) ./zstreamtest32 -v $(ZSTREAM_TESTTIME) $(FUZZER_FLAGS)\n\ntest-longmatch: longmatch\n\t$(QEMU_SYS) ./longmatch\n\ntest-largeDictionary: largeDictionary\n\t$(QEMU_SYS) ./largeDictionary\n\ntest-invalidDictionaries: invalidDictionaries\n\t$(QEMU_SYS) ./invalidDictionaries\n\ntest-legacy: legacy\n\t$(QEMU_SYS) ./legacy\n\ntest-decodecorpus: decodecorpus\n\t$(QEMU_SYS) ./decodecorpus -t $(DECODECORPUS_TESTTIME)\n\ntest-decodecorpus-cli: decodecorpus\n\t@echo \"\\n ---- decodecorpus basic cli tests ----\"\n\t@mkdir testdir\n\t./decodecorpus -n5 -otestdir -ptestdir\n\t@cd testdir && \\\n\t$(ZSTD) -d z000000.zst -o tmp0 && \\\n\t$(ZSTD) -d z000001.zst -o tmp1 && \\\n\t$(ZSTD) -d z000002.zst -o tmp2 && \\\n\t$(ZSTD) -d z000003.zst -o tmp3 && \\\n\t$(ZSTD) -d z000004.zst -o tmp4 && \\\n\tdiff z000000 tmp0 && \\\n\tdiff z000001 tmp1 && \\\n\tdiff z000002 tmp2 && \\\n\tdiff z000003 tmp3 && \\\n\tdiff z000004 tmp4 && \\\n\trm ./* && \\\n\tcd ..\n\t@echo \"\\n ---- decodecorpus dictionary cli tests ----\"\n\t./decodecorpus -n5 -otestdir -ptestdir --use-dict=1MB\n\t@cd testdir && \\\n\t$(ZSTD) -d z000000.zst -D dictionary -o tmp0 && \\\n\t$(ZSTD) -d z000001.zst -D dictionary -o tmp1 && \\\n\t$(ZSTD) -d z000002.zst -D dictionary -o tmp2 && \\\n\t$(ZSTD) -d z000003.zst -D dictionary -o tmp3 && \\\n\t$(ZSTD) -d z000004.zst -D dictionary -o tmp4 && \\\n\tdiff z000000 tmp0 && \\\n\tdiff z000001 tmp1 && \\\n\tdiff z000002 tmp2 && \\\n\tdiff z000003 tmp3 && \\\n\tdiff z000004 tmp4 && \\\n\tcd ..\n\t@rm -rf testdir\n\ntest-pool: poolTests\n\t$(QEMU_SYS) ./poolTests\n\ntest-lz4: ZSTD = $(PRGDIR)/zstd\ntest-lz4: ZSTD_LZ4 = ./lz4\ntest-lz4: ZSTD_UNLZ4 = ./unlz4\ntest-lz4: zstd decodecorpus datagen\n\t[ -f lz4 ] || ln -s $(PRGDIR)/zstd lz4\n\t[ -f unlz4 ] || ln -s $(PRGDIR)/zstd unlz4\n\n\t./decodecorpus -ptmp\n\t# lz4 -> zstd\n\tlz4 < tmp | \\\n\t$(ZSTD) -d | \\\n\tcmp - tmp\n\tlz4 < tmp | \\\n\t$(ZSTD_UNLZ4) | \\\n\tcmp - tmp\n\t# zstd -> lz4\n\t$(ZSTD) --format=lz4 < tmp | \\\n\tlz4 -d | \\\n\tcmp - tmp\n\t$(ZSTD_LZ4) < tmp | \\\n\tlz4 -d | \\\n\tcmp - tmp\n\t# zstd -> zstd\n\t$(ZSTD) --format=lz4 < tmp | \\\n\t$(ZSTD) -d | \\\n\tcmp - tmp\n\t# zstd -> zstd\n\t$(ZSTD) < tmp | \\\n\t$(ZSTD) -d | \\\n\tcmp - tmp\n\n\t./datagen -g384KB | $(ZSTD) --format=lz4 | $(ZSTD) -d > /dev/null\n\n\trm tmp lz4 unlz4\n\nendif\n"
  },
  {
    "path": "tests/README.md",
    "content": "Programs and scripts for automated testing of Zstandard\n=======================================================\n\nThis directory contains the following programs and scripts:\n- `datagen` : Synthetic and parametrable data generator, for tests\n- `fullbench`  : Precisely measure speed for each zstd inner functions\n- `fuzzer`  : Test tool, to check zstd integrity on target platform\n- `paramgrill` : parameter tester for zstd\n- `test-zstd-speed.py` : script for testing zstd speed difference between commits\n- `test-zstd-versions.py` : compatibility test between zstd versions stored on Github (v0.1+)\n- `zstreamtest` : Fuzzer test tool for zstd streaming API\n- `legacy` : Test tool to test decoding of legacy zstd frames\n- `decodecorpus` : Tool to generate valid Zstandard frames, for verifying decoder implementations\n\n\n#### `test-zstd-versions.py` - script for testing zstd interoperability between versions\n\nThis script creates `versionsTest` directory to which zstd repository is cloned.\nThen all tagged (released) versions of zstd are compiled.\nIn the following step interoperability between zstd versions is checked.\n\n#### `automated-benchmarking.py` - script for benchmarking zstd prs to dev\n\nThis script benchmarks facebook:dev and changes from pull requests made to zstd and compares\nthem against facebook:dev to detect regressions. This script currently runs on a dedicated\ndesktop machine for every pull request that is made to the zstd repo but can also\nbe run on any machine via the command line interface.\n\nThere are three modes of usage for this script: fastmode will just run a minimal single\nbuild comparison (between facebook:dev and facebook:release), onetime will pull all the current\npull requests from the zstd repo and compare facebook:dev to all of them once, continuous\nwill continuously get pull requests from the zstd repo and run benchmarks against facebook:dev.\n\n```\nExample usage: python automated_benchmarking.py\n```\n\n```\nusage: automated_benchmarking.py [-h] [--directory DIRECTORY]\n                                 [--levels LEVELS] [--iterations ITERATIONS]\n                                 [--emails EMAILS] [--frequency FREQUENCY]\n                                 [--mode MODE] [--dict DICT]\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --directory DIRECTORY\n                        directory with files to benchmark\n  --levels LEVELS       levels to test e.g. ('1,2,3')\n  --iterations ITERATIONS\n                        number of benchmark iterations to run\n  --emails EMAILS       email addresses of people who will be alerted upon\n                        regression. Only for continuous mode\n  --frequency FREQUENCY\n                        specifies the number of seconds to wait before each\n                        successive check for new PRs in continuous mode\n  --mode MODE           'fastmode', 'onetime', 'current', or 'continuous' (see\n                        README.md for details)\n  --dict DICT           filename of dictionary to use (when set, this\n                        dictionary will be used to compress the files provided\n                        inside --directory)\n```\n\n#### `test-zstd-speed.py` - script for testing zstd speed difference between commits\n\nDEPRECATED\n\nThis script creates `speedTest` directory to which zstd repository is cloned.\nThen it compiles all branches of zstd and performs a speed benchmark for a given list of files (the `testFileNames` parameter).\nAfter `sleepTime` (an optional parameter, default 300 seconds) seconds the script checks repository for new commits.\nIf a new commit is found it is compiled and a speed benchmark for this commit is performed.\nThe results of the speed benchmark are compared to the previous results.\nIf compression or decompression speed for one of zstd levels is lower than `lowerLimit` (an optional parameter, default 0.98) the speed benchmark is restarted.\nIf second results are also lower than `lowerLimit` the warning e-mail is sent to recipients from the list (the `emails` parameter).\n\nAdditional remarks:\n- To be sure that speed results are accurate the script should be run on a \"stable\" target system with no other jobs running in parallel\n- Using the script with virtual machines can lead to large variations of speed results\n- The speed benchmark is not performed until computers' load average is lower than `maxLoadAvg` (an optional parameter, default 0.75)\n- The script sends e-mails using `mutt`; if `mutt` is not available it sends e-mails without attachments using `mail`; if both are not available it only prints a warning\n\n\nThe example usage with two test files, one e-mail address, and with an additional message:\n```\n./test-zstd-speed.py \"silesia.tar calgary.tar\" \"email@gmail.com\" --message \"tested on my laptop\" --sleepTime 60\n```\n\nTo run the script in background please use:\n```\nnohup ./test-zstd-speed.py testFileNames emails &\n```\n\nThe full list of parameters:\n```\npositional arguments:\n  testFileNames         file names list for speed benchmark\n  emails                list of e-mail addresses to send warnings\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --message MESSAGE     attach an additional message to e-mail\n  --lowerLimit LOWERLIMIT\n                        send email if speed is lower than given limit\n  --maxLoadAvg MAXLOADAVG\n                        maximum load average to start testing\n  --lastCLevel LASTCLEVEL\n                        last compression level for testing\n  --sleepTime SLEEPTIME\n                        frequency of repository checking in seconds\n```\n\n#### `decodecorpus` - tool to generate Zstandard frames for decoder testing\nCommand line tool to generate test .zst files.\n\nThis tool will generate .zst files with checksums,\nas well as optionally output the corresponding correct uncompressed data for\nextra verification.\n\nExample:\n```\n./decodecorpus -ptestfiles -otestfiles -n10000 -s5\n```\nwill generate 10,000 sample .zst files using a seed of 5 in the `testfiles` directory,\nwith the zstd checksum field set,\nas well as the 10,000 original files for more detailed comparison of decompression results.\n\n```\n./decodecorpus -t -T1mn\n```\nwill choose a random seed, and for 1 minute,\ngenerate random test frames and ensure that the\nzstd library correctly decompresses them in both simple and streaming modes.\n\n#### `paramgrill` - tool for generating compression table parameters and optimizing parameters on file given constraints\n\nFull list of arguments\n```\n -T#          : set level 1 speed objective\n -B#          : cut input into blocks of size # (default : single block)\n -S           : benchmarks a single run (example command: -Sl3w10h12)\n    w# - windowLog\n    h# - hashLog\n    c# - chainLog\n    s# - searchLog\n    l# - minMatch\n    t# - targetLength\n    S# - strategy\n    L# - level\n --zstd=      : Single run, parameter selection syntax same as zstdcli with more parameters\n                    (Added forceAttachDictionary / fadt)\n                    When invoked with --optimize, this represents the sample to exceed.\n --optimize=  : find parameters to maximize compression ratio given parameters\n                    Can use all --zstd= commands to constrain the type of solution found in addition to the following constraints\n    cSpeed=   : Minimum compression speed\n    dSpeed=   : Minimum decompression speed\n    cMem=     : Maximum compression memory\n    lvl=      : Searches for solutions which are strictly better than that compression lvl in ratio and cSpeed,\n    stc=      : When invoked with lvl=, represents percentage slack in ratio/cSpeed allowed for a solution to be considered (Default 100%)\n              : In normal operation, represents percentage slack in choosing viable starting strategy selection in choosing the default parameters\n                    (Lower value will begin with stronger strategies) (Default 90%)\n    speedRatio=   (accepts decimals)\n              : determines value of gains in speed vs gains in ratio\n                    when determining overall winner (default 5 (1% ratio = 5% speed)).\n    tries=    : Maximum number of random restarts on a single strategy before switching (Default 5)\n                    Higher values will make optimizer run longer, more chances to find better solution.\n    memLog    : Limits the log of the size of each memotable (1 per strategy). Will use hash tables when state space is larger than max size.\n                    Setting memLog = 0 turns off memoization\n --display=   : specify which parameters are included in the output\n                    can use all --zstd parameter names and 'cParams' as a shorthand for all parameters used in ZSTD_compressionParameters\n                    (Default: display all params available)\n -P#          : generated sample compressibility (when no file is provided)\n -t#          : Caps runtime of operation in seconds (default: 99999 seconds (about 27 hours))\n -v           : Prints Benchmarking output\n -D           : Next argument dictionary file\n -s           : Benchmark all files separately\n -q           : Quiet, repeat for more quiet\n                  -q Prints parameters + results whenever a new best is found\n                  -qq Only prints parameters whenever a new best is found, prints final parameters + results\n                  -qqq Only print final parameters + results\n                  -qqqq Only prints final parameter set in the form --zstd=\n -v           : Verbose, cancels quiet, repeat for more volume\n                  -v Prints all candidate parameters and results\n\n```\n Any inputs afterwards are treated as files to benchmark.\n"
  },
  {
    "path": "tests/automated_benchmarking.py",
    "content": "# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ##########################################################################\n\nimport argparse\nimport glob\nimport json\nimport os\nimport time\nimport pickle as pk\nimport subprocess\nimport urllib.request\n\n\nGITHUB_API_PR_URL = \"https://api.github.com/repos/facebook/zstd/pulls?state=open\"\nGITHUB_URL_TEMPLATE = \"https://github.com/{}/zstd\"\nRELEASE_BUILD = {\"user\": \"facebook\", \"branch\": \"dev\", \"hash\": None}\n\n# check to see if there are any new PRs every minute\nDEFAULT_MAX_API_CALL_FREQUENCY_SEC = 60\nPREVIOUS_PRS_FILENAME = \"prev_prs.pk\"\n\n# Not sure what the threshold for triggering alarms should be\n# 1% regression sounds like a little too sensitive but the desktop\n# that I'm running it on is pretty stable so I think this is fine\nCSPEED_REGRESSION_TOLERANCE = 0.01\nDSPEED_REGRESSION_TOLERANCE = 0.01\n\n\ndef get_new_open_pr_builds(prev_state=True):\n    prev_prs = None\n    if os.path.exists(PREVIOUS_PRS_FILENAME):\n        with open(PREVIOUS_PRS_FILENAME, \"rb\") as f:\n            prev_prs = pk.load(f)\n    data = json.loads(urllib.request.urlopen(GITHUB_API_PR_URL).read().decode(\"utf-8\"))\n    prs = {\n        d[\"url\"]: {\n            \"user\": d[\"user\"][\"login\"],\n            \"branch\": d[\"head\"][\"ref\"],\n            \"hash\": d[\"head\"][\"sha\"].strip(),\n        }\n        for d in data\n    }\n    with open(PREVIOUS_PRS_FILENAME, \"wb\") as f:\n        pk.dump(prs, f)\n    if not prev_state or prev_prs == None:\n        return list(prs.values())\n    return [pr for url, pr in prs.items() if url not in prev_prs or prev_prs[url] != pr]\n\n\ndef get_latest_hashes():\n    tmp = subprocess.run([\"git\", \"log\", \"-1\"], stdout=subprocess.PIPE).stdout.decode(\n        \"utf-8\"\n    )\n    sha1 = tmp.split(\"\\n\")[0].split(\" \")[1]\n    tmp = subprocess.run(\n        [\"git\", \"show\", \"{}^1\".format(sha1)], stdout=subprocess.PIPE\n    ).stdout.decode(\"utf-8\")\n    sha2 = tmp.split(\"\\n\")[0].split(\" \")[1]\n    tmp = subprocess.run(\n        [\"git\", \"show\", \"{}^2\".format(sha1)], stdout=subprocess.PIPE\n    ).stdout.decode(\"utf-8\")\n    sha3 = \"\" if len(tmp) == 0 else tmp.split(\"\\n\")[0].split(\" \")[1]\n    return [sha1.strip(), sha2.strip(), sha3.strip()]\n\n\ndef get_builds_for_latest_hash():\n    hashes = get_latest_hashes()\n    for b in get_new_open_pr_builds(False):\n        if b[\"hash\"] in hashes:\n            return [b]\n    return []\n\n\ndef clone_and_build(build):\n    if build[\"user\"] != None:\n        github_url = GITHUB_URL_TEMPLATE.format(build[\"user\"])\n        os.system(\n            \"\"\"\n            rm -rf zstd-{user}-{sha} &&\n            git clone {github_url} zstd-{user}-{sha} &&\n            cd zstd-{user}-{sha} &&\n            {checkout_command}\n            make -j &&\n            cd ../\n        \"\"\".format(\n                user=build[\"user\"],\n                github_url=github_url,\n                sha=build[\"hash\"],\n                checkout_command=\"git checkout {} &&\".format(build[\"hash\"])\n                if build[\"hash\"] != None\n                else \"\",\n            )\n        )\n        return \"zstd-{user}-{sha}/zstd\".format(user=build[\"user\"], sha=build[\"hash\"])\n    else:\n        os.system(\"cd ../ && make -j && cd tests\")\n        return \"../zstd\"\n\n\ndef parse_benchmark_output(output):\n    idx = [i for i, d in enumerate(output) if d == \"MB/s\"]\n    return [float(output[idx[0] - 1]), float(output[idx[1] - 1])]\n\n\ndef benchmark_single(executable, level, filename):\n    return parse_benchmark_output((\n        subprocess.run(\n            [executable, \"-qb{}\".format(level), filename], stdout=subprocess.PIPE, stderr=subprocess.STDOUT,\n        )\n        .stdout.decode(\"utf-8\")\n        .split(\" \")\n    ))\n\n\ndef benchmark_n(executable, level, filename, n):\n    speeds_arr = [benchmark_single(executable, level, filename) for _ in range(n)]\n    cspeed, dspeed = max(b[0] for b in speeds_arr), max(b[1] for b in speeds_arr)\n    print(\n        \"Bench (executable={} level={} filename={}, iterations={}):\\n\\t[cspeed: {} MB/s, dspeed: {} MB/s]\".format(\n            os.path.basename(executable),\n            level,\n            os.path.basename(filename),\n            n,\n            cspeed,\n            dspeed,\n        )\n    )\n    return (cspeed, dspeed)\n\n\ndef benchmark(build, filenames, levels, iterations):\n    executable = clone_and_build(build)\n    return [\n        [benchmark_n(executable, l, f, iterations) for f in filenames] for l in levels\n    ]\n\n\ndef benchmark_dictionary_single(executable, filenames_directory, dictionary_filename, level, iterations):\n    cspeeds, dspeeds = [], []\n    for _ in range(iterations):\n        output = subprocess.run([executable, \"-qb{}\".format(level), \"-D\", dictionary_filename, \"-r\", filenames_directory], stdout=subprocess.PIPE).stdout.decode(\"utf-8\").split(\" \")\n        cspeed, dspeed = parse_benchmark_output(output)\n        cspeeds.append(cspeed)\n        dspeeds.append(dspeed)\n    max_cspeed, max_dspeed = max(cspeeds), max(dspeeds)\n    print(\n        \"Bench (executable={} level={} filenames_directory={}, dictionary_filename={}, iterations={}):\\n\\t[cspeed: {} MB/s, dspeed: {} MB/s]\".format(\n            os.path.basename(executable),\n            level,\n            os.path.basename(filenames_directory),\n            os.path.basename(dictionary_filename),\n            iterations,\n            max_cspeed,\n            max_dspeed,\n        )\n    )\n    return (max_cspeed, max_dspeed)\n\n\ndef benchmark_dictionary(build, filenames_directory, dictionary_filename, levels, iterations):\n    executable = clone_and_build(build)\n    return [benchmark_dictionary_single(executable, filenames_directory, dictionary_filename, l, iterations) for l in levels]\n\n\ndef parse_regressions_and_labels(old_cspeed, new_cspeed, old_dspeed, new_dspeed, baseline_build, test_build):\n    cspeed_reg = (old_cspeed - new_cspeed) / old_cspeed\n    dspeed_reg = (old_dspeed - new_dspeed) / old_dspeed\n    baseline_label = \"{}:{} ({})\".format(\n        baseline_build[\"user\"], baseline_build[\"branch\"], baseline_build[\"hash\"]\n    )\n    test_label = \"{}:{} ({})\".format(\n        test_build[\"user\"], test_build[\"branch\"], test_build[\"hash\"]\n    )\n    return cspeed_reg, dspeed_reg, baseline_label, test_label\n\n\ndef get_regressions(baseline_build, test_build, iterations, filenames, levels):\n    old = benchmark(baseline_build, filenames, levels, iterations)\n    new = benchmark(test_build, filenames, levels, iterations)\n    regressions = []\n    for j, level in enumerate(levels):\n        for k, filename in enumerate(filenames):\n            old_cspeed, old_dspeed = old[j][k]\n            new_cspeed, new_dspeed = new[j][k]\n            cspeed_reg, dspeed_reg, baseline_label, test_label = parse_regressions_and_labels(\n                old_cspeed, new_cspeed, old_dspeed, new_dspeed, baseline_build, test_build\n            )\n            if cspeed_reg > CSPEED_REGRESSION_TOLERANCE:\n                regressions.append(\n                    \"[COMPRESSION REGRESSION] (level={} filename={})\\n\\t{} -> {}\\n\\t{} -> {} ({:0.2f}%)\".format(\n                        level,\n                        filename,\n                        baseline_label,\n                        test_label,\n                        old_cspeed,\n                        new_cspeed,\n                        cspeed_reg * 100.0,\n                    )\n                )\n            if dspeed_reg > DSPEED_REGRESSION_TOLERANCE:\n                regressions.append(\n                    \"[DECOMPRESSION REGRESSION] (level={} filename={})\\n\\t{} -> {}\\n\\t{} -> {} ({:0.2f}%)\".format(\n                        level,\n                        filename,\n                        baseline_label,\n                        test_label,\n                        old_dspeed,\n                        new_dspeed,\n                        dspeed_reg * 100.0,\n                    )\n                )\n    return regressions\n\ndef get_regressions_dictionary(baseline_build, test_build, filenames_directory, dictionary_filename, levels, iterations):\n    old = benchmark_dictionary(baseline_build, filenames_directory, dictionary_filename, levels, iterations)\n    new = benchmark_dictionary(test_build, filenames_directory, dictionary_filename, levels, iterations)\n    regressions = []\n    for j, level in enumerate(levels):\n        old_cspeed, old_dspeed = old[j]\n        new_cspeed, new_dspeed = new[j]\n        cspeed_reg, dspeed_reg, baseline_label, test_label = parse_regressions_and_labels(\n            old_cspeed, new_cspeed, old_dspeed, new_dspeed, baseline_build, test_build\n        )\n        if cspeed_reg > CSPEED_REGRESSION_TOLERANCE:\n            regressions.append(\n                \"[COMPRESSION REGRESSION] (level={} filenames_directory={} dictionary_filename={})\\n\\t{} -> {}\\n\\t{} -> {} ({:0.2f}%)\".format(\n                    level,\n                    filenames_directory,\n                    dictionary_filename,\n                    baseline_label,\n                    test_label,\n                    old_cspeed,\n                    new_cspeed,\n                    cspeed_reg * 100.0,\n                )\n            )\n        if dspeed_reg > DSPEED_REGRESSION_TOLERANCE:\n            regressions.append(\n                \"[DECOMPRESSION REGRESSION] (level={} filenames_directory={} dictionary_filename={})\\n\\t{} -> {}\\n\\t{} -> {} ({:0.2f}%)\".format(\n                    level,\n                    filenames_directory,\n                    dictionary_filename,\n                    baseline_label,\n                    test_label,\n                    old_dspeed,\n                    new_dspeed,\n                    dspeed_reg * 100.0,\n                )\n            )\n        return regressions\n\n\ndef main(filenames, levels, iterations, builds=None, emails=None, continuous=False, frequency=DEFAULT_MAX_API_CALL_FREQUENCY_SEC, dictionary_filename=None):\n    if builds == None:\n        builds = get_new_open_pr_builds()\n    while True:\n        for test_build in builds:\n            if dictionary_filename == None:\n                regressions = get_regressions(\n                    RELEASE_BUILD, test_build, iterations, filenames, levels\n                )\n            else:\n                regressions = get_regressions_dictionary(\n                    RELEASE_BUILD, test_build, filenames, dictionary_filename, levels, iterations\n                )\n            body = \"\\n\".join(regressions)\n            if len(regressions) > 0:\n                if emails != None:\n                    os.system(\n                        \"\"\"\n                        echo \"{}\" | mutt -s \"[zstd regression] caused by new pr\" {}\n                    \"\"\".format(\n                            body, emails\n                        )\n                    )\n                    print(\"Emails sent to {}\".format(emails))\n                print(body)\n        if not continuous:\n            break\n        time.sleep(frequency)\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser()\n\n    parser.add_argument(\"--directory\", help=\"directory with files to benchmark\", default=\"golden-compression\")\n    parser.add_argument(\"--levels\", help=\"levels to test e.g. ('1,2,3')\", default=\"1\")\n    parser.add_argument(\"--iterations\", help=\"number of benchmark iterations to run\", default=\"1\")\n    parser.add_argument(\"--emails\", help=\"email addresses of people who will be alerted upon regression. Only for continuous mode\", default=None)\n    parser.add_argument(\"--frequency\", help=\"specifies the number of seconds to wait before each successive check for new PRs in continuous mode\", default=DEFAULT_MAX_API_CALL_FREQUENCY_SEC)\n    parser.add_argument(\"--mode\", help=\"'fastmode', 'onetime', 'current', or 'continuous' (see README.md for details)\", default=\"current\")\n    parser.add_argument(\"--dict\", help=\"filename of dictionary to use (when set, this dictionary will be used to compress the files provided inside --directory)\", default=None)\n\n    args = parser.parse_args()\n    filenames = args.directory\n    levels = [int(l) for l in args.levels.split(\",\")]\n    mode = args.mode\n    iterations = int(args.iterations)\n    emails = args.emails\n    frequency = int(args.frequency)\n    dictionary_filename = args.dict\n\n    if dictionary_filename == None:\n        filenames = glob.glob(\"{}/**\".format(filenames))\n\n    if (len(filenames) == 0):\n        print(\"0 files found\")\n        quit()\n\n    if mode == \"onetime\":\n        main(filenames, levels, iterations, frequency=frequency, dictionary_filename=dictionary_filename)\n    elif mode == \"current\":\n        builds = [{\"user\": None, \"branch\": \"None\", \"hash\": None}]\n        main(filenames, levels, iterations, builds, frequency=frequency, dictionary_filename=dictionary_filename)\n    elif mode == \"fastmode\":\n        builds = [{\"user\": \"facebook\", \"branch\": \"release\", \"hash\": None}]\n        main(filenames, levels, iterations, builds, frequency=frequency, dictionary_filename=dictionary_filename)\n    else:\n        main(filenames, levels, iterations, None, emails, True, frequency=frequency, dictionary_filename=dictionary_filename)\n"
  },
  {
    "path": "tests/checkTag.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* checkTag : validation tool for libzstd\n * command :\n * $ ./checkTag tag\n * checkTag validates tags of following format : v[0-9].[0-9].[0-9]{any}\n * The tag is then compared to zstd version number.\n * They are compatible if first 3 digits are identical.\n * Anything beyond that is free, and doesn't impact validation.\n * Example : tag v1.8.1.2 is compatible with version 1.8.1\n * When tag and version are not compatible, program exits with error code 1.\n * When they are compatible, it exists with a code 0.\n * checkTag is intended to be used in automated testing environment.\n */\n\n#include <stdio.h>   /* printf */\n#include <string.h>  /* strlen, strncmp */\n#include \"zstd.h\"    /* ZSTD_VERSION_STRING */\n\n\n/*  validate() :\n * @return 1 if tag is compatible, 0 if not.\n */\nstatic int validate(const char* const tag)\n{\n    size_t const tagLength = strlen(tag);\n    size_t const verLength = strlen(ZSTD_VERSION_STRING);\n\n    if (tagLength < 2) return 0;\n    if (tag[0] != 'v') return 0;\n    if (tagLength <= verLength) return 0;\n\n    if (strncmp(ZSTD_VERSION_STRING, tag+1, verLength)) return 0;\n\n    return 1;\n}\n\nint main(int argc, const char** argv)\n{\n    const char* const exeName = argv[0];\n    const char* const tag = argv[1];\n    if (argc!=2) {\n        printf(\"incorrect usage : %s tag \\n\", exeName);\n        return 2;\n    }\n\n    printf(\"Version : %s \\n\", ZSTD_VERSION_STRING);\n    printf(\"Tag     : %s \\n\", tag);\n\n    if (validate(tag)) {\n        printf(\"OK : tag is compatible with zstd version \\n\");\n        return 0;\n    }\n\n    printf(\"!! error : tag and versions are not compatible !! \\n\");\n    return 1;\n}\n"
  },
  {
    "path": "tests/check_size.py",
    "content": "#!/usr/bin/env python3\n# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ################################################################\n\nimport os\nimport subprocess\nimport sys\n\nif len(sys.argv) != 3:\n\tprint(f\"Usage: {sys.argv[0]} FILE SIZE_LIMIT\")\n\tsys.exit(1)\n\nfile = sys.argv[1]\nlimit = int(sys.argv[2])\n\nif not os.path.exists(file):\n\tprint(f\"{file} does not exist\")\n\tsys.exit(1)\n\nsize = os.path.getsize(file)\n\nif size > limit:\n\tprint(f\"file {file} is {size} bytes, which is greater than the limit of {limit} bytes\")\n\tsys.exit(1)\n"
  },
  {
    "path": "tests/cli-tests/.gitignore",
    "content": "!bin/\n!datagen\n!zstdcat\n\nscratch/\nbin/symlinks\n"
  },
  {
    "path": "tests/cli-tests/README.md",
    "content": "# CLI tests\n\nThe CLI tests are focused on testing the zstd CLI.\nThey are intended to be simple tests that the CLI and arguments work as advertised.\nThey are not intended to test the library, only the code in `programs/`.\nThe library will get incidental coverage, but if you find yourself trying to trigger a specific condition in the library, this is the wrong tool.\n\n## Test runner usage\n\nThe test runner `run.py` will run tests against the in-tree build of `zstd` and `datagen` by default. Which means that `zstd` and `datagen` must be built.\n\nThe `zstd` binary used can be passed with `--zstd /path/to/zstd`.\nAdditionally, to run `zstd` through a tool like `valgrind` or `qemu`, set the `--exec-prefix 'valgrind -q'` flag.\n\nSimilarly, the `--datagen`, and `--zstdgrep` flags can be set to specify\nthe paths to their respective binaries. However, these tools do not use\nthe `EXEC_PREFIX`.\n\nEach test executes in its own scratch directory under `scratch/test/name`. E.g. `scratch/basic/help.sh/`. Normally these directories are removed after the test executes. However, the `--preserve` flag will preserve these directories after execution, and save the tests exit code, stdout, and stderr in the scratch directory to `exit`, `stderr`, and `stdout` respectively. This can be useful for debugging/editing a test and updating the expected output.\n\n### Running all the tests\n\nBy default the test runner `run.py` will run all the tests, and report the results.\n\nExamples:\n\n```\n./run.py\n./run.py --preserve\n./run.py --zstd ../../build/programs/zstd --datagen ../../build/tests/datagen\n```\n\n### Running specific tests\n\nA set of test names can be passed to the test runner `run.py` to only execute those tests.\nThis can be useful for writing or debugging a test, especially with `--preserve`.\n\nThe test name can either be the path to the test file, or the test name, which is the path relative to the test directory.\n\nExamples:\n\n```\n./run.py basic/help.sh\n./run.py --preserve basic/help.sh basic/version.sh\n./run.py --preserve --verbose basic/help.sh\n```\n\n### Updating exact output\n\nIf a test is failing because a `.stderr.exact` or `.stdout.exact` no longer matches, you can re-run the tests with `--set-exact-output` and the correct output will be written.\n\nExample:\n```\n./run.py --set-exact-output\n./run.py basic/help.sh --set-exact-output\n```\n\n## Writing a test\n\nTest cases are arbitrary executables, and can be written in any language, but are generally shell scripts.\nAfter the script executes, the exit code, stderr, and stdout are compared against the expectations.\n\nEach test is run in a clean directory that the test can use for intermediate files. This directory will be cleaned up at the end of the test, unless `--preserve` is passed to the test runner. Additionally, the `setup` script can prepare the directory before the test runs.\n\n### Calling zstd, utilities, and environment variables\n\nThe `$PATH` for tests is prepended with the `bin/` sub-directory, which contains helper scripts for ease of testing.\nThe `zstd` binary will call the zstd binary specified by `run.py` with the correct `$EXEC_PREFIX`.\nSimilarly, `datagen`, `unzstd`, `zstdgrep`, `zstdcat`, etc, are provided.\n\nHelper utilities like `cmp_size`, `println`, and `die` are provided here too. See their scripts for details.\n\nCommon shell script libraries are provided under `common/`, with helper variables and functions. They can be sourced with `source \"$COMMON/library.sh`.\n\nLastly, environment variables are provided for testing, which can be listed when calling `run.py` with `--verbose`.\nThey are generally used by the helper scripts in `bin/` to coordinate everything.\n\n### Basic test case\n\nWhen executing your `$TEST` executable, by default the exit code is expected to be `0`. However, you can provide an alternate expected exit code in a `$TEST.exit` file.\n\nWhen executing your `$TEST` executable, by default the expected stderr and stdout are empty. However, you can override the default by providing one of three files:\n\n* `$TEST.{stdout,stderr}.exact`\n* `$TEST.{stdout,stderr}.glob`\n* `$TEST.{stdout,stderr}.ignore`\n\nIf you provide a `.exact` file, the output is expected to exactly match, byte-for-byte.\n\nIf you provide a `.glob` file, the output is expected to match the expected file, where each line is interpreted as a glob syntax. Additionally, a line containing only `...` matches all lines until the next expected line matches.\n\nIf you provide a `.ignore` file, the output is ignored.\n\n#### Passing examples\n\nAll these examples pass.\n\nExit 1, and change the expectation to be 1.\n\n```\nexit-1.sh\n---\n#!/bin/sh\nexit 1\n---\n\nexit-1.sh.exit\n---\n1\n---\n```\n\nCheck the stdout output exactly matches.\n\n```\necho.sh\n---\n#!/bin/sh\necho \"hello world\"\n---\n\necho.sh.stdout.exact\n---\nhello world\n---\n```\n\nCheck the stderr output using a glob.\n\n```\nrandom.sh\n---\n#!/bin/sh\nhead -c 10 < /dev/urandom | xxd >&2\n---\n\nrandom.sh.stderr.glob\n---\n00000000: * * * * *                 *\n```\n\nMultiple lines can be matched with ...\n\n```\nrandom-num-lines.sh\n---\n#!/bin/sh\necho hello\nseq 0 $RANDOM\necho world\n---\n\nrandom-num-lines.sh.stdout.glob\n---\nhello\n0\n...\nworld\n---\n```\n\n#### Failing examples\n\nExit code is expected to be 0, but is 1.\n\n```\nexit-1.sh\n---\n#!/bin/sh\nexit 1\n---\n```\n\nStdout is expected to be empty, but isn't.\n\n```\necho.sh\n---\n#!/bin/sh\necho hello world\n```\n\nStderr is expected to be hello but is world.\n\n```\nhello.sh\n---\n#!/bin/sh\necho world >&2\n---\n\nhello.sh.stderr.exact\n---\nhello\n---\n```\n\n### Setup & teardown scripts\n\nFinally, test writing can be eased with setup and teardown scripts.\nEach directory in the test directory is a test-suite consisting of all tests within that directory (but not sub-directories).\nThis test suite can come with 4 scripts to help test writing:\n\n* `setup_once`\n* `teardown_once`\n* `setup`\n* `teardown`\n\nThe `setup_once` and `teardown_once` are run once before and after all the tests in the suite respectively.\nThey operate in the scratch directory for the test suite, which is the parent directory of each scratch directory for each test case.\nThey can do work that is shared between tests to improve test efficiency.\nFor example, the `dictionaries/setup_once` script builds several dictionaries, for use in the `dictionaries` tests.\n\nThe `setup` and `teardown` scripts run before and after each test case respectively, in the test case's scratch directory.\nThese scripts can do work that is shared between test cases to make tests more succinct.\nFor example, the `dictionaries/setup` script copies the dictionaries built by the `dictionaries/setup_once` script into the test's scratch directory, to make them easier to use, and make sure they aren't accidentally modified.\n\n#### Examples\n\n```\nbasic/setup\n---\n#!/bin/sh\n# Create some files for testing with\ndatagen > file\ndatagen > file0\ndatagen > file1\n---\n\nbasic/test.sh\n---\n#!/bin/sh\nzstd file file0 file1\n---\n\ndictionaries/setup_once\n---\n#!/bin/sh\nset -e\n\nmkdir files/ dicts/\nfor i in $(seq 10); do\n\tdatagen -g1000 > files/$i\ndone\n\nzstd --train -r files/ -o dicts/0\n---\n\ndictionaries/setup\n---\n#!/bin/sh\n\n# Runs in the test case's scratch directory.\n# The test suite's scratch directory that\n# `setup_once` operates in is the parent directory.\ncp -r ../files ../dicts .\n---\n```\n"
  },
  {
    "path": "tests/cli-tests/basic/args.sh",
    "content": "#!/bin/sh\n\nprintln \"+ zstd --blah\" >&2\nzstd --blah\nprintln \"+ zstd -xz\" >&2\nzstd -xz\nprintln \"+ zstd --adapt=min=1,maxx=2 file.txt\" >&2\nzstd --adapt=min=1,maxx=2 file.txt\nprintln \"+ zstd --train-cover=k=48,d=8,steps32 file.txt\" >&2\nzstd --train-cover=k=48,d=8,steps32 file.txt\n"
  },
  {
    "path": "tests/cli-tests/basic/args.sh.exit",
    "content": "1\n"
  },
  {
    "path": "tests/cli-tests/basic/args.sh.stderr.glob",
    "content": "+ zstd --blah\nIncorrect parameter: --blah\n...\nUsage: zstd *\n\nOptions:\n...\n+ zstd -xz\nIncorrect parameter: -x\n...\nUsage: zstd *\n\nOptions:\n...\n+ zstd --adapt=min=1,maxx=2 file.txt\nIncorrect parameter: --adapt=min=1,maxx=2\n...\nUsage: zstd *\n\nOptions:\n...\n+ zstd --train-cover=k=48,d=8,steps32 file.txt\nIncorrect parameter: --train-cover=k=48,d=8,steps32\n...\nUsage: zstd *\n\nOptions:\n...\n"
  },
  {
    "path": "tests/cli-tests/basic/help.sh",
    "content": "#!/bin/sh\n\nset -e\n\nprintln \"+ zstd -h\"\nzstd -h\nprintln \"+ zstd -H\"\nzstd -H\nprintln \"+ zstd --help\"\nzstd --help\n"
  },
  {
    "path": "tests/cli-tests/basic/help.sh.stdout.glob",
    "content": "+ zstd -h\nCompress or decompress the INPUT file(s); reads from STDIN if INPUT is `-` or not provided.\n\nUsage: zstd *OPTIONS...* *INPUT... | -* *-o OUTPUT*\n\nOptions:\n  -o OUTPUT                     Write output to a single file, OUTPUT.\n  -c, --stdout                  Write to STDOUT (even if it is a console) and keep the INPUT file(s).\n  -k, --keep                    Preserve INPUT file(s). *Default*\n  --rm                          Remove INPUT file(s) after successful (de)compression to file.\n\n  -#                            Desired compression level, where `#` is a number between 1 and 19;\n                                lower numbers provide faster compression, higher numbers yield\n                                better compression ratios. *Default: 3*\n\n  -d, --decompress              Perform decompression.\n  -D DICT                       Use DICT as the dictionary for compression or decompression.\n\n  -f, --force                   Disable input and output checks. Allows overwriting existing files,\n                                receiving input from the console, printing output to STDOUT, and\n                                operating on links, block devices, etc. Unrecognized formats will be\n                                passed-through through as-is.\n\n  -h                            Display short usage and exit.\n  -H, --help                    Display full help and exit.\n  -V, --version                 Display the program version and exit.\n\n+ zstd -H\n...\nAdvanced options:\n...\n+ zstd --help\n...\nAdvanced options:\n...\n"
  },
  {
    "path": "tests/cli-tests/basic/memlimit.sh",
    "content": "#!/bin/sh\n\necho \"some data\" > file\n\nprintln \"+ zstd --memory=32LB file\"\nzstd --memory=32LB file && die \"Should not allow bogus suffix\"\nprintln \"+ zstd --memory=32LiB file\"\nzstd --memory=32LiB file && die \"Should not allow bogus suffix\"\nprintln \"+ zstd --memory=32A file\"\nzstd --memory=32A file && die \"Should not allow bogus suffix\"\nprintln \"+ zstd --memory=32r82347dn83 file\"\nzstd --memory=32r82347dn83 file && die \"Should not allow bogus suffix\"\nprintln \"+ zstd --memory=32asbdf file\"\nzstd --memory=32asbdf file && die \"Should not allow bogus suffix\"\nprintln \"+ zstd --memory=hello file\"\nzstd --memory=hello file && die \"Should not allow non-numeric parameter\"\nprintln \"+ zstd --memory=1 file\"\nzstd -q --memory=1 file && die \"Should allow numeric parameter without suffix\"\nrm file.zst\nprintln \"+ zstd --memory=1K file\"\nzstd -q --memory=1K file && die \"Should allow numeric parameter with expected suffix\"\nrm file.zst\nprintln \"+ zstd --memory=1KB file\"\nzstd -q --memory=1KB file && die \"Should allow numeric parameter with expected suffix\"\nrm file.zst\nprintln \"+ zstd --memory=1KiB file\"\nzstd -q --memory=1KiB file && die \"Should allow numeric parameter with expected suffix\"\nrm file.zst\nprintln \"+ zstd --memory=1M file\"\nzstd -q --memory=1M file && die \"Should allow numeric parameter with expected suffix\"\nrm file.zst\nprintln \"+ zstd --memory=1MB file\"\nzstd -q --memory=1MB file && die \"Should allow numeric parameter with expected suffix\"\nrm file.zst\nprintln \"+ zstd --memory=1MiB file\"\nzstd -q --memory=1MiB file && die \"Should allow numeric parameter with expected suffix\"\nrm file.zst\nprintln \"+ zstd --memory=1G file\"\nzstd -q --memory=1G file && die \"Should allow numeric parameter with expected suffix\"\nrm file.zst\nprintln \"+ zstd --memory=1GB file\"\nzstd -q --memory=1GB file && die \"Should allow numeric parameter with expected suffix\"\nrm file.zst\nprintln \"+ zstd --memory=1GiB file\"\nzstd -q --memory=1GiB file && die \"Should allow numeric parameter with expected suffix\"\nrm file.zst\nprintln \"+ zstd --memory=3G file\"\nzstd -q --memory=3G file && die \"Should allow numeric parameter with expected suffix\"\nrm file.zst\nprintln \"+ zstd --memory=3GB file\"\nzstd -q --memory=3GB file && die \"Should allow numeric parameter with expected suffix\"\nrm file.zst\nprintln \"+ zstd --memory=3GiB file\"\nzstd -q --memory=3GiB file && die \"Should allow numeric parameter with expected suffix\"\nrm file.zst\nprintln \"+ zstd --memory=4G file\"\nzstd --memory=4G file && die \"Should not allow out-of-bound numeric parameter\"\nprintln \"+ zstd --memory=4GB file\"\nzstd --memory=4GB file && die \"Should not allow out-of-bound numeric parameter\"\nprintln \"+ zstd --memory=4GiB file\"\nzstd --memory=4GiB file && die \"Should not allow out-of-bound numeric parameter\"\n\nrm file\nexit 0\n"
  },
  {
    "path": "tests/cli-tests/basic/memlimit.sh.stderr.exact",
    "content": "error: only numeric values with optional suffixes K, KB, KiB, M, MB, MiB, G, GB, GiB are allowed \nerror: only numeric values with optional suffixes K, KB, KiB, M, MB, MiB, G, GB, GiB are allowed \nerror: only numeric values with optional suffixes K, KB, KiB, M, MB, MiB, G, GB, GiB are allowed \nerror: only numeric values with optional suffixes K, KB, KiB, M, MB, MiB, G, GB, GiB are allowed \nerror: only numeric values with optional suffixes K, KB, KiB, M, MB, MiB, G, GB, GiB are allowed \nerror: only numeric values with optional suffixes K, KB, KiB, M, MB, MiB, G, GB, GiB are allowed \nShould allow numeric parameter without suffix\nShould allow numeric parameter with expected suffix\nShould allow numeric parameter with expected suffix\nShould allow numeric parameter with expected suffix\nShould allow numeric parameter with expected suffix\nShould allow numeric parameter with expected suffix\nShould allow numeric parameter with expected suffix\nShould allow numeric parameter with expected suffix\nShould allow numeric parameter with expected suffix\nShould allow numeric parameter with expected suffix\nShould allow numeric parameter with expected suffix\nShould allow numeric parameter with expected suffix\nShould allow numeric parameter with expected suffix\nerror: numeric value overflows 32-bit unsigned int \nerror: numeric value overflows 32-bit unsigned int \nerror: numeric value overflows 32-bit unsigned int \n"
  },
  {
    "path": "tests/cli-tests/basic/memlimit.sh.stdout.exact",
    "content": "+ zstd --memory=32LB file\n+ zstd --memory=32LiB file\n+ zstd --memory=32A file\n+ zstd --memory=32r82347dn83 file\n+ zstd --memory=32asbdf file\n+ zstd --memory=hello file\n+ zstd --memory=1 file\n+ zstd --memory=1K file\n+ zstd --memory=1KB file\n+ zstd --memory=1KiB file\n+ zstd --memory=1M file\n+ zstd --memory=1MB file\n+ zstd --memory=1MiB file\n+ zstd --memory=1G file\n+ zstd --memory=1GB file\n+ zstd --memory=1GiB file\n+ zstd --memory=3G file\n+ zstd --memory=3GB file\n+ zstd --memory=3GiB file\n+ zstd --memory=4G file\n+ zstd --memory=4GB file\n+ zstd --memory=4GiB file\n"
  },
  {
    "path": "tests/cli-tests/basic/output_dir.sh",
    "content": "#!/bin/sh\n\nprintln \"+ zstd -r * --output-dir-mirror=\\\"\\\"\"\nzstd -r * --output-dir-mirror=\"\" && die \"Should not allow empty output dir!\"\nprintln \"+ zstd -r * --output-dir-flat=\\\"\\\"\"\nzstd -r * --output-dir-flat=\"\" && die \"Should not allow empty output dir!\"\nexit 0\n"
  },
  {
    "path": "tests/cli-tests/basic/output_dir.sh.stderr.exact",
    "content": "error: output dir cannot be empty string (did you mean to pass '.' instead?)\nerror: output dir cannot be empty string (did you mean to pass '.' instead?)\n"
  },
  {
    "path": "tests/cli-tests/basic/output_dir.sh.stdout.exact",
    "content": "+ zstd -r * --output-dir-mirror=\"\"\n+ zstd -r * --output-dir-flat=\"\"\n"
  },
  {
    "path": "tests/cli-tests/basic/version.sh",
    "content": "#!/bin/sh\n\nset -e\n\nzstd -V\nzstd --version\n"
  },
  {
    "path": "tests/cli-tests/basic/version.sh.stdout.glob",
    "content": "*** Zstandard CLI (*-bit) v1.*.*, by Yann Collet ***\n*** Zstandard CLI (*-bit) v1.*.*, by Yann Collet ***\n"
  },
  {
    "path": "tests/cli-tests/bin/cmp_size",
    "content": "#!/bin/sh\n\nset -e\n\nusage()\n{\n\tprintf \"USAGE:\\n\\t$0 [-eq|-ne|-lt|-le|-gt|-ge] FILE1 FILE2\\n\"\n}\n\nhelp()\n{\n\tprintf \"Small utility to compare file sizes without printing them with set -x.\\n\\n\"\n\tusage\n}\n\ncase \"$1\" in\n\t-h) help; exit 0  ;;\n\t--help) help; exit 0 ;;\nesac\n\nif ! test -f $2; then\n\tprintf \"FILE1='%b' is not a file\\n\\n\" \"$2\"\n\tusage\n\texit 1\nfi\n\nif ! test -f $3; then\n\tprintf \"FILE2='%b' is not a file\\n\\n\" \"$3\"\n\tusage\n\texit 1\nfi\n\n\nsize1=$(wc -c < $2)\nsize2=$(wc -c < $3)\n\ncase \"$1\" in\n\t-eq) [ \"$size1\" -eq \"$size2\" ] ;;\n\t-ne) [ \"$size1\" -ne \"$size2\" ] ;;\n\t-lt) [ \"$size1\" -lt \"$size2\" ] ;;\n\t-le) [ \"$size1\" -le \"$size2\" ] ;;\n\t-gt) [ \"$size1\" -gt \"$size2\" ] ;;\n\t-ge) [ \"$size1\" -ge \"$size2\" ] ;;\nesac\n"
  },
  {
    "path": "tests/cli-tests/bin/datagen",
    "content": "#!/bin/sh\n\n\"$DATAGEN_BIN\" $@\n"
  },
  {
    "path": "tests/cli-tests/bin/die",
    "content": "#!/bin/sh\n\nprintln \"${*}\" 1>&2\nexit 1\n"
  },
  {
    "path": "tests/cli-tests/bin/println",
    "content": "#!/bin/sh\nprintf '%b\\n' \"${*}\"\n"
  },
  {
    "path": "tests/cli-tests/bin/zstd",
    "content": "#!/bin/sh\n\nzstdname=$(basename $0)\n\nif [ -z \"$EXEC_PREFIX\" ]; then\n    \"$ZSTD_SYMLINK_DIR/$zstdname\" $@\nelse\n    $EXEC_PREFIX \"$ZSTD_SYMLINK_DIR/$zstdname\" $@\nfi\n"
  },
  {
    "path": "tests/cli-tests/bin/zstdgrep",
    "content": "#!/bin/sh\n\"$ZSTDGREP_BIN\" $@\n"
  },
  {
    "path": "tests/cli-tests/bin/zstdless",
    "content": "#!/bin/sh\n\"$ZSTDLESS_BIN\" $@\n"
  },
  {
    "path": "tests/cli-tests/cltools/setup",
    "content": "#!/bin/sh\n\nset -e\n\necho \"1234\" > file\nzstd file\n"
  },
  {
    "path": "tests/cli-tests/cltools/zstdgrep.sh",
    "content": "#!/bin/sh\n\nset -e\n\nprintln \"+ good path\"\nzstdgrep \"1234\" file file.zst\nprintln \"+ bad path\"\nzstdgrep \"1234\" bad.zst\n"
  },
  {
    "path": "tests/cli-tests/cltools/zstdgrep.sh.exit",
    "content": "1"
  },
  {
    "path": "tests/cli-tests/cltools/zstdgrep.sh.stderr.exact",
    "content": "zstd: can't stat bad.zst : No such file or directory -- ignored \n"
  },
  {
    "path": "tests/cli-tests/cltools/zstdgrep.sh.stdout.glob",
    "content": "+ good path\nfile:1234\nfile.zst:1234\n+ bad path\n"
  },
  {
    "path": "tests/cli-tests/cltools/zstdless.sh",
    "content": "#!/bin/sh\n\nset -e\n\nprintln \"+ good path\"\nzstdless file.zst\nprintln \"+ pass parameters\"\nzstdless -N file.zst # This parameter does not produce line #s when piped, but still serves to test that the flag went to less and not zstd\nprintln \"+ bad path\"\nzstdless bad.zst >&2\n"
  },
  {
    "path": "tests/cli-tests/cltools/zstdless.sh.stderr.exact",
    "content": "zstd: can't stat bad.zst : No such file or directory -- ignored \nbad.zst: No such file or directory\n"
  },
  {
    "path": "tests/cli-tests/cltools/zstdless.sh.stdout.glob",
    "content": "+ good path\n1234\n+ pass parameters\n1234\n+ bad path\n"
  },
  {
    "path": "tests/cli-tests/common/format.sh",
    "content": "#!/bin/sh\n\n. \"$COMMON/platform.sh\"\n\nzstd_supports_format()\n{\n\tzstd -h | grep > $INTOVOID -- \"--format=$1\"\n}\n\nformat_extension()\n{\n\tif [ \"$1\" = \"zstd\" ]; then\n\t\tprintf \"zst\"\n\telif [ \"$1\" = \"gzip\" ]; then\n\t\tprintf \"gz\"\n\telse\n\t\tprintf \"$1\"\n\tfi\n}\n"
  },
  {
    "path": "tests/cli-tests/common/mtime.sh",
    "content": ". \"$COMMON/platform.sh\"\n\nMTIME=\"stat -c %Y\"\ncase \"$UNAME\" in\n    Darwin | FreeBSD | OpenBSD | NetBSD) MTIME=\"stat -f %m\" ;;\nesac\n\nassertSameMTime() {\n    MT1=$($MTIME \"$1\")\n    MT2=$($MTIME \"$2\")\n    echo MTIME $MT1 $MT2\n    [ \"$MT1\" = \"$MT2\" ] || die \"mtime on $1 doesn't match mtime on $2 ($MT1 != $MT2)\"\n}\n"
  },
  {
    "path": "tests/cli-tests/common/permissions.sh",
    "content": ". \"$COMMON/platform.sh\"\n\nGET_PERMS=\"stat -c %a\"\ncase \"$UNAME\" in\n    Darwin | FreeBSD | OpenBSD | NetBSD) GET_PERMS=\"stat -f %Lp\" ;;\nesac\n\nassertFilePermissions() {\n    STAT1=$($GET_PERMS \"$1\")\n    STAT2=$2\n    [ \"$STAT1\" = \"$STAT2\" ] || die \"permissions on $1 don't match expected ($STAT1 != $STAT2)\"\n}\n\nassertSamePermissions() {\n    STAT1=$($GET_PERMS \"$1\")\n    STAT2=$($GET_PERMS \"$2\")\n    [ \"$STAT1\" = \"$STAT2\" ] || die \"permissions on $1 don't match those on $2 ($STAT1 != $STAT2)\"\n}\n"
  },
  {
    "path": "tests/cli-tests/common/platform.sh",
    "content": "#!/bin/sh\n\nUNAME=$(uname)\n\nisWindows=false\nINTOVOID=\"/dev/null\"\ncase \"$UNAME\" in\n  GNU) DEVDEVICE=\"/dev/random\" ;;\n  *) DEVDEVICE=\"/dev/zero\" ;;\nesac\ncase \"$OS\" in\n  Windows*)\n    isWindows=true\n    INTOVOID=\"NUL\"\n    DEVDEVICE=\"NUL\"\n    ;;\nesac\n\ncase \"$UNAME\" in\n  Darwin) MD5SUM=\"md5 -r\" ;;\n  NetBSD) MD5SUM=\"md5 -n\" ;;\n  OpenBSD) MD5SUM=\"md5\" ;;\n  *) MD5SUM=\"md5sum\" ;;\nesac\n\nmd5hash() {\n  $MD5SUM | dd bs=1 count=32 status=none\n  echo\n}\n\nDIFF=\"diff\"\ncase \"$UNAME\" in\n  SunOS) DIFF=\"gdiff\" ;;\nesac\n\nif echo hello | zstd -v -T2 2>&1 > $INTOVOID | grep -q 'multi-threading is disabled'\nthen\n    hasMT=\"\"\nelse\n    hasMT=\"true\"\nfi\n\nif zstd -vv --version | grep -q 'non-deterministic'; then\n  NON_DETERMINISTIC=\"true\"\nelse\n  NON_DETERMINISTIC=\"\"\nfi\n"
  },
  {
    "path": "tests/cli-tests/compression/adapt.sh",
    "content": "#!/bin/sh\n\nset -e\n\n# Test --adapt\nzstd -f file --adapt -c | zstd -t\n\ndatagen -g100M > file100M\n\n# Pick parameters to force fast adaptation, even on slow systems\nzstd --adapt -vvvv -19 --zstd=wlog=10 file100M -o /dev/null 2>&1 | grep -q \"faster speed , lighter compression\"\n\n# Adaption still happens with --no-progress\nzstd --no-progress --adapt -vvvv -19 --zstd=wlog=10 file100M -o /dev/null 2>&1 | grep -q \"faster speed , lighter compression\"\n"
  },
  {
    "path": "tests/cli-tests/compression/basic.sh",
    "content": "#!/bin/sh\n\nset -e\n\n# Uncomment the set -v line for debugging\n# set -v\n\n# Test compression flags and check that they work\nzstd file                 ; zstd -t file.zst\nzstd -f file              ; zstd -t file.zst\nzstd -f -z file           ; zstd -t file.zst\nzstd -f -k file           ; zstd -t file.zst\nzstd -f -C file           ; zstd -t file.zst\nzstd -f --check file      ; zstd -t file.zst\nzstd -f --no-check file   ; zstd -t file.zst\nzstd -f -- file           ; zstd -t file.zst\n\n# Test output file compression\nzstd -o file-out.zst ; zstd -t file-out.zst\nzstd -fo file-out.zst; zstd -t file-out.zst\n\n# Test compression to stdout\nzstd -c file       | zstd -t\nzstd --stdout file | zstd -t\nprintln bob | zstd | zstd -t\n\n# Test keeping input file when compressing to stdout in gzip mode\nif $(command -v $ZSTD_SYMLINK_DIR/gzip); then\n    $ZSTD_SYMLINK_DIR/gzip -c file       | zstd -t ; test -f file\n    $ZSTD_SYMLINK_DIR/gzip --stdout file | zstd -t ; test -f file\nfi\n\n# Test --rm\ncp file file-rm\nzstd --rm file-rm; zstd -t file-rm.zst\ntest ! -f file-rm\n"
  },
  {
    "path": "tests/cli-tests/compression/compress-literals.sh",
    "content": "#!/bin/sh\n\nset -e\n\n# Test --[no-]compress-literals\nzstd file --no-compress-literals -1 -c       | zstd -t\nzstd file --no-compress-literals -19 -c      | zstd -t\nzstd file --no-compress-literals --fast=1 -c | zstd -t\nzstd file --compress-literals -1 -c          | zstd -t\nzstd file --compress-literals --fast=1 -c    | zstd -t\n"
  },
  {
    "path": "tests/cli-tests/compression/format.sh",
    "content": "#!/bin/sh\n\n. \"$COMMON/format.sh\"\n\nset -e\n\n# Test --format\nzstd --format=zstd file -f\nzstd -t file.zst\nfor format in \"gzip\" \"lz4\" \"xz\" \"lzma\"; do\n\tif zstd_supports_format $format; then\n\t\tzstd --format=$format file\n\t\tzstd -t file.$(format_extension $format)\n\t\tzstd -c --format=$format file | zstd -t --format=$format\n\tfi\ndone\n"
  },
  {
    "path": "tests/cli-tests/compression/golden.sh",
    "content": "#!/bin/sh\n\nset -e\n\nGOLDEN_DIR=\"$ZSTD_REPO_DIR/tests/golden-compression/\"\ncp -r \"$GOLDEN_DIR\" golden/\n\nzstd -rf golden/ --output-dir-mirror golden-compressed/\nzstd -r -t golden-compressed/\n\nzstd --target-compressed-block-size=1024 -rf golden/ --output-dir-mirror golden-compressed/\nzstd -r -t golden-compressed/\n\n# PR #3517 block splitter corruption test\nzstd -rf -19 --zstd=mml=7 golden/ --output-dir-mirror golden-compressed/\nzstd -r -t golden-compressed/"
  },
  {
    "path": "tests/cli-tests/compression/gzip-compat.sh",
    "content": "#!/bin/sh\n\nset -e\n\n# Uncomment the set -v line for debugging\n# set -v\n\n# Test gzip specific compression option\nif $(command -v $ZSTD_SYMLINK_DIR/gzip); then\n    $ZSTD_SYMLINK_DIR/gzip --fast file ; $ZSTD_SYMLINK_DIR/gzip -d file.gz\n    $ZSTD_SYMLINK_DIR/gzip --best file ; $ZSTD_SYMLINK_DIR/gzip -d file.gz\n\n    # Test -n / --no-name: do not embed original filename in archive\n    $ZSTD_SYMLINK_DIR/gzip -n file           ; grep -qv file file.gz  ; $ZSTD_SYMLINK_DIR/gzip -d file.gz\n    $ZSTD_SYMLINK_DIR/gzip --no-name file    ; grep -qv file file.gz  ; $ZSTD_SYMLINK_DIR/gzip -d file.gz\n    $ZSTD_SYMLINK_DIR/gzip -c --no-name file | grep -qv file\nfi\n"
  },
  {
    "path": "tests/cli-tests/compression/levels.sh",
    "content": "#!/bin/sh\n\nset -e\nset -v\n\ndatagen > file\n\n# Retrieve the program's version information\n# Note: command echoing differs between macos and linux, so it's disabled below\nset +v\nversion_info=$(zstd -V)\nset -v\n\n# Compress with various levels and ensure that their sizes are ordered\nzstd --fast=10 file -o file-f10.zst -q\nzstd --fast=1 file -o file-f1.zst -q\nzstd -1 file -o file-1.zst -q\nzstd -19 file -o file-19.zst -q\nif echo \"$version_info\" | grep -q '32-bit'; then\n    # skip --max test: not enough address space\n    cp file-19.zst file-max.zst\nelse\n    zstd --max file -o file-max.zst -q\nfi\n\nzstd -t file-f10.zst file-f1.zst file-1.zst file-19.zst file-max.zst\n\ncmp_size -le file-max.zst file-19.zst\ncmp_size -lt file-19.zst file-1.zst\ncmp_size -lt file-1.zst file-f1.zst\ncmp_size -lt file-f1.zst file-f10.zst\n\n# Test default levels\nzstd --fast file -f -q\ncmp file.zst file-f1.zst || die \"--fast is not level -1\"\n\nzstd -0 file -o file-0.zst -q\nzstd -f file -q\ncmp file.zst file-0.zst || die \"Level 0 is not the default level\"\n\n# Test level clamping\nzstd -99 file -o file-99.zst -q\ncmp file-19.zst file-99.zst || die \"Level 99 is clamped to 19\"\nzstd --fast=200000 file -c | zstd -t\n\nzstd -5000000000 -f file       && die \"Level too large, must fail\" ||:\nzstd --fast=5000000000 -f file && die \"Level too large, must fail\" ||:\n\n# Test setting a level through the environment variable\nZSTD_CLEVEL=-10 zstd file -o file-f10-env.zst -q\nZSTD_CLEVEL=1 zstd file -o file-1-env.zst -q\nZSTD_CLEVEL=+19 zstd file -o file-19-env.zst -q\nZSTD_CLEVEL=+99 zstd file -o file-99-env.zst -q\n\ncmp file-f10.zst file-f10-env.zst || die \"Environment variable failed to set level\"\ncmp file-1.zst file-1-env.zst || die \"Environment variable failed to set level\"\ncmp file-19.zst file-19-env.zst || die \"Environment variable failed to set level\"\ncmp file-99.zst file-99-env.zst || die \"Environment variable failed to set level\"\n\n# Test invalid environment clevel is the default level\nzstd -f file -q\nZSTD_CLEVEL=- zstd -f file -o file-env.zst -q      ; cmp file.zst file-env.zst\nZSTD_CLEVEL=+ zstd -f file -o file-env.zst -q      ; cmp file.zst file-env.zst\nZSTD_CLEVEL=a zstd -f file -o file-env.zst -q      ; cmp file.zst file-env.zst\nZSTD_CLEVEL=-a zstd -f file -o file-env.zst -q     ; cmp file.zst file-env.zst\nZSTD_CLEVEL=+a zstd -f file -o file-env.zst -q     ; cmp file.zst file-env.zst\nZSTD_CLEVEL=3a7 zstd -f file -o file-env.zst -q    ; cmp file.zst file-env.zst\nZSTD_CLEVEL=5000000000 zstd -f file -o file-env.zst -q ; cmp file.zst file-env.zst\n\n# Test environment clevel is overridden by command line\nZSTD_CLEVEL=10 zstd -f file -1 -o file-1-env.zst -q\nZSTD_CLEVEL=10 zstd -f file --fast=1 -o file-f1-env.zst -q\n\ncmp file-1.zst file-1-env.zst  || die \"Environment variable not overridden\"\ncmp file-f1.zst file-f1-env.zst || die \"Environment variable not overridden\"\n"
  },
  {
    "path": "tests/cli-tests/compression/levels.sh.stderr.exact",
    "content": "\ndatagen > file\n\n# Retrieve the program's version information\n# Note: command echoing differs between macos and linux, so it's disabled below\nset +v\n\n# Compress with various levels and ensure that their sizes are ordered\nzstd --fast=10 file -o file-f10.zst -q\nzstd --fast=1 file -o file-f1.zst -q\nzstd -1 file -o file-1.zst -q\nzstd -19 file -o file-19.zst -q\nif echo \"$version_info\" | grep -q '32-bit'; then\n    # skip --max test: not enough address space\n    cp file-19.zst file-max.zst\nelse\n    zstd --max file -o file-max.zst -q\nfi\n\nzstd -t file-f10.zst file-f1.zst file-1.zst file-19.zst file-max.zst\n5 files decompressed : 327685 bytes total \n\ncmp_size -le file-max.zst file-19.zst\ncmp_size -lt file-19.zst file-1.zst\ncmp_size -lt file-1.zst file-f1.zst\ncmp_size -lt file-f1.zst file-f10.zst\n\n# Test default levels\nzstd --fast file -f -q\ncmp file.zst file-f1.zst || die \"--fast is not level -1\"\n\nzstd -0 file -o file-0.zst -q\nzstd -f file -q\ncmp file.zst file-0.zst || die \"Level 0 is not the default level\"\n\n# Test level clamping\nzstd -99 file -o file-99.zst -q\ncmp file-19.zst file-99.zst || die \"Level 99 is clamped to 19\"\nzstd --fast=200000 file -c | zstd -t\n/*stdin*\\           : 65537 bytes \n\nzstd -5000000000 -f file       && die \"Level too large, must fail\" ||:\nerror: numeric value overflows 32-bit unsigned int \nzstd --fast=5000000000 -f file && die \"Level too large, must fail\" ||:\nerror: numeric value overflows 32-bit unsigned int \n\n# Test setting a level through the environment variable\nZSTD_CLEVEL=-10 zstd file -o file-f10-env.zst -q\nZSTD_CLEVEL=1 zstd file -o file-1-env.zst -q\nZSTD_CLEVEL=+19 zstd file -o file-19-env.zst -q\nZSTD_CLEVEL=+99 zstd file -o file-99-env.zst -q\n\ncmp file-f10.zst file-f10-env.zst || die \"Environment variable failed to set level\"\ncmp file-1.zst file-1-env.zst || die \"Environment variable failed to set level\"\ncmp file-19.zst file-19-env.zst || die \"Environment variable failed to set level\"\ncmp file-99.zst file-99-env.zst || die \"Environment variable failed to set level\"\n\n# Test invalid environment clevel is the default level\nzstd -f file -q\nZSTD_CLEVEL=- zstd -f file -o file-env.zst -q      ; cmp file.zst file-env.zst\nIgnore environment variable setting ZSTD_CLEVEL=-: not a valid integer value \nZSTD_CLEVEL=+ zstd -f file -o file-env.zst -q      ; cmp file.zst file-env.zst\nIgnore environment variable setting ZSTD_CLEVEL=+: not a valid integer value \nZSTD_CLEVEL=a zstd -f file -o file-env.zst -q      ; cmp file.zst file-env.zst\nIgnore environment variable setting ZSTD_CLEVEL=a: not a valid integer value \nZSTD_CLEVEL=-a zstd -f file -o file-env.zst -q     ; cmp file.zst file-env.zst\nIgnore environment variable setting ZSTD_CLEVEL=-a: not a valid integer value \nZSTD_CLEVEL=+a zstd -f file -o file-env.zst -q     ; cmp file.zst file-env.zst\nIgnore environment variable setting ZSTD_CLEVEL=+a: not a valid integer value \nZSTD_CLEVEL=3a7 zstd -f file -o file-env.zst -q    ; cmp file.zst file-env.zst\nIgnore environment variable setting ZSTD_CLEVEL=3a7: not a valid integer value \nZSTD_CLEVEL=5000000000 zstd -f file -o file-env.zst -q ; cmp file.zst file-env.zst\nIgnore environment variable setting ZSTD_CLEVEL=5000000000: numeric value too large \n\n# Test environment clevel is overridden by command line\nZSTD_CLEVEL=10 zstd -f file -1 -o file-1-env.zst -q\nZSTD_CLEVEL=10 zstd -f file --fast=1 -o file-f1-env.zst -q\n\ncmp file-1.zst file-1-env.zst  || die \"Environment variable not overridden\"\ncmp file-f1.zst file-f1-env.zst || die \"Environment variable not overridden\"\n"
  },
  {
    "path": "tests/cli-tests/compression/long-distance-matcher.sh",
    "content": "#!/bin/sh\n\nset -e\n\n# Test --long\nzstd -f file --long   ; zstd -t file.zst\nzstd -f file --long=20; zstd -t file.zst\n"
  },
  {
    "path": "tests/cli-tests/compression/multi-threaded.sh",
    "content": "#!/bin/sh\n\nset -e\n\n# Test multi-threaded flags\nzstd --single-thread file -f -q         ; zstd -t file.zst\nzstd -T2 -f file -q                     ; zstd -t file.zst\nzstd --rsyncable -f file -q             ; zstd -t file.zst\nzstd -T0 -f file -q                     ; zstd -t file.zst\nzstd -T0 --auto-threads=logical -f file -q ; zstd -t file.zst\nzstd -T0 --auto-threads=physical -f file -q ; zstd -t file.zst\nzstd -T0 --jobsize=1M -f file -q        ; zstd -t file.zst\n\n# multi-thread decompression warning test\nzstd -T0 -f file -q                     ; zstd -t file.zst; zstd -T0 -d file.zst -o file3\nzstd -T0 -f file -q                     ; zstd -t file.zst; zstd -T2 -d file.zst -o file4\n# setting multi-thread via environment variable does not trigger decompression warning\nzstd -T0 -f file -q                     ; zstd -t file.zst; ZSTD_NBTHREADS=0 zstd -df file.zst -o file3\nzstd -T0 -f file -q                     ; zstd -t file.zst; ZSTD_NBTHREADS=2 zstd -df file.zst -o file4\n# setting nbThreads==1 does not trigger decompression warning\nzstd -T0 -f file -q                     ; zstd -t file.zst; zstd -T1 -df file.zst -o file3\nzstd -T0 -f file -q                     ; zstd -t file.zst; zstd -T2 -T1 -df file.zst -o file4\n"
  },
  {
    "path": "tests/cli-tests/compression/multi-threaded.sh.stderr.exact",
    "content": "file.zst            : 65537 bytes \nfile.zst            : 65537 bytes \nfile.zst            : 65537 bytes \nfile.zst            : 65537 bytes \nfile.zst            : 65537 bytes \nfile.zst            : 65537 bytes \nfile.zst            : 65537 bytes \nfile.zst            : 65537 bytes \nWarning : decompression does not support multi-threading\nfile.zst            : 65537 bytes \nfile.zst            : 65537 bytes \nWarning : decompression does not support multi-threading\nfile.zst            : 65537 bytes \nfile.zst            : 65537 bytes \nfile.zst            : 65537 bytes \nfile.zst            : 65537 bytes \nfile.zst            : 65537 bytes \nfile.zst            : 65537 bytes \nfile.zst            : 65537 bytes \nfile.zst            : 65537 bytes \nfile.zst            : 65537 bytes \n"
  },
  {
    "path": "tests/cli-tests/compression/multiple-files.sh",
    "content": "#!/bin/sh\nset -e\n\n# setup\necho \"file1\" > file1\necho \"file2\" > file2\n\necho \"Test zstd ./file1 - file2\"\nrm -f ./file*.zst\necho \"stdin\" | zstd ./file1 - ./file2 | zstd -d\ncat file1.zst | zstd -d\ncat file2.zst | zstd -d\n\necho \"Test zstd -d ./file1.zst - file2.zst\"\nrm ./file1 ./file2\necho \"stdin\" | zstd - | zstd -d ./file1.zst - file2.zst\ncat file1\ncat file2\n\necho \"zstd -d ./file1.zst - file2.zst -c\"\necho \"stdin\" | zstd | zstd -d ./file1.zst - file2.zst -c\n"
  },
  {
    "path": "tests/cli-tests/compression/multiple-files.sh.stdout.exact",
    "content": "Test zstd ./file1 - file2\nstdin\nfile1\nfile2\nTest zstd -d ./file1.zst - file2.zst\nstdin\nfile1\nfile2\nzstd -d ./file1.zst - file2.zst -c\nfile1\nstdin\nfile2\n"
  },
  {
    "path": "tests/cli-tests/compression/row-match-finder.sh",
    "content": "#!/bin/sh\n\nset -e\n\n# Test --[no-]row-match-finder\nzstd file -7f --row-match-finder\nzstd file -7f --no-row-match-finder\n"
  },
  {
    "path": "tests/cli-tests/compression/setup",
    "content": "#!/bin/sh\n\nset -e\n\ndatagen > file\ndatagen > file0\ndatagen > file1\n"
  },
  {
    "path": "tests/cli-tests/compression/stream-size.sh",
    "content": "#!/bin/sh\n\nset -e\n\n# Test stream size & hint\ndatagen -g7654 | zstd --stream-size=7654 | zstd -t\ndatagen -g7654 | zstd --size-hint=7000   | zstd -t\n"
  },
  {
    "path": "tests/cli-tests/compression/verbose-wlog.sh",
    "content": "#!/bin/sh\n\nset -e\n\n. \"$COMMON/platform.sh\"\n\nzstd < file -vv -19 -o file.19.zst\nzstd -vv -l file.19.zst\n\nzstd < file -vv -19 --long -o file.19.long.zst\nzstd -vv -l file.19.long.zst\n"
  },
  {
    "path": "tests/cli-tests/compression/verbose-wlog.sh.stderr.glob",
    "content": "...\n*wlog=23*\n...\n*wlog=27*\n...\n"
  },
  {
    "path": "tests/cli-tests/compression/verbose-wlog.sh.stdout.glob",
    "content": "...\n*Window Size: 8388608 B*\n...\n*Window Size: 134217728 B*\n...\n"
  },
  {
    "path": "tests/cli-tests/compression/window-resize.sh",
    "content": "#!/bin/sh\ndatagen -g1G > file\nzstd --long=30 -1 --single-thread --no-content-size -f file\nzstd -l -v file.zst\n\n# We want to ignore stderr (its outputting \"*** zstd command line interface\n# 64-bits v1.5.3, by Yann Collet ***\")\n\nrm file file.zst\n"
  },
  {
    "path": "tests/cli-tests/compression/window-resize.sh.stderr.ignore",
    "content": ""
  },
  {
    "path": "tests/cli-tests/compression/window-resize.sh.stdout.glob",
    "content": "...\nWindow Size: 1.000 GiB (1073741824 B)\n...\n"
  },
  {
    "path": "tests/cli-tests/decompression/detectErrors.sh",
    "content": "#!/bin/sh\n\nset -e\n\nGOLDEN_DIR=\"$ZSTD_REPO_DIR/tests/golden-decompression-errors/\"\n\nfor file in \"$GOLDEN_DIR\"/*; do\n    zstd -t $file && die \"should have detected an error\"\ndone\nexit 0\n\n"
  },
  {
    "path": "tests/cli-tests/decompression/golden.sh",
    "content": "#!/bin/sh\n\nset -e\n\nGOLDEN_DIR=\"$ZSTD_REPO_DIR/tests/golden-decompression/\"\n\nzstd -r -t \"$GOLDEN_DIR\"\n"
  },
  {
    "path": "tests/cli-tests/decompression/pass-through.sh",
    "content": "#!/bin/sh\n\nset -e\n\n. \"$COMMON/platform.sh\"\n\necho \"\" > 1\necho \"2\" > 2\necho \"23\" > 3\necho \"234\" > 4\necho \"some data\" > file\n\nprintln \"+ passthrough enabled\"\n\nzstd file\n\n# Test short files\nzstd -dc --pass-through 1 2 3 4\n\n# Test *cat symlinks\nzstdcat file\n\"$ZSTD_SYMLINK_DIR/zcat\" file\n\"$ZSTD_SYMLINK_DIR/gzcat\" file\n\n# Test multiple files with mix of compressed & not\nzstdcat file file.zst\nzstdcat file.zst file\n\n# Test --pass-through\nzstd -dc --pass-through file\nzstd -d --pass-through file -o pass-through-file\n\n# Test legacy implicit passthrough with -fc\nzstd -dcf file\nzstd -dcf file file.zst\nzstd -df < file\nzstd -dcf < file file.zst -\nzstd -dcf < file.zst file -\n\n$DIFF file pass-through-file\n\nprintln \"+ passthrough disabled\"\n\n# Test *cat\nzstdcat --no-pass-through file && die \"should fail\"\n\"$ZSTD_SYMLINK_DIR/zcat\" --no-pass-through file && die \"should fail\"\n\"$ZSTD_SYMLINK_DIR/gzcat\" --no-pass-through file && die \"should fail\"\n# Test zstd without implicit passthrough\nzstd -d file -o no-pass-through-file && die \"should fail\"\nzstd -d < file && die \"should fail\"\n\n# Test legacy implicit passthrough with -fc\nzstd --no-pass-through -dcf file && die \"should fail\"\nzstd --no-pass-through -dcf file file.zst && die \"should fail\"\nzstd --no-pass-through -df < file && die \"should fail\"\nzstd --no-pass-through -dcf < file file.zst - && die \"should fail\"\nzstd --no-pass-through -dcf < file.zst file - && die \"should fail\" ||:\n"
  },
  {
    "path": "tests/cli-tests/decompression/pass-through.sh.stderr.exact",
    "content": "file                 :230.00%   (    10 B =>     23 B, file.zst) \nzstd: file: unsupported format \nzstd: file: unsupported format \nzstd: file: unsupported format \nzstd: file: unsupported format \nzstd: /*stdin*\\: unsupported format \nzstd: file: unsupported format \nzstd: file: unsupported format \nzstd: /*stdin*\\: unsupported format \nzstd: /*stdin*\\: unsupported format \nzstd: file: unsupported format \n"
  },
  {
    "path": "tests/cli-tests/decompression/pass-through.sh.stdout.exact",
    "content": "+ passthrough enabled\n\n2\n23\n234\nsome data\nsome data\nsome data\nsome data\nsome data\nsome data\nsome data\nsome data\nsome data\nsome data\nsome data\nsome data\nsome data\nsome data\nsome data\nsome data\n+ passthrough disabled\nsome data\nsome data\nsome data\n"
  },
  {
    "path": "tests/cli-tests/determinism/basic.sh",
    "content": "#!/bin/sh\n\n. \"$COMMON/platform.sh\"\n\nset -e\n\n# To update checksums on version change run this from the tests/ directory\n# make update-cli-tests\n\nif [ -n \"$NON_DETERMINISTIC\" ]; then\n    # Skip tests if we have a non-deterministic build\n    cat \"$CLI_TESTS/determinism/basic.sh.stdout.exact\"\n    exit 0\nfi\n\nfor level in $(seq 1 19); do\n    for file in $(ls files/); do\n        file=\"files/$file\"\n        echo \"level $level, file $file\"\n        zstd --single-thread -q -$level $file -c | md5hash\n    done\ndone\n\nfor file in $(ls files/); do\n    file=\"files/$file\"\n    echo \"level 1, long=18, file $file\"\n    zstd --long=18 --single-thread -q -1 $file -c | md5hash\n    echo \"level 19, long=18, file $file\"\n    zstd --long=18 --single-thread -q -19 $file -c | md5hash\ndone\n\nfor file in $(ls files/); do\n    file=\"files/$file\"\n    echo \"level -1, file $file\"\n    zstd -q --single-thread --fast=1 $file -c | md5hash\ndone\n"
  },
  {
    "path": "tests/cli-tests/determinism/basic.sh.stderr.exact",
    "content": ""
  },
  {
    "path": "tests/cli-tests/determinism/basic.sh.stdout.exact",
    "content": "level 1, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 1, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 1, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 1, file files/g100\nc94d1ef6bbec8b4899486b06207ee829\nlevel 1, file files/g1000\n6bf2f4b179864fd8db4676037465feed\nlevel 1, file files/g10000\n2ae44c4053b2b47724c8f612dfb60d24\nlevel 1, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 1, file files/g10000-P10\n2d0eeab6a966098583a1dfeafb5090c1\nlevel 1, file files/g10000-P100\n93436482b4da30ce2300d356448c8990\nlevel 1, file files/g10000-P25\nc64b5f512c44b6a647da81753791b9a7\nlevel 1, file files/g10000-P50\n3982325490d90c8307e734c1b25790df\nlevel 1, file files/g10000-P75\nb7504f80fee16b5ba6a0f46571eb563a\nlevel 1, file files/g10000-P90\n350892bec7f7ad6a7d6af01c5d8b07c7\nlevel 1, file files/g100000\ndaa38a869130494c077290cf54f2d895\nlevel 1, file files/g1000000\na1d548531221d408b95dc5d9c600b3f0\nlevel 1, file files/g20000\n1da5b56511e8693867c0cdd962c521aa\nlevel 1, file files/g200000\n41fb3b3d46d4221f2f0b072c65dd6e0a\nlevel 1, file files/g30000\n788bc5abca5e33d79bb79a4eca98b9cd\nlevel 1, file files/g50000\n0bf9fafd84a2d56a788a9159f1f23f26\nlevel 1, file files/g500000\n73401d6df0657e091de20468f32579a9\nlevel 2, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 2, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 2, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 2, file files/g100\nc94d1ef6bbec8b4899486b06207ee829\nlevel 2, file files/g1000\na14988fb331bc6f8b33d9eba3a0416dc\nlevel 2, file files/g10000\na8656ebab20efa8a3fb281327aab5d58\nlevel 2, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 2, file files/g10000-P10\n9db9877242632964c232ebd4485dba07\nlevel 2, file files/g10000-P100\n93436482b4da30ce2300d356448c8990\nlevel 2, file files/g10000-P25\nd7a7223240a607fe28a2e8fd641a969d\nlevel 2, file files/g10000-P50\n86478908f9caa5ca4029454005063078\nlevel 2, file files/g10000-P75\n14f5dcdb347e87790d49c1eb99ac5069\nlevel 2, file files/g10000-P90\n05bdb42a2eeb5788d6288dc241cde12c\nlevel 2, file files/g100000\n12c6a4c50fad3e479e0f0ffe1d4df324\nlevel 2, file files/g1000000\n4f9cdc0de37b22d657fd9d3c61ec5b44\nlevel 2, file files/g20000\n1e70c3fe429c1af41e9cb8a536fb6df1\nlevel 2, file files/g200000\nbb1cc37142783345db29c3fd5838ce4e\nlevel 2, file files/g30000\n52528017fe0eec85b6c3244e6fceb4ed\nlevel 2, file files/g50000\na38bdd671b6d3bd76b479dfc01d1c7fb\nlevel 2, file files/g500000\ncd2090a38bbd677b385238355c996c01\nlevel 3, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 3, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 3, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 3, file files/g100\nc94d1ef6bbec8b4899486b06207ee829\nlevel 3, file files/g1000\n3ec47dcb2d606b9fdef3f19b1304f8fe\nlevel 3, file files/g10000\n69a9d518b84fe2a66b57dfb4ab8905ae\nlevel 3, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 3, file files/g10000-P10\nac9866ac355c4ed8939deb9fbeec1aef\nlevel 3, file files/g10000-P100\n93436482b4da30ce2300d356448c8990\nlevel 3, file files/g10000-P25\n5e1fe7a3831f6632bc8c9873ab8b633d\nlevel 3, file files/g10000-P50\n76295f181396a98565eb9cc69b96dc75\nlevel 3, file files/g10000-P75\n1f751dc70508e81fef197311e8583e99\nlevel 3, file files/g10000-P90\n47c7b061c299dc253c6aaaf489e936cb\nlevel 3, file files/g100000\n4b30b2be3394f03f1cf1f37a08dcec12\nlevel 3, file files/g1000000\n4301dea72cc4dd6162e46caa59788a09\nlevel 3, file files/g20000\n30456361833d27c0962c2faaa254e615\nlevel 3, file files/g200000\n0f01c07c57d60298dd54c6b6b197c3d3\nlevel 3, file files/g30000\n0b3c506a1b1b6ccbb54a852c370f5cdc\nlevel 3, file files/g50000\n81368c0b96bf1a2f318940b836b46074\nlevel 3, file files/g500000\n0c1ef9c6d3d75bfa0dd5d893f65da47c\nlevel 4, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 4, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 4, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 4, file files/g100\nc94d1ef6bbec8b4899486b06207ee829\nlevel 4, file files/g1000\n6a1214c19ab13d15934244a4655fa327\nlevel 4, file files/g10000\n09bbd556d9ee9f74f36b36bfa6b17325\nlevel 4, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 4, file files/g10000-P10\n1adb177b7a441c3585ffd781654758ba\nlevel 4, file files/g10000-P100\n93436482b4da30ce2300d356448c8990\nlevel 4, file files/g10000-P25\n3a62170477d7f17d64dc49b971388ff7\nlevel 4, file files/g10000-P50\nde93403eafd68786410fa52a95752514\nlevel 4, file files/g10000-P75\nf5466b3cfc3ba1e5afecb8d8bb91250f\nlevel 4, file files/g10000-P90\n132869db4091a9b9bdbc5236435a1d98\nlevel 4, file files/g100000\ndd92f22c593f40e0ccd6b31ad09d9d18\nlevel 4, file files/g1000000\ncfe7c063909c635f22438f83eb824082\nlevel 4, file files/g20000\nf8be159b057c6ee827f36cdd2ee5c43f\nlevel 4, file files/g200000\n71362cc7c28dcc730b591e3002fe888c\nlevel 4, file files/g30000\nf0b899995c6ba86066bd7f407fc708ef\nlevel 4, file files/g50000\n2f293e665d5161e68d8e1f86ac6841be\nlevel 4, file files/g500000\n42c5c45c595af60d5cf28f4cdd8ab392\nlevel 5, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 5, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 5, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 5, file files/g100\nc94d1ef6bbec8b4899486b06207ee829\nlevel 5, file files/g1000\nd47284586e181d455017d821bd3de1ef\nlevel 5, file files/g10000\nd6cd223f1c215d332654ca241a376549\nlevel 5, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 5, file files/g10000-P10\n66b935a7666ae668ac990d5c9aaac652\nlevel 5, file files/g10000-P100\n15fede9faa3d7c484dead66071fb8c5d\nlevel 5, file files/g10000-P25\nb292339cacea797a184554a2de3c1ed3\nlevel 5, file files/g10000-P50\n10b65af5125bf21a6810b8fb7a30b8b1\nlevel 5, file files/g10000-P75\n04fc60ea83db4b6101778f91a73d6040\nlevel 5, file files/g10000-P90\n302c8c7355082a7f40efe4ea40912411\nlevel 5, file files/g100000\n338f5e822a469774462f144d7ae371a0\nlevel 5, file files/g1000000\n46b8608a1f833477387e2fc844a817d5\nlevel 5, file files/g20000\nb7a468d363a7797d3d7a48577cd20213\nlevel 5, file files/g200000\n5ed09b3fd58ba540128319c02f9259cb\nlevel 5, file files/g30000\nfd4c0e5acb85271c101fd8ae1f411232\nlevel 5, file files/g50000\n2a14c76d629615bd50a370e587d13eb8\nlevel 5, file files/g500000\ncb1122167d4a747f3f8e0dd18bce6fa3\nlevel 6, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 6, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 6, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 6, file files/g100\nc94d1ef6bbec8b4899486b06207ee829\nlevel 6, file files/g1000\n19187f900e7540efdcab3735f489f718\nlevel 6, file files/g10000\n70c03e642fb98b896f2d96c0fa0eca74\nlevel 6, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 6, file files/g10000-P10\n70e2df33337095c818051d86ea68f188\nlevel 6, file files/g10000-P100\n15fede9faa3d7c484dead66071fb8c5d\nlevel 6, file files/g10000-P25\ndd4ed2ced4ae48672d5c8c0d4a7d58a5\nlevel 6, file files/g10000-P50\n9182b845f45f4990c8993e1c54e1e2e6\nlevel 6, file files/g10000-P75\nd3e6bb5a8e9790d23dda0a38b3def532\nlevel 6, file files/g10000-P90\n21da6c8aefa00b3e16f7674c642aa043\nlevel 6, file files/g100000\n350a0f07d7ddbcd0c629da0bcf734f02\nlevel 6, file files/g1000000\nd40c700beee149ab272b94c7ef0f3811\nlevel 6, file files/g20000\n335bc3f5767a7d4ad479408b0e289459\nlevel 6, file files/g200000\n032e3313ca247a8f4687059fa708284c\nlevel 6, file files/g30000\na4b9fed2e1005298617125ee3b00cb06\nlevel 6, file files/g50000\nd7b3dab8d19fb992795c440d5f953c94\nlevel 6, file files/g500000\n44e59ccbf7a9794d4ea03f3f59f61ffd\nlevel 7, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 7, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 7, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 7, file files/g100\nc94d1ef6bbec8b4899486b06207ee829\nlevel 7, file files/g1000\n19187f900e7540efdcab3735f489f718\nlevel 7, file files/g10000\n495f1e5d30de3b34c5a76301875fa231\nlevel 7, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 7, file files/g10000-P10\n8a91fa2460ec9bd0387baa31beb81060\nlevel 7, file files/g10000-P100\n15fede9faa3d7c484dead66071fb8c5d\nlevel 7, file files/g10000-P25\n7dc0563f2e66a2e57c0f119e4d5e636e\nlevel 7, file files/g10000-P50\ne93a6eb179f7b26daa896328b2583b04\nlevel 7, file files/g10000-P75\ncb1e5facfc34fca7323000c6188ad657\nlevel 7, file files/g10000-P90\ne9984c6557f5a392f16e5c139dbe4994\nlevel 7, file files/g100000\n6e493dbe2985fec69860ef34728ac01a\nlevel 7, file files/g1000000\n455023a055f3a4de76c7295408ce3c8f\nlevel 7, file files/g20000\n2359efcd587e36ac9b74a8344bbf0e53\nlevel 7, file files/g200000\nca80dbc88183a5aabb4aae955c449dff\nlevel 7, file files/g30000\n7e1be7e841c9fddd776dbe94b50db0ab\nlevel 7, file files/g50000\n09b80b58d70622de6f2354a06c15cb2a\nlevel 7, file files/g500000\nc90609f0558f0979eccb572ce0af4aa3\nlevel 8, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 8, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 8, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 8, file files/g100\nc94d1ef6bbec8b4899486b06207ee829\nlevel 8, file files/g1000\n19187f900e7540efdcab3735f489f718\nlevel 8, file files/g10000\n495f1e5d30de3b34c5a76301875fa231\nlevel 8, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 8, file files/g10000-P10\n8a91fa2460ec9bd0387baa31beb81060\nlevel 8, file files/g10000-P100\n15fede9faa3d7c484dead66071fb8c5d\nlevel 8, file files/g10000-P25\n526c95fd77cbcc2079720bb1b5515a54\nlevel 8, file files/g10000-P50\n50d4e0154067af438e56729716c3eda7\nlevel 8, file files/g10000-P75\nc94a94cce795566b065f2d3dca554c28\nlevel 8, file files/g10000-P90\n8f83ce03eb280cba48bafafbd066b752\nlevel 8, file files/g100000\ndbc4c43d9dc0937e67e92a908688a51e\nlevel 8, file files/g1000000\n5a4e6e44c89c3538fdb09823e649c8f6\nlevel 8, file files/g20000\n3653750b7ea2e8dc97d1d24ccec72153\nlevel 8, file files/g200000\ne978eb15e94cf221f1c7c55a059bbc4a\nlevel 8, file files/g30000\n9668f8c1292931955e14b81d67c2c648\nlevel 8, file files/g50000\n36a864d5bb5d9167d19ac237ce3bef51\nlevel 8, file files/g500000\neaaac1f3c4861d4d501d9c92fa67cc08\nlevel 9, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 9, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 9, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 9, file files/g100\nc94d1ef6bbec8b4899486b06207ee829\nlevel 9, file files/g1000\n42d1f8aa9ee42135013077f09b77fd1a\nlevel 9, file files/g10000\nae4166250554922e9ed27e436c13bf6b\nlevel 9, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 9, file files/g10000-P10\nbd9ede6738524ef732c9516146536acd\nlevel 9, file files/g10000-P100\n93436482b4da30ce2300d356448c8990\nlevel 9, file files/g10000-P25\n526c95fd77cbcc2079720bb1b5515a54\nlevel 9, file files/g10000-P50\naf6f029bd0d9baee1a78b8f7ffef5df3\nlevel 9, file files/g10000-P75\nf56895eec07a63269ea3eaeb59e87f40\nlevel 9, file files/g10000-P90\nc5cef2890886bfaf2d747b37ededc261\nlevel 9, file files/g100000\nf11c301dcf8c791e4f2db29e1b388eba\nlevel 9, file files/g1000000\nf90563e0d0962955d31af45fc8f2b19d\nlevel 9, file files/g20000\n49820710f3fbc6627b60071e91dba56d\nlevel 9, file files/g200000\n4689b0eb28c34619d8a9087cfa33fc88\nlevel 9, file files/g30000\nc14b029711fa6abc627ed3a051902b4c\nlevel 9, file files/g50000\n2d1cde6271f46081fbeaaba10f1c48bb\nlevel 9, file files/g500000\neaaac1f3c4861d4d501d9c92fa67cc08\nlevel 10, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 10, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 10, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 10, file files/g100\nc94d1ef6bbec8b4899486b06207ee829\nlevel 10, file files/g1000\n42d1f8aa9ee42135013077f09b77fd1a\nlevel 10, file files/g10000\nae4166250554922e9ed27e436c13bf6b\nlevel 10, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 10, file files/g10000-P10\nbd9ede6738524ef732c9516146536acd\nlevel 10, file files/g10000-P100\n93436482b4da30ce2300d356448c8990\nlevel 10, file files/g10000-P25\n526c95fd77cbcc2079720bb1b5515a54\nlevel 10, file files/g10000-P50\n6f821eef670933208d85daad6a9a2791\nlevel 10, file files/g10000-P75\n9c944c50c800d72294bdc9a9a452dc90\nlevel 10, file files/g10000-P90\n838a22c0731a67d185cac135b2bac5c7\nlevel 10, file files/g100000\nbbb2e91bdee192ae6f23404542a35bfb\nlevel 10, file files/g1000000\n1e52803b3311c2d4428c56d059901721\nlevel 10, file files/g20000\n939b50f472cf67c6dfbc4d3074e04011\nlevel 10, file files/g200000\nadc5f0c58c75e79e4bc4800c015d2401\nlevel 10, file files/g30000\n43e46ec5aae76c55c890a18f49b0163b\nlevel 10, file files/g50000\n65c57573aef37a38bd6c587ef4388800\nlevel 10, file files/g500000\nd3c45fce79c26bce889c3fa6a5480200\nlevel 11, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 11, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 11, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 11, file files/g100\nc94d1ef6bbec8b4899486b06207ee829\nlevel 11, file files/g1000\n4aa08662527d6d7f996705929e0dd8e0\nlevel 11, file files/g10000\n330f75029558d7cb6fa2756d85a998bd\nlevel 11, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 11, file files/g10000-P10\n990879c5b3d1c99aa5ef39f6049cebc9\nlevel 11, file files/g10000-P100\n049015191cf579b24653c8730fcc10f5\nlevel 11, file files/g10000-P25\n26a10f96c2008608a33a731ff39cd9c8\nlevel 11, file files/g10000-P50\n129c6082daea0da5f52358c71b252750\nlevel 11, file files/g10000-P75\n7ff21b2c10548b9fc8ec5b61f86b9db0\nlevel 11, file files/g10000-P90\n0def9775620838420b295c07fd50a196\nlevel 11, file files/g100000\nc115057c51f9bb603a7d0c6bdf76e422\nlevel 11, file files/g1000000\nd28d3aed914ba7368dd004a9431c0173\nlevel 11, file files/g20000\n650cf27ffca49ed98f0e5dbb8997d7eb\nlevel 11, file files/g200000\n3210b89239e35e559be0ccd842577bb4\nlevel 11, file files/g30000\n09fe5a276e3fec09490c85962263fb26\nlevel 11, file files/g50000\na9fa2677e4faab0eaa2334f278b3ec7d\nlevel 11, file files/g500000\n86815b1a35a46312a081f1af4946a62e\nlevel 12, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 12, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 12, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 12, file files/g100\nc94d1ef6bbec8b4899486b06207ee829\nlevel 12, file files/g1000\n6cb98f0115baf96a720638cf92b7803b\nlevel 12, file files/g10000\nb73485abce0df9802dcfeee652c45a8d\nlevel 12, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 12, file files/g10000-P10\nd00ac554fefc8a0f40420f908ff6fe69\nlevel 12, file files/g10000-P100\n049015191cf579b24653c8730fcc10f5\nlevel 12, file files/g10000-P25\n9e20110ea128e4201c9a09eb48ad16c8\nlevel 12, file files/g10000-P50\n07287871c8b4ec3b5a925563a97451ce\nlevel 12, file files/g10000-P75\n2a47bb2eb7fb84a157f4525da9f78a77\nlevel 12, file files/g10000-P90\nd9c87f3f0faf212ec2d60cb611dac8a9\nlevel 12, file files/g100000\nd5d45068ded1319342ac3b7867d8c8fd\nlevel 12, file files/g1000000\nd28d3aed914ba7368dd004a9431c0173\nlevel 12, file files/g20000\n650cf27ffca49ed98f0e5dbb8997d7eb\nlevel 12, file files/g200000\n077d0f0ef9e9af86b1a298624fc70062\nlevel 12, file files/g30000\n09fe5a276e3fec09490c85962263fb26\nlevel 12, file files/g50000\na9fa2677e4faab0eaa2334f278b3ec7d\nlevel 12, file files/g500000\n86815b1a35a46312a081f1af4946a62e\nlevel 13, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 13, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 13, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 13, file files/g100\ne6e88e42b891fbc82c87a60928d88e97\nlevel 13, file files/g1000\n773b6b59d472db0932b5ad1ad75eac64\nlevel 13, file files/g10000\ndfd1e66b36c80b191c338d0b14813920\nlevel 13, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 13, file files/g10000-P10\n40b5f47e143e235198f6408a099208e8\nlevel 13, file files/g10000-P100\n049015191cf579b24653c8730fcc10f5\nlevel 13, file files/g10000-P25\ndeaa99c2458ca8ea661b358ef837ef58\nlevel 13, file files/g10000-P50\ndd575cdc1ac009a7f2407013063d02e3\nlevel 13, file files/g10000-P75\n0d411eb9beee65c6f5dd7764b639097b\nlevel 13, file files/g10000-P90\n61db327f8fdd9a735e68259f05f71f0d\nlevel 13, file files/g100000\ndece3af6a1b7ef4ab80cad69119a3b61\nlevel 13, file files/g1000000\n916989f734410afce6b3ae72a3352e68\nlevel 13, file files/g20000\n7ce4e5c10392cbae28ed79b0707f627f\nlevel 13, file files/g200000\nab3d3f2a0fb5d4e54f8e799213d7e995\nlevel 13, file files/g30000\n61f3ce2b87a584169e92791fa54c7361\nlevel 13, file files/g50000\naba34c68e1d812fab8ce9863169e050b\nlevel 13, file files/g500000\n9f16a159f5fa88b875e5c1e0574a999c\nlevel 14, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 14, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 14, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 14, file files/g100\ne6e88e42b891fbc82c87a60928d88e97\nlevel 14, file files/g1000\n773b6b59d472db0932b5ad1ad75eac64\nlevel 14, file files/g10000\ndfd1e66b36c80b191c338d0b14813920\nlevel 14, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 14, file files/g10000-P10\n40b5f47e143e235198f6408a099208e8\nlevel 14, file files/g10000-P100\n049015191cf579b24653c8730fcc10f5\nlevel 14, file files/g10000-P25\ndeaa99c2458ca8ea661b358ef837ef58\nlevel 14, file files/g10000-P50\n246b1782db44f4226d32c8718e39ac8c\nlevel 14, file files/g10000-P75\n023a4c9c041fbcd4f584d5e65f9b4444\nlevel 14, file files/g10000-P90\nd57d3ce213e81d7ce80930115afc9f71\nlevel 14, file files/g100000\n29c1d79c3dc1dc51ec4ee3fd19fdbd10\nlevel 14, file files/g1000000\n7721785c341760a66ac9e2fb39cfeb33\nlevel 14, file files/g20000\n1055a0a808598d1eedf0442fceff44e0\nlevel 14, file files/g200000\n87df6235943fd09ba3f6a1f24cbc3a3a\nlevel 14, file files/g30000\n74c32e0cd8bcd62bd4e1cf599c193abf\nlevel 14, file files/g50000\n10d3bbb5e9822fa5c31fc2e79aeae7e9\nlevel 14, file files/g500000\nf8865d65f1790f723184007b2f940127\nlevel 15, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 15, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 15, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 15, file files/g100\ne6e88e42b891fbc82c87a60928d88e97\nlevel 15, file files/g1000\n773b6b59d472db0932b5ad1ad75eac64\nlevel 15, file files/g10000\ndfd1e66b36c80b191c338d0b14813920\nlevel 15, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 15, file files/g10000-P10\n40b5f47e143e235198f6408a099208e8\nlevel 15, file files/g10000-P100\n049015191cf579b24653c8730fcc10f5\nlevel 15, file files/g10000-P25\ndeaa99c2458ca8ea661b358ef837ef58\nlevel 15, file files/g10000-P50\n91cc04148eef18ae4222038ad05f0586\nlevel 15, file files/g10000-P75\naa5e9e619fe89644098c9ad17a8b9ad4\nlevel 15, file files/g10000-P90\n28d6d71a33f507d1e7acd56d586e3981\nlevel 15, file files/g100000\n29c1d79c3dc1dc51ec4ee3fd19fdbd10\nlevel 15, file files/g1000000\nde1091b6021db006820019edfcb1384c\nlevel 15, file files/g20000\n1055a0a808598d1eedf0442fceff44e0\nlevel 15, file files/g200000\n0096718cf88b77da67fc2211bf85e3ca\nlevel 15, file files/g30000\n74c32e0cd8bcd62bd4e1cf599c193abf\nlevel 15, file files/g50000\n10d3bbb5e9822fa5c31fc2e79aeae7e9\nlevel 15, file files/g500000\n53aa49e42ffac4621397b88d4749c9c0\nlevel 16, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 16, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 16, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 16, file files/g100\ne6e88e42b891fbc82c87a60928d88e97\nlevel 16, file files/g1000\nf3eeeae11e293292fe1810d8745d0ae1\nlevel 16, file files/g10000\n23c5d58cca20ab65ff8a5d780f09e075\nlevel 16, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 16, file files/g10000-P10\ncced9c0f5709262da932fc8540bb72f4\nlevel 16, file files/g10000-P100\n049015191cf579b24653c8730fcc10f5\nlevel 16, file files/g10000-P25\n6676c9b599408491f7abc00947782054\nlevel 16, file files/g10000-P50\n9af82247b7fe18900592ae4fd5f1890a\nlevel 16, file files/g10000-P75\nd44f2305f023fbff3d1a872ab740958a\nlevel 16, file files/g10000-P90\n517f98319c717526b5e211079f073fbc\nlevel 16, file files/g100000\n95ec61667f371a3621b34a042f1f4a0a\nlevel 16, file files/g1000000\nb71641629b58754f1961ac394f177d7c\nlevel 16, file files/g20000\n7bd4e03d703ead21e15fddd4423ef79e\nlevel 16, file files/g200000\nfd1c701e9872f304a71f0e7f7aa9f918\nlevel 16, file files/g30000\nbc2211b250b5f4ed0a7bd97d447132e0\nlevel 16, file files/g50000\na6d98ebd2ed96688482c7d1181dded42\nlevel 16, file files/g500000\n44e339bb9e57842b77476f6d75ff3fbd\nlevel 17, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 17, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 17, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 17, file files/g100\ne6e88e42b891fbc82c87a60928d88e97\nlevel 17, file files/g1000\nf3eeeae11e293292fe1810d8745d0ae1\nlevel 17, file files/g10000\n23c5d58cca20ab65ff8a5d780f09e075\nlevel 17, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 17, file files/g10000-P10\ncced9c0f5709262da932fc8540bb72f4\nlevel 17, file files/g10000-P100\n049015191cf579b24653c8730fcc10f5\nlevel 17, file files/g10000-P25\n6676c9b599408491f7abc00947782054\nlevel 17, file files/g10000-P50\n607968cd37d41631312307f6c8a37ab4\nlevel 17, file files/g10000-P75\n818c2b0124e0dad26f9d95d753b11140\nlevel 17, file files/g10000-P90\n2d01bb79185ec88e5d7e684d3983eff8\nlevel 17, file files/g100000\n95ec61667f371a3621b34a042f1f4a0a\nlevel 17, file files/g1000000\ncbd03f012664a02441271c50ba1330bf\nlevel 17, file files/g20000\n7bd4e03d703ead21e15fddd4423ef79e\nlevel 17, file files/g200000\nfd1c701e9872f304a71f0e7f7aa9f918\nlevel 17, file files/g30000\nbc2211b250b5f4ed0a7bd97d447132e0\nlevel 17, file files/g50000\na6d98ebd2ed96688482c7d1181dded42\nlevel 17, file files/g500000\n01223076923dc7e3e06eeb3d71c467d2\nlevel 18, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 18, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 18, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 18, file files/g100\ne6e88e42b891fbc82c87a60928d88e97\nlevel 18, file files/g1000\nf3eeeae11e293292fe1810d8745d0ae1\nlevel 18, file files/g10000\n23c5d58cca20ab65ff8a5d780f09e075\nlevel 18, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 18, file files/g10000-P10\ncced9c0f5709262da932fc8540bb72f4\nlevel 18, file files/g10000-P100\n049015191cf579b24653c8730fcc10f5\nlevel 18, file files/g10000-P25\n6676c9b599408491f7abc00947782054\nlevel 18, file files/g10000-P50\nc61ad9309da86f7229498e46daacd6d9\nlevel 18, file files/g10000-P75\n8bf1c42a6a1f46ff8549e87f7b6daa54\nlevel 18, file files/g10000-P90\n29077b7a282975006c20701bca0d439d\nlevel 18, file files/g100000\n95ec61667f371a3621b34a042f1f4a0a\nlevel 18, file files/g1000000\n1e598049810de86924756bcda8941085\nlevel 18, file files/g20000\n7bd4e03d703ead21e15fddd4423ef79e\nlevel 18, file files/g200000\nab03b5ab84b6ebe79fa325118a895c6b\nlevel 18, file files/g30000\nbc2211b250b5f4ed0a7bd97d447132e0\nlevel 18, file files/g50000\na6d98ebd2ed96688482c7d1181dded42\nlevel 18, file files/g500000\n1b5374095c0bdc676655fe4db94286d1\nlevel 19, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 19, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 19, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 19, file files/g100\ne6e88e42b891fbc82c87a60928d88e97\nlevel 19, file files/g1000\nf3eeeae11e293292fe1810d8745d0ae1\nlevel 19, file files/g10000\n23c5d58cca20ab65ff8a5d780f09e075\nlevel 19, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 19, file files/g10000-P10\ncced9c0f5709262da932fc8540bb72f4\nlevel 19, file files/g10000-P100\n049015191cf579b24653c8730fcc10f5\nlevel 19, file files/g10000-P25\n6676c9b599408491f7abc00947782054\nlevel 19, file files/g10000-P50\nc61ad9309da86f7229498e46daacd6d9\nlevel 19, file files/g10000-P75\nd3171f297dfd08e444d481b30b1bbefa\nlevel 19, file files/g10000-P90\n87c4a59ec6e15f6da86b26969044a8a4\nlevel 19, file files/g100000\n7ae11dc1919d94e80979d41d12a0b578\nlevel 19, file files/g1000000\nd4b9ee8879d7f30bed3ec9e70520ca67\nlevel 19, file files/g20000\n70028792166e24282f5497592b632192\nlevel 19, file files/g200000\nab03b5ab84b6ebe79fa325118a895c6b\nlevel 19, file files/g30000\nd698feea5119e141a08656439c4c1508\nlevel 19, file files/g50000\nb81384753f0db76004ac97681f6ef757\nlevel 19, file files/g500000\n0a25ba39483255a2c16899ab80a3ed8f\nlevel 1, long=18, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 19, long=18, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 1, long=18, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 19, long=18, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 1, long=18, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 19, long=18, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 1, long=18, file files/g100\nc94d1ef6bbec8b4899486b06207ee829\nlevel 19, long=18, file files/g100\ne6e88e42b891fbc82c87a60928d88e97\nlevel 1, long=18, file files/g1000\n6bf2f4b179864fd8db4676037465feed\nlevel 19, long=18, file files/g1000\nf3eeeae11e293292fe1810d8745d0ae1\nlevel 1, long=18, file files/g10000\n2ae44c4053b2b47724c8f612dfb60d24\nlevel 19, long=18, file files/g10000\n23c5d58cca20ab65ff8a5d780f09e075\nlevel 1, long=18, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 19, long=18, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 1, long=18, file files/g10000-P10\n6a8f6e75ab538eb08a422febc8b68006\nlevel 19, long=18, file files/g10000-P10\ncced9c0f5709262da932fc8540bb72f4\nlevel 1, long=18, file files/g10000-P100\n5db6fbe04a2de772ad4e49f5357d0543\nlevel 19, long=18, file files/g10000-P100\n049015191cf579b24653c8730fcc10f5\nlevel 1, long=18, file files/g10000-P25\n6fd603b31365845346faab9cd64fd647\nlevel 19, long=18, file files/g10000-P25\n6676c9b599408491f7abc00947782054\nlevel 1, long=18, file files/g10000-P50\nd1de679e9a8c962ed1cc668a96bf930a\nlevel 19, long=18, file files/g10000-P50\nc61ad9309da86f7229498e46daacd6d9\nlevel 1, long=18, file files/g10000-P75\ndcf9822423e2ad42a569985707cd5ab4\nlevel 19, long=18, file files/g10000-P75\nf0ea19930e3866ff7a1932931346e0ac\nlevel 1, long=18, file files/g10000-P90\n87d249fd8c1ad0064d067a1e5ad97647\nlevel 19, long=18, file files/g10000-P90\n582e2c4c5a06e452d8dae22e7210c070\nlevel 1, long=18, file files/g100000\ndaa38a869130494c077290cf54f2d895\nlevel 19, long=18, file files/g100000\n7ae11dc1919d94e80979d41d12a0b578\nlevel 1, long=18, file files/g1000000\n81b9ffd138f3b25254a7078b06950e5f\nlevel 19, long=18, file files/g1000000\ndb54f06bf3abdbfd57892ab3aad18233\nlevel 1, long=18, file files/g20000\n1da5b56511e8693867c0cdd962c521aa\nlevel 19, long=18, file files/g20000\n70028792166e24282f5497592b632192\nlevel 1, long=18, file files/g200000\n17eb9ff8d912da9c445def85cb748e54\nlevel 19, long=18, file files/g200000\nab03b5ab84b6ebe79fa325118a895c6b\nlevel 1, long=18, file files/g30000\n788bc5abca5e33d79bb79a4eca98b9cd\nlevel 19, long=18, file files/g30000\nd698feea5119e141a08656439c4c1508\nlevel 1, long=18, file files/g50000\n0bf9fafd84a2d56a788a9159f1f23f26\nlevel 19, long=18, file files/g50000\nb81384753f0db76004ac97681f6ef757\nlevel 1, long=18, file files/g500000\nf035223dc02f581daf5dd79773c4dc2b\nlevel 19, long=18, file files/g500000\n97093f718faf7b9094e27ea822fd1a29\nlevel -1, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel -1, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel -1, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel -1, file files/g100\neb805e7fdb95bc42231b20d0e12e2a53\nlevel -1, file files/g1000\nac7c900e31b9e4fe37b7846a898c7d48\nlevel -1, file files/g10000\n55e1e6ed7fcf5581a17f72f3a32e0834\nlevel -1, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel -1, file files/g10000-P10\n0bf549bdfc20b644c37901918de0d0eb\nlevel -1, file files/g10000-P100\n93436482b4da30ce2300d356448c8990\nlevel -1, file files/g10000-P25\nb65475ee206e480b3adc9fcc7b79c54b\nlevel -1, file files/g10000-P50\nae4bf85c8343052ecb1d666bd9766fbc\nlevel -1, file files/g10000-P75\nb0674333f519e71708f226f935ae63d5\nlevel -1, file files/g10000-P90\n2daa80aa34a8259fed7e04ae41397d6c\nlevel -1, file files/g100000\n586e12a3aa574f35aedf0afadee3040c\nlevel -1, file files/g1000000\n1cc8eb9ee1e4c20373fe3c1b0aa1a982\nlevel -1, file files/g20000\nb220e6387b1f5036c203f8be5f1a571c\nlevel -1, file files/g200000\nfc42db710c19a4f4a27f004fb4678d9c\nlevel -1, file files/g30000\n5350a7346d815f4ad42216b91ba8749a\nlevel -1, file files/g50000\n4f00a5a94e8f98c6972053057f6ac971\nlevel -1, file files/g500000\n4abb2e46c936c273955778c00f3eb492\n"
  },
  {
    "path": "tests/cli-tests/determinism/multithread.sh",
    "content": "#!/bin/sh\n\n. \"$COMMON/platform.sh\"\n\nset -e\n\n# To update checksums on version change run this from the tests/ directory\n# make update-cli-tests\n\nif [ -n \"$NON_DETERMINISTIC\" ] || [ -z \"$hasMT\" ]; then\n    # Skip tests if we have a non-deterministic build\n    cat \"$CLI_TESTS/determinism/multithread.sh.stdout.exact\"\n    exit 0\nfi\n\nfor level in 1 3 7 19; do\n    for file in $(ls files/); do\n        file=\"files/$file\"\n        echo \"level $level, file $file\"\n        zstd -T2 -q -$level $file -c | md5hash\n    done\ndone\n\nfor file in $(ls files/); do\n    file=\"files/$file\"\n    echo \"level 1, long=18, file $file\"\n    zstd --long=18 -T2 -q -1 $file -c | md5hash\n    echo \"level 19, long=18, file $file\"\n    zstd --long=18 -T2 -q -19 $file -c | md5hash\ndone\n\nfor file in $(ls files/); do\n    file=\"files/$file\"\n    echo \"Vary number of threads on $file\"\n    zstd -qf -1 $file -o $file.zst.good\n\n    zstd -qf -T1 -1 $file\n    $DIFF $file.zst $file.zst.good\n\n    zstd -qf -T2 -1 $file\n    $DIFF $file.zst $file.zst.good\n\n    zstd -qf -T4 -1 $file\n    $DIFF $file.zst $file.zst.good\ndone\n"
  },
  {
    "path": "tests/cli-tests/determinism/multithread.sh.stderr.exact",
    "content": ""
  },
  {
    "path": "tests/cli-tests/determinism/multithread.sh.stdout.exact",
    "content": "level 1, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 1, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 1, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 1, file files/g100\nc94d1ef6bbec8b4899486b06207ee829\nlevel 1, file files/g1000\n6bf2f4b179864fd8db4676037465feed\nlevel 1, file files/g10000\n2ae44c4053b2b47724c8f612dfb60d24\nlevel 1, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 1, file files/g10000-P10\n2d0eeab6a966098583a1dfeafb5090c1\nlevel 1, file files/g10000-P100\n93436482b4da30ce2300d356448c8990\nlevel 1, file files/g10000-P25\nc64b5f512c44b6a647da81753791b9a7\nlevel 1, file files/g10000-P50\n3982325490d90c8307e734c1b25790df\nlevel 1, file files/g10000-P75\nb7504f80fee16b5ba6a0f46571eb563a\nlevel 1, file files/g10000-P90\n350892bec7f7ad6a7d6af01c5d8b07c7\nlevel 1, file files/g100000\ndaa38a869130494c077290cf54f2d895\nlevel 1, file files/g1000000\na1d548531221d408b95dc5d9c600b3f0\nlevel 1, file files/g20000\n1da5b56511e8693867c0cdd962c521aa\nlevel 1, file files/g200000\n41fb3b3d46d4221f2f0b072c65dd6e0a\nlevel 1, file files/g30000\n788bc5abca5e33d79bb79a4eca98b9cd\nlevel 1, file files/g50000\n0bf9fafd84a2d56a788a9159f1f23f26\nlevel 1, file files/g500000\n73401d6df0657e091de20468f32579a9\nlevel 3, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 3, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 3, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 3, file files/g100\nc94d1ef6bbec8b4899486b06207ee829\nlevel 3, file files/g1000\n3ec47dcb2d606b9fdef3f19b1304f8fe\nlevel 3, file files/g10000\n69a9d518b84fe2a66b57dfb4ab8905ae\nlevel 3, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 3, file files/g10000-P10\nac9866ac355c4ed8939deb9fbeec1aef\nlevel 3, file files/g10000-P100\n93436482b4da30ce2300d356448c8990\nlevel 3, file files/g10000-P25\n5e1fe7a3831f6632bc8c9873ab8b633d\nlevel 3, file files/g10000-P50\n76295f181396a98565eb9cc69b96dc75\nlevel 3, file files/g10000-P75\n1f751dc70508e81fef197311e8583e99\nlevel 3, file files/g10000-P90\n47c7b061c299dc253c6aaaf489e936cb\nlevel 3, file files/g100000\n4b30b2be3394f03f1cf1f37a08dcec12\nlevel 3, file files/g1000000\n4301dea72cc4dd6162e46caa59788a09\nlevel 3, file files/g20000\n30456361833d27c0962c2faaa254e615\nlevel 3, file files/g200000\n0f01c07c57d60298dd54c6b6b197c3d3\nlevel 3, file files/g30000\n0b3c506a1b1b6ccbb54a852c370f5cdc\nlevel 3, file files/g50000\n81368c0b96bf1a2f318940b836b46074\nlevel 3, file files/g500000\n0c1ef9c6d3d75bfa0dd5d893f65da47c\nlevel 7, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 7, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 7, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 7, file files/g100\nc94d1ef6bbec8b4899486b06207ee829\nlevel 7, file files/g1000\n19187f900e7540efdcab3735f489f718\nlevel 7, file files/g10000\n495f1e5d30de3b34c5a76301875fa231\nlevel 7, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 7, file files/g10000-P10\n8a91fa2460ec9bd0387baa31beb81060\nlevel 7, file files/g10000-P100\n15fede9faa3d7c484dead66071fb8c5d\nlevel 7, file files/g10000-P25\n7dc0563f2e66a2e57c0f119e4d5e636e\nlevel 7, file files/g10000-P50\ne93a6eb179f7b26daa896328b2583b04\nlevel 7, file files/g10000-P75\ncb1e5facfc34fca7323000c6188ad657\nlevel 7, file files/g10000-P90\ne9984c6557f5a392f16e5c139dbe4994\nlevel 7, file files/g100000\n6e493dbe2985fec69860ef34728ac01a\nlevel 7, file files/g1000000\n455023a055f3a4de76c7295408ce3c8f\nlevel 7, file files/g20000\n2359efcd587e36ac9b74a8344bbf0e53\nlevel 7, file files/g200000\nca80dbc88183a5aabb4aae955c449dff\nlevel 7, file files/g30000\n7e1be7e841c9fddd776dbe94b50db0ab\nlevel 7, file files/g50000\n09b80b58d70622de6f2354a06c15cb2a\nlevel 7, file files/g500000\nc90609f0558f0979eccb572ce0af4aa3\nlevel 19, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 19, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 19, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 19, file files/g100\ne6e88e42b891fbc82c87a60928d88e97\nlevel 19, file files/g1000\nf3eeeae11e293292fe1810d8745d0ae1\nlevel 19, file files/g10000\n23c5d58cca20ab65ff8a5d780f09e075\nlevel 19, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 19, file files/g10000-P10\ncced9c0f5709262da932fc8540bb72f4\nlevel 19, file files/g10000-P100\n049015191cf579b24653c8730fcc10f5\nlevel 19, file files/g10000-P25\n6676c9b599408491f7abc00947782054\nlevel 19, file files/g10000-P50\nc61ad9309da86f7229498e46daacd6d9\nlevel 19, file files/g10000-P75\nd3171f297dfd08e444d481b30b1bbefa\nlevel 19, file files/g10000-P90\n87c4a59ec6e15f6da86b26969044a8a4\nlevel 19, file files/g100000\n7ae11dc1919d94e80979d41d12a0b578\nlevel 19, file files/g1000000\nd4b9ee8879d7f30bed3ec9e70520ca67\nlevel 19, file files/g20000\n70028792166e24282f5497592b632192\nlevel 19, file files/g200000\nab03b5ab84b6ebe79fa325118a895c6b\nlevel 19, file files/g30000\nd698feea5119e141a08656439c4c1508\nlevel 19, file files/g50000\nb81384753f0db76004ac97681f6ef757\nlevel 19, file files/g500000\n0a25ba39483255a2c16899ab80a3ed8f\nlevel 1, long=18, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 19, long=18, file files/g0\n5d80401e01d33084c65e94f93351e94c\nlevel 1, long=18, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 19, long=18, file files/g1\n8436b07a7eb916ac9c48af847b7e612f\nlevel 1, long=18, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 19, long=18, file files/g10\n6cf177a3e6494ac3c76c857df6a9b31d\nlevel 1, long=18, file files/g100\nc94d1ef6bbec8b4899486b06207ee829\nlevel 19, long=18, file files/g100\ne6e88e42b891fbc82c87a60928d88e97\nlevel 1, long=18, file files/g1000\n6bf2f4b179864fd8db4676037465feed\nlevel 19, long=18, file files/g1000\nf3eeeae11e293292fe1810d8745d0ae1\nlevel 1, long=18, file files/g10000\n2ae44c4053b2b47724c8f612dfb60d24\nlevel 19, long=18, file files/g10000\n23c5d58cca20ab65ff8a5d780f09e075\nlevel 1, long=18, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 19, long=18, file files/g10000-P0\n6c2641d3b83775c50b766793b39967c4\nlevel 1, long=18, file files/g10000-P10\n6a8f6e75ab538eb08a422febc8b68006\nlevel 19, long=18, file files/g10000-P10\ncced9c0f5709262da932fc8540bb72f4\nlevel 1, long=18, file files/g10000-P100\n5db6fbe04a2de772ad4e49f5357d0543\nlevel 19, long=18, file files/g10000-P100\n049015191cf579b24653c8730fcc10f5\nlevel 1, long=18, file files/g10000-P25\n6fd603b31365845346faab9cd64fd647\nlevel 19, long=18, file files/g10000-P25\n6676c9b599408491f7abc00947782054\nlevel 1, long=18, file files/g10000-P50\nd1de679e9a8c962ed1cc668a96bf930a\nlevel 19, long=18, file files/g10000-P50\nc61ad9309da86f7229498e46daacd6d9\nlevel 1, long=18, file files/g10000-P75\ndcf9822423e2ad42a569985707cd5ab4\nlevel 19, long=18, file files/g10000-P75\nf0ea19930e3866ff7a1932931346e0ac\nlevel 1, long=18, file files/g10000-P90\n87d249fd8c1ad0064d067a1e5ad97647\nlevel 19, long=18, file files/g10000-P90\n582e2c4c5a06e452d8dae22e7210c070\nlevel 1, long=18, file files/g100000\ndaa38a869130494c077290cf54f2d895\nlevel 19, long=18, file files/g100000\n7ae11dc1919d94e80979d41d12a0b578\nlevel 1, long=18, file files/g1000000\n2c410773bb02367d20d20569393faf1e\nlevel 19, long=18, file files/g1000000\ne3f5ef0204aedbac03e80d4300b3afc7\nlevel 1, long=18, file files/g20000\n1da5b56511e8693867c0cdd962c521aa\nlevel 19, long=18, file files/g20000\n70028792166e24282f5497592b632192\nlevel 1, long=18, file files/g200000\n17eb9ff8d912da9c445def85cb748e54\nlevel 19, long=18, file files/g200000\nab03b5ab84b6ebe79fa325118a895c6b\nlevel 1, long=18, file files/g30000\n788bc5abca5e33d79bb79a4eca98b9cd\nlevel 19, long=18, file files/g30000\nd698feea5119e141a08656439c4c1508\nlevel 1, long=18, file files/g50000\n0bf9fafd84a2d56a788a9159f1f23f26\nlevel 19, long=18, file files/g50000\nb81384753f0db76004ac97681f6ef757\nlevel 1, long=18, file files/g500000\nf035223dc02f581daf5dd79773c4dc2b\nlevel 19, long=18, file files/g500000\n97093f718faf7b9094e27ea822fd1a29\nVary number of threads on files/g0\nVary number of threads on files/g1\nVary number of threads on files/g10\nVary number of threads on files/g100\nVary number of threads on files/g1000\nVary number of threads on files/g10000\nVary number of threads on files/g10000-P0\nVary number of threads on files/g10000-P10\nVary number of threads on files/g10000-P100\nVary number of threads on files/g10000-P25\nVary number of threads on files/g10000-P50\nVary number of threads on files/g10000-P75\nVary number of threads on files/g10000-P90\nVary number of threads on files/g100000\nVary number of threads on files/g1000000\nVary number of threads on files/g20000\nVary number of threads on files/g200000\nVary number of threads on files/g30000\nVary number of threads on files/g50000\nVary number of threads on files/g500000\n"
  },
  {
    "path": "tests/cli-tests/determinism/reuse.sh",
    "content": "#!/bin/sh\n\n. \"$COMMON/platform.sh\"\n\nset -e\n\n# To update checksums on version change run this from the tests/ directory\n# make update-cli-tests\n\nif [ -n \"$NON_DETERMINISTIC\" ]; then\n    # Skip tests if we have a non-deterministic build\n    cat \"$CLI_TESTS/determinism/reuse.sh.stdout.exact\"\n    exit 0\nfi\n\ndatagen -g0 > file0\ndatagen -g1 > file1\ndatagen -g1000 > file1000\ndatagen -g100000 > file100000\n\nvalidate() {\n    $DIFF file0.zst file0.zst.good\n    $DIFF file1.zst file1.zst.good\n    $DIFF file1000.zst file1000.zst.good\n    $DIFF file100000.zst file100000.zst.good\n}\n\n# Check that context reuse doesn't impact determinism\nfor level in $(seq 1 19); do\n    echo $level\n    zstd -qf --single-thread -$level file0 -o file0.zst.good\n    zstd -qf --single-thread -$level file1 -o file1.zst.good\n    zstd -qf --single-thread -$level file1000 -o file1000.zst.good\n    zstd -qf --single-thread -$level file100000 -o file100000.zst.good\n\n    zstd -qf --single-thread -$level file0 file1 file1000 file100000\n    validate\n    zstd -qf --single-thread -$level file1 file0 file1000 file100000\n    validate\n    zstd -qf --single-thread -$level file1000 file1 file0 file100000\n    validate\n    zstd -qf --single-thread -$level file100000 file1000 file1 file0\n    validate\ndone\n"
  },
  {
    "path": "tests/cli-tests/determinism/reuse.sh.stderr.exact",
    "content": ""
  },
  {
    "path": "tests/cli-tests/determinism/reuse.sh.stdout.exact",
    "content": "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n"
  },
  {
    "path": "tests/cli-tests/determinism/setup",
    "content": "#!/bin/sh\n\nset -e\n\ncp -r ../files .\n"
  },
  {
    "path": "tests/cli-tests/determinism/setup_once",
    "content": "#!/bin/sh\n\nset -e\n\n. \"$COMMON/platform.sh\"\n\n\nmkdir files/\n\ndatagen -g0 > files/g0\ndatagen -g1 > files/g1\ndatagen -g10 > files/g10\ndatagen -g100 > files/g100\ndatagen -g1000 > files/g1000\ndatagen -g10000 > files/g10000\ndatagen -g20000 > files/g20000\ndatagen -g30000 > files/g30000\ndatagen -g50000 > files/g50000\ndatagen -g100000 > files/g100000\ndatagen -g200000 > files/g200000\ndatagen -g500000 > files/g500000\ndatagen -g1000000 > files/g1000000\n\ndatagen -g10000 -P0 > files/g10000-P0\ndatagen -g10000 -P10 > files/g10000-P10\ndatagen -g10000 -P25 > files/g10000-P25\ndatagen -g10000 -P50 > files/g10000-P50\ndatagen -g10000 -P75 > files/g10000-P75\ndatagen -g10000 -P90 > files/g10000-P90\ndatagen -g10000 -P100 > files/g10000-P100\n"
  },
  {
    "path": "tests/cli-tests/dict-builder/empty-input.sh",
    "content": "#!/bin/sh\nset -e\nfor i in $(seq 50); do\n    datagen -s$i > file$i\ndone\ntouch empty\n\nset -v\nzstd -q --train empty file*\n"
  },
  {
    "path": "tests/cli-tests/dict-builder/empty-input.sh.stderr.exact",
    "content": "zstd -q --train empty file*\n"
  },
  {
    "path": "tests/cli-tests/dict-builder/no-inputs.sh",
    "content": "#!/bin/sh\nset -v\nzstd --train\n"
  },
  {
    "path": "tests/cli-tests/dict-builder/no-inputs.sh.exit",
    "content": "14\n"
  },
  {
    "path": "tests/cli-tests/dict-builder/no-inputs.sh.stderr.exact",
    "content": "zstd --train\n!  Warning : nb of samples too low for proper processing !\n!  Please provide _one file per sample_.\n!  Alternatively, split file(s) into fixed-size samples, with --split=#\nError 14 : nb of samples too low\n"
  },
  {
    "path": "tests/cli-tests/dictionaries/dictionary-mismatch.sh",
    "content": "#!/bin/sh\n\n. \"$COMMON/platform.sh\"\n\nset -e\n\nif [ false ]; then\n\tfor seed in $(seq 100); do\n\t\tdatagen -g1000 -s$seed > file$seed\n\tdone\n\n\tzstd --train -r . -o dict0 -qq\n\n\tfor seed in $(seq 101 200); do\n\t\tdatagen -g1000 -s$seed > file$seed\n\tdone\n\n\tzstd --train -r . -o dict1 -qq\n\n\t[ \"$($MD5SUM < dict0)\" != \"$($MD5SUM < dict1)\" ] || die \"dictionaries must not match\"\n\n\tdatagen -g1000 -s0 > file0\nfi\n\nset -v\nzstd files/0 -D dicts/0 -q\nzstd -t files/0.zst -D dicts/0\nzstd -t files/0.zst -D dicts/1 && die \"Must fail\" ||:\nzstd -t files/0.zst            && die \"Must fail\" ||:\n"
  },
  {
    "path": "tests/cli-tests/dictionaries/dictionary-mismatch.sh.stderr.exact",
    "content": "zstd files/0 -D dicts/0 -q\nzstd -t files/0.zst -D dicts/0\nfiles/0.zst         : 1000 bytes \nzstd -t files/0.zst -D dicts/1 && die \"Must fail\" ||:\nfiles/0.zst : Decoding error (36) : Dictionary mismatch \nzstd -t files/0.zst            && die \"Must fail\" ||:\nfiles/0.zst : Decoding error (36) : Dictionary mismatch \n"
  },
  {
    "path": "tests/cli-tests/dictionaries/golden.sh",
    "content": "#!/bin/sh\n\nset -e\n\nGOLDEN_COMP_DIR=\"$ZSTD_REPO_DIR/tests/golden-compression/\"\nGOLDEN_DICT_DIR=\"$ZSTD_REPO_DIR/tests/golden-dictionaries/\"\n\nzstd -D \"$GOLDEN_DICT_DIR/http-dict-missing-symbols\" \"$GOLDEN_COMP_DIR/http\" -o http.zst\nzstd -D \"$GOLDEN_DICT_DIR/http-dict-missing-symbols\" -t http.zst\n"
  },
  {
    "path": "tests/cli-tests/dictionaries/setup",
    "content": "#!/bin/sh\n\nset -e\n\ncp -r ../files .\ncp -r ../dicts .\n"
  },
  {
    "path": "tests/cli-tests/dictionaries/setup_once",
    "content": "#!/bin/sh\n\nset -e\n\n. \"$COMMON/platform.sh\"\n\n\nmkdir files/ dicts/\n\nfor seed in $(seq 50); do\n\tdatagen -g1000 -s$seed > files/$seed\ndone\n\nzstd --train -r files -o dicts/0 -qq\n\nfor seed in $(seq 51 100); do\n\tdatagen -g1000 -s$seed > files/$seed\ndone\n\nzstd --train -r files -o dicts/1 -qq\n\ncmp dicts/0 dicts/1 && die \"dictionaries must not match!\"\n\ndatagen -g1000 > files/0\n"
  },
  {
    "path": "tests/cli-tests/file-handling/directory-mirror.sh",
    "content": "#!/bin/sh\nset -e\n\n# setup\nmkdir -p src/.hidden src/dir\nmkdir mid dst\n\necho \"file1\" > src/file1\necho \"file2\" > src/.file2\necho \"file3\" > src/.hidden/.file3\necho \"file4\" > src/dir/.file4\n\n# relative paths\nzstd -q -r --output-dir-mirror mid/ src/\nzstd -q -d -r --output-dir-mirror dst/ mid/src/\n\ndiff --brief --recursive --new-file src/ dst/mid/src/\n\n# reset\nrm -rf mid dst\nmkdir mid dst\n\n# from inside the directory\n(cd src; zstd -q -r --output-dir-mirror ../mid/ ./)\n(cd mid; zstd -q -d -r --output-dir-mirror ../dst/ ./)\n\ndiff --brief --recursive --new-file src/ dst/\n\n# reset\nrm -rf mid dst\nmkdir mid dst\n\n# absolute paths\nexport BASE_PATH=\"$(pwd)\"\n\nzstd -q -r --output-dir-mirror mid/ \"${BASE_PATH}/src/\"\nzstd -q -d -r --output-dir-mirror  dst/ \"${BASE_PATH}/mid/${BASE_PATH}/src/\"\n\ndiff --brief --recursive --new-file src/ \"dst/${BASE_PATH}/mid/${BASE_PATH}/src/\"\n\n# reset\nrm -rf mid dst\nmkdir mid dst\n\n# dots\nzstd -q -r --output-dir-mirror mid/ ./src/./\nzstd -q -d -r --output-dir-mirror  dst/ ./mid/./src/./\n\ndiff --brief --recursive --new-file src/ dst/mid/src/\n"
  },
  {
    "path": "tests/cli-tests/file-handling/directory-mirror.sh.stderr.exact",
    "content": ""
  },
  {
    "path": "tests/cli-tests/file-handling/directory-mirror.sh.stdout.exact",
    "content": ""
  },
  {
    "path": "tests/cli-tests/file-stat/compress-file-to-dir-without-write-perm.sh",
    "content": "#!/bin/sh\n\n# motivated by issue #3523\n\ndatagen > file\nmkdir out\nchmod 000 out\n\nzstd file -q --trace-file-stat -o out/file.zst\nzstd -tq out/file.zst\n\nchmod 777 out\n"
  },
  {
    "path": "tests/cli-tests/file-stat/compress-file-to-dir-without-write-perm.sh.stderr.exact",
    "content": "Trace:FileStat: > UTIL_isLink(file)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isConsole(2)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_getFileSize(file)\nTrace:FileStat:  > UTIL_stat(-1, file)\nTrace:FileStat:  < 1\nTrace:FileStat: < 65537\nTrace:FileStat: > UTIL_stat(-1, file)\nTrace:FileStat: < 1\nTrace:FileStat: > UTIL_isDirectoryStat()\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_stat(-1, file)\nTrace:FileStat: < 1\nTrace:FileStat: > UTIL_isSameFile(file, out/file.zst)\nTrace:FileStat:  > UTIL_stat(-1, file)\nTrace:FileStat:  < 1\nTrace:FileStat:  > UTIL_stat(-1, out/file.zst)\nTrace:FileStat:  < 0\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isRegularFile(out/file.zst)\nTrace:FileStat:  > UTIL_stat(-1, out/file.zst)\nTrace:FileStat:  < 0\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isFdRegularFile(-1)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isFileDescriptorPipe(out/file.zst)\nTrace:FileStat: < 0\nzstd: out/file.zst: Permission denied\nzstd: can't stat out/file.zst : Permission denied -- ignored \n"
  },
  {
    "path": "tests/cli-tests/file-stat/compress-file-to-file.sh",
    "content": "#!/bin/sh\n\nset -e\n\ndatagen > file\nchmod 642 file\n\nzstd file -q --trace-file-stat -o file.zst\nzstd -tq file.zst\n"
  },
  {
    "path": "tests/cli-tests/file-stat/compress-file-to-file.sh.stderr.glob",
    "content": "Trace:FileStat: > UTIL_isLink(file)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isConsole(2)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_getFileSize(file)\nTrace:FileStat:  > UTIL_stat(-1, file)\nTrace:FileStat:  < 1\nTrace:FileStat: < 65537\nTrace:FileStat: > UTIL_stat(-1, file)\nTrace:FileStat: < 1\nTrace:FileStat: > UTIL_isDirectoryStat()\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_stat(-1, file)\nTrace:FileStat: < 1\nTrace:FileStat: > UTIL_isSameFile(file, file.zst)\nTrace:FileStat:  > UTIL_stat(-1, file)\nTrace:FileStat:  < 1\nTrace:FileStat:  > UTIL_stat(-1, file.zst)\nTrace:FileStat:  < 0\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isRegularFile(file.zst)\nTrace:FileStat:  > UTIL_stat(-1, file.zst)\nTrace:FileStat:  < 0\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isFdRegularFile(*)\nTrace:FileStat:  > UTIL_stat(*, )\nTrace:FileStat:  < 1\nTrace:FileStat: < 1\nTrace:FileStat: > UTIL_isRegularFile(file.zst)\nTrace:FileStat:  > UTIL_stat(-1, file.zst)\nTrace:FileStat:  < 1\nTrace:FileStat: < 1\nTrace:FileStat: > UTIL_getFileSize(file)\nTrace:FileStat:  > UTIL_stat(-1, file)\nTrace:FileStat:  < 1\nTrace:FileStat: < 65537\nTrace:FileStat: > UTIL_setFileStat(4, file.zst)\nTrace:FileStat:  > UTIL_stat(4, file.zst)\nTrace:FileStat:  < 1\nTrace:FileStat:  > UTIL_chmod(file.zst, 0642)\nTrace:FileStat:   > fchmod\nTrace:FileStat:   < 0\nTrace:FileStat:  < 0\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_utime(file.zst)\nTrace:FileStat: < 0\n"
  },
  {
    "path": "tests/cli-tests/file-stat/compress-file-to-stdout.sh",
    "content": "#!/bin/sh\n\nset -e\n\ndatagen > file\n\nzstd file -cq --trace-file-stat > file.zst\nzstd -tq file.zst\n"
  },
  {
    "path": "tests/cli-tests/file-stat/compress-file-to-stdout.sh.stderr.exact",
    "content": "Trace:FileStat: > UTIL_isLink(file)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isConsole(1)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isConsole(2)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_getFileSize(file)\nTrace:FileStat:  > UTIL_stat(-1, file)\nTrace:FileStat:  < 1\nTrace:FileStat: < 65537\nTrace:FileStat: > UTIL_stat(-1, file)\nTrace:FileStat: < 1\nTrace:FileStat: > UTIL_isDirectoryStat()\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_stat(-1, file)\nTrace:FileStat: < 1\nTrace:FileStat: > UTIL_isRegularFile(/*stdout*\\)\nTrace:FileStat:  > UTIL_stat(-1, /*stdout*\\)\nTrace:FileStat:  < 0\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_getFileSize(file)\nTrace:FileStat:  > UTIL_stat(-1, file)\nTrace:FileStat:  < 1\nTrace:FileStat: < 65537\n"
  },
  {
    "path": "tests/cli-tests/file-stat/compress-stdin-to-file.sh",
    "content": "#!/bin/sh\n\nset -e\n\ndatagen > file\n\nzstd < file -q --trace-file-stat -o file.zst\nzstd -tq file.zst\n"
  },
  {
    "path": "tests/cli-tests/file-stat/compress-stdin-to-file.sh.stderr.glob",
    "content": "Trace:FileStat: > UTIL_isConsole(0)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isConsole(2)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_getFileSize(/*stdin*\\)\nTrace:FileStat:  > UTIL_stat(-1, /*stdin*\\)\nTrace:FileStat:  < 0\nTrace:FileStat: < -1\nTrace:FileStat: > UTIL_isSameFile(/*stdin*\\, file.zst)\nTrace:FileStat:  > UTIL_stat(-1, /*stdin*\\)\nTrace:FileStat:  < 0\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isRegularFile(file.zst)\nTrace:FileStat:  > UTIL_stat(-1, file.zst)\nTrace:FileStat:  < 0\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isFdRegularFile(*)\nTrace:FileStat:  > UTIL_stat(*, )\nTrace:FileStat:  < 1\nTrace:FileStat: < 1\nTrace:FileStat: > UTIL_isRegularFile(file.zst)\nTrace:FileStat:  > UTIL_stat(-1, file.zst)\nTrace:FileStat:  < 1\nTrace:FileStat: < 1\nTrace:FileStat: > UTIL_getFileSize(/*stdin*\\)\nTrace:FileStat:  > UTIL_stat(-1, /*stdin*\\)\nTrace:FileStat:  < 0\nTrace:FileStat: < -1\n"
  },
  {
    "path": "tests/cli-tests/file-stat/compress-stdin-to-stdout.sh",
    "content": "#!/bin/sh\n\nset -e\n\ndatagen > file\n\nzstd < file -cq --trace-file-stat > file.zst\nzstd -tq file.zst\n"
  },
  {
    "path": "tests/cli-tests/file-stat/compress-stdin-to-stdout.sh.stderr.exact",
    "content": "Trace:FileStat: > UTIL_isConsole(0)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isConsole(1)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isConsole(2)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_getFileSize(/*stdin*\\)\nTrace:FileStat:  > UTIL_stat(-1, /*stdin*\\)\nTrace:FileStat:  < 0\nTrace:FileStat: < -1\nTrace:FileStat: > UTIL_isRegularFile(/*stdout*\\)\nTrace:FileStat:  > UTIL_stat(-1, /*stdout*\\)\nTrace:FileStat:  < 0\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_getFileSize(/*stdin*\\)\nTrace:FileStat:  > UTIL_stat(-1, /*stdin*\\)\nTrace:FileStat:  < 0\nTrace:FileStat: < -1\n"
  },
  {
    "path": "tests/cli-tests/file-stat/decompress-file-to-file.sh",
    "content": "#!/bin/sh\n\nset -e\n\ndatagen | zstd -q > file.zst\nchmod 642 file.zst\n\nzstd -dq --trace-file-stat file.zst\n"
  },
  {
    "path": "tests/cli-tests/file-stat/decompress-file-to-file.sh.stderr.glob",
    "content": "Trace:FileStat: > UTIL_isLink(file.zst)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isConsole(1)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isConsole(2)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isDirectory(file.zst)\nTrace:FileStat:  > UTIL_stat(-1, file.zst)\nTrace:FileStat:  < 1\nTrace:FileStat:  > UTIL_isDirectoryStat()\nTrace:FileStat:  < 0\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_stat(-1, file.zst)\nTrace:FileStat: < 1\nTrace:FileStat: > UTIL_isSameFile(file.zst, file)\nTrace:FileStat:  > UTIL_stat(-1, file.zst)\nTrace:FileStat:  < 1\nTrace:FileStat:  > UTIL_stat(-1, file)\nTrace:FileStat:  < 0\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isRegularFile(file)\nTrace:FileStat:  > UTIL_stat(-1, file)\nTrace:FileStat:  < 0\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isFdRegularFile(*)\nTrace:FileStat:  > UTIL_stat(*, )\nTrace:FileStat:  < 1\nTrace:FileStat: < 1\nTrace:FileStat: > UTIL_isRegularFile(file)\nTrace:FileStat:  > UTIL_stat(-1, file)\nTrace:FileStat:  < 1\nTrace:FileStat: < 1\nTrace:FileStat: > UTIL_setFileStat(4, file)\nTrace:FileStat:  > UTIL_stat(4, file)\nTrace:FileStat:  < 1\nTrace:FileStat:  > UTIL_chmod(file, 0642)\nTrace:FileStat:   > fchmod\nTrace:FileStat:   < 0\nTrace:FileStat:  < 0\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_utime(file)\nTrace:FileStat: < 0\n"
  },
  {
    "path": "tests/cli-tests/file-stat/decompress-file-to-stdout.sh",
    "content": "#!/bin/sh\n\nset -e\n\ndatagen | zstd -q > file.zst\n\nzstd -dcq --trace-file-stat file.zst > file\n"
  },
  {
    "path": "tests/cli-tests/file-stat/decompress-file-to-stdout.sh.stderr.exact",
    "content": "Trace:FileStat: > UTIL_isLink(file.zst)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isConsole(1)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isConsole(2)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isDirectory(file.zst)\nTrace:FileStat:  > UTIL_stat(-1, file.zst)\nTrace:FileStat:  < 1\nTrace:FileStat:  > UTIL_isDirectoryStat()\nTrace:FileStat:  < 0\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_stat(-1, file.zst)\nTrace:FileStat: < 1\nTrace:FileStat: > UTIL_isRegularFile(/*stdout*\\)\nTrace:FileStat:  > UTIL_stat(-1, /*stdout*\\)\nTrace:FileStat:  < 0\nTrace:FileStat: < 0\n"
  },
  {
    "path": "tests/cli-tests/file-stat/decompress-stdin-to-file.sh",
    "content": "#!/bin/sh\n\nset -e\n\ndatagen | zstd -q > file.zst\n\nzstd -dcq --trace-file-stat < file.zst -o file\n"
  },
  {
    "path": "tests/cli-tests/file-stat/decompress-stdin-to-file.sh.stderr.glob",
    "content": "Trace:FileStat: > UTIL_isConsole(0)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isConsole(2)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isDirectory(/*stdin*\\)\nTrace:FileStat:  > UTIL_stat(-1, /*stdin*\\)\nTrace:FileStat:  < 0\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isSameFile(/*stdin*\\, file)\nTrace:FileStat:  > UTIL_stat(-1, /*stdin*\\)\nTrace:FileStat:  < 0\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isRegularFile(file)\nTrace:FileStat:  > UTIL_stat(-1, file)\nTrace:FileStat:  < 0\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isFdRegularFile(*)\nTrace:FileStat:  > UTIL_stat(*, )\nTrace:FileStat:  < 1\nTrace:FileStat: < 1\nTrace:FileStat: > UTIL_isRegularFile(file)\nTrace:FileStat:  > UTIL_stat(-1, file)\nTrace:FileStat:  < 1\nTrace:FileStat: < 1\n"
  },
  {
    "path": "tests/cli-tests/file-stat/decompress-stdin-to-stdout.sh",
    "content": "#!/bin/sh\n\nset -e\n\ndatagen | zstd -q > file.zst\n\nzstd -dcq --trace-file-stat < file.zst > file\n"
  },
  {
    "path": "tests/cli-tests/file-stat/decompress-stdin-to-stdout.sh.stderr.exact",
    "content": "Trace:FileStat: > UTIL_isConsole(0)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isConsole(1)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isConsole(2)\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isDirectory(/*stdin*\\)\nTrace:FileStat:  > UTIL_stat(-1, /*stdin*\\)\nTrace:FileStat:  < 0\nTrace:FileStat: < 0\nTrace:FileStat: > UTIL_isRegularFile(/*stdout*\\)\nTrace:FileStat:  > UTIL_stat(-1, /*stdout*\\)\nTrace:FileStat:  < 0\nTrace:FileStat: < 0\n"
  },
  {
    "path": "tests/cli-tests/progress/no-progress.sh",
    "content": "#!/bin/sh\n\n#!/bin/sh\n\n. \"$COMMON/platform.sh\"\n\nset -e\n\necho hello > hello\necho world > world\n\nzstd -q hello world\n\nprintln >&2 \"Tests cases where progress information should not be printed\"\n\nfor args in \\\n\t\"\" \\\n\t\"--fake-stderr-is-console -q\" \\\n\t\"--fake-stderr-is-console -qq --progress\" \\\n\t\"--no-progress --fake-stderr-is-console\" \\\n\t\"--no-progress --fake-stderr-is-console -v\"\ndo\n\tprintln >&2 \"args = $args\"\n\tprintln >&2 \"compress file to file\"\n\tzstd $args -f hello\n\tprintln >&2 \"compress pipe to pipe\"\n\tzstd $args < hello > $INTOVOID\n\tprintln >&2 \"compress pipe to file\"\n\tzstd $args < hello -fo hello.zst\n\tprintln >&2 \"compress file to pipe\"\n\tzstd $args hello -c > $INTOVOID\n\tprintln >&2 \"compress 2 files\"\n\tzstd $args -f hello world\n\n\tprintln >&2 \"decompress file to file\"\n\tzstd $args -d -f hello.zst\n\tprintln >&2 \"decompress pipe to pipe\"\n\tzstd $args -d < hello.zst > $INTOVOID\n\tprintln >&2 \"decompress pipe to file\"\n\tzstd $args -d < hello.zst -fo hello\n\tprintln >&2 \"decompress file to pipe\"\n\tzstd $args -d hello.zst -c > $INTOVOID\n\tprintln >&2 \"decompress 2 files\"\n\tzstd $args -d -f hello.zst world.zst\n\tprintln >&2 \"\"\ndone\n"
  },
  {
    "path": "tests/cli-tests/progress/no-progress.sh.stderr.glob",
    "content": "Tests cases where progress information should not be printed\nargs =\ncompress file to file\nhello*hello.zst*\ncompress pipe to pipe\ncompress pipe to file\n*stdin*hello.zst*\ncompress file to pipe\ncompress 2 files\n2 files compressed*\ndecompress file to file\nhello.zst*\ndecompress pipe to pipe\ndecompress pipe to file\n*stdin*\ndecompress file to pipe\ndecompress 2 files\n2 files decompressed*\n\nargs = --fake-stderr-is-console -q\ncompress file to file\ncompress pipe to pipe\ncompress pipe to file\ncompress file to pipe\ncompress 2 files\ndecompress file to file\ndecompress pipe to pipe\ndecompress pipe to file\ndecompress file to pipe\ndecompress 2 files\n\nargs = --fake-stderr-is-console -qq --progress\ncompress file to file\ncompress pipe to pipe\ncompress pipe to file\ncompress file to pipe\ncompress 2 files\ndecompress file to file\ndecompress pipe to pipe\ndecompress pipe to file\ndecompress file to pipe\ndecompress 2 files\n\nargs = --no-progress --fake-stderr-is-console\ncompress file to file\nhello*hello.zst*\ncompress pipe to pipe\ncompress pipe to file\n*stdin*hello.zst*\ncompress file to pipe\ncompress 2 files\n2 files compressed*\ndecompress file to file\nhello.zst*\ndecompress pipe to pipe\ndecompress pipe to file\n*stdin*\ndecompress file to pipe\ndecompress 2 files\n2 files decompressed*\n\nargs = --no-progress --fake-stderr-is-console -v\ncompress file to file\n*Zstandard CLI*\nhello*hello.zst*\ncompress pipe to pipe\n*Zstandard CLI*\n*stdin*stdout*\ncompress pipe to file\n*Zstandard CLI*\n*stdin*hello.zst*\ncompress file to pipe\n*Zstandard CLI*\n*hello*stdout*\ncompress 2 files\n*Zstandard CLI*\n*hello*hello.zst*\n*world*world.zst*\n2 files compressed*\ndecompress file to file\n*Zstandard CLI*\nhello.zst*\ndecompress pipe to pipe\n*Zstandard CLI*\n*stdin*\ndecompress pipe to file\n*Zstandard CLI*\n*stdin*\ndecompress file to pipe\n*Zstandard CLI*\nhello.zst*\ndecompress 2 files\n*Zstandard CLI*\nhello.zst*\nworld.zst*\n2 files decompressed*\n"
  },
  {
    "path": "tests/cli-tests/progress/progress.sh",
    "content": "#!/bin/sh\n\n. \"$COMMON/platform.sh\"\n\nset -e\n\nprintln >&2 \"Tests cases where progress information should be printed\"\n\necho hello > hello\necho world > world\n\nzstd -q hello world\n\nfor args in \\\n\t\"--progress\" \\\n\t\"--fake-stderr-is-console\" \\\n\t\"--progress --fake-stderr-is-console -q\"; do\n\tprintln >&2 \"args = $args\"\n\tprintln >&2 \"compress file to file\"\n\tzstd $args -f hello\n\tprintln >&2 \"compress pipe to pipe\"\n\tzstd $args < hello > $INTOVOID\n\tprintln >&2 \"compress pipe to file\"\n\tzstd $args < hello -fo hello.zst\n\tprintln >&2 \"compress file to pipe\"\n\tzstd $args hello -c > $INTOVOID\n\tprintln >&2 \"compress 2 files\"\n\tzstd $args -f hello world\n\n\tprintln >&2 \"decompress file to file\"\n\tzstd $args -d -f hello.zst\n\tprintln >&2 \"decompress pipe to pipe\"\n\tzstd $args -d < hello.zst > $INTOVOID\n\tprintln >&2 \"decompress pipe to file\"\n\tzstd $args -d < hello.zst -fo hello\n\tprintln >&2 \"decompress file to pipe\"\n\tzstd $args -d hello.zst -c > $INTOVOID\n\tprintln >&2 \"decompress 2 files\"\n\tzstd $args -d -f hello.zst world.zst\n\tprintln >&2 \"\"\ndone\n"
  },
  {
    "path": "tests/cli-tests/progress/progress.sh.stderr.glob",
    "content": "Tests cases where progress information should be printed\nargs = --progress\ncompress file to file\n*Read:*hello*hello.zst*\ncompress pipe to pipe\n*Read:*stdin*stdout*\ncompress pipe to file\n*Read:*stdin*hello.zst*\ncompress file to pipe\n*Read:*hello*stdout*\ncompress 2 files\n*Read*2 files compressed*\ndecompress file to file\n*hello.zst*hello.zst*\ndecompress pipe to pipe\n*stdin*stdin*\ndecompress pipe to file\n*stdin*stdin*\ndecompress file to pipe\n*hello.zst*hello.zst*\ndecompress 2 files\n*hello.zst*2 files decompressed*\n\nargs = --fake-stderr-is-console\ncompress file to file\n*Read:*hello*hello.zst*\ncompress pipe to pipe\ncompress pipe to file\n*Read:*stdin*hello.zst*\ncompress file to pipe\ncompress 2 files\n*Read*2 files compressed*\ndecompress file to file\n*hello.zst*hello.zst*\ndecompress pipe to pipe\ndecompress pipe to file\n*stdin*stdin*\ndecompress file to pipe\ndecompress 2 files\n*hello.zst*2 files decompressed*\n\nargs = --progress --fake-stderr-is-console -q\ncompress file to file\n*Read:*hello*hello.zst*\ncompress pipe to pipe\n*Read:*stdin*stdout*\ncompress pipe to file\n*Read:*stdin*hello.zst*\ncompress file to pipe\n*Read:*hello*stdout*\ncompress 2 files\n*Read*2 files compressed*\ndecompress file to file\n*hello.zst*hello.zst*\ndecompress pipe to pipe\n*stdin*stdin*\ndecompress pipe to file\n*stdin*stdin*\ndecompress file to pipe\n*hello.zst*hello.zst*\ndecompress 2 files\n*hello.zst*2 files decompressed*\n"
  },
  {
    "path": "tests/cli-tests/run.py",
    "content": "#!/usr/bin/env python3\n# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ##########################################################################\n\nimport argparse\nimport contextlib\nimport copy\nimport fnmatch\nimport os\nimport shutil\nimport subprocess\nimport sys\nimport tempfile\nimport typing\n\n\nZSTD_SYMLINKS = [\n    \"zstd\",\n    \"zstdmt\",\n    \"unzstd\",\n    \"zstdcat\",\n    \"zcat\",\n    \"gzip\",\n    \"gunzip\",\n    \"gzcat\",\n    \"lzma\",\n    \"unlzma\",\n    \"xz\",\n    \"unxz\",\n    \"lz4\",\n    \"unlz4\",\n]\n\n\nEXCLUDED_DIRS = {\n    \"bin\",\n    \"common\",\n    \"scratch\",\n}\n\n\nEXCLUDED_BASENAMES = {\n    \"setup\",\n    \"setup_once\",\n    \"teardown\",\n    \"teardown_once\",\n    \"README.md\",\n    \"run.py\",\n    \".gitignore\",\n}\n\nEXCLUDED_SUFFIXES = [\n    \".exact\",\n    \".glob\",\n    \".ignore\",\n    \".exit\",\n]\n\n\ndef exclude_dir(dirname: str) -> bool:\n    \"\"\"\n    Should files under the directory :dirname: be excluded from the test runner?\n    \"\"\"\n    if dirname in EXCLUDED_DIRS:\n        return True\n    return False\n\n\ndef exclude_file(filename: str) -> bool:\n    \"\"\"Should the file :filename: be excluded from the test runner?\"\"\"\n    if filename in EXCLUDED_BASENAMES:\n        return True\n    for suffix in EXCLUDED_SUFFIXES:\n        if filename.endswith(suffix):\n            return True\n    return False\n\ndef read_file(filename: str) -> bytes:\n    \"\"\"Reads the file :filename: and returns the contents as bytes.\"\"\"\n    with open(filename, \"rb\") as f:\n        return f.read()\n\n\ndef diff(a: bytes, b: bytes) -> str:\n    \"\"\"Returns a diff between two different byte-strings :a: and :b:.\"\"\"\n    assert a != b\n    with tempfile.NamedTemporaryFile(\"wb\") as fa:\n        fa.write(a)\n        fa.flush()\n        with tempfile.NamedTemporaryFile(\"wb\") as fb:\n            fb.write(b)\n            fb.flush()\n\n            diff_bytes = subprocess.run([\"diff\", fa.name, fb.name], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout\n            return diff_bytes.decode(\"utf8\")\n\n\ndef pop_line(data: bytes) -> typing.Tuple[typing.Optional[bytes], bytes]:\n    \"\"\"\n    Pop the first line from :data: and returns the first line and the remainder\n    of the data as a tuple. If :data: is empty, returns :(None, data):. Otherwise\n    the first line always ends in a :\\n:, even if it is the last line and :data:\n    doesn't end in :\\n:.\n    \"\"\"\n    NEWLINE = b\"\\n\"\n\n    if data == b'':\n        return (None, data)\n\n    parts = data.split(NEWLINE, maxsplit=1)\n    line = parts[0] + NEWLINE\n    if len(parts) == 1:\n        return line, b''\n\n    return line, parts[1]\n\n\ndef glob_line_matches(actual: bytes, expect: bytes) -> bool:\n    \"\"\"\n    Does the `actual` line match the expected glob line `expect`?\n    \"\"\"\n    return fnmatch.fnmatchcase(actual.strip(), expect.strip())\n\n\ndef glob_diff(actual: bytes, expect: bytes) -> bytes:\n    \"\"\"\n    Returns None if the :actual: content matches the expected glob :expect:,\n    otherwise returns the diff bytes.\n    \"\"\"\n    diff = b''\n    actual_line, actual = pop_line(actual)\n    expect_line, expect = pop_line(expect)\n    while True:\n        # Handle end of file conditions - allow extra newlines\n        while expect_line is None and actual_line == b\"\\n\":\n            actual_line, actual = pop_line(actual)\n        while actual_line is None and expect_line == b\"\\n\":\n            expect_line, expect = pop_line(expect)\n\n        if expect_line is None and actual_line is None:\n            if diff == b'':\n                return None\n            return diff\n        elif expect_line is None:\n            diff += b\"---\\n\"\n            while actual_line != None:\n                diff += b\"> \"\n                diff += actual_line\n                actual_line, actual = pop_line(actual)\n            return diff\n        elif actual_line is None:\n            diff += b\"---\\n\"\n            while expect_line != None:\n                diff += b\"< \"\n                diff += expect_line\n                expect_line, expect = pop_line(expect)\n            return diff\n\n        assert expect_line is not None\n        assert actual_line is not None\n\n        if expect_line == b'...\\n':\n            next_expect_line, expect = pop_line(expect)\n            if next_expect_line is None:\n                if diff == b'':\n                    return None\n                return diff\n            while not glob_line_matches(actual_line, next_expect_line):\n                actual_line, actual = pop_line(actual)\n                if actual_line is None:\n                    diff += b\"---\\n\"\n                    diff += b\"< \"\n                    diff += next_expect_line\n                    return diff\n            expect_line = next_expect_line\n            continue\n\n        if not glob_line_matches(actual_line, expect_line):\n            diff += b'---\\n'\n            diff += b'< ' + expect_line\n            diff += b'> ' + actual_line\n\n        actual_line, actual = pop_line(actual)\n        expect_line, expect = pop_line(expect)\n\n\nclass Options:\n    \"\"\"Options configuring how to run a :TestCase:.\"\"\"\n    def __init__(\n        self,\n        env: typing.Dict[str, str],\n        timeout: typing.Optional[int],\n        verbose: bool,\n        preserve: bool,\n        scratch_dir: str,\n        test_dir: str,\n        set_exact_output: bool,\n    ) -> None:\n        self.env = env\n        self.timeout = timeout\n        self.verbose = verbose\n        self.preserve = preserve\n        self.scratch_dir = scratch_dir\n        self.test_dir = test_dir\n        self.set_exact_output = set_exact_output\n\n\nclass TestCase:\n    \"\"\"\n    Logic and state related to running a single test case.\n\n    1. Initialize the test case.\n    2. Launch the test case with :TestCase.launch():.\n       This will start the test execution in a subprocess, but\n       not wait for completion. So you could launch multiple test\n       cases in parallel. This will now print any test output.\n    3. Analyze the results with :TestCase.analyze():. This will\n       join the test subprocess, check the results against the\n       expectations, and print the results to stdout.\n\n    :TestCase.run(): is also provided which combines the launch & analyze\n    steps for single-threaded use-cases.\n\n    All other methods, prefixed with _, are private helper functions.\n    \"\"\"\n    def __init__(self, test_filename: str, options: Options) -> None:\n        \"\"\"\n        Initialize the :TestCase: for the test located in :test_filename:\n        with the given :options:.\n        \"\"\"\n        self._opts = options\n        self._test_file = test_filename\n        self._test_name = os.path.normpath(\n            os.path.relpath(test_filename, start=self._opts.test_dir)\n        )\n        self._success = {}\n        self._message = {}\n        self._test_stdin = None\n        self._scratch_dir = os.path.abspath(os.path.join(self._opts.scratch_dir, self._test_name))\n\n    @property\n    def name(self) -> str:\n        \"\"\"Returns the unique name for the test.\"\"\"\n        return self._test_name\n\n    def launch(self) -> None:\n        \"\"\"\n        Launch the test case as a subprocess, but do not block on completion.\n        This allows users to run multiple tests in parallel. Results aren't yet\n        printed out.\n        \"\"\"\n        self._launch_test()\n\n    def analyze(self) -> bool:\n        \"\"\"\n        Must be called after :TestCase.launch():. Joins the test subprocess and\n        checks the results against expectations. Finally prints the results to\n        stdout and returns the success.\n        \"\"\"\n        self._join_test()\n        self._check_exit()\n        self._check_stderr()\n        self._check_stdout()\n        self._analyze_results()\n        return self._succeeded\n\n    def run(self) -> bool:\n        \"\"\"Shorthand for combining both :TestCase.launch(): and :TestCase.analyze():.\"\"\"\n        self.launch()\n        return self.analyze()\n\n    def _log(self, *args, **kwargs) -> None:\n        \"\"\"Logs test output.\"\"\"\n        print(file=sys.stdout, *args, **kwargs)\n\n    def _vlog(self, *args, **kwargs) -> None:\n        \"\"\"Logs verbose test output.\"\"\"\n        if self._opts.verbose:\n            print(file=sys.stdout, *args, **kwargs)\n\n    def _test_environment(self) -> typing.Dict[str, str]:\n        \"\"\"\n        Returns the environment to be used for the\n        test subprocess.\n        \"\"\"\n        # We want to omit ZSTD cli flags so tests will be consistent across environments\n        env = {k: v for k, v in os.environ.items() if not k.startswith(\"ZSTD\")}\n        for k, v in self._opts.env.items():\n            self._vlog(f\"${k}='{v}'\")\n            env[k] = v\n        return env\n\n    def _launch_test(self) -> None:\n        \"\"\"Launch the test subprocess, but do not join it.\"\"\"\n        args = [os.path.abspath(self._test_file)]\n        stdin_name = f\"{self._test_file}.stdin\"\n        if os.path.exists(stdin_name):\n            self._test_stdin = open(stdin_name, \"rb\")\n            stdin = self._test_stdin\n        else:\n            stdin = subprocess.DEVNULL\n        cwd = self._scratch_dir\n        env = self._test_environment()\n        self._test_process = subprocess.Popen(\n            args=args,\n            stdin=stdin,\n            cwd=cwd,\n            env=env,\n            stderr=subprocess.PIPE,\n            stdout=subprocess.PIPE\n        )\n\n    def _join_test(self) -> None:\n        \"\"\"Join the test process and save stderr, stdout, and the exit code.\"\"\"\n        (stdout, stderr) = self._test_process.communicate(timeout=self._opts.timeout)\n        self._output = {}\n        self._output[\"stdout\"] = stdout\n        self._output[\"stderr\"] = stderr\n        self._exit_code = self._test_process.returncode\n        self._test_process = None\n        if self._test_stdin is not None:\n            self._test_stdin.close()\n            self._test_stdin = None\n\n    def _check_output_exact(self, out_name: str, expected: bytes, exact_name: str) -> None:\n        \"\"\"\n        Check the output named :out_name: for an exact match against the :expected: content.\n        Saves the success and message.\n        \"\"\"\n        check_name = f\"check_{out_name}\"\n        actual = self._output[out_name]\n        if actual == expected:\n            self._success[check_name] = True\n            self._message[check_name] = f\"{out_name} matches!\"\n        else:\n            self._success[check_name] = False\n            self._message[check_name] = f\"{out_name} does not match!\\n> diff expected actual\\n{diff(expected, actual)}\"\n\n            if self._opts.set_exact_output:\n                with open(exact_name, \"wb\") as f:\n                    f.write(actual)\n\n    def _check_output_glob(self, out_name: str, expected: bytes) -> None:\n        \"\"\"\n        Check the output named :out_name: for a glob match against the :expected: glob.\n        Saves the success and message.\n        \"\"\"\n        check_name = f\"check_{out_name}\"\n        actual = self._output[out_name]\n        diff = glob_diff(actual, expected)\n        if diff is None:\n            self._success[check_name] = True\n            self._message[check_name] = f\"{out_name} matches!\"\n        else:\n            utf8_diff = diff.decode('utf8')\n            self._success[check_name] = False\n            self._message[check_name] = f\"{out_name} does not match!\\n> diff expected actual\\n{utf8_diff}\"\n\n    def _check_output(self, out_name: str) -> None:\n        \"\"\"\n        Checks the output named :out_name: for a match against the expectation.\n        We check for a .exact, .glob, and a .ignore file. If none are found we\n        expect that the output should be empty.\n\n        If :Options.preserve: was set then we save the scratch directory and\n        save the stderr, stdout, and exit code to the scratch directory for\n        debugging.\n        \"\"\"\n        if self._opts.preserve:\n            # Save the output to the scratch directory\n            actual_name = os.path.join(self._scratch_dir, f\"{out_name}\")\n            with open(actual_name, \"wb\") as f:\n                    f.write(self._output[out_name])\n\n        exact_name = f\"{self._test_file}.{out_name}.exact\"\n        glob_name = f\"{self._test_file}.{out_name}.glob\"\n        ignore_name = f\"{self._test_file}.{out_name}.ignore\"\n\n        if os.path.exists(exact_name):\n            return self._check_output_exact(out_name, read_file(exact_name), exact_name)\n        elif os.path.exists(glob_name):\n            return self._check_output_glob(out_name, read_file(glob_name))\n        else:\n            check_name = f\"check_{out_name}\"\n            self._success[check_name] = True\n            self._message[check_name] = f\"{out_name} ignored!\"\n\n    def _check_stderr(self) -> None:\n        \"\"\"Checks the stderr output against the expectation.\"\"\"\n        self._check_output(\"stderr\")\n\n    def _check_stdout(self) -> None:\n        \"\"\"Checks the stdout output against the expectation.\"\"\"\n        self._check_output(\"stdout\")\n\n    def _check_exit(self) -> None:\n        \"\"\"\n        Checks the exit code against expectations. If a .exit file\n        exists, we expect that the exit code matches the contents.\n        Otherwise we expect the exit code to be zero.\n\n        If :Options.preserve: is set we save the exit code to the\n        scratch directory under the filename \"exit\".\n        \"\"\"\n        if self._opts.preserve:\n            exit_name = os.path.join(self._scratch_dir, \"exit\")\n            with open(exit_name, \"w\") as f:\n                f.write(str(self._exit_code) + \"\\n\")\n        exit_name = f\"{self._test_file}.exit\"\n        if os.path.exists(exit_name):\n            exit_code: int = int(read_file(exit_name))\n        else:\n            exit_code: int = 0\n        if exit_code == self._exit_code:\n            self._success[\"check_exit\"] = True\n            self._message[\"check_exit\"] = \"Exit code matches!\"\n        else:\n            self._success[\"check_exit\"] = False\n            self._message[\"check_exit\"] = f\"Exit code mismatch! Expected {exit_code} but got {self._exit_code}\"\n\n    def _analyze_results(self) -> None:\n        \"\"\"\n        After all tests have been checked, collect all the successes\n        and messages, and print the results to stdout.\n        \"\"\"\n        STATUS = {True: \"PASS\", False: \"FAIL\"}\n        checks = sorted(self._success.keys())\n        self._succeeded = all(self._success.values())\n        self._log(f\"{STATUS[self._succeeded]}: {self._test_name}\")\n\n        if not self._succeeded or self._opts.verbose:\n            for check in checks:\n                if self._opts.verbose or not self._success[check]:\n                    self._log(f\"{STATUS[self._success[check]]}: {self._test_name}.{check}\")\n                    self._log(self._message[check])\n\n        self._log(\"----------------------------------------\")\n\n\nclass TestSuite:\n    \"\"\"\n    Setup & teardown test suite & cases.\n    This class is intended to be used as a context manager.\n\n    TODO: Make setup/teardown failure emit messages, not throw exceptions.\n    \"\"\"\n    def __init__(self, test_directory: str, options: Options) -> None:\n        self._opts = options\n        self._test_dir = os.path.abspath(test_directory)\n        rel_test_dir = os.path.relpath(test_directory, start=self._opts.test_dir)\n        assert not rel_test_dir.startswith(os.path.sep)\n        self._scratch_dir = os.path.normpath(os.path.join(self._opts.scratch_dir, rel_test_dir))\n\n    def __enter__(self) -> 'TestSuite':\n        self._setup_once()\n        return self\n\n    def __exit__(self, _exc_type, _exc_value, _traceback) -> None:\n        self._teardown_once()\n\n    @contextlib.contextmanager\n    def test_case(self, test_basename: str) -> TestCase:\n        \"\"\"\n        Context manager for a test case in the test suite.\n        Pass the basename of the test relative to the :test_directory:.\n        \"\"\"\n        assert os.path.dirname(test_basename) == \"\"\n        try:\n            self._setup(test_basename)\n            test_filename = os.path.join(self._test_dir, test_basename)\n            yield TestCase(test_filename, self._opts)\n        finally:\n            self._teardown(test_basename)\n\n    def _remove_scratch_dir(self, dir: str) -> None:\n        \"\"\"Helper to remove a scratch directory with sanity checks\"\"\"\n        assert \"scratch\" in dir\n        assert dir.startswith(self._scratch_dir)\n        assert os.path.exists(dir)\n        shutil.rmtree(dir)\n\n    def _setup_once(self) -> None:\n        if os.path.exists(self._scratch_dir):\n            self._remove_scratch_dir(self._scratch_dir)\n        os.makedirs(self._scratch_dir)\n        setup_script = os.path.join(self._test_dir, \"setup_once\")\n        if os.path.exists(setup_script):\n            self._run_script(setup_script, cwd=self._scratch_dir)\n\n    def _teardown_once(self) -> None:\n        assert os.path.exists(self._scratch_dir)\n        teardown_script = os.path.join(self._test_dir, \"teardown_once\")\n        if os.path.exists(teardown_script):\n            self._run_script(teardown_script, cwd=self._scratch_dir)\n        if not self._opts.preserve:\n            self._remove_scratch_dir(self._scratch_dir)\n\n    def _setup(self, test_basename: str) -> None:\n        test_scratch_dir = os.path.join(self._scratch_dir, test_basename)\n        assert not os.path.exists(test_scratch_dir)\n        os.makedirs(test_scratch_dir)\n        setup_script = os.path.join(self._test_dir, \"setup\")\n        if os.path.exists(setup_script):\n            self._run_script(setup_script, cwd=test_scratch_dir)\n\n    def _teardown(self, test_basename: str) -> None:\n        test_scratch_dir = os.path.join(self._scratch_dir, test_basename)\n        assert os.path.exists(test_scratch_dir)\n        teardown_script = os.path.join(self._test_dir, \"teardown\")\n        if os.path.exists(teardown_script):\n            self._run_script(teardown_script, cwd=test_scratch_dir)\n        if not self._opts.preserve:\n            self._remove_scratch_dir(test_scratch_dir)\n\n    def _run_script(self, script: str, cwd: str) -> None:\n        env = copy.copy(os.environ)\n        for k, v in self._opts.env.items():\n            env[k] = v\n        try:\n            subprocess.run(\n                args=[script],\n                stdin=subprocess.DEVNULL,\n                stdout=subprocess.PIPE,\n                stderr=subprocess.PIPE,\n                cwd=cwd,\n                env=env,\n                check=True,\n            )\n        except subprocess.CalledProcessError as e:\n            print(f\"{script} failed with exit code {e.returncode}!\")\n            print(f\"stderr:\\n{e.stderr}\")\n            print(f\"stdout:\\n{e.stdout}\")\n            raise\n\nTestSuites = typing.Dict[str, typing.List[str]]\n\ndef get_all_tests(options: Options) -> TestSuites:\n    \"\"\"\n    Find all the test in the test directory and return the test suites.\n    \"\"\"\n    test_suites = {}\n    for root, dirs, files in os.walk(options.test_dir, topdown=True):\n        dirs[:] = [d for d in dirs if not exclude_dir(d)]\n        test_cases = []\n        for file in files:\n            if not exclude_file(file):\n                test_cases.append(file)\n        assert root == os.path.normpath(root)\n        test_suites[root] = test_cases\n    return test_suites\n\n\ndef resolve_listed_tests(\n    tests: typing.List[str], options: Options\n) -> TestSuites:\n    \"\"\"\n    Resolve the list of tests passed on the command line into their\n    respective test suites. Tests can either be paths, or test names\n    relative to the test directory.\n    \"\"\"\n    test_suites = {}\n    for test in tests:\n        if not os.path.exists(test):\n            test = os.path.join(options.test_dir, test)\n            if not os.path.exists(test):\n                raise RuntimeError(f\"Test {test} does not exist!\")\n\n        test = os.path.normpath(os.path.abspath(test))\n        assert test.startswith(options.test_dir)\n        test_suite = os.path.dirname(test)\n        test_case = os.path.basename(test)\n        test_suites.setdefault(test_suite, []).append(test_case)\n\n    return test_suites\n\ndef run_tests(test_suites: TestSuites, options: Options) -> bool:\n    \"\"\"\n    Runs all the test in the :test_suites: with the given :options:.\n    Prints the results to stdout.\n    \"\"\"\n    tests = {}\n    for test_dir, test_files in test_suites.items():\n        with TestSuite(test_dir, options) as test_suite:\n            test_files = sorted(set(test_files))\n            for test_file in test_files:\n                with test_suite.test_case(test_file) as test_case:\n                    tests[test_case.name] = test_case.run()\n\n    successes = 0\n    for test, status in tests.items():\n        if status:\n            successes += 1\n        else:\n            print(f\"FAIL: {test}\")\n    if successes == len(tests):\n        print(f\"PASSED all {len(tests)} tests!\")\n        return True\n    else:\n        print(f\"FAILED {len(tests) - successes} / {len(tests)} tests!\")\n        return False\n\n\ndef setup_zstd_symlink_dir(zstd_symlink_dir: str, zstd: str) -> None:\n    assert os.path.join(\"bin\", \"symlinks\") in zstd_symlink_dir\n    if not os.path.exists(zstd_symlink_dir):\n        os.makedirs(zstd_symlink_dir)\n    for symlink in ZSTD_SYMLINKS:\n        path = os.path.join(zstd_symlink_dir, symlink)\n        if os.path.exists(path):\n            os.remove(path)\n        os.symlink(zstd, path)\n\nif __name__ == \"__main__\":\n    CLI_TEST_DIR = os.path.dirname(sys.argv[0])\n    REPO_DIR = os.path.join(CLI_TEST_DIR, \"..\", \"..\")\n    PROGRAMS_DIR = os.path.join(REPO_DIR, \"programs\")\n    TESTS_DIR = os.path.join(REPO_DIR, \"tests\")\n    ZSTD_PATH = os.path.join(PROGRAMS_DIR, \"zstd\")\n    ZSTDGREP_PATH = os.path.join(PROGRAMS_DIR, \"zstdgrep\")\n    ZSTDLESS_PATH = os.path.join(PROGRAMS_DIR, \"zstdless\")\n    DATAGEN_PATH = os.path.join(TESTS_DIR, \"datagen\")\n\n    parser = argparse.ArgumentParser(\n        (\n            \"Runs the zstd CLI tests. Exits nonzero on failure. Default arguments are\\n\"\n            \"generally correct. Pass --preserve to preserve test output for debugging,\\n\"\n            \"and --verbose to get verbose test output.\\n\"\n        )\n    )\n    parser.add_argument(\n        \"--preserve\",\n        action=\"store_true\",\n        help=\"Preserve the scratch directory TEST_DIR/scratch/ for debugging purposes.\"\n    )\n    parser.add_argument(\"--verbose\", action=\"store_true\", help=\"Verbose test output.\")\n    parser.add_argument(\"--timeout\", default=800, type=int, help=\"Test case timeout in seconds. Set to 0 to disable timeouts.\")\n    parser.add_argument(\n        \"--exec-prefix\",\n        default=None,\n        help=\"Sets the EXEC_PREFIX environment variable. Prefix to invocations of the zstd CLI.\"\n    )\n    parser.add_argument(\n        \"--zstd\",\n        default=ZSTD_PATH,\n        help=\"Sets the ZSTD_BIN environment variable. Path of the zstd CLI.\"\n    )\n    parser.add_argument(\n        \"--zstdgrep\",\n        default=ZSTDGREP_PATH,\n        help=\"Sets the ZSTDGREP_BIN environment variable. Path of the zstdgrep CLI.\"\n    )\n    parser.add_argument(\n        \"--zstdless\",\n        default=ZSTDLESS_PATH,\n        help=\"Sets the ZSTDLESS_BIN environment variable. Path of the zstdless CLI.\"\n    )\n    parser.add_argument(\n        \"--datagen\",\n        default=DATAGEN_PATH,\n        help=\"Sets the DATAGEN_BIN environment variable. Path to the datagen CLI.\"\n    )\n    parser.add_argument(\n        \"--test-dir\",\n        default=CLI_TEST_DIR,\n        help=(\n            \"Runs the tests under this directory. \"\n            \"Adds TEST_DIR/bin/ to path. \"\n            \"Scratch directory located in TEST_DIR/scratch/.\"\n        )\n    )\n    parser.add_argument(\n        \"--set-exact-output\",\n        action=\"store_true\",\n        help=\"Set stderr.exact and stdout.exact for all failing tests, unless .ignore or .glob already exists\"\n    )\n    parser.add_argument(\n        \"tests\",\n        nargs=\"*\",\n        help=\"Run only these test cases. Can either be paths or test names relative to TEST_DIR/\"\n    )\n    args = parser.parse_args()\n\n    if args.timeout <= 0:\n        args.timeout = None\n\n    args.test_dir = os.path.normpath(os.path.abspath(args.test_dir))\n    bin_dir = os.path.abspath(os.path.join(args.test_dir, \"bin\"))\n    zstd_symlink_dir = os.path.join(bin_dir, \"symlinks\")\n    scratch_dir = os.path.join(args.test_dir, \"scratch\")\n\n    setup_zstd_symlink_dir(zstd_symlink_dir, os.path.abspath(args.zstd))\n\n    env = {}\n    if args.exec_prefix is not None:\n        env[\"EXEC_PREFIX\"] = args.exec_prefix\n    env[\"ZSTD_SYMLINK_DIR\"] = zstd_symlink_dir\n    env[\"ZSTD_REPO_DIR\"] = os.path.abspath(REPO_DIR)\n    env[\"DATAGEN_BIN\"] = os.path.abspath(args.datagen)\n    env[\"ZSTDGREP_BIN\"] = os.path.abspath(args.zstdgrep)\n    env[\"ZSTDLESS_BIN\"] = os.path.abspath(args.zstdless)\n    env[\"CLI_TESTS\"] = os.path.abspath(args.test_dir)\n    env[\"COMMON\"] = os.path.abspath(os.path.join(args.test_dir, \"common\"))\n    env[\"PATH\"] = bin_dir + \":\" + os.getenv(\"PATH\", \"\")\n    env[\"LC_ALL\"] = \"C\"\n\n    opts = Options(\n        env=env,\n        timeout=args.timeout,\n        verbose=args.verbose,\n        preserve=args.preserve,\n        test_dir=args.test_dir,\n        scratch_dir=scratch_dir,\n        set_exact_output=args.set_exact_output,\n    )\n\n    if len(args.tests) == 0:\n        tests = get_all_tests(opts)\n    else:\n        tests = resolve_listed_tests(args.tests, opts)\n\n    success = run_tests(tests, opts)\n    if success:\n        sys.exit(0)\n    else:\n        sys.exit(1)\n"
  },
  {
    "path": "tests/cli-tests/zstd-symlinks/setup",
    "content": "#!/bin/sh\nset -e\n\nprintln \"hello\" > hello\nprintln \"world\" > world\nzstd hello world\n"
  },
  {
    "path": "tests/cli-tests/zstd-symlinks/zstdcat.sh",
    "content": "#!/bin/sh\nset -e\n\n# Test zstdcat symlink in bin/\nzstdcat hello.zst\nzstdcat hello.zst world\nzstdcat hello world.zst\nzstdcat hello.zst world.zst\n\n# Test local zstdcat symlink\nln -s $(which zstd) ./zstdcat\n./zstdcat hello.zst\n"
  },
  {
    "path": "tests/cli-tests/zstd-symlinks/zstdcat.sh.stdout.exact",
    "content": "hello\nhello\nworld\nhello\nworld\nhello\nworld\nhello\n"
  },
  {
    "path": "tests/datagencli.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/*-************************************\n *  Dependencies\n **************************************/\n#include <stdio.h>    /* fprintf, stderr */\n#include \"datagen.h\"  /* RDG_generate */\n#include \"loremOut.h\" /* LOREM_genOut */\n#include \"util.h\"     /* Compiler options */\n\n/*-************************************\n *  Constants\n **************************************/\n#define KB *(1 << 10)\n#define MB *(1 << 20)\n#define GB *(1U << 30)\n\n#define SIZE_DEFAULT ((64 KB) + 1)\n#define SEED_DEFAULT 0\n#define COMPRESSIBILITY_DEFAULT 9999\n\n/*-************************************\n *  Macros\n **************************************/\n#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)\n#define DISPLAYLEVEL(l, ...)  \\\n    if (displayLevel >= l) {  \\\n        DISPLAY(__VA_ARGS__); \\\n    }\nstatic unsigned displayLevel = 2;\n\n/*-*******************************************************\n *  Command line\n *********************************************************/\nstatic int usage(const char* programName)\n{\n    DISPLAY(\"Compressible data generator\\n\");\n    DISPLAY(\"Usage :\\n\");\n    DISPLAY(\"      %s [args]\\n\", programName);\n    DISPLAY(\"\\n\");\n    DISPLAY(\"Arguments :\\n\");\n    DISPLAY(\" -g#    : generate # data (default:%i)\\n\", SIZE_DEFAULT);\n    DISPLAY(\" -s#    : Select seed (default:%i)\\n\", SEED_DEFAULT);\n    DISPLAY(\" -P#    : Select compressibility in %% (range [0-100])\\n\");\n    DISPLAY(\" -h     : display help and exit\\n\");\n    return 0;\n}\n\nint main(int argc, const char** argv)\n{\n    unsigned probaU32             = COMPRESSIBILITY_DEFAULT;\n    double litProba               = 0.0;\n    U64 size                      = SIZE_DEFAULT;\n    U32 seed                      = SEED_DEFAULT;\n    const char* const programName = argv[0];\n\n    int argNb;\n    for (argNb = 1; argNb < argc; argNb++) {\n        const char* argument = argv[argNb];\n\n        if (!argument)\n            continue; /* Protection if argument empty */\n\n        /* Handle commands. Aggregated commands are allowed */\n        if (*argument == '-') {\n            argument++;\n            while (*argument != 0) {\n                switch (*argument) {\n                    case 'h':\n                        return usage(programName);\n                    case 'g':\n                        argument++;\n                        size = 0;\n                        while ((*argument >= '0') && (*argument <= '9'))\n                            size *= 10, size += (U64)(*argument++ - '0');\n                        if (*argument == 'K') {\n                            size <<= 10;\n                            argument++;\n                        }\n                        if (*argument == 'M') {\n                            size <<= 20;\n                            argument++;\n                        }\n                        if (*argument == 'G') {\n                            size <<= 30;\n                            argument++;\n                        }\n                        if (*argument == 'B') {\n                            argument++;\n                        }\n                        break;\n                    case 's':\n                        argument++;\n                        seed = 0;\n                        while ((*argument >= '0') && (*argument <= '9'))\n                            seed *= 10, seed += (U32)(*argument++ - '0');\n                        break;\n                    case 'P':\n                        argument++;\n                        probaU32 = 0;\n                        while ((*argument >= '0') && (*argument <= '9'))\n                            probaU32 *= 10,\n                                    probaU32 += (U32)(*argument++ - '0');\n                        if (probaU32 > 100)\n                            probaU32 = 100;\n                        break;\n                    case 'L': /* hidden argument : Literal distribution\n                                 probability */\n                        argument++;\n                        litProba = 0.;\n                        while ((*argument >= '0') && (*argument <= '9'))\n                            litProba *= 10, litProba += *argument++ - '0';\n                        if (litProba > 100.)\n                            litProba = 100.;\n                        litProba /= 100.;\n                        break;\n                    case 'v':\n                        displayLevel = 4;\n                        argument++;\n                        break;\n                    default:\n                        return usage(programName);\n                }\n            }\n        }\n    } /* for(argNb=1; argNb<argc; argNb++) */\n\n    DISPLAYLEVEL(4, \"Compressible data Generator \\n\");\n    DISPLAYLEVEL(3, \"Seed = %u \\n\", (unsigned)seed);\n\n    if (probaU32 != COMPRESSIBILITY_DEFAULT) {\n        DISPLAYLEVEL(3, \"Compressibility : %i%%\\n\", probaU32);\n        RDG_genStdout(size, (double)probaU32 / 100, litProba, seed);\n    } else {\n        LOREM_genOut(size, seed);\n    }\n\n    DISPLAYLEVEL(3, \"\\n\");\n\n    return 0;\n}\n"
  },
  {
    "path": "tests/decodecorpus.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include <limits.h>\n#include <math.h>\n#include <stddef.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>  /* time(), for seed random initialization */\n\n#include \"util.h\"\n#include \"timefn.h\"   /* UTIL_clockSpanMicro, SEC_TO_MICRO, UTIL_TIME_INITIALIZER */\n#include \"zstd.h\"\n#include \"zstd_internal.h\"\n#include \"mem.h\"\n#define ZDICT_STATIC_LINKING_ONLY\n#include \"zdict.h\"\n\n/* Direct access to internal compression functions is required */\n#include \"compress/zstd_compress.c\" /* ZSTD_resetSeqStore, ZSTD_storeSeq, *_TO_OFFBASE, HIST_countFast_wksp, HIST_isError */\n#include \"decompress/zstd_decompress_block.h\" /* ZSTD_decompressBlock_deprecated */\n\n#define XXH_STATIC_LINKING_ONLY\n#include \"xxhash.h\"     /* XXH64 */\n\n#if !(defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */))\n# define inline  /* disable */\n#endif\n\n/*-************************************\n*  DISPLAY Macros\n**************************************/\n#define DISPLAY(...)          fprintf(stderr, __VA_ARGS__)\n#define DISPLAYLEVEL(l, ...)  if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); }\nstatic U32 g_displayLevel = 2;\n\n#define DISPLAYUPDATE(...)                                                     \\\n    do {                                                                       \\\n        if ((UTIL_clockSpanMicro(g_displayClock) > g_refreshRate) ||           \\\n            (g_displayLevel >= 4)) {                                           \\\n            g_displayClock = UTIL_getTime();                                   \\\n            DISPLAY(__VA_ARGS__);                                              \\\n            if (g_displayLevel >= 4) fflush(stderr);                           \\\n        }                                                                      \\\n    } while (0)\n\nstatic const U64 g_refreshRate = SEC_TO_MICRO / 6;\nstatic UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER;\n\n#define CHECKERR(code)                                                         \\\n    do {                                                                       \\\n        if (ZSTD_isError(code)) {                                              \\\n            DISPLAY(\"Error occurred while generating data: %s\\n\",              \\\n                    ZSTD_getErrorName(code));                                  \\\n            exit(1);                                                           \\\n        }                                                                      \\\n    } while (0)\n\n\n/*-*******************************************************\n*  Random function\n*********************************************************/\nstatic U32 RAND(U32* src)\n{\n#define RAND_rotl32(x,r) ((x << r) | (x >> (32 - r)))\n    static const U32 prime1 = 2654435761U;\n    static const U32 prime2 = 2246822519U;\n    U32 rand32 = *src;\n    rand32 *= prime1;\n    rand32 += prime2;\n    rand32  = RAND_rotl32(rand32, 13);\n    *src = rand32;\n    return RAND_rotl32(rand32, 27);\n#undef RAND_rotl32\n}\n\n#define DISTSIZE (8192)\n\n/* Write `size` bytes into `ptr`, all of which are less than or equal to `maxSymb` */\nstatic void RAND_bufferMaxSymb(U32* seed, void* ptr, size_t size, int maxSymb)\n{\n    size_t i;\n    BYTE* op = ptr;\n\n    for (i = 0; i < size; i++) {\n        op[i] = (BYTE) (RAND(seed) % (maxSymb + 1));\n    }\n}\n\n/* Write `size` random bytes into `ptr` */\nstatic void RAND_buffer(U32* seed, void* ptr, size_t size)\n{\n    size_t i;\n    BYTE* op = ptr;\n\n    for (i = 0; i + 4 <= size; i += 4) {\n        MEM_writeLE32(op + i, RAND(seed));\n    }\n    for (; i < size; i++) {\n        op[i] = RAND(seed) & 0xff;\n    }\n}\n\n/* Write `size` bytes into `ptr` following the distribution `dist` */\nstatic void RAND_bufferDist(U32* seed, BYTE* dist, void* ptr, size_t size)\n{\n    size_t i;\n    BYTE* op = ptr;\n\n    for (i = 0; i < size; i++) {\n        op[i] = dist[RAND(seed) % DISTSIZE];\n    }\n}\n\n/* Generate a random distribution where the frequency of each symbol follows a\n * geometric distribution defined by `weight`\n * `dist` should have size at least `DISTSIZE` */\nstatic void RAND_genDist(U32* seed, BYTE* dist, double weight)\n{\n    size_t i = 0;\n    size_t statesLeft = DISTSIZE;\n    BYTE symb = (BYTE) (RAND(seed) % 256);\n    BYTE step = (BYTE) ((RAND(seed) % 256) | 1); /* force it to be odd so it's relatively prime to 256 */\n\n    while (i < DISTSIZE) {\n        size_t states = ((size_t)(weight * (double)statesLeft)) + 1;\n        size_t j;\n        for (j = 0; j < states && i < DISTSIZE; j++, i++) {\n            dist[i] = symb;\n        }\n\n        symb += step;\n        statesLeft -= states;\n    }\n}\n\n/* Generates a random number in the range [min, max) */\nstatic inline U32 RAND_range(U32* seed, U32 min, U32 max)\n{\n    return (RAND(seed) % (max-min)) + min;\n}\n\n#define ROUND(x) ((U32)(x + 0.5))\n\n/* Generates a random number in an exponential distribution with mean `mean` */\nstatic double RAND_exp(U32* seed, double mean)\n{\n    double const u = RAND(seed) / (double) UINT_MAX;\n    return log(1-u) * (-mean);\n}\n\n/*-*******************************************************\n*  Constants and Structs\n*********************************************************/\nconst char* BLOCK_TYPES[] = {\"raw\", \"rle\", \"compressed\"};\n\n#define MAX_DECOMPRESSED_SIZE_LOG 20\n#define MAX_DECOMPRESSED_SIZE (1ULL << MAX_DECOMPRESSED_SIZE_LOG)\n\n#define MAX_WINDOW_LOG 22 /* Recommended support is 8MB, so limit to 4MB + mantissa */\n\n#define MIN_SEQ_LEN (3)\n#define MAX_NB_SEQ ((ZSTD_BLOCKSIZE_MAX + MIN_SEQ_LEN - 1) / MIN_SEQ_LEN)\n\n#ifndef MAX_PATH\n    #ifdef PATH_MAX\n        #define MAX_PATH PATH_MAX\n    #else\n        #define MAX_PATH 256\n    #endif\n#endif\n\nBYTE CONTENT_BUFFER[MAX_DECOMPRESSED_SIZE];\nBYTE FRAME_BUFFER[MAX_DECOMPRESSED_SIZE * 2];\nBYTE LITERAL_BUFFER[ZSTD_BLOCKSIZE_MAX];\n\nSeqDef SEQUENCE_BUFFER[MAX_NB_SEQ];\nBYTE SEQUENCE_LITERAL_BUFFER[ZSTD_BLOCKSIZE_MAX]; /* storeSeq expects a place to copy literals to */\nBYTE SEQUENCE_LLCODE[ZSTD_BLOCKSIZE_MAX];\nBYTE SEQUENCE_MLCODE[ZSTD_BLOCKSIZE_MAX];\nBYTE SEQUENCE_OFCODE[ZSTD_BLOCKSIZE_MAX];\n\nU64 WKSP[HUF_WORKSPACE_SIZE_U64];\n\ntypedef struct {\n    size_t contentSize; /* 0 means unknown (unless contentSize == windowSize == 0) */\n    unsigned windowSize; /* contentSize >= windowSize means single segment */\n} frameHeader_t;\n\n/* For repeat modes */\ntypedef struct {\n    U32 rep[ZSTD_REP_NUM];\n\n    int hufInit;\n    /* the distribution used in the previous block for repeat mode */\n    BYTE hufDist[DISTSIZE];\n    HUF_CElt hufTable [HUF_CTABLE_SIZE_ST(255)];\n\n    int fseInit;\n    FSE_CTable offcodeCTable  [FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)];\n    FSE_CTable matchlengthCTable[FSE_CTABLE_SIZE_U32(MLFSELog, MaxML)];\n    FSE_CTable litlengthCTable  [FSE_CTABLE_SIZE_U32(LLFSELog, MaxLL)];\n\n    /* Symbols that were present in the previous distribution, for use with\n     * set_repeat */\n    BYTE litlengthSymbolSet[36];\n    BYTE offsetSymbolSet[29];\n    BYTE matchlengthSymbolSet[53];\n} cblockStats_t;\n\ntypedef struct {\n    void* data;\n    void* dataStart;\n    void* dataEnd;\n\n    void* src;\n    void* srcStart;\n    void* srcEnd;\n\n    frameHeader_t header;\n\n    cblockStats_t stats;\n    cblockStats_t oldStats; /* so they can be rolled back if uncompressible */\n} frame_t;\n\ntypedef struct {\n    int useDict;\n    U32 dictID;\n    size_t dictContentSize;\n    BYTE* dictContent;\n} dictInfo;\n\ntypedef enum {\n  gt_frame = 0,  /* generate frames */\n  gt_block,      /* generate compressed blocks without block/frame headers */\n} genType_e;\n\n#ifndef MIN\n    #define MIN(a, b) ((a) < (b) ? (a) : (b))\n#endif\n\ntypedef enum {\n  lt_raw,\n  lt_rle,\n  lt_compressed,\n} literalType_e;\n\n/*-*******************************************************\n*  Global variables (set from command line)\n*********************************************************/\nU32 g_maxDecompressedSizeLog = MAX_DECOMPRESSED_SIZE_LOG;  /* <= 20 */\nU32 g_maxBlockSize = ZSTD_BLOCKSIZE_MAX;                       /* <= 128 KB */\n\n/*-*******************************************************\n*  Generator Functions\n*********************************************************/\n\nstruct {\n    int contentSize; /* force the content size to be present */\n    blockType_e *blockType; /* force specific block type */\n    literalType_e *literalType; /* force specific literals type */\n    int frame_header_only; /* generate only frame header */\n    int no_magic; /* do not generate magic number */\n} opts;\n\n/* Generate and write a random frame header */\nstatic void writeFrameHeader(U32* seed, frame_t* frame, dictInfo info)\n{\n    BYTE* const op = frame->data;\n    size_t pos = 0;\n    frameHeader_t fh;\n\n    BYTE windowByte = 0;\n\n    int singleSegment = 0;\n    int contentSizeFlag = 0;\n    int fcsCode = 0;\n\n    memset(&fh, 0, sizeof(fh));\n\n    /* generate window size */\n    {\n        /* Follow window algorithm from specification */\n        int const exponent = RAND(seed) % (MAX_WINDOW_LOG - 10);\n        int const mantissa = RAND(seed) % 8;\n        windowByte = (BYTE) ((exponent << 3) | mantissa);\n        fh.windowSize = (1U << (exponent + 10));\n        fh.windowSize += fh.windowSize / 8 * mantissa;\n    }\n\n    {\n        /* Generate random content size */\n        int force_block_type = opts.blockType != NULL;\n        size_t highBit;\n        if (RAND(seed) & 7 && g_maxDecompressedSizeLog > 7) {\n            /* do content of at least 128 bytes */\n            highBit = 1ULL << RAND_range(seed, 7, g_maxDecompressedSizeLog);\n        } else if (force_block_type) {\n            if ((RAND(seed) & 3) || (*(opts.blockType) == bt_rle)) {\n                /* do small content */\n                highBit = 1ULL << RAND_range(seed, 0, MIN(7, 1U << g_maxDecompressedSizeLog));\n            } else {\n                /* 0 size frame */\n                highBit = 0;\n            }\n        } else if (RAND(seed) & 3) {\n            /* do small content */\n            highBit = 1ULL << RAND_range(seed, 0, MIN(7, 1U << g_maxDecompressedSizeLog));\n        } else {\n            /* 0 size frame */\n            highBit = 0;\n        }\n        fh.contentSize = highBit ? highBit + (RAND(seed) % highBit) : 0;\n\n        /* provide size sometimes */\n        contentSizeFlag = opts.contentSize | (RAND(seed) & 1);\n\n        if (contentSizeFlag && (fh.contentSize == 0 || !(RAND(seed) & 7))) {\n            /* do single segment sometimes */\n            fh.windowSize = (U32) fh.contentSize;\n            singleSegment = 1;\n        }\n    }\n\n    if (contentSizeFlag) {\n        /* Determine how large fcs field has to be */\n        int minFcsCode = (fh.contentSize >= 256) +\n                               (fh.contentSize >= 65536 + 256) +\n                               (fh.contentSize > 0xFFFFFFFFU);\n        if (!singleSegment && !minFcsCode) {\n            minFcsCode = 1;\n        }\n        fcsCode = minFcsCode + (RAND(seed) % (4 - minFcsCode));\n        if (fcsCode == 1 && fh.contentSize < 256) fcsCode++;\n    }\n\n    /* write out the header */\n    if (!opts.no_magic) {\n        MEM_writeLE32(op + pos, ZSTD_MAGICNUMBER);\n        pos += 4;\n    }\n\n    {\n        /*\n         * fcsCode: 2-bit flag specifying how many bytes used to represent Frame_Content_Size (bits 7-6)\n         * singleSegment: 1-bit flag describing if data must be regenerated within a single continuous memory segment. (bit 5)\n         * contentChecksumFlag: 1-bit flag that is set if frame includes checksum at the end -- set to 1 below (bit 2)\n         * dictBits: 2-bit flag describing how many bytes Dictionary_ID uses -- set to 3 (bits 1-0)\n         * For more information: https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#frame_header\n         */\n        int const dictBits = info.useDict ? 3 : 0;\n        BYTE const frameHeaderDescriptor =\n                (BYTE) ((fcsCode << 6) | (singleSegment << 5) | (1 << 2) | dictBits);\n        op[pos++] = frameHeaderDescriptor;\n    }\n\n    if (!singleSegment) {\n        op[pos++] = windowByte;\n    }\n    if (info.useDict) {\n        MEM_writeLE32(op + pos, (U32) info.dictID);\n        pos += 4;\n    }\n    if (contentSizeFlag) {\n        switch (fcsCode) {\n        default: /* Impossible */\n        case 0: op[pos++] = (BYTE) fh.contentSize; break;\n        case 1: MEM_writeLE16(op + pos, (U16) (fh.contentSize - 256)); pos += 2; break;\n        case 2: MEM_writeLE32(op + pos, (U32) fh.contentSize); pos += 4; break;\n        case 3: MEM_writeLE64(op + pos, (U64) fh.contentSize); pos += 8; break;\n        }\n    }\n\n    DISPLAYLEVEL(3, \" frame content size:\\t%u\\n\", (unsigned)fh.contentSize);\n    DISPLAYLEVEL(3, \" frame window size:\\t%u\\n\", fh.windowSize);\n    DISPLAYLEVEL(3, \" content size flag:\\t%d\\n\", contentSizeFlag);\n    DISPLAYLEVEL(3, \" single segment flag:\\t%d\\n\", singleSegment);\n\n    frame->data = op + pos;\n    frame->header = fh;\n}\n\n/* Write a literal block in either raw or RLE form, return the literals size */\nstatic size_t writeLiteralsBlockSimple(U32* seed, frame_t* frame, size_t contentSize)\n{\n    int force_literal_type = opts.literalType != NULL;\n    int const type = (force_literal_type) ? *(opts.literalType) : RAND(seed) % 2;\n\n    BYTE* op = (BYTE*)frame->data;\n    int const sizeFormatDesc = RAND(seed) % 8;\n    size_t litSize;\n    size_t maxLitSize = MIN(contentSize, g_maxBlockSize);\n\n    if (sizeFormatDesc == 0) {\n        /* Size_FormatDesc = ?0 */\n        maxLitSize = MIN(maxLitSize, 31);\n    } else if (sizeFormatDesc <= 4) {\n        /* Size_FormatDesc = 01 */\n        maxLitSize = MIN(maxLitSize, 4095);\n    } else {\n        /* Size_Format = 11 */\n        maxLitSize = MIN(maxLitSize, 1048575);\n    }\n\n    litSize = RAND(seed) % (maxLitSize + 1);\n    if (frame->src == frame->srcStart && litSize == 0) {\n        litSize = 1; /* no empty literals if there's nothing preceding this block */\n    }\n    if (litSize + 3 > contentSize) {\n        litSize = contentSize; /* no matches shorter than 3 are allowed */\n    }\n    /* use smallest size format that fits */\n    if (litSize < 32) {\n        op[0] = (type | (0 << 2) | (litSize << 3)) & 0xff;\n        op += 1;\n    } else if (litSize < 4096) {\n        op[0] = (type | (1 << 2) | (litSize << 4)) & 0xff;\n        op[1] = (litSize >> 4) & 0xff;\n        op += 2;\n    } else {\n        op[0] = (type | (3 << 2) | (litSize << 4)) & 0xff;\n        op[1] = (litSize >> 4) & 0xff;\n        op[2] = (litSize >> 12) & 0xff;\n        op += 3;\n    }\n\n    if (type == 0) {\n        /* Raw literals */\n        DISPLAYLEVEL(4, \"   raw literals\\n\");\n\n        RAND_buffer(seed, LITERAL_BUFFER, litSize);\n        memcpy(op, LITERAL_BUFFER, litSize);\n        op += litSize;\n    } else {\n        /* RLE literals */\n        BYTE const symb = (BYTE) (RAND(seed) % 256);\n\n        DISPLAYLEVEL(4, \"   rle literals: 0x%02x\\n\", (unsigned)symb);\n\n        memset(LITERAL_BUFFER, symb, litSize);\n        op[0] = symb;\n        op++;\n    }\n\n    frame->data = op;\n\n    return litSize;\n}\n\n/* Generate a Huffman header for the given source */\nstatic size_t writeHufHeader(U32* seed, HUF_CElt* hufTable, void* dst, size_t dstSize,\n                                 const void* src, size_t srcSize)\n{\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* op = ostart;\n\n    unsigned huffLog = 11;\n    unsigned maxSymbolValue = 255;\n\n    unsigned count[HUF_SYMBOLVALUE_MAX+1];\n\n    /* Scan input and build symbol stats */\n    {   size_t const largest = HIST_count_wksp (count, &maxSymbolValue, (const BYTE*)src, srcSize, WKSP, sizeof(WKSP));\n        assert(!HIST_isError(largest));\n        if (largest == srcSize) { *ostart = ((const BYTE*)src)[0]; return 0; }   /* single symbol, rle */\n        if (largest <= (srcSize >> 7)+1) return 0;   /* Fast heuristic : not compressible enough */\n    }\n\n    /* Build Huffman Tree */\n    /* Max Huffman log is 11, min is highbit(maxSymbolValue)+1 */\n    huffLog = RAND_range(seed, ZSTD_highbit32(maxSymbolValue)+1, huffLog+1);\n    DISPLAYLEVEL(6, \"     huffman log: %u\\n\", huffLog);\n    {   size_t const maxBits = HUF_buildCTable_wksp (hufTable, count, maxSymbolValue, huffLog, WKSP, sizeof(WKSP));\n        CHECKERR(maxBits);\n        huffLog = (U32)maxBits;\n    }\n\n    /* Write table description header */\n    {   size_t const hSize = HUF_writeCTable_wksp (op, dstSize, hufTable, maxSymbolValue, huffLog, WKSP, sizeof(WKSP));\n        if (hSize + 12 >= srcSize) return 0;   /* not useful to try compression */\n        op += hSize;\n    }\n\n    return op - ostart;\n}\n\n/* Write a Huffman coded literals block and return the literals size */\nstatic size_t writeLiteralsBlockCompressed(U32* seed, frame_t* frame, size_t contentSize)\n{\n    BYTE* origop = (BYTE*)frame->data;\n    BYTE* opend = (BYTE*)frame->dataEnd;\n    BYTE* op;\n    BYTE* const ostart = origop;\n    int const sizeFormat = RAND(seed) % 4;\n    size_t litSize;\n    size_t hufHeaderSize = 0;\n    size_t compressedSize = 0;\n    size_t maxLitSize = MIN(contentSize-3, g_maxBlockSize);\n\n    SymbolEncodingType_e hType;\n\n    if (contentSize < 64) {\n        /* make sure we get reasonably-sized literals for compression */\n        return ERROR(GENERIC);\n    }\n\n    DISPLAYLEVEL(4, \"   compressed literals\\n\");\n\n    switch (sizeFormat) {\n    case 0: /* fall through, size is the same as case 1 */\n    case 1:\n        maxLitSize = MIN(maxLitSize, 1023);\n        origop += 3;\n        break;\n    case 2:\n        maxLitSize = MIN(maxLitSize, 16383);\n        origop += 4;\n        break;\n    case 3:\n        maxLitSize = MIN(maxLitSize, 262143);\n        origop += 5;\n        break;\n    default:; /* impossible */\n    }\n\n    do {\n        op = origop;\n        do {\n            litSize = RAND(seed) % (maxLitSize + 1);\n        } while (litSize < 32); /* avoid small literal sizes */\n        if (litSize + 3 > contentSize) {\n            litSize = contentSize; /* no matches shorter than 3 are allowed */\n        }\n\n        /* most of the time generate a new distribution */\n        if ((RAND(seed) & 3) || !frame->stats.hufInit) {\n            do {\n                if (RAND(seed) & 3) {\n                    /* add 10 to ensure some compressibility */\n                    double const weight = ((RAND(seed) % 90) + 10) / 100.0;\n\n                    DISPLAYLEVEL(5, \"    distribution weight: %d%%\\n\",\n                                 (int)(weight * 100));\n\n                    RAND_genDist(seed, frame->stats.hufDist, weight);\n                } else {\n                    /* sometimes do restricted range literals to force\n                     * non-huffman headers */\n                    DISPLAYLEVEL(5, \"    small range literals\\n\");\n                    RAND_bufferMaxSymb(seed, frame->stats.hufDist, DISTSIZE,\n                                       15);\n                }\n                RAND_bufferDist(seed, frame->stats.hufDist, LITERAL_BUFFER,\n                                litSize);\n\n                /* generate the header from the distribution instead of the\n                 * actual data to avoid bugs with symbols that were in the\n                 * distribution but never showed up in the output */\n                hufHeaderSize = writeHufHeader(\n                        seed, frame->stats.hufTable, op, opend - op,\n                        frame->stats.hufDist, DISTSIZE);\n                CHECKERR(hufHeaderSize);\n                /* repeat until a valid header is written */\n            } while (hufHeaderSize == 0);\n            op += hufHeaderSize;\n            hType = set_compressed;\n\n            frame->stats.hufInit = 1;\n        } else {\n            /* repeat the distribution/table from last time */\n            DISPLAYLEVEL(5, \"    huffman repeat stats\\n\");\n            RAND_bufferDist(seed, frame->stats.hufDist, LITERAL_BUFFER,\n                            litSize);\n            hufHeaderSize = 0;\n            hType = set_repeat;\n        }\n\n        do {\n            compressedSize =\n                    sizeFormat == 0\n                            ? HUF_compress1X_usingCTable(\n                                      op, opend - op, LITERAL_BUFFER, litSize,\n                                      frame->stats.hufTable, /* flags */ 0)\n                            : HUF_compress4X_usingCTable(\n                                      op, opend - op, LITERAL_BUFFER, litSize,\n                                      frame->stats.hufTable, /* flags */ 0);\n            CHECKERR(compressedSize);\n            /* this only occurs when it could not compress or similar */\n        } while (compressedSize <= 0);\n\n        op += compressedSize;\n\n        compressedSize += hufHeaderSize;\n        DISPLAYLEVEL(5, \"    regenerated size: %u\\n\", (unsigned)litSize);\n        DISPLAYLEVEL(5, \"    compressed size: %u\\n\", (unsigned)compressedSize);\n        if (compressedSize >= litSize) {\n            DISPLAYLEVEL(5, \"     trying again\\n\");\n            /* if we have to try again, reset the stats so we don't accidentally\n             * try to repeat a distribution we just made */\n            frame->stats = frame->oldStats;\n        } else {\n            break;\n        }\n    } while (1);\n\n    /* write header */\n    switch (sizeFormat) {\n    case 0: /* fall through, size is the same as case 1 */\n    case 1: {\n        U32 const header = hType | (sizeFormat << 2) | ((U32)litSize << 4) |\n                           ((U32)compressedSize << 14);\n        MEM_writeLE24(ostart, header);\n        break;\n    }\n    case 2: {\n        U32 const header = hType | (sizeFormat << 2) | ((U32)litSize << 4) |\n                           ((U32)compressedSize << 18);\n        MEM_writeLE32(ostart, header);\n        break;\n    }\n    case 3: {\n        U32 const header = hType | (sizeFormat << 2) | ((U32)litSize << 4) |\n                           ((U32)compressedSize << 22);\n        MEM_writeLE32(ostart, header);\n        ostart[4] = (BYTE)(compressedSize >> 10);\n        break;\n    }\n    default:; /* impossible */\n    }\n\n    frame->data = op;\n    return litSize;\n}\n\nstatic size_t writeLiteralsBlock(U32* seed, frame_t* frame, size_t contentSize)\n{\n    int select_compressed = 0;\n    if (opts.literalType) {\n        select_compressed = *(opts.literalType) == lt_compressed;\n    } else {\n        /* only do compressed for larger segments to avoid compressibility issues */\n        select_compressed = RAND(seed) & 7 && contentSize >= 64;\n    }\n\n    if (select_compressed) {\n        return writeLiteralsBlockCompressed(seed, frame, contentSize);\n    } else {\n        return writeLiteralsBlockSimple(seed, frame, contentSize);\n    }\n}\n\nstatic inline void initSeqStore(SeqStore_t *seqStore) {\n    seqStore->maxNbSeq = MAX_NB_SEQ;\n    seqStore->maxNbLit = ZSTD_BLOCKSIZE_MAX;\n    seqStore->sequencesStart = SEQUENCE_BUFFER;\n    seqStore->litStart = SEQUENCE_LITERAL_BUFFER;\n    seqStore->llCode = SEQUENCE_LLCODE;\n    seqStore->mlCode = SEQUENCE_MLCODE;\n    seqStore->ofCode = SEQUENCE_OFCODE;\n\n    ZSTD_resetSeqStore(seqStore);\n}\n\n/* Randomly generate sequence commands */\nstatic U32\ngenerateSequences(U32* seed, frame_t* frame, SeqStore_t* seqStore,\n                  size_t contentSize, size_t literalsSize, dictInfo info)\n{\n    /* The total length of all the matches */\n    size_t const remainingMatch = contentSize - literalsSize;\n    size_t excessMatch = 0;\n    U32 numSequences = 0;\n    U32 i;\n\n    const BYTE* literals = LITERAL_BUFFER;\n    BYTE* srcPtr = frame->src;\n\n    if (literalsSize != contentSize) {\n        /* each match must be at least MIN_SEQ_LEN, so this is the maximum\n         * number of sequences we can have */\n        U32 const maxSequences = (U32)remainingMatch / MIN_SEQ_LEN;\n        numSequences = (RAND(seed) % maxSequences) + 1;\n\n        /* the extra match lengths we have to allocate to each sequence */\n        excessMatch = remainingMatch - numSequences * MIN_SEQ_LEN;\n    }\n\n    DISPLAYLEVEL(5, \"    total match lengths: %u\\n\", (unsigned)remainingMatch);\n    for (i = 0; i < numSequences; i++) {\n        /* Generate match and literal lengths by exponential distribution to\n         * ensure nice numbers */\n        U32 matchLen =\n                MIN_SEQ_LEN +\n                ROUND(RAND_exp(seed, (double)excessMatch / (double)(numSequences - i)));\n        U32 literalLen =\n                (RAND(seed) & 7)\n                        ? ROUND(RAND_exp(seed,\n                                         (double)literalsSize /\n                                                 (double)(numSequences - i)))\n                        : 0;\n        /* actual offset, code to send, and point to copy up to when shifting\n         * codes in the repeat offsets history */\n        U32 offset, offBase, repIndex;\n\n        /* bounds checks */\n        matchLen = (U32) MIN(matchLen, excessMatch + MIN_SEQ_LEN);\n        literalLen = MIN(literalLen, (U32) literalsSize);\n        if (i == 0 && srcPtr == frame->srcStart && literalLen == 0) literalLen = 1;\n        if (i + 1 == numSequences) matchLen = MIN_SEQ_LEN + (U32) excessMatch;\n\n        memcpy(srcPtr, literals, literalLen);\n        srcPtr += literalLen;\n        do {\n            if (RAND(seed) & 7) {\n                /* do a normal offset */\n                U32 const dataDecompressed = (U32)((BYTE*)srcPtr-(BYTE*)frame->srcStart);\n                offset = (RAND(seed) %\n                          MIN(frame->header.windowSize,\n                              (size_t)((BYTE*)srcPtr - (BYTE*)frame->srcStart))) +\n                         1;\n                if (info.useDict && (RAND(seed) & 1) && i + 1 != numSequences && dataDecompressed < frame->header.windowSize) {\n                    /* need to occasionally generate offsets that go past the start */\n                    /* including i+1 != numSequences because the last sequences has to adhere to predetermined contentSize */\n                    U32 lenPastStart = (RAND(seed) % info.dictContentSize) + 1;\n                    offset = (U32)((BYTE*)srcPtr - (BYTE*)frame->srcStart)+lenPastStart;\n                    if (offset > frame->header.windowSize) {\n                        if (lenPastStart < MIN_SEQ_LEN) {\n                            /* when offset > windowSize, matchLen bound by end of dictionary (lenPastStart) */\n                            /* this also means that lenPastStart must be greater than MIN_SEQ_LEN */\n                            /* make sure lenPastStart does not go past dictionary start though */\n                            lenPastStart = MIN(lenPastStart+MIN_SEQ_LEN, (U32)info.dictContentSize);\n                            offset = (U32)((BYTE*)srcPtr - (BYTE*)frame->srcStart) + lenPastStart;\n                        }\n                        {   U32 const matchLenBound = MIN(frame->header.windowSize, lenPastStart);\n                            matchLen = MIN(matchLen, matchLenBound);\n                        }\n                    }\n                }\n                offBase = OFFSET_TO_OFFBASE(offset);\n                repIndex = 2;\n            } else {\n                /* do a repeat offset */\n                U32 const randomRepIndex = RAND(seed) % 3;\n                offBase = REPCODE_TO_OFFBASE(randomRepIndex + 1);  /* expects values between 1 & 3 */\n                if (literalLen > 0) {\n                    offset = frame->stats.rep[randomRepIndex];\n                    repIndex = randomRepIndex;\n                } else {\n                    /* special case : literalLen == 0 */\n                    offset = randomRepIndex == 2 ? frame->stats.rep[0] - 1\n                                           : frame->stats.rep[randomRepIndex + 1];\n                    repIndex = MIN(2, randomRepIndex + 1);\n                }\n            }\n        } while (((!info.useDict) && (offset > (size_t)((BYTE*)srcPtr - (BYTE*)frame->srcStart))) || offset == 0);\n\n        {   BYTE* const dictEnd = ZSTD_maybeNullPtrAdd(info.dictContent, info.dictContentSize);\n            size_t j;\n            for (j = 0; j < matchLen; j++) {\n                if ((U32)((BYTE*)srcPtr - (BYTE*)frame->srcStart) < offset) {\n                    /* copy from dictionary instead of literals */\n                    size_t const dictOffset = offset - (srcPtr - (BYTE*)frame->srcStart);\n                    *srcPtr = *(dictEnd - dictOffset);\n                }\n                else {\n                    *srcPtr = *(srcPtr-offset);\n                }\n                srcPtr++;\n        }   }\n\n        {   int r;\n            for (r = repIndex; r > 0; r--) {\n                frame->stats.rep[r] = frame->stats.rep[r - 1];\n            }\n            frame->stats.rep[0] = offset;\n        }\n\n        DISPLAYLEVEL(6, \"      LL: %5u OF: %5u ML: %5u\",\n                    (unsigned)literalLen, (unsigned)offset, (unsigned)matchLen);\n        DISPLAYLEVEL(7, \" srcPos: %8u seqNb: %3u\",\n                     (unsigned)((BYTE*)srcPtr - (BYTE*)frame->srcStart), (unsigned)i);\n        DISPLAYLEVEL(6, \"\\n\");\n        if (OFFBASE_IS_REPCODE(offBase)) {  /* expects sumtype numeric representation of ZSTD_storeSeq() */\n            DISPLAYLEVEL(7, \"        repeat offset: %d\\n\", (int)repIndex);\n        }\n        /* use libzstd sequence handling */\n        ZSTD_storeSeq(seqStore, literalLen, literals, literals + literalLen,\n                      offBase, matchLen);\n\n        literalsSize -= literalLen;\n        excessMatch -= (matchLen - MIN_SEQ_LEN);\n        literals += literalLen;\n    }\n\n    memcpy(srcPtr, literals, literalsSize);\n    srcPtr += literalsSize;\n    DISPLAYLEVEL(6, \"      excess literals: %5u \", (unsigned)literalsSize);\n    DISPLAYLEVEL(7, \"srcPos: %8u \", (unsigned)((BYTE*)srcPtr - (BYTE*)frame->srcStart));\n    DISPLAYLEVEL(6, \"\\n\");\n\n    return numSequences;\n}\n\nstatic void initSymbolSet(const BYTE* symbols, size_t len, BYTE* set, BYTE maxSymbolValue)\n{\n    size_t i;\n\n    memset(set, 0, (size_t)maxSymbolValue+1);\n\n    for (i = 0; i < len; i++) {\n        set[symbols[i]] = 1;\n    }\n}\n\nstatic int isSymbolSubset(const BYTE* symbols, size_t len, const BYTE* set, BYTE maxSymbolValue)\n{\n    size_t i;\n\n    for (i = 0; i < len; i++) {\n        if (symbols[i] > maxSymbolValue || !set[symbols[i]]) {\n            return 0;\n        }\n    }\n    return 1;\n}\n\nstatic size_t writeSequences(U32* seed, frame_t* frame, SeqStore_t* seqStorePtr,\n                             size_t nbSeq)\n{\n    /* This code is mostly copied from ZSTD_compressSequences in zstd_compress.c */\n    unsigned count[MaxSeq+1];\n    S16 norm[MaxSeq+1];\n    FSE_CTable* CTable_LitLength = frame->stats.litlengthCTable;\n    FSE_CTable* CTable_OffsetBits = frame->stats.offcodeCTable;\n    FSE_CTable* CTable_MatchLength = frame->stats.matchlengthCTable;\n    U32 LLtype, Offtype, MLtype;   /* compressed, raw or rle */\n    const SeqDef* const sequences = seqStorePtr->sequencesStart;\n    const BYTE* const ofCodeTable = seqStorePtr->ofCode;\n    const BYTE* const llCodeTable = seqStorePtr->llCode;\n    const BYTE* const mlCodeTable = seqStorePtr->mlCode;\n    BYTE* const oend = (BYTE*)frame->dataEnd;\n    BYTE* op = (BYTE*)frame->data;\n    BYTE* seqHead;\n    BYTE scratchBuffer[FSE_BUILD_CTABLE_WORKSPACE_SIZE(MaxSeq, MaxFSELog)];\n\n    /* literals compressing block removed so that can be done separately */\n\n    /* Sequences Header */\n    if ((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead */) return ERROR(dstSize_tooSmall);\n    if (nbSeq < 128) *op++ = (BYTE)nbSeq;\n    else if (nbSeq < LONGNBSEQ) op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;\n    else op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;\n\n    if (nbSeq==0) {\n        frame->data = op;\n        return 0;\n    }\n\n    /* seqHead : flags for FSE encoding type */\n    seqHead = op++;\n\n    /* convert length/distances into codes */\n    ZSTD_seqToCodes(seqStorePtr);\n\n    /* CTable for Literal Lengths */\n    {   unsigned max = MaxLL;\n        size_t const mostFrequent = HIST_countFast_wksp(count, &max, llCodeTable, nbSeq, WKSP, sizeof(WKSP));   /* cannot fail */\n        assert(!HIST_isError(mostFrequent));\n        if (frame->stats.fseInit && !(RAND(seed) & 3) &&\n                   isSymbolSubset(llCodeTable, nbSeq,\n                                  frame->stats.litlengthSymbolSet, 35)) {\n            /* maybe do repeat mode if we're allowed to */\n            LLtype = set_repeat;\n        } else if (mostFrequent == nbSeq) {\n            /* do RLE if we have the chance */\n            *op++ = llCodeTable[0];\n            FSE_buildCTable_rle(CTable_LitLength, (BYTE)max);\n            LLtype = set_rle;\n        } else if (!(RAND(seed) & 3)) {\n            /* maybe use the default distribution */\n            CHECKERR(FSE_buildCTable_wksp(CTable_LitLength, LL_defaultNorm, MaxLL, LL_defaultNormLog, scratchBuffer, sizeof(scratchBuffer)));\n            LLtype = set_basic;\n        } else {\n            /* fall back on a full table */\n            size_t nbSeq_1 = nbSeq;\n            const U32 tableLog = FSE_optimalTableLog(LLFSELog, nbSeq, max);\n            if (count[llCodeTable[nbSeq-1]]>1) { count[llCodeTable[nbSeq-1]]--; nbSeq_1--; }\n            FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max, nbSeq >= 2048);\n            { size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog);   /* overflow protected */\n              if (FSE_isError(NCountSize)) return ERROR(GENERIC);\n              op += NCountSize; }\n            CHECKERR(FSE_buildCTable_wksp(CTable_LitLength, norm, max, tableLog, scratchBuffer, sizeof(scratchBuffer)));\n            LLtype = set_compressed;\n    }   }\n\n    /* CTable for Offsets */\n    /* see Literal Lengths for descriptions of mode choices */\n    {   unsigned max = MaxOff;\n        size_t const mostFrequent = HIST_countFast_wksp(count, &max, ofCodeTable, nbSeq, WKSP, sizeof(WKSP));   /* cannot fail */\n        assert(!HIST_isError(mostFrequent));\n        if (frame->stats.fseInit && !(RAND(seed) & 3) &&\n                   isSymbolSubset(ofCodeTable, nbSeq,\n                                  frame->stats.offsetSymbolSet, 28)) {\n            Offtype = set_repeat;\n        } else if (mostFrequent == nbSeq) {\n            *op++ = ofCodeTable[0];\n            FSE_buildCTable_rle(CTable_OffsetBits, (BYTE)max);\n            Offtype = set_rle;\n        } else if (!(RAND(seed) & 3)) {\n            FSE_buildCTable_wksp(CTable_OffsetBits, OF_defaultNorm, DefaultMaxOff, OF_defaultNormLog, scratchBuffer, sizeof(scratchBuffer));\n            Offtype = set_basic;\n        } else {\n            size_t nbSeq_1 = nbSeq;\n            const U32 tableLog = FSE_optimalTableLog(OffFSELog, nbSeq, max);\n            if (count[ofCodeTable[nbSeq-1]]>1) { count[ofCodeTable[nbSeq-1]]--; nbSeq_1--; }\n            FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max, nbSeq >= 2048);\n            { size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog);   /* overflow protected */\n              if (FSE_isError(NCountSize)) return ERROR(GENERIC);\n              op += NCountSize; }\n            FSE_buildCTable_wksp(CTable_OffsetBits, norm, max, tableLog, scratchBuffer, sizeof(scratchBuffer));\n            Offtype = set_compressed;\n    }   }\n\n    /* CTable for MatchLengths */\n    /* see Literal Lengths for descriptions of mode choices */\n    {   unsigned max = MaxML;\n        size_t const mostFrequent = HIST_countFast_wksp(count, &max, mlCodeTable, nbSeq, WKSP, sizeof(WKSP));   /* cannot fail */\n        assert(!HIST_isError(mostFrequent));\n        if (frame->stats.fseInit && !(RAND(seed) & 3) &&\n                   isSymbolSubset(mlCodeTable, nbSeq,\n                                  frame->stats.matchlengthSymbolSet, 52)) {\n            MLtype = set_repeat;\n        } else if (mostFrequent == nbSeq) {\n            *op++ = *mlCodeTable;\n            FSE_buildCTable_rle(CTable_MatchLength, (BYTE)max);\n            MLtype = set_rle;\n        } else if (!(RAND(seed) & 3)) {\n            /* sometimes do default distribution */\n            FSE_buildCTable_wksp(CTable_MatchLength, ML_defaultNorm, MaxML, ML_defaultNormLog, scratchBuffer, sizeof(scratchBuffer));\n            MLtype = set_basic;\n        } else {\n            /* fall back on table */\n            size_t nbSeq_1 = nbSeq;\n            const U32 tableLog = FSE_optimalTableLog(MLFSELog, nbSeq, max);\n            if (count[mlCodeTable[nbSeq-1]]>1) { count[mlCodeTable[nbSeq-1]]--; nbSeq_1--; }\n            FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max, nbSeq >= 2048);\n            { size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog);   /* overflow protected */\n              if (FSE_isError(NCountSize)) return ERROR(GENERIC);\n              op += NCountSize; }\n            FSE_buildCTable_wksp(CTable_MatchLength, norm, max, tableLog, scratchBuffer, sizeof(scratchBuffer));\n            MLtype = set_compressed;\n    }   }\n    frame->stats.fseInit = 1;\n    initSymbolSet(llCodeTable, nbSeq, frame->stats.litlengthSymbolSet, 35);\n    initSymbolSet(ofCodeTable, nbSeq, frame->stats.offsetSymbolSet, 28);\n    initSymbolSet(mlCodeTable, nbSeq, frame->stats.matchlengthSymbolSet, 52);\n\n    DISPLAYLEVEL(5, \"    LL type: %d OF type: %d ML type: %d\\n\", (unsigned)LLtype, (unsigned)Offtype, (unsigned)MLtype);\n\n    *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));\n\n    /* Encoding Sequences */\n    {   BIT_CStream_t blockStream;\n        FSE_CState_t  stateMatchLength;\n        FSE_CState_t  stateOffsetBits;\n        FSE_CState_t  stateLitLength;\n\n        RETURN_ERROR_IF(\n            ERR_isError(BIT_initCStream(&blockStream, op, oend-op)),\n            dstSize_tooSmall, \"not enough space remaining\");\n\n        /* first symbols */\n        FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]);\n        FSE_initCState2(&stateOffsetBits,  CTable_OffsetBits,  ofCodeTable[nbSeq-1]);\n        FSE_initCState2(&stateLitLength,   CTable_LitLength,   llCodeTable[nbSeq-1]);\n        BIT_addBits(&blockStream, sequences[nbSeq-1].litLength, LL_bits[llCodeTable[nbSeq-1]]);\n        if (MEM_32bits()) BIT_flushBits(&blockStream);\n        BIT_addBits(&blockStream, sequences[nbSeq-1].mlBase, ML_bits[mlCodeTable[nbSeq-1]]);\n        if (MEM_32bits()) BIT_flushBits(&blockStream);\n        BIT_addBits(&blockStream, sequences[nbSeq-1].offBase, ofCodeTable[nbSeq-1]);\n        BIT_flushBits(&blockStream);\n\n        {   size_t n;\n            for (n=nbSeq-2 ; n<nbSeq ; n--) {      /* intentional underflow */\n                BYTE const llCode = llCodeTable[n];\n                BYTE const ofCode = ofCodeTable[n];\n                BYTE const mlCode = mlCodeTable[n];\n                U32  const llBits = LL_bits[llCode];\n                U32  const ofBits = ofCode;                                     /* 32b*/  /* 64b*/\n                U32  const mlBits = ML_bits[mlCode];\n                                                                                /* (7)*/  /* (7)*/\n                FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode);       /* 15 */  /* 15 */\n                FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode);      /* 24 */  /* 24 */\n                if (MEM_32bits()) BIT_flushBits(&blockStream);                  /* (7)*/\n                FSE_encodeSymbol(&blockStream, &stateLitLength, llCode);        /* 16 */  /* 33 */\n                if (MEM_32bits() || (ofBits+mlBits+llBits >= 64-7-(LLFSELog+MLFSELog+OffFSELog)))\n                    BIT_flushBits(&blockStream);                                /* (7)*/\n                BIT_addBits(&blockStream, sequences[n].litLength, llBits);\n                if (MEM_32bits() && ((llBits+mlBits)>24)) BIT_flushBits(&blockStream);\n                BIT_addBits(&blockStream, sequences[n].mlBase, mlBits);\n                if (MEM_32bits()) BIT_flushBits(&blockStream);                  /* (7)*/\n                BIT_addBits(&blockStream, sequences[n].offBase, ofBits);         /* 31 */\n                BIT_flushBits(&blockStream);                                    /* (7)*/\n        }   }\n\n        FSE_flushCState(&blockStream, &stateMatchLength);\n        FSE_flushCState(&blockStream, &stateOffsetBits);\n        FSE_flushCState(&blockStream, &stateLitLength);\n\n        {   size_t const streamSize = BIT_closeCStream(&blockStream);\n            if (streamSize==0) return ERROR(dstSize_tooSmall);   /* not enough space */\n            op += streamSize;\n    }   }\n\n    frame->data = op;\n\n    return 0;\n}\n\nstatic size_t writeSequencesBlock(U32* seed, frame_t* frame, size_t contentSize,\n                                  size_t literalsSize, dictInfo info)\n{\n    SeqStore_t seqStore;\n    size_t numSequences;\n\n\n    initSeqStore(&seqStore);\n\n    /* randomly generate sequences */\n    numSequences = generateSequences(seed, frame, &seqStore, contentSize, literalsSize, info);\n    /* write them out to the frame data */\n    CHECKERR(writeSequences(seed, frame, &seqStore, numSequences));\n\n    return numSequences;\n}\n\nstatic size_t writeCompressedBlock(U32* seed, frame_t* frame, size_t contentSize, dictInfo info)\n{\n    BYTE* const blockStart = (BYTE*)frame->data;\n    size_t literalsSize;\n    size_t nbSeq;\n\n    DISPLAYLEVEL(4, \"  compressed block:\\n\");\n\n    literalsSize = writeLiteralsBlock(seed, frame, contentSize);\n\n    DISPLAYLEVEL(4, \"   literals size: %u\\n\", (unsigned)literalsSize);\n\n    nbSeq = writeSequencesBlock(seed, frame, contentSize, literalsSize, info);\n\n    DISPLAYLEVEL(4, \"   number of sequences: %u\\n\", (unsigned)nbSeq);\n\n    return (BYTE*)frame->data - blockStart;\n}\n\nstatic void writeBlock(U32* seed, frame_t* frame, size_t contentSize,\n                       int lastBlock, dictInfo info)\n{\n    int force_block_type = opts.blockType != NULL;\n    int const blockTypeDesc = (force_block_type) ? *(opts.blockType) : RAND(seed) % 8;\n    size_t blockSize;\n    int blockType;\n\n    BYTE *const header = (BYTE*)frame->data;\n    BYTE *op = header + 3;\n\n    DISPLAYLEVEL(4, \" block:\\n\");\n    DISPLAYLEVEL(4, \"  block content size: %u\\n\", (unsigned)contentSize);\n    DISPLAYLEVEL(4, \"  last block: %s\\n\", lastBlock ? \"yes\" : \"no\");\n\n    if (blockTypeDesc == 0) {\n        /* Raw data frame */\n\n        RAND_buffer(seed, frame->src, contentSize);\n        memcpy(op, frame->src, contentSize);\n\n        op += contentSize;\n        blockType = 0;\n        blockSize = contentSize;\n    } else if (blockTypeDesc == 1 && frame->header.contentSize > 0) {\n        /* RLE (Don't create RLE block if frame content is 0 since block size of 1 may exceed max block size)*/\n        BYTE const symbol = RAND(seed) & 0xff;\n\n        op[0] = symbol;\n        memset(frame->src, symbol, contentSize);\n\n        op++;\n        blockType = 1;\n        blockSize = contentSize;\n    } else {\n        /* compressed, most common */\n        size_t compressedSize;\n        blockType = 2;\n\n        frame->oldStats = frame->stats;\n\n        frame->data = op;\n        compressedSize = writeCompressedBlock(seed, frame, contentSize, info);\n        if (compressedSize >= contentSize && !force_block_type) {   /* compressed block must be strictly smaller than uncompressed one */\n            blockType = 0;\n            memcpy(op, frame->src, contentSize);\n\n            op += contentSize;\n            blockSize = contentSize; /* fall back on raw block if data doesn't\n                                        compress */\n\n            frame->stats = frame->oldStats; /* don't update the stats */\n        } else {\n            op += compressedSize;\n            blockSize = compressedSize;\n        }\n    }\n    frame->src = (BYTE*)frame->src + contentSize;\n\n    DISPLAYLEVEL(4, \"  block type: %s\\n\", BLOCK_TYPES[blockType]);\n    DISPLAYLEVEL(4, \"  block size field: %u\\n\", (unsigned)blockSize);\n\n    header[0] = (BYTE) ((lastBlock | (blockType << 1) | (blockSize << 3)) & 0xff);\n    MEM_writeLE16(header + 1, (U16) (blockSize >> 5));\n\n    frame->data = op;\n}\n\nstatic void writeBlocks(U32* seed, frame_t* frame, dictInfo info)\n{\n    size_t contentLeft = frame->header.contentSize;\n    size_t const maxBlockSize = MIN(g_maxBlockSize, frame->header.windowSize);\n    while (1) {\n        /* 1 in 4 chance of ending frame */\n        int const lastBlock = contentLeft > maxBlockSize ? 0 : !(RAND(seed) & 3);\n        size_t blockContentSize;\n        if (lastBlock) {\n            blockContentSize = contentLeft;\n        } else {\n            if (contentLeft > 0 && (RAND(seed) & 7)) {\n                /* some variable size block */\n                blockContentSize = RAND(seed) % (MIN(maxBlockSize, contentLeft)+1);\n            } else if (contentLeft > maxBlockSize && (RAND(seed) & 1)) {\n                /* some full size block */\n                blockContentSize = maxBlockSize;\n            } else {\n                /* some empty block */\n                blockContentSize = 0;\n            }\n        }\n\n        writeBlock(seed, frame, blockContentSize, lastBlock, info);\n\n        contentLeft -= blockContentSize;\n        if (lastBlock) break;\n    }\n}\n\nstatic void writeChecksum(frame_t* frame)\n{\n    /* write checksum so implementations can verify their output */\n    U64 digest = XXH64(frame->srcStart, (BYTE*)frame->src-(BYTE*)frame->srcStart, 0);\n    DISPLAYLEVEL(3, \"  checksum: %08x\\n\", (unsigned)digest);\n    MEM_writeLE32(frame->data, (U32)digest);\n    frame->data = (BYTE*)frame->data + 4;\n}\n\nstatic void outputBuffer(const void* buf, size_t size, const char* const path)\n{\n    /* write data out to file */\n    const BYTE* ip = (const BYTE*)buf;\n    FILE* out;\n    if (path) {\n        out = fopen(path, \"wb\");\n    } else {\n        out = stdout;\n    }\n    if (!out) {\n        fprintf(stderr, \"Failed to open file at %s: \", path);\n        perror(NULL);\n        exit(1);\n    }\n\n    {   size_t fsize = size;\n        size_t written = 0;\n        while (written < fsize) {\n            written += fwrite(ip + written, 1, fsize - written, out);\n            if (ferror(out)) {\n                fprintf(stderr, \"Failed to write to file at %s: \", path);\n                perror(NULL);\n                exit(1);\n            }\n        }\n    }\n\n    if (path) {\n        fclose(out);\n    }\n}\n\nstatic void initFrame(frame_t* fr)\n{\n    memset(fr, 0, sizeof(*fr));\n    fr->data = fr->dataStart = FRAME_BUFFER;\n    fr->dataEnd = FRAME_BUFFER + sizeof(FRAME_BUFFER);\n    fr->src = fr->srcStart = CONTENT_BUFFER;\n    fr->srcEnd = CONTENT_BUFFER + sizeof(CONTENT_BUFFER);\n\n    /* init repeat codes */\n    fr->stats.rep[0] = 1;\n    fr->stats.rep[1] = 4;\n    fr->stats.rep[2] = 8;\n}\n\n/**\n * Generated a single zstd compressed block with no block/frame header.\n * Returns the final seed.\n */\nstatic U32 generateCompressedBlock(U32 seed, frame_t* frame, dictInfo info)\n{\n    size_t blockContentSize;\n    int blockWritten = 0;\n    BYTE* op;\n    DISPLAYLEVEL(4, \"block seed: %u\\n\", (unsigned)seed);\n    initFrame(frame);\n    op = (BYTE*)frame->data;\n\n    while (!blockWritten) {\n        size_t cSize;\n        /* generate window size */\n        {   int const exponent = RAND(&seed) % (MAX_WINDOW_LOG - 10);\n            int const mantissa = RAND(&seed) % 8;\n            frame->header.windowSize = (1U << (exponent + 10));\n            frame->header.windowSize += (frame->header.windowSize / 8) * mantissa;\n        }\n\n        /* generate content size */\n        {   size_t const maxBlockSize = MIN(g_maxBlockSize, frame->header.windowSize);\n            if (RAND(&seed) & 15) {\n                /* some full size blocks */\n                blockContentSize = maxBlockSize;\n            } else if (RAND(&seed) & 7 && g_maxBlockSize >= (1U << 7)) {\n                /* some small blocks <= 128 bytes*/\n                blockContentSize = RAND(&seed) % (1U << 7);\n            } else {\n                /* some variable size blocks */\n                blockContentSize = RAND(&seed) % maxBlockSize;\n            }\n        }\n\n        /* try generating a compressed block */\n        frame->oldStats = frame->stats;\n        frame->data = op;\n        cSize = writeCompressedBlock(&seed, frame, blockContentSize, info);\n        if (cSize >= blockContentSize) {  /* compressed size must be strictly smaller than decompressed size : https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#blocks */\n            /* data doesn't compress -- try again */\n            frame->stats = frame->oldStats; /* don't update the stats */\n            DISPLAYLEVEL(5, \"   can't compress block : try again \\n\");\n        } else {\n            blockWritten = 1;\n            DISPLAYLEVEL(4, \"   block size: %u \\n\", (unsigned)cSize);\n            frame->src = (BYTE*)frame->src + blockContentSize;\n        }\n    }\n    return seed;\n}\n\n/* Return the final seed */\nstatic U32 generateFrame(U32 seed, frame_t* fr, dictInfo info)\n{\n    /* generate a complete frame */\n    DISPLAYLEVEL(3, \"frame seed: %u\\n\", (unsigned)seed);\n    initFrame(fr);\n\n\n    writeFrameHeader(&seed, fr, info);\n    if (opts.frame_header_only)\n        return seed;\n\n    writeBlocks(&seed, fr, info);\n    writeChecksum(fr);\n\n    return seed;\n}\n\n/*_*******************************************************\n*  Dictionary Helper Functions\n*********************************************************/\n/* returns 0 if successful, otherwise returns 1 upon error */\nstatic int genRandomDict(U32 dictID, U32 seed, size_t dictSize, BYTE* fullDict)\n{\n    /* allocate space for samples */\n    int ret = 0;\n    unsigned const numSamples = 4;\n    size_t sampleSizes[4];\n    BYTE* const samples = malloc(5000*sizeof(BYTE));\n    if (samples == NULL) {\n        DISPLAY(\"Error: could not allocate space for samples\\n\");\n        return 1;\n    }\n\n    /* generate samples */\n    {   unsigned literalValue = 1;\n        unsigned samplesPos = 0;\n        size_t currSize = 1;\n        while (literalValue <= 4) {\n            sampleSizes[literalValue - 1] = currSize;\n            {   size_t k;\n                for (k = 0; k < currSize; k++) {\n                    *(samples + (samplesPos++)) = (BYTE)literalValue;\n            }   }\n            literalValue++;\n            currSize *= 16;\n    }   }\n\n    {   size_t dictWriteSize = 0;\n        ZDICT_params_t zdictParams;\n        size_t const headerSize = MAX(dictSize/4, 256);\n        size_t const dictContentSize = dictSize - headerSize;\n        BYTE* const dictContent = fullDict + headerSize;\n        if (dictContentSize < ZDICT_CONTENTSIZE_MIN || dictSize < ZDICT_DICTSIZE_MIN) {\n            DISPLAY(\"Error: dictionary size is too small\\n\");\n            ret = 1;\n            goto exitGenRandomDict;\n        }\n\n        /* init dictionary params */\n        memset(&zdictParams, 0, sizeof(zdictParams));\n        zdictParams.dictID = dictID;\n        zdictParams.notificationLevel = 1;\n\n        /* fill in dictionary content */\n        RAND_buffer(&seed, (void*)dictContent, dictContentSize);\n\n        /* finalize dictionary with random samples */\n        dictWriteSize = ZDICT_finalizeDictionary(fullDict, dictSize,\n                                    dictContent, dictContentSize,\n                                    samples, sampleSizes, numSamples,\n                                    zdictParams);\n\n        if (ZDICT_isError(dictWriteSize)) {\n            DISPLAY(\"Could not finalize dictionary: %s\\n\", ZDICT_getErrorName(dictWriteSize));\n            ret = 1;\n        }\n    }\n\nexitGenRandomDict:\n    free(samples);\n    return ret;\n}\n\nstatic dictInfo initDictInfo(int useDict, size_t dictContentSize, BYTE* dictContent, U32 dictID){\n    /* allocate space statically */\n    dictInfo dictOp;\n    memset(&dictOp, 0, sizeof(dictOp));\n    dictOp.useDict = useDict;\n    dictOp.dictContentSize = dictContentSize;\n    dictOp.dictContent = dictContent;\n    dictOp.dictID = dictID;\n    return dictOp;\n}\n\n/*-*******************************************************\n*  Test Mode\n*********************************************************/\n\nBYTE DECOMPRESSED_BUFFER[MAX_DECOMPRESSED_SIZE];\n\nstatic size_t testDecodeSimple(frame_t* fr)\n{\n    /* test decoding the generated data with the simple API */\n    size_t const ret = ZSTD_decompress(DECOMPRESSED_BUFFER, MAX_DECOMPRESSED_SIZE,\n                           fr->dataStart, (BYTE*)fr->data - (BYTE*)fr->dataStart);\n\n    if (ZSTD_isError(ret)) return ret;\n\n    if (memcmp(DECOMPRESSED_BUFFER, fr->srcStart,\n               (BYTE*)fr->src - (BYTE*)fr->srcStart) != 0) {\n        return ERROR(corruption_detected);\n    }\n\n    return ret;\n}\n\nstatic size_t testDecodeStreaming(frame_t* fr)\n{\n    /* test decoding the generated data with the streaming API */\n    ZSTD_DStream* zd = ZSTD_createDStream();\n    ZSTD_inBuffer in;\n    ZSTD_outBuffer out;\n    size_t ret;\n\n    if (!zd) return ERROR(memory_allocation);\n\n    in.src = fr->dataStart;\n    in.pos = 0;\n    in.size = (BYTE*)fr->data - (BYTE*)fr->dataStart;\n\n    out.dst = DECOMPRESSED_BUFFER;\n    out.pos = 0;\n    out.size = ZSTD_DStreamOutSize();\n\n    ZSTD_initDStream(zd);\n    while (1) {\n        ret = ZSTD_decompressStream(zd, &out, &in);\n        if (ZSTD_isError(ret)) goto cleanup; /* error */\n        if (ret == 0) break; /* frame is done */\n\n        /* force decoding to be done in chunks */\n        out.size += MIN(ZSTD_DStreamOutSize(), MAX_DECOMPRESSED_SIZE - out.size);\n    }\n\n    ret = out.pos;\n\n    if (memcmp(out.dst, fr->srcStart, out.pos) != 0) {\n        return ERROR(corruption_detected);\n    }\n\ncleanup:\n    ZSTD_freeDStream(zd);\n    return ret;\n}\n\nstatic size_t testDecodeWithDict(U32 seed, genType_e genType)\n{\n    /* create variables */\n    size_t const dictSize = RAND(&seed) % (10 << 20) + ZDICT_DICTSIZE_MIN + ZDICT_CONTENTSIZE_MIN;\n    U32 const dictID = RAND(&seed);\n    size_t errorDetected = 0;\n    BYTE* const fullDict = malloc(dictSize);\n    if (fullDict == NULL) {\n        return ERROR(GENERIC);\n    }\n\n    /* generate random dictionary */\n    if (genRandomDict(dictID, seed, dictSize, fullDict)) {  /* return 0 on success */\n        errorDetected = ERROR(GENERIC);\n        goto dictTestCleanup;\n    }\n\n\n    {   frame_t fr;\n        dictInfo info;\n        ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n        size_t ret;\n\n        /* get dict info */\n        {   size_t const headerSize = MAX(dictSize/4, 256);\n            size_t const dictContentSize = dictSize-headerSize;\n            BYTE* const dictContent = fullDict+headerSize;\n            info = initDictInfo(1, dictContentSize, dictContent, dictID);\n        }\n\n        /* manually decompress and check difference */\n        if (genType == gt_frame) {\n            /* Test frame */\n            generateFrame(seed, &fr, info);\n            ret = ZSTD_decompress_usingDict(dctx, DECOMPRESSED_BUFFER, MAX_DECOMPRESSED_SIZE,\n                                            fr.dataStart, (BYTE*)fr.data - (BYTE*)fr.dataStart,\n                                            fullDict, dictSize);\n        } else {\n            /* Test block */\n            generateCompressedBlock(seed, &fr, info);\n            ret = ZSTD_decompressBegin_usingDict(dctx, fullDict, dictSize);\n            if (ZSTD_isError(ret)) {\n                errorDetected = ret;\n                ZSTD_freeDCtx(dctx);\n                goto dictTestCleanup;\n            }\n            ret = ZSTD_decompressBlock_deprecated(dctx, DECOMPRESSED_BUFFER, MAX_DECOMPRESSED_SIZE,\n                                       fr.dataStart, (BYTE*)fr.data - (BYTE*)fr.dataStart);\n        }\n        ZSTD_freeDCtx(dctx);\n\n        if (ZSTD_isError(ret)) {\n            errorDetected = ret;\n            goto dictTestCleanup;\n        }\n\n        if (memcmp(DECOMPRESSED_BUFFER, fr.srcStart, (BYTE*)fr.src - (BYTE*)fr.srcStart) != 0) {\n            errorDetected = ERROR(corruption_detected);\n            goto dictTestCleanup;\n        }\n    }\n\ndictTestCleanup:\n    free(fullDict);\n    return errorDetected;\n}\n\nstatic size_t testDecodeRawBlock(frame_t* fr)\n{\n    ZSTD_DCtx* dctx = ZSTD_createDCtx();\n    size_t ret = ZSTD_decompressBegin(dctx);\n    if (ZSTD_isError(ret)) return ret;\n\n    ret = ZSTD_decompressBlock_deprecated(\n            dctx,\n            DECOMPRESSED_BUFFER, MAX_DECOMPRESSED_SIZE,\n            fr->dataStart, (BYTE*)fr->data - (BYTE*)fr->dataStart);\n    ZSTD_freeDCtx(dctx);\n    if (ZSTD_isError(ret)) return ret;\n\n    if (memcmp(DECOMPRESSED_BUFFER, fr->srcStart,\n               (BYTE*)fr->src - (BYTE*)fr->srcStart) != 0) {\n        return ERROR(corruption_detected);\n    }\n\n    return ret;\n}\n\nstatic int runBlockTest(U32* seed)\n{\n    frame_t fr;\n    U32 const seedCopy = *seed;\n    {   dictInfo const info = initDictInfo(0, 0, NULL, 0);\n        *seed = generateCompressedBlock(*seed, &fr, info);\n    }\n\n    {   size_t const r = testDecodeRawBlock(&fr);\n        if (ZSTD_isError(r)) {\n            DISPLAY(\"Error in block mode on test seed %u: %s\\n\",\n                    (unsigned)seedCopy, ZSTD_getErrorName(r));\n            return 1;\n        }\n    }\n\n    {   size_t const r = testDecodeWithDict(*seed, gt_block);\n        if (ZSTD_isError(r)) {\n            DISPLAY(\"Error in block mode with dictionary on test seed %u: %s\\n\",\n                    (unsigned)seedCopy, ZSTD_getErrorName(r));\n            return 1;\n        }\n    }\n    return 0;\n}\n\nstatic int runFrameTest(U32* seed)\n{\n    frame_t fr;\n    U32 const seedCopy = *seed;\n    {   dictInfo const info = initDictInfo(0, 0, NULL, 0);\n        *seed = generateFrame(*seed, &fr, info);\n    }\n\n    {   size_t const r = testDecodeSimple(&fr);\n        if (ZSTD_isError(r)) {\n            DISPLAY(\"Error in simple mode on test seed %u: %s\\n\",\n                    (unsigned)seedCopy, ZSTD_getErrorName(r));\n            return 1;\n        }\n    }\n    {   size_t const r = testDecodeStreaming(&fr);\n        if (ZSTD_isError(r)) {\n            DISPLAY(\"Error in streaming mode on test seed %u: %s\\n\",\n                    (unsigned)seedCopy, ZSTD_getErrorName(r));\n            return 1;\n        }\n    }\n    {   size_t const r = testDecodeWithDict(*seed, gt_frame);  /* avoid big dictionaries */\n        if (ZSTD_isError(r)) {\n            DISPLAY(\"Error in dictionary mode on test seed %u: %s\\n\",\n                    (unsigned)seedCopy, ZSTD_getErrorName(r));\n            return 1;\n        }\n    }\n    return 0;\n}\n\nstatic int runTestMode(U32 seed, unsigned numFiles, unsigned const testDurationS,\n                       genType_e genType)\n{\n    unsigned fnum;\n\n    UTIL_time_t const startClock = UTIL_getTime();\n    U64 const maxClockSpan = testDurationS * SEC_TO_MICRO;\n\n    if (numFiles == 0 && !testDurationS) numFiles = 1;\n\n    DISPLAY(\"seed: %u\\n\", (unsigned)seed);\n\n    for (fnum = 0; fnum < numFiles || UTIL_clockSpanMicro(startClock) < maxClockSpan; fnum++) {\n        if (fnum < numFiles)\n            DISPLAYUPDATE(\"\\r%u/%u        \", fnum, numFiles);\n        else\n            DISPLAYUPDATE(\"\\r%u           \", fnum);\n\n        {   int const ret = (genType == gt_frame) ?\n                            runFrameTest(&seed) :\n                            runBlockTest(&seed);\n            if (ret) return ret;\n        }\n    }\n\n    DISPLAY(\"\\r%u tests completed: \", fnum);\n    DISPLAY(\"OK\\n\");\n\n    return 0;\n}\n\n/*-*******************************************************\n*  File I/O\n*********************************************************/\n\nstatic int generateFile(U32 seed, const char* const path,\n                        const char* const origPath, genType_e genType)\n{\n    frame_t fr;\n\n    DISPLAY(\"seed: %u\\n\", (unsigned)seed);\n\n    {   dictInfo const info = initDictInfo(0, 0, NULL, 0);\n        if (genType == gt_frame) {\n            generateFrame(seed, &fr, info);\n        } else {\n            generateCompressedBlock(seed, &fr, info);\n        }\n    }\n    outputBuffer(fr.dataStart, (BYTE*)fr.data - (BYTE*)fr.dataStart, path);\n    if (origPath) {\n        outputBuffer(fr.srcStart, (BYTE*)fr.src - (BYTE*)fr.srcStart, origPath);\n    }\n    return 0;\n}\n\nstatic int generateCorpus(U32 seed, unsigned numFiles, const char* const path,\n                          const char* const origPath, genType_e genType)\n{\n    char outPath[MAX_PATH];\n    unsigned fnum;\n\n    DISPLAY(\"seed: %u\\n\", (unsigned)seed);\n\n    for (fnum = 0; fnum < numFiles; fnum++) {\n        frame_t fr;\n\n        DISPLAYUPDATE(\"\\r%u/%u        \", fnum, numFiles);\n\n        {   dictInfo const info = initDictInfo(0, 0, NULL, 0);\n            if (genType == gt_frame) {\n                seed = generateFrame(seed, &fr, info);\n            } else {\n                seed = generateCompressedBlock(seed, &fr, info);\n            }\n        }\n\n        if (snprintf(outPath, MAX_PATH, \"%s/z%06u.zst\", path, fnum) + 1 > MAX_PATH) {\n            DISPLAY(\"Error: path too long\\n\");\n            return 1;\n        }\n        outputBuffer(fr.dataStart, (BYTE*)fr.data - (BYTE*)fr.dataStart, outPath);\n\n        if (origPath) {\n            if (snprintf(outPath, MAX_PATH, \"%s/z%06u\", origPath, fnum) + 1 > MAX_PATH) {\n                DISPLAY(\"Error: path too long\\n\");\n                return 1;\n            }\n            outputBuffer(fr.srcStart, (BYTE*)fr.src - (BYTE*)fr.srcStart, outPath);\n        }\n    }\n\n    DISPLAY(\"\\r%u/%u      \\n\", fnum, numFiles);\n\n    return 0;\n}\n\nstatic int generateCorpusWithDict(U32 seed, unsigned numFiles, const char* const path,\n                                  const char* const origPath, const size_t dictSize,\n                                  genType_e genType)\n{\n    char outPath[MAX_PATH];\n    BYTE* fullDict;\n    U32 const dictID = RAND(&seed);\n    int errorDetected = 0;\n\n    if (snprintf(outPath, MAX_PATH, \"%s/dictionary\", path) + 1 > MAX_PATH) {\n        DISPLAY(\"Error: path too long\\n\");\n        return 1;\n    }\n\n    /* allocate space for the dictionary */\n    fullDict = malloc(dictSize);\n    if (fullDict == NULL) {\n        DISPLAY(\"Error: could not allocate space for full dictionary.\\n\");\n        return 1;\n    }\n\n    /* randomly generate the dictionary */\n    {   int const ret = genRandomDict(dictID, seed, dictSize, fullDict);\n        if (ret != 0) {\n            errorDetected = ret;\n            goto dictCleanup;\n        }\n    }\n\n    /* write out dictionary */\n    if (numFiles != 0) {\n        if (snprintf(outPath, MAX_PATH, \"%s/dictionary\", path) + 1 > MAX_PATH) {\n            DISPLAY(\"Error: dictionary path too long\\n\");\n            errorDetected = 1;\n            goto dictCleanup;\n        }\n        outputBuffer(fullDict, dictSize, outPath);\n    }\n    else {\n        outputBuffer(fullDict, dictSize, \"dictionary\");\n    }\n\n    /* generate random compressed/decompressed files */\n    {   unsigned fnum;\n        for (fnum = 0; fnum < MAX(numFiles, 1); fnum++) {\n            frame_t fr;\n            DISPLAYUPDATE(\"\\r%u/%u        \", fnum, numFiles);\n            {\n                size_t const headerSize = MAX(dictSize/4, 256);\n                size_t const dictContentSize = dictSize-headerSize;\n                BYTE* const dictContent = fullDict+headerSize;\n                dictInfo const info = initDictInfo(1, dictContentSize, dictContent, dictID);\n                if (genType == gt_frame) {\n                    seed = generateFrame(seed, &fr, info);\n                } else {\n                    seed = generateCompressedBlock(seed, &fr, info);\n                }\n            }\n\n            if (numFiles != 0) {\n                if (snprintf(outPath, MAX_PATH, \"%s/z%06u.zst\", path, fnum) + 1 > MAX_PATH) {\n                    DISPLAY(\"Error: path too long\\n\");\n                    errorDetected = 1;\n                    goto dictCleanup;\n                }\n                outputBuffer(fr.dataStart, (BYTE*)fr.data - (BYTE*)fr.dataStart, outPath);\n\n                if (origPath) {\n                    if (snprintf(outPath, MAX_PATH, \"%s/z%06u\", origPath, fnum) + 1 > MAX_PATH) {\n                        DISPLAY(\"Error: path too long\\n\");\n                        errorDetected = 1;\n                        goto dictCleanup;\n                    }\n                    outputBuffer(fr.srcStart, (BYTE*)fr.src - (BYTE*)fr.srcStart, outPath);\n                }\n            }\n            else {\n                outputBuffer(fr.dataStart, (BYTE*)fr.data - (BYTE*)fr.dataStart, path);\n                if (origPath) {\n                    outputBuffer(fr.srcStart, (BYTE*)fr.src - (BYTE*)fr.srcStart, origPath);\n                }\n            }\n        }\n    }\n\ndictCleanup:\n    free(fullDict);\n    return errorDetected;\n}\n\n\n/*_*******************************************************\n*  Command line\n*********************************************************/\nstatic U32 makeSeed(void)\n{\n    U32 t = (U32) time(NULL);\n    return XXH32(&t, sizeof(t), 0) % 65536;\n}\n\nstatic unsigned readInt(const char** argument)\n{\n    unsigned val = 0;\n    while ((**argument>='0') && (**argument<='9')) {\n        val *= 10;\n        val += **argument - '0';\n        (*argument)++;\n    }\n    return val;\n}\n\nstatic void usage(const char* programName)\n{\n    DISPLAY( \"Usage :\\n\");\n    DISPLAY( \"      %s [args]\\n\", programName);\n    DISPLAY( \"\\n\");\n    DISPLAY( \"Arguments :\\n\");\n    DISPLAY( \" -p<path> : select output path (default:stdout)\\n\");\n    DISPLAY( \"                in multiple files mode this should be a directory\\n\");\n    DISPLAY( \" -o<path> : select path to output original file (default:no output)\\n\");\n    DISPLAY( \"                in multiple files mode this should be a directory\\n\");\n    DISPLAY( \" -s#      : select seed (default:random based on time)\\n\");\n    DISPLAY( \" -n#      : number of files to generate (default:1)\\n\");\n    DISPLAY( \" -t       : activate test mode (test files against libzstd instead of outputting them)\\n\");\n    DISPLAY( \" -T#      : length of time to run tests for\\n\");\n    DISPLAY( \" -v       : increase verbosity level (default:0, max:7)\\n\");\n    DISPLAY( \" -h/H     : display help/long help and exit\\n\");\n}\n\nstatic void advancedUsage(const char* programName)\n{\n    usage(programName);\n    DISPLAY( \"\\n\");\n    DISPLAY( \"Advanced arguments        :\\n\");\n    DISPLAY( \" --content-size           : always include the content size in the frame header\\n\");\n    DISPLAY( \" --use-dict=#             : include a dictionary used to decompress the corpus\\n\");\n    DISPLAY( \" --gen-blocks             : generate raw compressed blocks without block/frame headers\\n\");\n    DISPLAY( \" --max-block-size-log=#   : max block size log, must be in range [2, 17]\\n\");\n    DISPLAY( \" --max-content-size-log=# : max content size log, must be <= 20\\n\");\n    DISPLAY( \"                            (this is ignored with gen-blocks)\\n\");\n    DISPLAY( \" --block-type=#           : force certain block type (raw=0, rle=1, compressed=2)\\n\");\n    DISPLAY( \" --frame-header-only      : dump only frame header\\n\");\n    DISPLAY( \" --no-magic               : do not add magic number\\n\");\n}\n\n/*! readU32FromChar() :\n    @return : unsigned integer value read from input in `char` format\n    allows and interprets K, KB, KiB, M, MB and MiB suffix.\n    Will also modify `*stringPtr`, advancing it to position where it stopped reading.\n    Note : function result can overflow if digit string > MAX_UINT */\nstatic unsigned readU32FromChar(const char** stringPtr)\n{\n    unsigned result = 0;\n    while ((**stringPtr >='0') && (**stringPtr <='9'))\n        result *= 10, result += **stringPtr - '0', (*stringPtr)++ ;\n    if ((**stringPtr=='K') || (**stringPtr=='M')) {\n        result <<= 10;\n        if (**stringPtr=='M') result <<= 10;\n        (*stringPtr)++ ;\n        if (**stringPtr=='i') (*stringPtr)++;\n        if (**stringPtr=='B') (*stringPtr)++;\n    }\n    return result;\n}\n\n/** longCommandWArg() :\n *  check if *stringPtr is the same as longCommand.\n *  If yes, @return 1 and advances *stringPtr to the position which immediately follows longCommand.\n *  @return 0 and doesn't modify *stringPtr otherwise.\n */\nstatic unsigned longCommandWArg(const char** stringPtr, const char* longCommand)\n{\n    size_t const comSize = strlen(longCommand);\n    int const result = !strncmp(*stringPtr, longCommand, comSize);\n    if (result) *stringPtr += comSize;\n    return result;\n}\n\nint main(int argc, char** argv)\n{\n    U32 seed = 0;\n    int seedset = 0;\n    unsigned numFiles = 0;\n    unsigned testDuration = 0;\n    int testMode = 0;\n    const char* path = NULL;\n    const char* origPath = NULL;\n    int useDict = 0;\n    unsigned dictSize = (10 << 10); /* 10 kB default */\n    genType_e genType = gt_frame;\n\n    int argNb;\n\n    /* Check command line */\n    for (argNb=1; argNb<argc; argNb++) {\n        const char* argument = argv[argNb];\n        if(!argument) continue;   /* Protection if argument empty */\n\n        /* Handle commands. Aggregated commands are allowed */\n        if (argument[0]=='-') {\n            argument++;\n            while (*argument!=0) {\n                switch(*argument)\n                {\n                case 'h':\n                    usage(argv[0]);\n                    return 0;\n                case 'H':\n                    advancedUsage(argv[0]);\n                    return 0;\n                case 'v':\n                    argument++;\n                    g_displayLevel++;\n                    break;\n                case 's':\n                    argument++;\n                    seedset=1;\n                    seed = readInt(&argument);\n                    break;\n                case 'n':\n                    argument++;\n                    numFiles = readInt(&argument);\n                    break;\n                case 'T':\n                    argument++;\n                    testDuration = readInt(&argument);\n                    if (*argument == 'm') {\n                        testDuration *= 60;\n                        argument++;\n                        if (*argument == 'n') argument++;\n                    }\n                    break;\n                case 'o':\n                    argument++;\n                    origPath = argument;\n                    argument += strlen(argument);\n                    break;\n                case 'p':\n                    argument++;\n                    path = argument;\n                    argument += strlen(argument);\n                    break;\n                case 't':\n                    argument++;\n                    testMode = 1;\n                    break;\n                case '-':\n                    argument++;\n                    if (strcmp(argument, \"content-size\") == 0) {\n                        opts.contentSize = 1;\n                    } else if (longCommandWArg(&argument, \"use-dict=\")) {\n                        dictSize = readU32FromChar(&argument);\n                        useDict = 1;\n                    } else if (strcmp(argument, \"gen-blocks\") == 0) {\n                        genType = gt_block;\n                    } else if (longCommandWArg(&argument, \"max-block-size-log=\")) {\n                        U32 value = readU32FromChar(&argument);\n                        if (value >= 2 && value <= ZSTD_BLOCKSIZE_MAX) {\n                            g_maxBlockSize = 1U << value;\n                        }\n                    } else if (longCommandWArg(&argument, \"max-content-size-log=\")) {\n                        U32 value = readU32FromChar(&argument);\n                        g_maxDecompressedSizeLog =\n                                MIN(MAX_DECOMPRESSED_SIZE_LOG, value);\n                    } else if (longCommandWArg(&argument, \"block-type=\")) {\n                        U32 value = readU32FromChar(&argument);\n                        opts.blockType = malloc(sizeof(blockType_e));\n                        *(opts.blockType) = value;\n                    } else if (longCommandWArg(&argument, \"literal-type=\")) {\n                        U32 value = readU32FromChar(&argument);\n                        opts.literalType = malloc(sizeof(literalType_e));\n                        *(opts.literalType) = value;\n                    } else if (strcmp(argument, \"frame-header-only\") == 0) {\n                        opts.frame_header_only = 1;\n                    } else if (strcmp(argument, \"no-magic\") == 0) {\n                        opts.no_magic = 1;\n                    } else {\n                        advancedUsage(argv[0]);\n                        return 1;\n                    }\n                    argument += strlen(argument);\n                    break;\n                default:\n                    usage(argv[0]);\n                    return 1;\n    }   }   }   }   /* for (argNb=1; argNb<argc; argNb++) */\n\n    if (opts.blockType) {\n        if ((opts.contentSize == 0) && (*(opts.blockType) == bt_rle)) {\n            DISPLAY(\"Error: content-size has to be used together with blockType=1 (rle block)\\n\");\n            return 1;\n        }\n\n        if (opts.literalType && (*(opts.blockType) != bt_compressed)) {\n            DISPLAY(\"Error: literal-type can be used only with blockType=2 (compressed block)\\n\");\n            return 1;\n        }\n    }\n\n    if (!seedset) {\n        seed = makeSeed();\n    }\n\n    if (testMode) {\n        return runTestMode(seed, numFiles, testDuration, genType);\n    } else {\n        if (testDuration) {\n            DISPLAY(\"Error: -T requires test mode (-t)\\n\\n\");\n            usage(argv[0]);\n            return 1;\n        }\n    }\n\n    if (!path) {\n        DISPLAY(\"Error: path is required in file generation mode\\n\");\n        usage(argv[0]);\n        return 1;\n    }\n\n    if (numFiles == 0 && useDict == 0) {\n        return generateFile(seed, path, origPath, genType);\n    } else if (useDict == 0){\n        return generateCorpus(seed, numFiles, path, origPath, genType);\n    } else {\n        /* should generate files with a dictionary */\n        return generateCorpusWithDict(seed, numFiles, path, origPath, dictSize, genType);\n    }\n\n}\n"
  },
  {
    "path": "tests/external_matchfinder.c",
    "content": "/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"external_matchfinder.h\"\n#include <string.h>\n#include \"zstd_compress_internal.h\"\n\n#define HSIZE 1024\nstatic U32 const HLOG = 10;\nstatic U32 const MLS = 4;\nstatic U32 const BADIDX = 0xffffffff;\n\nstatic size_t simpleSequenceProducer(\n  void* sequenceProducerState,\n  ZSTD_Sequence* outSeqs, size_t outSeqsCapacity,\n  const void* src, size_t srcSize,\n  const void* dict, size_t dictSize,\n  int compressionLevel,\n  size_t windowSize\n) {\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* ip = istart;\n    const BYTE* anchor = istart;\n    size_t seqCount = 0;\n    U32 hashTable[HSIZE];\n\n    (void)sequenceProducerState;\n    (void)dict;\n    (void)dictSize;\n    (void)outSeqsCapacity;\n    (void)compressionLevel;\n\n    {   int i;\n        for (i=0; i < HSIZE; i++) {\n            hashTable[i] = BADIDX;\n    }   }\n\n    while (ip + MLS < iend) {\n        size_t const hash = ZSTD_hashPtr(ip, HLOG, MLS);\n        U32 const matchIndex = hashTable[hash];\n        hashTable[hash] = (U32)(ip - istart);\n\n        if (matchIndex != BADIDX) {\n            const BYTE* const match = istart + matchIndex;\n            U32 const matchLen = (U32)ZSTD_count(ip, match, iend);\n            if (matchLen >= ZSTD_MINMATCH_MIN) {\n                U32 const litLen = (U32)(ip - anchor);\n                U32 const offset = (U32)(ip - match);\n                ZSTD_Sequence const seq = {\n                    offset, litLen, matchLen, 0\n                };\n\n                /* Note: it's crucial to stay within the window size! */\n                if (offset <= windowSize) {\n                    outSeqs[seqCount++] = seq;\n                    ip += matchLen;\n                    anchor = ip;\n                    continue;\n                }\n            }\n        }\n\n        ip++;\n    }\n\n    {   ZSTD_Sequence const finalSeq = {\n            0, (U32)(iend - anchor), 0, 0\n        };\n        outSeqs[seqCount++] = finalSeq;\n    }\n\n    return seqCount;\n}\n\nsize_t zstreamSequenceProducer(\n  void* sequenceProducerState,\n  ZSTD_Sequence* outSeqs, size_t outSeqsCapacity,\n  const void* src, size_t srcSize,\n  const void* dict, size_t dictSize,\n  int compressionLevel,\n  size_t windowSize\n) {\n    EMF_testCase const testCase = *((EMF_testCase*)sequenceProducerState);\n    memset(outSeqs, 0, outSeqsCapacity);\n\n    switch (testCase) {\n        case EMF_ZERO_SEQS:\n            return 0;\n        case EMF_ONE_BIG_SEQ:\n            outSeqs[0].offset = 0;\n            outSeqs[0].matchLength = 0;\n            outSeqs[0].litLength = (U32)(srcSize);\n            return 1;\n         case EMF_LOTS_OF_SEQS:\n            return simpleSequenceProducer(\n                sequenceProducerState,\n                outSeqs, outSeqsCapacity,\n                src, srcSize,\n                dict, dictSize,\n                compressionLevel,\n                windowSize\n            );\n        case EMF_INVALID_OFFSET:\n            outSeqs[0].offset = 1 << 20;\n            outSeqs[0].matchLength = 4;\n            outSeqs[0].litLength = (U32)(srcSize - 4);\n            return 1;\n        case EMF_INVALID_MATCHLEN:\n            outSeqs[0].offset = 1;\n            outSeqs[0].matchLength = (U32)(srcSize);\n            outSeqs[0].litLength = 1;\n            return 1;\n        case EMF_INVALID_LITLEN:\n            outSeqs[0].offset = 0;\n            outSeqs[0].matchLength = 0;\n            outSeqs[0].litLength = (U32)(srcSize + 1);\n            return 1;\n        case EMF_INVALID_LAST_LITS:\n            outSeqs[0].offset = 1;\n            outSeqs[0].matchLength = 1;\n            outSeqs[0].litLength = 1;\n            outSeqs[1].offset = 0;\n            outSeqs[1].matchLength = 0;\n            outSeqs[1].litLength = (U32)(srcSize - 1);\n            return 2;\n        case EMF_SMALL_ERROR:\n            return outSeqsCapacity + 1;\n        case EMF_BIG_ERROR:\n        default:\n            return ZSTD_SEQUENCE_PRODUCER_ERROR;\n    }\n}\n"
  },
  {
    "path": "tests/external_matchfinder.h",
    "content": "/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef EXTERNAL_MATCHFINDER\n#define EXTERNAL_MATCHFINDER\n\n#define ZSTD_STATIC_LINKING_ONLY\n#include \"zstd.h\"\n\n/* See external_matchfinder.c for details on each test case */\ntypedef enum {\n    EMF_ZERO_SEQS = 0,\n    EMF_ONE_BIG_SEQ = 1,\n    EMF_LOTS_OF_SEQS = 2,\n    EMF_BIG_ERROR = 3,\n    EMF_SMALL_ERROR = 4,\n    EMF_INVALID_OFFSET = 5,\n    EMF_INVALID_MATCHLEN = 6,\n    EMF_INVALID_LITLEN = 7,\n    EMF_INVALID_LAST_LITS = 8\n} EMF_testCase;\n\nsize_t zstreamSequenceProducer(\n  void* sequenceProducerState,\n  ZSTD_Sequence* outSeqs, size_t outSeqsCapacity,\n  const void* src, size_t srcSize,\n  const void* dict, size_t dictSize,\n  int compressionLevel,\n  size_t windowSize\n);\n\n#endif /* EXTERNAL_MATCHFINDER */\n"
  },
  {
    "path": "tests/fullbench.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/*_************************************\n*  Includes\n**************************************/\n#define _CRT_SECURE_NO_WARNINGS /* disable Visual warning that it doesn't like fopen() */\n#define ZSTD_DISABLE_DEPRECATE_WARNINGS /* No deprecation warnings, we still bench some deprecated functions */\n#include <limits.h>\n#include \"util.h\"        /* Compiler options, UTIL_GetFileSize */\n#include <stdlib.h>      /* malloc */\n#include <stdio.h>       /* fprintf, fopen, ftello64 */\n#include <assert.h>\n\n#include \"mem.h\"         /* U32 */\n#include \"compress/zstd_compress_internal.h\"\n#ifndef ZSTD_DLL_IMPORT\n    #include \"zstd_internal.h\"   /* ZSTD_decodeSeqHeaders, ZSTD_blockHeaderSize, ZSTD_getcBlockSize, blockType_e, KB, MB */\n    #include \"decompress/zstd_decompress_internal.h\"   /* ZSTD_DCtx struct */\n#else\n    #define KB *(1 <<10)\n    #define MB *(1 <<20)\n    #define GB *(1U<<30)\n    typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e;\n#endif\n#define ZSTD_STATIC_LINKING_ONLY  /* ZSTD_compressBegin, ZSTD_compressContinue, etc. */\n#include \"zstd.h\"        /* ZSTD_versionString */\n#include \"util.h\"        /* time functions */\n#include \"datagen.h\"\n#include \"lorem.h\"\n#include \"benchfn.h\"     /* CustomBench */\n#include \"benchzstd.h\"   /* MB_UNIT */\n\n/*_************************************\n*  Constants\n**************************************/\n#define PROGRAM_DESCRIPTION \"Zstandard speed analyzer\"\n#define AUTHOR \"Yann Collet\"\n#define WELCOME_MESSAGE \"*** %s %s %i-bits, by %s (%s) ***\\n\", PROGRAM_DESCRIPTION, ZSTD_versionString(), (int)(sizeof(void*)*8), AUTHOR, __DATE__\n\n#define NBLOOPS    6\n#define TIMELOOP_S 2\n\n#define MAX_MEM    (1984 MB)\n\n#define DEFAULT_CLEVEL 1\n\n#define COMPRESSIBILITY_DEFAULT (-1.0)\nstatic const size_t kSampleSizeDefault = 10000000;\n\n#define TIMELOOP_NANOSEC      (1*1000000000ULL) /* 1 second */\n\n\n/*_************************************\n*  Macros\n**************************************/\n#define DISPLAY(...)  fprintf(stderr, __VA_ARGS__)\n\n#define CONTROL(c)  { if (!(c)) { abort(); } }   /* like assert(), but cannot be disabled */\n\n\n/*_************************************\n*  Benchmark Parameters\n**************************************/\nstatic unsigned g_nbIterations = NBLOOPS;\n\n\n/*_*******************************************************\n*  Private functions\n*********************************************************/\nstatic size_t BMK_findMaxMem(U64 requiredMem)\n{\n    size_t const step = 64 MB;\n    void* testmem = NULL;\n\n    requiredMem = (((requiredMem >> 26) + 1) << 26);\n    if (requiredMem > MAX_MEM) requiredMem = MAX_MEM;\n\n    requiredMem += step;\n    do {\n        testmem = malloc ((size_t)requiredMem);\n        requiredMem -= step;\n    } while (!testmem);\n\n    free (testmem);\n    return (size_t) requiredMem;\n}\n\n\n/*_*******************************************************\n*  Benchmark wrappers\n*********************************************************/\n\nstatic ZSTD_CCtx* g_zcc = NULL;\nstatic size_t\nlocal_ZSTD_compress(const void* src, size_t srcSize,\n                    void* dst, size_t dstSize,\n                    void* payload)\n{\n    ZSTD_parameters p;\n    ZSTD_frameParameters f = { 1 /* contentSizeHeader*/, 0, 0 };\n    p.fParams = f;\n    p.cParams = *(ZSTD_compressionParameters*)payload;\n    return ZSTD_compress_advanced (g_zcc, dst, dstSize, src, srcSize, NULL ,0, p);\n}\n\nstatic size_t\nlocal_ZSTD_compress_freshCCtx(const void* src, size_t srcSize,\n                    void* dst, size_t dstSize,\n                    void* payload)\n{\n    ZSTD_parameters p;\n    ZSTD_frameParameters f = { 1 /* contentSizeHeader*/, 0, 0 };\n    p.fParams = f;\n    p.cParams = *(ZSTD_compressionParameters*)payload;\n    if (g_zcc != NULL) ZSTD_freeCCtx(g_zcc);\n    g_zcc = ZSTD_createCCtx();\n    assert(g_zcc != NULL);\n    {   size_t const r = ZSTD_compress_advanced (g_zcc, dst, dstSize, src, srcSize, NULL ,0, p);\n        ZSTD_freeCCtx(g_zcc);\n        g_zcc = NULL;\n        return r;\n    }\n}\n\ntypedef struct {\n    void* prepBuffer;\n    size_t prepSize;\n    void* dst;\n    size_t dstCapacity;\n    size_t fixedOrigSize;  /* optional, 0 means \"no modification\" */\n} PrepResult;\n#define PREPRESULT_INIT { NULL, 0, NULL, 0, 0 }\n\nstatic PrepResult prepDecompress(const void* src, size_t srcSize, int cLevel)\n{\n    size_t prepCapacity = ZSTD_compressBound(srcSize);\n    void* prepBuffer = malloc(prepCapacity);\n    size_t cSize = ZSTD_compress(prepBuffer, prepCapacity, src, srcSize, cLevel);\n    void* dst = malloc(srcSize);\n    PrepResult r = PREPRESULT_INIT;\n    assert(dst != NULL);\n    r.prepBuffer = prepBuffer;\n    r.prepSize = cSize;\n    r.dst = dst;\n    r.dstCapacity = srcSize;\n    return r;\n}\n\nstatic size_t local_ZSTD_decompress(const void* src, size_t srcSize,\n                                    void* dst, size_t dstSize,\n                                    void* unused)\n{\n    (void)unused;\n    return ZSTD_decompress(dst, dstSize, src, srcSize);\n}\n\nstatic ZSTD_DCtx* g_zdc = NULL; /* will be initialized within benchMem */\nstatic size_t local_ZSTD_decompressDCtx(const void* src, size_t srcSize,\n                                    void* dst, size_t dstSize,\n                                    void* unused)\n{\n    (void)unused;\n    return ZSTD_decompressDCtx(g_zdc, dst, dstSize, src, srcSize);\n}\n\n#ifndef ZSTD_DLL_IMPORT\n\nstatic PrepResult prepLiterals(const void* src, size_t srcSize, int cLevel)\n{\n    PrepResult r = PREPRESULT_INIT;\n    size_t dstCapacity = srcSize;\n    void* dst = malloc(dstCapacity);\n    void* prepBuffer;\n    size_t prepSize = ZSTD_compress(dst, dstCapacity, src, srcSize, cLevel);\n    size_t frameHeaderSize = ZSTD_frameHeaderSize(dst, ZSTD_FRAMEHEADERSIZE_PREFIX(ZSTD_f_zstd1));\n    CONTROL(!ZSTD_isError(frameHeaderSize));\n    /* check block is compressible, hence contains a literals section */\n    {   blockProperties_t bp;\n        ZSTD_getcBlockSize((char*)dst+frameHeaderSize, dstCapacity, &bp);  /* Get 1st block type */\n        if (bp.blockType != bt_compressed) {\n            DISPLAY(\"no compressed literals\\n\");\n            return r;\n    }   }\n    {   size_t const skippedSize = frameHeaderSize + ZSTD_blockHeaderSize;\n        prepSize -= skippedSize;\n        prepBuffer = malloc(prepSize);\n        CONTROL(prepBuffer != NULL);\n        memmove(prepBuffer, (char*)dst+skippedSize, prepSize);\n    }\n    ZSTD_decompressBegin(g_zdc);\n    r.prepBuffer = prepBuffer;\n    r.prepSize = prepSize;\n    r.dst = dst;\n    r.dstCapacity = dstCapacity;\n    r.fixedOrigSize = srcSize > 128 KB ? 128 KB : srcSize;    /* speed relative to block */\n    return r;\n}\n\nextern size_t ZSTD_decodeLiteralsBlock_wrapper(ZSTD_DCtx* dctx,\n                          const void* src, size_t srcSize,\n                          void* dst, size_t dstCapacity);\nstatic size_t\nlocal_ZSTD_decodeLiteralsBlock(const void* src, size_t srcSize, void* dst, size_t dstCapacity, void* unused)\n{\n    (void)unused;\n    return ZSTD_decodeLiteralsBlock_wrapper(g_zdc, src, srcSize, dst, dstCapacity);\n}\n\nFORCE_NOINLINE size_t ZSTD_decodeLiteralsHeader(ZSTD_DCtx* dctx, void const* src, size_t srcSize)\n{\n    RETURN_ERROR_IF(srcSize < MIN_CBLOCK_SIZE, corruption_detected, \"\");\n    {\n        BYTE const* istart = (BYTE const*)src;\n        SymbolEncodingType_e const litEncType = (SymbolEncodingType_e)(istart[0] & 3);\n        if (litEncType == set_compressed) {\n            RETURN_ERROR_IF(srcSize < 5, corruption_detected, \"srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3\");\n            {\n                size_t lhSize, litSize, litCSize;\n                U32 const lhlCode = (istart[0] >> 2) & 3;\n                U32 const lhc = MEM_readLE32(istart);\n                int const flags = ZSTD_DCtx_get_bmi2(dctx) ? HUF_flags_bmi2 : 0;\n                switch(lhlCode)\n                {\n                case 0: case 1: default:   /* note : default is impossible, since lhlCode into [0..3] */\n                    /* 2 - 2 - 10 - 10 */\n                    lhSize = 3;\n                    litSize  = (lhc >> 4) & 0x3FF;\n                    litCSize = (lhc >> 14) & 0x3FF;\n                    break;\n                case 2:\n                    /* 2 - 2 - 14 - 14 */\n                    lhSize = 4;\n                    litSize  = (lhc >> 4) & 0x3FFF;\n                    litCSize = lhc >> 18;\n                    break;\n                case 3:\n                    /* 2 - 2 - 18 - 18 */\n                    lhSize = 5;\n                    litSize  = (lhc >> 4) & 0x3FFFF;\n                    litCSize = (lhc >> 22) + ((size_t)istart[4] << 10);\n                    break;\n                }\n                RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected, \"\");\n                RETURN_ERROR_IF(litCSize + lhSize > srcSize, corruption_detected, \"\");\n#ifndef HUF_FORCE_DECOMPRESS_X2\n                return HUF_readDTableX1_wksp(\n                        dctx->entropy.hufTable,\n                        istart+lhSize, litCSize,\n                        dctx->workspace, sizeof(dctx->workspace),\n                        flags);\n#else\n                return HUF_readDTableX2_wksp(\n                        dctx->entropy.hufTable,\n                        istart+lhSize, litCSize,\n                        dctx->workspace, sizeof(dctx->workspace), flags);\n#endif\n            }\n        }\n    }\n    return 0;\n}\n\nstatic size_t\nlocal_ZSTD_decodeLiteralsHeader(const void* src, size_t srcSize, void* dst, size_t dstCapacity, void* unused)\n{\n    (void)dst; (void)dstCapacity; (void)unused;\n    return ZSTD_decodeLiteralsHeader(g_zdc, src, srcSize);\n}\n\nstatic PrepResult prepSequences1stBlock(const void* src, size_t srcSize, int cLevel)\n{\n    PrepResult r = PREPRESULT_INIT;\n    size_t const dstCapacity = srcSize;\n    void* dst = malloc(dstCapacity);\n    const BYTE* ip = dst;\n    const BYTE* iend;\n    {   size_t const cSize = ZSTD_compress(dst, dstCapacity, src, srcSize, cLevel);\n        CONTROL(cSize > ZSTD_FRAMEHEADERSIZE_PREFIX(ZSTD_f_zstd1));\n    }\n    /* Skip frame Header */\n    {   size_t const frameHeaderSize = ZSTD_frameHeaderSize(dst, ZSTD_FRAMEHEADERSIZE_PREFIX(ZSTD_f_zstd1));\n        CONTROL(!ZSTD_isError(frameHeaderSize));\n        ip += frameHeaderSize;\n    }\n    /* Find end of block */\n    {   blockProperties_t bp;\n        size_t const cBlockSize = ZSTD_getcBlockSize(ip, dstCapacity, &bp);   /* Get 1st block type */\n        if (bp.blockType != bt_compressed) {\n            DISPLAY(\"no compressed sequences\\n\");\n            return r;\n        }\n        iend = ip + ZSTD_blockHeaderSize + cBlockSize;   /* End of first block */\n    }\n    ip += ZSTD_blockHeaderSize;    /* skip block header */\n    ZSTD_decompressBegin(g_zdc);\n    CONTROL(iend > ip);\n    ip += ZSTD_decodeLiteralsBlock_wrapper(g_zdc, ip, (size_t)(iend-ip), dst, dstCapacity);   /* skip literal segment */\n    r.prepSize = (size_t)(iend-ip);\n    r.prepBuffer = malloc(r.prepSize);\n    CONTROL(r.prepBuffer != NULL);\n    memmove(r.prepBuffer, ip, r.prepSize);   /* copy rest of block (it starts by SeqHeader) */\n    r.dst = dst;\n    r.dstCapacity = dstCapacity;\n    r.fixedOrigSize = srcSize > 128 KB ? 128 KB : srcSize;   /* speed relative to block */\n    return r;\n}\n\nstatic size_t\nlocal_ZSTD_decodeSeqHeaders(const void* src, size_t srcSize, void* dst, size_t dstCapacity, void* unused)\n{\n    int nbSeq;\n    (void)unused; (void)dst; (void)dstCapacity;\n    return ZSTD_decodeSeqHeaders(g_zdc, &nbSeq, src, srcSize);\n}\n\n#endif\n\nstatic ZSTD_CStream* g_cstream= NULL;\nstatic size_t\nlocal_ZSTD_compressStream(const void* src, size_t srcSize,\n                          void* dst, size_t dstCapacity,\n                          void* payload)\n{\n    ZSTD_outBuffer buffOut;\n    ZSTD_inBuffer buffIn;\n    ZSTD_parameters p;\n    ZSTD_frameParameters f = {1 /* contentSizeHeader*/, 0, 0};\n    p.fParams = f;\n    p.cParams = *(ZSTD_compressionParameters*)payload;\n    ZSTD_initCStream_advanced(g_cstream, NULL, 0, p, ZSTD_CONTENTSIZE_UNKNOWN);\n    buffOut.dst = dst;\n    buffOut.size = dstCapacity;\n    buffOut.pos = 0;\n    buffIn.src = src;\n    buffIn.size = srcSize;\n    buffIn.pos = 0;\n    ZSTD_compressStream(g_cstream, &buffOut, &buffIn);\n    ZSTD_endStream(g_cstream, &buffOut);\n    return buffOut.pos;\n}\n\nstatic size_t\nlocal_ZSTD_compressStream_freshCCtx(const void* src, size_t srcSize,\n                          void* dst, size_t dstCapacity,\n                          void* payload)\n{\n    if (g_cstream != NULL) ZSTD_freeCCtx(g_cstream);\n    g_cstream = ZSTD_createCCtx();\n    assert(g_cstream != NULL);\n\n    {   size_t const r = local_ZSTD_compressStream(src, srcSize, dst, dstCapacity, payload);\n        ZSTD_freeCCtx(g_cstream);\n        g_cstream = NULL;\n        return r;\n    }\n}\n\nstatic size_t\nlocal_ZSTD_compress2(const void* src, size_t srcSize,\n                           void* dst, size_t dstCapacity,\n                           void* payload)\n{\n    (void)payload;\n    return ZSTD_compress2(g_cstream, dst, dstCapacity, src, srcSize);\n}\n\nstatic size_t\nlocal_ZSTD_compressStream2_end(const void* src, size_t srcSize,\n    void* dst, size_t dstCapacity,\n    void* payload)\n{\n    ZSTD_outBuffer buffOut;\n    ZSTD_inBuffer buffIn;\n    (void)payload;\n    buffOut.dst = dst;\n    buffOut.size = dstCapacity;\n    buffOut.pos = 0;\n    buffIn.src = src;\n    buffIn.size = srcSize;\n    buffIn.pos = 0;\n    ZSTD_compressStream2(g_cstream, &buffOut, &buffIn, ZSTD_e_end);\n    return buffOut.pos;\n}\n\nstatic size_t\nlocal_ZSTD_compressStream2_continue(const void* src, size_t srcSize,\n                                 void* dst, size_t dstCapacity,\n                                 void* payload)\n{\n    ZSTD_outBuffer buffOut;\n    ZSTD_inBuffer buffIn;\n    (void)payload;\n    buffOut.dst = dst;\n    buffOut.size = dstCapacity;\n    buffOut.pos = 0;\n    buffIn.src = src;\n    buffIn.size = srcSize;\n    buffIn.pos = 0;\n    ZSTD_compressStream2(g_cstream, &buffOut, &buffIn, ZSTD_e_continue);\n    ZSTD_compressStream2(g_cstream, &buffOut, &buffIn, ZSTD_e_end);\n    return buffOut.pos;\n}\n\nstatic size_t\nlocal_ZSTD_compress_generic_T2_end(const void* src, size_t srcSize,\n                                   void* dst, size_t dstCapacity,\n                                   void* payload)\n{\n    (void)payload;\n    ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_nbWorkers, 2);\n    return ZSTD_compress2(g_cstream, dst, dstCapacity, src, srcSize);\n}\n\nstatic size_t\nlocal_ZSTD_compress_generic_T2_continue(const void* src, size_t srcSize,\n                                        void* dst, size_t dstCapacity,\n                                        void* payload)\n{\n    ZSTD_outBuffer buffOut;\n    ZSTD_inBuffer buffIn;\n    (void)payload;\n    ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_nbWorkers, 2);\n    buffOut.dst = dst;\n    buffOut.size = dstCapacity;\n    buffOut.pos = 0;\n    buffIn.src = src;\n    buffIn.size = srcSize;\n    buffIn.pos = 0;\n    ZSTD_compressStream2(g_cstream, &buffOut, &buffIn, ZSTD_e_continue);\n    while(ZSTD_compressStream2(g_cstream, &buffOut, &buffIn, ZSTD_e_end)) {}\n    return buffOut.pos;\n}\n\nstatic ZSTD_DStream* g_dstream= NULL;\nstatic size_t\nlocal_ZSTD_decompressStream(const void* src, size_t srcSize,\n                            void* dst, size_t dstCapacity,\n                            void* unused)\n{\n    ZSTD_outBuffer buffOut;\n    ZSTD_inBuffer buffIn;\n    (void)unused;\n    ZSTD_initDStream(g_dstream);\n    buffOut.dst = dst;\n    buffOut.size = dstCapacity;\n    buffOut.pos = 0;\n    buffIn.src = src;\n    buffIn.size = srcSize;\n    buffIn.pos = 0;\n    ZSTD_decompressStream(g_dstream, &buffOut, &buffIn);\n    return buffOut.pos;\n}\n\nstatic size_t local_ZSTD_compressContinue(const void* src, size_t srcSize,\n                                          void* dst, size_t dstCapacity,\n                                          void* payload)\n{\n    ZSTD_parameters p;\n    ZSTD_frameParameters f = { 1 /* contentSizeHeader*/, 0, 0 };\n    p.fParams = f;\n    p.cParams = *(ZSTD_compressionParameters*)payload;\n    ZSTD_compressBegin_advanced(g_zcc, NULL, 0, p, srcSize);\n    return ZSTD_compressEnd(g_zcc, dst, dstCapacity, src, srcSize);\n}\n\n#define FIRST_BLOCK_SIZE 8\nstatic size_t\nlocal_ZSTD_compressContinue_extDict(const void* src, size_t srcSize,\n                                    void* dst, size_t dstCapacity,\n                                    void* payload)\n{\n    BYTE firstBlockBuf[FIRST_BLOCK_SIZE];\n\n    ZSTD_parameters p;\n    ZSTD_frameParameters const f = { 1, 0, 0 };\n    p.fParams = f;\n    p.cParams = *(ZSTD_compressionParameters*)payload;\n    ZSTD_compressBegin_advanced(g_zcc, NULL, 0, p, srcSize);\n    memcpy(firstBlockBuf, src, FIRST_BLOCK_SIZE);\n\n    {   size_t const compressResult = ZSTD_compressContinue(g_zcc,\n                                            dst, dstCapacity,\n                                            firstBlockBuf, FIRST_BLOCK_SIZE);\n        if (ZSTD_isError(compressResult)) {\n            DISPLAY(\"local_ZSTD_compressContinue_extDict error : %s\\n\",\n                    ZSTD_getErrorName(compressResult));\n            return compressResult;\n        }\n        dst = (BYTE*)dst + compressResult;\n        dstCapacity -= compressResult;\n    }\n    return ZSTD_compressEnd(g_zcc, dst, dstCapacity,\n                            (const BYTE*)src + FIRST_BLOCK_SIZE,\n                            srcSize - FIRST_BLOCK_SIZE);\n}\n\nstatic size_t local_ZSTD_decompressContinue(const void* src, size_t srcSize,\n                                            void* dst, size_t dstCapacity,\n                                            void* unused)\n{\n    size_t regeneratedSize = 0;\n    const BYTE* ip = (const BYTE*)src;\n    const BYTE* const iend = ip + srcSize;\n    BYTE* op = (BYTE*)dst;\n    size_t remainingCapacity = dstCapacity;\n\n    (void)unused;\n    ZSTD_decompressBegin(g_zdc);\n    while (ip < iend) {\n        size_t const iSize = ZSTD_nextSrcSizeToDecompress(g_zdc);\n        size_t const decodedSize = ZSTD_decompressContinue(g_zdc, op, remainingCapacity, ip, iSize);\n        ip += iSize;\n        regeneratedSize += decodedSize;\n        op += decodedSize;\n        remainingCapacity -= decodedSize;\n    }\n\n    return regeneratedSize;\n}\n\nstatic PrepResult prepSequences(const void* src, size_t srcSize, int cLevel)\n{\n    PrepResult r = PREPRESULT_INIT;\n    size_t const dstCapacity = ZSTD_compressBound(srcSize);\n    void* const dst = malloc(dstCapacity);\n    size_t const prepCapacity = dstCapacity * 4;\n    void* prepBuffer = malloc(prepCapacity);\n    void* sequencesStart = (char*)prepBuffer + 2*sizeof(unsigned);\n    ZSTD_Sequence* const seqs = sequencesStart;\n    size_t const seqsCapacity = prepCapacity / sizeof(ZSTD_Sequence);\n    size_t nbSeqs;\n    ZSTD_CCtx_reset(g_zcc, ZSTD_reset_session_and_parameters);\n    ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_compressionLevel, cLevel);\n    nbSeqs = ZSTD_generateSequences(g_zcc, seqs, seqsCapacity, src, srcSize);\n    CONTROL(srcSize < UINT_MAX);\n    MEM_write32(prepBuffer, (U32)srcSize);\n    MEM_write32((char*)prepBuffer+4, (U32)nbSeqs);\n    memcpy(seqs + nbSeqs, src, srcSize);\n    r.prepBuffer = prepBuffer;\n    r.prepSize = 8 + sizeof(ZSTD_Sequence)*nbSeqs + srcSize;\n    r.dst = dst;\n    r.dstCapacity = dstCapacity;\n    return r;\n}\n\nstatic size_t local_compressSequences(const void* input, size_t inputSize,\n                                      void* dst, size_t dstCapacity,\n                                      void* payload)\n{\n    const char* ip = input;\n    size_t srcSize = MEM_read32(ip);\n    size_t nbSeqs = MEM_read32(ip+=4);\n    const ZSTD_Sequence* seqs = (const ZSTD_Sequence*)(const void*)(ip+=4);\n    const void* src = (ip+=nbSeqs * sizeof(ZSTD_Sequence));\n    ZSTD_CCtx_reset(g_zcc, ZSTD_reset_session_and_parameters);\n    ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters);\n    assert(8 + nbSeqs * sizeof(ZSTD_Sequence) + srcSize == inputSize); (void)inputSize;\n    (void)payload;\n\n    return ZSTD_compressSequences(g_zcc, dst, dstCapacity, seqs, nbSeqs, src, srcSize);\n}\n\nstatic PrepResult prepSequencesAndLiterals(const void* src, size_t srcSize, int cLevel)\n{\n    PrepResult r = PREPRESULT_INIT;\n    size_t const dstCapacity = ZSTD_compressBound(srcSize);\n    void* const dst = malloc(dstCapacity);\n    size_t const prepCapacity = dstCapacity * 4;\n    void* prepBuffer = malloc(prepCapacity);\n    void* sequencesStart = (char*)prepBuffer + 3*sizeof(unsigned);\n    ZSTD_Sequence* const seqs = sequencesStart;\n    size_t const seqsCapacity = prepCapacity / sizeof(ZSTD_Sequence);\n    size_t nbSeqs;\n    ZSTD_CCtx_reset(g_zcc, ZSTD_reset_session_and_parameters);\n    ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_compressionLevel, cLevel);\n    nbSeqs = ZSTD_generateSequences(g_zcc, seqs, seqsCapacity, src, srcSize);\n    CONTROL(srcSize < UINT_MAX);\n    MEM_write32(prepBuffer, (U32)srcSize);\n    MEM_write32((char*)prepBuffer+4, (U32)nbSeqs);\n    /* copy literals */\n    {   char* const litStart = (char*)(seqs + nbSeqs);\n        size_t nbLiterals = 0;\n        const char* ip = src;\n        size_t n;\n        for (n=0; n<nbSeqs; n++) {\n            size_t const litSize = seqs[n].litLength;\n            memcpy(litStart + nbLiterals, ip, litSize);\n            ip += litSize + seqs[n].matchLength;\n            nbLiterals += litSize;\n        }\n        MEM_write32((char*)prepBuffer+8, (U32)nbLiterals);\n        r.prepBuffer = prepBuffer;\n        r.prepSize = 12 + sizeof(ZSTD_Sequence)*nbSeqs + nbLiterals;\n        r.dst = dst;\n        r.dstCapacity = dstCapacity;\n    }\n    return r;\n}\n\nstatic size_t\nlocal_compressSequencesAndLiterals(const void* input, size_t inputSize,\n                                    void* dst, size_t dstCapacity,\n                                    void* payload)\n{\n    const char* ip = input;\n    size_t decompressedSize = MEM_read32(ip);\n    size_t nbSeqs = MEM_read32(ip+=4);\n    size_t nbLiterals = MEM_read32(ip+=4);\n    const ZSTD_Sequence* seqs = (const ZSTD_Sequence*)(const void*)(ip+=4);\n    const void* literals = (ip+=nbSeqs * sizeof(ZSTD_Sequence));\n    ZSTD_CCtx_reset(g_zcc, ZSTD_reset_session_and_parameters);\n    ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters);\n# if 0 /* for tests */\n    ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_repcodeResolution, ZSTD_ps_enable);\n#endif\n    assert(12 + nbSeqs * sizeof(ZSTD_Sequence) + nbLiterals == inputSize); (void)inputSize;\n    (void)payload;\n\n    return ZSTD_compressSequencesAndLiterals(g_zcc, dst, dstCapacity, seqs, nbSeqs, literals, nbLiterals, nbLiterals + 8, decompressedSize);\n}\n\nstatic PrepResult prepConvertSequences(const void* src, size_t srcSize, int cLevel)\n{\n    PrepResult r = PREPRESULT_INIT;\n    size_t const prepCapacity = srcSize * 4;\n    void* prepBuffer = malloc(prepCapacity);\n    void* sequencesStart = (char*)prepBuffer + 2*sizeof(unsigned);\n    ZSTD_Sequence* const seqs = sequencesStart;\n    size_t const seqsCapacity = prepCapacity / sizeof(ZSTD_Sequence);\n    size_t totalNbSeqs, nbSeqs, blockSize=0;\n    ZSTD_CCtx_reset(g_zcc, ZSTD_reset_session_and_parameters);\n    ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_compressionLevel, cLevel);\n    totalNbSeqs = ZSTD_generateSequences(g_zcc, seqs, seqsCapacity, src, srcSize);\n    CONTROL(!ZSTD_isError(totalNbSeqs));\n    /* find nb sequences in first block */\n    {   size_t n;\n        for (n=0; n<totalNbSeqs; n++) {\n            if (seqs[n].matchLength == 0) break;\n            blockSize += seqs[n].litLength + seqs[n].matchLength;\n        }\n        blockSize += seqs[n].litLength;\n        nbSeqs = n+1;\n#if 0\n        printf(\"found %zu sequences representing a first block of size %zu\\n\", nbSeqs, blockSize);\n#endif\n    }\n    /* generate benchmarked input */\n    CONTROL(blockSize < UINT_MAX);\n    MEM_write32(prepBuffer, (U32)blockSize);\n    MEM_write32((char*)prepBuffer+4, (U32)nbSeqs);\n    memcpy(seqs + nbSeqs, src, srcSize);\n    r.prepBuffer = prepBuffer;\n    r.prepSize = 8 + sizeof(ZSTD_Sequence) * nbSeqs;\n    r.fixedOrigSize = blockSize;\n    return r;\n}\n\nstatic size_t\nlocal_convertSequences(const void* input, size_t inputSize,\n                       void* dst, size_t dstCapacity,\n                       void* payload)\n{\n    const char* ip = input;\n    size_t const blockSize = MEM_read32(ip);\n    size_t const nbSeqs = MEM_read32(ip+=4);\n    const ZSTD_Sequence* seqs = (const ZSTD_Sequence*)(const void*)(ip+=4);\n    ZSTD_CCtx_reset(g_zcc, ZSTD_reset_session_and_parameters);\n    ZSTD_resetSeqStore(&g_zcc->seqStore);\n    ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters);\n# if 0 /* for tests */\n    ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_repcodeResolution, ZSTD_ps_enable);\n#endif\n    assert(8 + nbSeqs * sizeof(ZSTD_Sequence) == inputSize); (void)inputSize;\n    (void)dst; (void)dstCapacity;\n    (void)payload; (void)blockSize;\n\n    (void)ZSTD_convertBlockSequences(g_zcc, seqs, nbSeqs, 0);\n    return nbSeqs;\n}\n\nstatic size_t\ncheck_compressedSequences(const void* compressed, size_t cSize, const void* orig, size_t origSize)\n{\n    size_t decSize;\n    int diff;\n    void* decompressed = malloc(origSize);\n    if (decompressed == NULL) return 2;\n\n    decSize = ZSTD_decompress(decompressed, origSize, compressed, cSize);\n    if (decSize != origSize) { free(decompressed); DISPLAY(\"ZSTD_decompress failed (%u) \", (unsigned)decSize); return 1; }\n\n    diff = memcmp(decompressed, orig, origSize);\n    if (diff) { free(decompressed); return 1; }\n\n    free(decompressed);\n    return 0;\n}\n\nstatic size_t\nlocal_get1BlockSummary(const void* input, size_t inputSize,\n                       void* dst, size_t dstCapacity,\n                       void* payload)\n{\n    const char* ip = input;\n    size_t const blockSize = MEM_read32(ip);\n    size_t const nbSeqs = MEM_read32(ip+=4);\n    const ZSTD_Sequence* seqs = (const ZSTD_Sequence*)(const void*)(ip+=4);\n    ZSTD_CCtx_reset(g_zcc, ZSTD_reset_session_and_parameters);\n    ZSTD_resetSeqStore(&g_zcc->seqStore);\n    ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters);\n    assert(8 + nbSeqs * sizeof(ZSTD_Sequence) == inputSize); (void)inputSize;\n    (void)dst; (void)dstCapacity;\n    (void)payload; (void)blockSize;\n\n    (void)ZSTD_get1BlockSummary(seqs, nbSeqs);\n    return nbSeqs;\n}\n\nstatic PrepResult prepCopy(const void* src, size_t srcSize, int cLevel)\n{\n    PrepResult r = PREPRESULT_INIT;\n    (void)cLevel;\n    r.prepSize = srcSize;\n    r.prepBuffer = malloc(srcSize);\n    CONTROL(r.prepBuffer != NULL);\n    memcpy(r.prepBuffer, src, srcSize);\n    r.dstCapacity = ZSTD_compressBound(srcSize);\n    r.dst = malloc(r.dstCapacity);\n    CONTROL(r.dst != NULL);\n    return r;\n}\n\nstatic PrepResult prepShorterDstCapacity(const void* src, size_t srcSize, int cLevel)\n{\n    PrepResult r = prepCopy(src, srcSize, cLevel);\n    assert(r.dstCapacity > 1);\n    r.dstCapacity -= 1;\n    return r;\n}\n\n/*_*******************************************************\n*  List of Scenarios\n*********************************************************/\n\n/* if PrepFunction_f returns PrepResult.prepBuffSize == 0, benchmarking is cancelled */\ntypedef PrepResult (*PrepFunction_f)(const void* src, size_t srcSize, int cLevel);\ntypedef size_t (*BenchedFunction_f)(const void* src, size_t srcSize, void* dst, size_t dstSize, void* opaque);\n/* must return 0, otherwise verification is considered failed */\ntypedef size_t (*VerifFunction_f)(const void* processed, size_t procSize, const void* input, size_t inputSize);\n\ntypedef struct {\n    const char* name;\n    PrepFunction_f preparation_f;\n    BenchedFunction_f benched_f;\n    VerifFunction_f verif_f; /* optional */\n} BenchScenario;\n\nstatic BenchScenario kScenarios[] = {\n    { \"compress\", NULL, local_ZSTD_compress, check_compressedSequences },\n    { \"decompress\", prepDecompress, local_ZSTD_decompress, NULL },\n    { \"compress_freshCCtx\", NULL, local_ZSTD_compress_freshCCtx, check_compressedSequences },\n    { \"decompressDCtx\", prepDecompress, local_ZSTD_decompressDCtx, NULL },\n    { \"compressContinue\", NULL, local_ZSTD_compressContinue, check_compressedSequences },\n    { \"compressContinue_extDict\", NULL, local_ZSTD_compressContinue_extDict, NULL },\n    { \"decompressContinue\", prepDecompress, local_ZSTD_decompressContinue, NULL },\n    { \"compressStream\", NULL, local_ZSTD_compressStream, check_compressedSequences },\n    { \"compressStream_freshCCtx\", NULL, local_ZSTD_compressStream_freshCCtx, check_compressedSequences },\n    { \"decompressStream\", prepDecompress, local_ZSTD_decompressStream, NULL },\n    { \"compress2\", NULL, local_ZSTD_compress2, check_compressedSequences },\n    { \"compressStream2, end\", NULL, local_ZSTD_compressStream2_end, check_compressedSequences },\n    { \"compressStream2, end & short\", prepShorterDstCapacity, local_ZSTD_compressStream2_end, check_compressedSequences },\n    { \"compressStream2, continue\", NULL, local_ZSTD_compressStream2_continue, check_compressedSequences },\n    { \"compressStream2, -T2, continue\", NULL, local_ZSTD_compress_generic_T2_continue, check_compressedSequences },\n    { \"compressStream2, -T2, end\", NULL, local_ZSTD_compress_generic_T2_end, check_compressedSequences },\n    { \"compressSequences\", prepSequences, local_compressSequences, check_compressedSequences },\n    { \"compressSequencesAndLiterals\", prepSequencesAndLiterals, local_compressSequencesAndLiterals, check_compressedSequences },\n    { \"convertSequences (1st block)\", prepConvertSequences, local_convertSequences, NULL },\n    { \"get1BlockSummary (1st block)\", prepConvertSequences, local_get1BlockSummary, NULL },\n#ifndef ZSTD_DLL_IMPORT\n    { \"decodeLiteralsHeader (1st block)\", prepLiterals, local_ZSTD_decodeLiteralsHeader, NULL },\n    { \"decodeLiteralsBlock (1st block)\", prepLiterals, local_ZSTD_decodeLiteralsBlock, NULL },\n    { \"decodeSeqHeaders (1st block)\", prepSequences1stBlock, local_ZSTD_decodeSeqHeaders, NULL },\n#endif\n};\n#define NB_SCENARIOS (sizeof(kScenarios) / sizeof(kScenarios[0]))\n\n/*_*******************************************************\n*  Bench loop\n*********************************************************/\nstatic int benchMem(unsigned scenarioID,\n                    const void* origSrc, size_t origSrcSize,\n                    int cLevel, ZSTD_compressionParameters cparams)\n{\n    size_t dstCapacity = 0;\n    void*  dst = NULL;\n    void*  prepBuff = NULL;\n    size_t prepBuffSize = 0;\n    void*  payload;\n    const char* benchName;\n    BMK_benchFn_t benchFunction;\n    PrepFunction_f prep_f;\n    VerifFunction_f verif_f;\n    int errorcode = 0;\n\n    if (scenarioID >= NB_SCENARIOS) return 0; /* scenario doesn't exist */\n\n    benchName = kScenarios[scenarioID].name;\n    benchFunction = kScenarios[scenarioID].benched_f;\n    prep_f = kScenarios[scenarioID].preparation_f;\n    verif_f = kScenarios[scenarioID].verif_f;\n    if (prep_f == NULL) prep_f = prepCopy; /* default */\n\n    /* Initialization */\n    if (g_zcc==NULL) g_zcc = ZSTD_createCCtx();\n    if (g_zdc==NULL) g_zdc = ZSTD_createDCtx();\n    if (g_cstream==NULL) g_cstream = ZSTD_createCStream();\n    if (g_dstream==NULL) g_dstream = ZSTD_createDStream();\n\n    /* DISPLAY(\"params: cLevel %d, wlog %d hlog %d clog %d slog %d mml %d tlen %d strat %d \\n\",\n          cLevel, cparams->windowLog, cparams->hashLog, cparams->chainLog, cparams->searchLog,\n          cparams->minMatch, cparams->targetLength, cparams->strategy); */\n\n    ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_compressionLevel, cLevel);\n    ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_windowLog, (int)cparams.windowLog);\n    ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_hashLog, (int)cparams.hashLog);\n    ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_chainLog, (int)cparams.chainLog);\n    ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_searchLog, (int)cparams.searchLog);\n    ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_minMatch, (int)cparams.minMatch);\n    ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_targetLength, (int)cparams.targetLength);\n    ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_strategy, (int)cparams.strategy);\n\n    ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_compressionLevel, cLevel);\n    ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_windowLog, (int)cparams.windowLog);\n    ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_hashLog, (int)cparams.hashLog);\n    ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_chainLog, (int)cparams.chainLog);\n    ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_searchLog, (int)cparams.searchLog);\n    ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_minMatch, (int)cparams.minMatch);\n    ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_targetLength, (int)cparams.targetLength);\n    ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_strategy, (int)cparams.strategy);\n\n    /* Preparation */\n    payload = &cparams;\n    {   PrepResult pr = prep_f(origSrc, origSrcSize, cLevel);\n        dst = pr.dst;\n        dstCapacity = pr.dstCapacity;\n        prepBuff = pr.prepBuffer;\n        prepBuffSize = pr.prepSize;\n        if (pr.fixedOrigSize) origSrcSize = pr.fixedOrigSize;\n    }\n    if (prepBuffSize==0) goto _cleanOut; /* failed preparation */\n\n     /* warming up dstBuff */\n    { size_t i; for (i=0; i<dstCapacity; i++) ((BYTE*)dst)[i]=(BYTE)i; }\n\n    /* benchmark loop */\n    {   BMK_timedFnState_t* const tfs = BMK_createTimedFnState(g_nbIterations * 1000, 1000);\n        void* const avoidStrictAliasingPtr = &dst;\n        const void* prepSrc = prepBuff;\n        BMK_benchParams_t bp;\n        BMK_runTime_t bestResult;\n        bestResult.sumOfReturn = 0;\n        bestResult.nanoSecPerRun = (double)TIMELOOP_NANOSEC * 2000000000;  /* hopefully large enough : must be larger than any potential measurement */\n        CONTROL(tfs != NULL);\n\n        bp.benchFn = benchFunction;\n        bp.benchPayload = payload;\n        bp.initFn = NULL;\n        bp.initPayload = NULL;\n        bp.errorFn = ZSTD_isError;\n        bp.blockCount = 1;\n        bp.srcBuffers = &prepSrc;\n        bp.srcSizes = &prepBuffSize;\n        bp.dstBuffers = (void* const*) avoidStrictAliasingPtr;  /* circumvent strict aliasing warning on gcc-8,\n                                                                 * because gcc considers that `void* const *`  and `void**` are 2 different types */\n        bp.dstCapacities = &dstCapacity;\n        bp.blockResults = NULL;\n\n        for (;;) {\n            BMK_runOutcome_t const bOutcome = BMK_benchTimedFn(tfs, bp);\n\n            if (!BMK_isSuccessful_runOutcome(bOutcome)) {\n                DISPLAY(\"ERROR: Scenario %u: %s \\n\", scenarioID, ZSTD_getErrorName(BMK_extract_errorResult(bOutcome)));\n                errorcode = 1;\n                BMK_freeTimedFnState(tfs);\n                goto _cleanOut;\n            }\n\n            {   BMK_runTime_t const newResult = BMK_extract_runTime(bOutcome);\n                if (newResult.nanoSecPerRun < bestResult.nanoSecPerRun )\n                    bestResult.nanoSecPerRun = newResult.nanoSecPerRun;\n                DISPLAY(\"\\r%2u#%-31.31s:%8.1f MB/s  (%8u) \",\n                        scenarioID, benchName,\n                        (double)origSrcSize * TIMELOOP_NANOSEC / bestResult.nanoSecPerRun / MB_UNIT,\n                        (unsigned)newResult.sumOfReturn );\n\n                if (verif_f) {\n                    size_t const vRes = verif_f(dst, newResult.sumOfReturn, origSrc, origSrcSize);\n                    if (vRes) {\n                        DISPLAY(\" validation failed ! (%u)\\n\", (unsigned)vRes);\n                        break;\n                    }\n                }\n            }\n\n            if ( BMK_isCompleted_TimedFn(tfs) ) break;\n        }\n        BMK_freeTimedFnState(tfs);\n    }\n    DISPLAY(\"\\n\");\n\n_cleanOut:\n    free(prepBuff);\n    free(dst);\n    ZSTD_freeCCtx(g_zcc); g_zcc=NULL;\n    ZSTD_freeDCtx(g_zdc); g_zdc=NULL;\n    ZSTD_freeCStream(g_cstream); g_cstream=NULL;\n    ZSTD_freeDStream(g_dstream); g_dstream=NULL;\n    return errorcode;\n}\n\n\n#define BENCH_ALL_SCENARIOS 999\n/*\n * if @compressibility < 0.0, use Lorem Ipsum generator\n * otherwise, @compressibility is expected to be between 0.0 and 1.0\n * if scenarioID == BENCH_ALL_SCENARIOS, all scenarios will be run on the sample\n*/\nstatic int benchSample(U32 scenarioID,\n                       size_t benchedSize, double compressibility,\n                       int cLevel, ZSTD_compressionParameters cparams)\n{\n    /* Allocation */\n    void* const origBuff = malloc(benchedSize);\n    if (!origBuff) { DISPLAY(\"\\nError: not enough memory!\\n\"); return 12; }\n\n    /* Fill buffer */\n    if (compressibility < 0.0) {\n        LOREM_genBuffer(origBuff, benchedSize, 0);\n    } else {\n        RDG_genBuffer(origBuff, benchedSize, compressibility, 0.0, 0);\n\n    }\n\n    /* bench */\n    DISPLAY(\"\\r%70s\\r\", \"\");\n    DISPLAY(\" Sample %u bytes : \\n\", (unsigned)benchedSize);\n    if (scenarioID == BENCH_ALL_SCENARIOS) {\n        for (scenarioID=0; scenarioID<100; scenarioID++) {\n            benchMem(scenarioID, origBuff, benchedSize, cLevel, cparams);\n        }\n    } else {\n        benchMem(scenarioID, origBuff, benchedSize, cLevel, cparams);\n    }\n\n    free(origBuff);\n    return 0;\n}\n\n\nstatic int benchFiles(U32 scenarioID,\n                      const char** fileNamesTable, const int nbFiles,\n                      int cLevel, ZSTD_compressionParameters cparams)\n{\n    /* Loop for each file */\n    int fileIdx;\n    for (fileIdx=0; fileIdx<nbFiles; fileIdx++) {\n        const char* const inFileName = fileNamesTable[fileIdx];\n        FILE* const inFile = fopen( inFileName, \"rb\" );\n        size_t benchedSize;\n\n        /* Check file existence */\n        if (inFile==NULL) { DISPLAY( \"Pb opening %s\\n\", inFileName); return 11; }\n\n        /* Memory allocation & restrictions */\n        {   U64 const inFileSize = UTIL_getFileSize(inFileName);\n            if (inFileSize == UTIL_FILESIZE_UNKNOWN) {\n                DISPLAY( \"Cannot measure size of %s\\n\", inFileName);\n                fclose(inFile);\n                return 11;\n            }\n            benchedSize = BMK_findMaxMem(inFileSize*3) / 3;\n            if ((U64)benchedSize > inFileSize)\n                benchedSize = (size_t)inFileSize;\n            if ((U64)benchedSize < inFileSize) {\n                DISPLAY(\"Not enough memory for '%s' full size; testing %u MB only... \\n\",\n                        inFileName, (unsigned)(benchedSize>>20));\n        }   }\n\n        /* Alloc */\n        {   void* const origBuff = malloc(benchedSize);\n            if (!origBuff) { DISPLAY(\"\\nError: not enough memory!\\n\"); fclose(inFile); return 12; }\n\n            /* Fill input buffer */\n            DISPLAY(\"Loading %s...       \\r\", inFileName);\n            {   size_t const readSize = fread(origBuff, 1, benchedSize, inFile);\n                fclose(inFile);\n                if (readSize != benchedSize) {\n                    DISPLAY(\"\\nError: problem reading file '%s' !!    \\n\", inFileName);\n                    free(origBuff);\n                    return 13;\n            }   }\n\n            /* bench */\n            DISPLAY(\"\\r%70s\\r\", \"\");   /* blank line */\n            DISPLAY(\" %s : \\n\", inFileName);\n            if (scenarioID == BENCH_ALL_SCENARIOS) {\n                for (scenarioID=0; scenarioID<100; scenarioID++) {\n                    benchMem(scenarioID, origBuff, benchedSize, cLevel, cparams);\n                }\n            } else {\n                benchMem(scenarioID, origBuff, benchedSize, cLevel, cparams);\n            }\n\n            free(origBuff);\n    }   }\n\n    return 0;\n}\n\n\n\n/*_*******************************************************\n*  Argument Parsing\n*********************************************************/\n\n#define ERROR_OUT(msg) { DISPLAY(\"%s \\n\", msg); exit(1); }\n\nstatic unsigned readU32FromChar(const char** stringPtr)\n{\n    const char errorMsg[] = \"error: numeric value too large\";\n    unsigned result = 0;\n    while ((**stringPtr >='0') && (**stringPtr <='9')) {\n        unsigned const max = (((unsigned)(-1)) / 10) - 1;\n        if (result > max) ERROR_OUT(errorMsg);\n        result *= 10;\n        result += (unsigned)(**stringPtr - '0');\n        (*stringPtr)++ ;\n    }\n    if ((**stringPtr=='K') || (**stringPtr=='M')) {\n        unsigned const maxK = ((unsigned)(-1)) >> 10;\n        if (result > maxK) ERROR_OUT(errorMsg);\n        result <<= 10;\n        if (**stringPtr=='M') {\n            if (result > maxK) ERROR_OUT(errorMsg);\n            result <<= 10;\n        }\n        (*stringPtr)++;  /* skip `K` or `M` */\n        if (**stringPtr=='i') (*stringPtr)++;\n        if (**stringPtr=='B') (*stringPtr)++;\n    }\n    return result;\n}\n\nstatic int longCommandWArg(const char** stringPtr, const char* longCommand)\n{\n    size_t const comSize = strlen(longCommand);\n    int const result = !strncmp(*stringPtr, longCommand, comSize);\n    if (result) *stringPtr += comSize;\n    return result;\n}\n\n\n/*_*******************************************************\n*  Command line\n*********************************************************/\n\nstatic int usage(const char* exename)\n{\n    DISPLAY( \"Usage :\\n\");\n    DISPLAY( \"      %s [arg] file1 file2 ... fileX\\n\", exename);\n    DISPLAY( \"Arguments :\\n\");\n    DISPLAY( \" -H/-h  : Help (this text + advanced options)\\n\");\n    return 0;\n}\n\nstatic int usage_advanced(const char* exename)\n{\n    usage(exename);\n    DISPLAY( \"\\nAdvanced options :\\n\");\n    DISPLAY( \" -b#    : test only function # \\n\");\n    DISPLAY( \" -l#    : benchmark functions at that compression level (default : %i)\\n\", DEFAULT_CLEVEL);\n    DISPLAY( \"--zstd= : custom parameter selection. Format same as zstdcli \\n\");\n    DISPLAY( \" -P#    : sample compressibility (default : %.1f%%)\\n\", COMPRESSIBILITY_DEFAULT * 100);\n    DISPLAY( \" -B#    : sample size (default : %u)\\n\", (unsigned)kSampleSizeDefault);\n    DISPLAY( \" -i#    : iteration loops [1-9](default : %i)\\n\", NBLOOPS);\n    return 0;\n}\n\nstatic int badusage(const char* exename)\n{\n    DISPLAY(\"Wrong parameters\\n\");\n    usage(exename);\n    return 1;\n}\n\nint main(int argc, const char** argv)\n{\n    int argNb, filenamesStart=0, result;\n    const char* const exename = argv[0];\n    const char* input_filename = NULL;\n    U32 scenarioID = BENCH_ALL_SCENARIOS, main_pause = 0;\n    int cLevel = DEFAULT_CLEVEL;\n    ZSTD_compressionParameters cparams = ZSTD_getCParams(cLevel, 0, 0);\n    size_t sampleSize = kSampleSizeDefault;\n    double compressibility = COMPRESSIBILITY_DEFAULT;\n\n    DISPLAY(WELCOME_MESSAGE);\n    if (argc<1) return badusage(exename);\n\n    for (argNb=1; argNb<argc; argNb++) {\n        const char* argument = argv[argNb];\n        CONTROL(argument != NULL);\n\n        if (longCommandWArg(&argument, \"--zstd=\")) {\n            for ( ; ;) {\n                if (longCommandWArg(&argument, \"windowLog=\") || longCommandWArg(&argument, \"wlog=\")) { cparams.windowLog = readU32FromChar(&argument); if (argument[0]==',') { argument++; continue; } else break; }\n                if (longCommandWArg(&argument, \"chainLog=\") || longCommandWArg(&argument, \"clog=\")) { cparams.chainLog = readU32FromChar(&argument); if (argument[0]==',') { argument++; continue; } else break; }\n                if (longCommandWArg(&argument, \"hashLog=\") || longCommandWArg(&argument, \"hlog=\")) { cparams.hashLog = readU32FromChar(&argument); if (argument[0]==',') { argument++; continue; } else break; }\n                if (longCommandWArg(&argument, \"searchLog=\") || longCommandWArg(&argument, \"slog=\")) { cparams.searchLog = readU32FromChar(&argument); if (argument[0]==',') { argument++; continue; } else break; }\n                if (longCommandWArg(&argument, \"minMatch=\") || longCommandWArg(&argument, \"mml=\")) { cparams.minMatch = readU32FromChar(&argument); if (argument[0]==',') { argument++; continue; } else break; }\n                if (longCommandWArg(&argument, \"targetLength=\") || longCommandWArg(&argument, \"tlen=\")) { cparams.targetLength = readU32FromChar(&argument); if (argument[0]==',') { argument++; continue; } else break; }\n                if (longCommandWArg(&argument, \"strategy=\") || longCommandWArg(&argument, \"strat=\")) { cparams.strategy = (ZSTD_strategy)(readU32FromChar(&argument)); if (argument[0]==',') { argument++; continue; } else break; }\n                if (longCommandWArg(&argument, \"level=\") || longCommandWArg(&argument, \"lvl=\")) { cLevel = (int)readU32FromChar(&argument); cparams = ZSTD_getCParams(cLevel, 0, 0); if (argument[0]==',') { argument++; continue; } else break; }\n                DISPLAY(\"invalid compression parameter \\n\");\n                return 1;\n            }\n\n            /* check end of string */\n            if (argument[0] != 0) {\n                DISPLAY(\"invalid --zstd= format \\n\");\n                return 1;\n            } else {\n                continue;\n            }\n\n        } else if (argument[0]=='-') { /* Commands (note : aggregated commands are allowed) */\n            argument++;\n            while (argument[0]!=0) {\n\n                switch(argument[0])\n                {\n                    /* Display help on usage */\n                case 'h':\n                case 'H': return usage_advanced(exename);\n\n                    /* Pause at the end (hidden option) */\n                case 'p': main_pause = 1; break;\n\n                    /* Select specific algorithm to bench */\n                case 'b':\n                    argument++;\n                    scenarioID = readU32FromChar(&argument);\n                    break;\n\n                    /* Select compression level to use */\n                case 'l':\n                    argument++;\n                    cLevel = (int)readU32FromChar(&argument);\n                    cparams = ZSTD_getCParams(cLevel, 0, 0);\n                    break;\n\n                    /* Select compressibility of synthetic sample */\n                case 'P':\n                    argument++;\n                    compressibility = (double)readU32FromChar(&argument) / 100.;\n                    break;\n\n                    /* Select size of synthetic sample */\n                case 'B':\n                    argument++;\n                    sampleSize = (size_t)readU32FromChar(&argument);\n                    break;\n\n                    /* Modify Nb Iterations */\n                case 'i':\n                    argument++;\n                    g_nbIterations = readU32FromChar(&argument);\n                    break;\n\n                    /* Unknown command */\n                default : return badusage(exename);\n                }\n            }\n            continue;\n        }\n\n        /* first provided filename is input */\n        if (!input_filename) { input_filename=argument; filenamesStart=argNb; continue; }\n    }\n\n\n\n    if (filenamesStart==0)   /* no input file */\n        result = benchSample(scenarioID, sampleSize, compressibility, cLevel, cparams);\n    else\n        result = benchFiles(scenarioID, argv+filenamesStart, argc-filenamesStart, cLevel, cparams);\n\n    if (main_pause) { int unused; printf(\"press enter...\\n\"); unused = getchar(); (void)unused; }\n\n    return result;\n}\n"
  },
  {
    "path": "tests/fuzz/.gitignore",
    "content": "# test artefacts\ncorpora\nblock_decompress\nblock_round_trip\ndictionary_decompress\ndictionary_loader\ndictionary_round_trip\ndictionary_stream_round_trip\nraw_dictionary_round_trip\nsimple_compress\nsimple_decompress\nsimple_round_trip\nstream_decompress\nstream_round_trip\nzstd_frame_info\ndecompress_dstSize_tooSmall\nfse_read_ncount\nsequence_compression_api\nseekable_roundtrip\nhuf_decompress\nhuf_round_trip\nfuzz-*.log\nrt_lib_*\nd_lib_*\ncrash-*\ndecompress_cross_format\ngenerate_sequences\n\n# misc\ntrace\ntmp*\n"
  },
  {
    "path": "tests/fuzz/Makefile",
    "content": "# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ################################################################\n\n# Optionally user defined flags\nCFLAGS ?= -O3\nCXXFLAGS ?= -O3\nCPPFLAGS ?=\nASFLAGS ?=\nLDFLAGS ?=\nARFLAGS ?=\nLIB_FUZZING_ENGINE ?= libregression.a\nPYTHON ?= python\nifeq ($(shell sh -c 'MSYSTEM=\"MSYS\" uname') , Darwin)\n\tDOWNLOAD?=curl -L -o\nelse\n\tDOWNLOAD?=wget -O\nendif\nCORPORA_URL_PREFIX:=https://github.com/facebook/zstd/releases/download/fuzz-corpora/\n\nLIBZSTD_MK_DIR = ../../lib\nDEBUGLEVEL ?= 2\nZSTD_LEGACY_SUPPORT ?= 1\n\n.PHONY: default\ndefault: all\n\ninclude $(LIBZSTD_MK_DIR)/libzstd.mk\n\nPRGDIR = ../../programs\nCONTRIBDIR = ../../contrib\n\nDEFAULT_SEQ_PROD_DIR = $(CONTRIBDIR)/externalSequenceProducer\nDEFAULT_SEQ_PROD_SRC = $(DEFAULT_SEQ_PROD_DIR)/sequence_producer.c\nTHIRD_PARTY_SEQ_PROD_OBJ ?=\n\nFUZZ_CPPFLAGS := -I$(LIB_SRCDIR) -I$(LIB_SRCDIR)/common -I$(LIB_SRCDIR)/compress \\\n\t-I$(LIB_SRCDIR)/dictBuilder -I$(LIB_SRCDIR)/deprecated -I$(LIB_SRCDIR)/legacy \\\n\t-I$(CONTRIBDIR)/seekable_format -I$(PRGDIR) -I$(DEFAULT_SEQ_PROD_DIR) \\\n\t-DZSTD_MULTITHREAD -DZSTD_LEGACY_SUPPORT=1 $(CPPFLAGS)\nFUZZ_EXTRA_FLAGS := -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \\\n\t-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \\\n\t-Wstrict-prototypes -Wundef \\\n\t-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \\\n\t-Wredundant-decls -Wno-deprecated-declarations \\\n\t-g -fno-omit-frame-pointer\nFUZZ_CFLAGS := $(FUZZ_EXTRA_FLAGS) $(CFLAGS)\nFUZZ_ASFLAGS := $(FUZZ_EXTRA_FLAGS) $(ASFLAGS)\nFUZZ_CXXFLAGS := $(FUZZ_EXTRA_FLAGS) -std=c++11 $(CXXFLAGS)\nFUZZ_LDFLAGS := -pthread $(LDFLAGS)\nFUZZ_ARFLAGS := $(ARFLAGS)\nFUZZ_TARGET_FLAGS = $(FUZZ_CPPFLAGS) $(FUZZ_CXXFLAGS) $(FUZZ_LDFLAGS)\n\nFUZZ_ROUND_TRIP_FLAGS := -DFUZZING_ASSERT_VALID_SEQUENCE\n\nFUZZ_HEADERS := fuzz_helpers.h fuzz.h zstd_helpers.h fuzz_data_producer.h\nFUZZ_SRC := $(PRGDIR)/util.c ./fuzz_helpers.c ./zstd_helpers.c ./fuzz_data_producer.c\n\nSEEKABLE_HEADERS = $(CONTRIBDIR)/seekable_format/zstd_seekable.h\nSEEKABLE_OBJS = $(CONTRIBDIR)/seekable_format/zstdseek_compress.c $(CONTRIBDIR)/seekable_format/zstdseek_decompress.c\n\nZSTDCOMMON_SRC := $(ZSTD_COMMON_FILES)\nZSTDCOMP_SRC   := $(ZSTD_COMPRESS_FILES)\nZSTDDECOMP_SRC := $(ZSTD_DECOMPRESS_FILES)\nZSTDDICT_SRC := $(ZSTD_DICTBUILDER_FILES)\nZSTDLEGACY_SRC := $(ZSTD_LEGACY_FILES)\nFUZZ_SRC       := \\\n\t$(FUZZ_SRC) \\\n\t$(ZSTDDECOMP_SRC) \\\n\t$(ZSTDCOMMON_SRC) \\\n\t$(ZSTDCOMP_SRC) \\\n\t$(ZSTDDICT_SRC) \\\n\t$(ZSTDLEGACY_SRC) \\\n\t$(DEFAULT_SEQ_PROD_SRC)\nFUZZ_SRC := $(sort $(wildcard $(FUZZ_SRC)))\n\nFUZZ_D_OBJ1 := $(subst $(LIB_SRCDIR)/common/,d_lib_common_,$(FUZZ_SRC))\nFUZZ_D_OBJ2 := $(subst $(LIB_SRCDIR)/compress/,d_lib_compress_,$(FUZZ_D_OBJ1))\nFUZZ_D_OBJ3 := $(subst $(LIB_SRCDIR)/decompress/,d_lib_decompress_,$(FUZZ_D_OBJ2))\nFUZZ_D_OBJ4 := $(subst $(LIB_SRCDIR)/dictBuilder/,d_lib_dictBuilder_,$(FUZZ_D_OBJ3))\nFUZZ_D_OBJ5 := $(subst $(LIB_SRCDIR)/legacy/,d_lib_legacy_,$(FUZZ_D_OBJ4))\nFUZZ_D_OBJ6 := $(subst $(PRGDIR)/,d_prg_,$(FUZZ_D_OBJ5))\nFUZZ_D_OBJ7 := $(subst $(DEFAULT_SEQ_PROD_DIR)/,d_default_seq_prod_,$(FUZZ_D_OBJ6))\nFUZZ_D_OBJ8 := $(subst $\\./,d_fuzz_,$(FUZZ_D_OBJ7))\nFUZZ_D_OBJ9 := $(FUZZ_D_OBJ8:.c=.o)\nFUZZ_D_OBJ10 := $(THIRD_PARTY_SEQ_PROD_OBJ) $(FUZZ_D_OBJ9)\nFUZZ_DECOMPRESS_OBJ := $(FUZZ_D_OBJ10:.S=.o)\n\nFUZZ_RT_OBJ1 := $(subst $(LIB_SRCDIR)/common/,rt_lib_common_,$(FUZZ_SRC))\nFUZZ_RT_OBJ2 := $(subst $(LIB_SRCDIR)/compress/,rt_lib_compress_,$(FUZZ_RT_OBJ1))\nFUZZ_RT_OBJ3 := $(subst $(LIB_SRCDIR)/decompress/,rt_lib_decompress_,$(FUZZ_RT_OBJ2))\nFUZZ_RT_OBJ4 := $(subst $(LIB_SRCDIR)/dictBuilder/,rt_lib_dictBuilder_,$(FUZZ_RT_OBJ3))\nFUZZ_RT_OBJ5 := $(subst $(LIB_SRCDIR)/legacy/,rt_lib_legacy_,$(FUZZ_RT_OBJ4))\nFUZZ_RT_OBJ6 := $(subst $(PRGDIR)/,rt_prg_,$(FUZZ_RT_OBJ5))\nFUZZ_RT_OBJ7 := $(subst $(DEFAULT_SEQ_PROD_DIR)/,rt_default_seq_prod_,$(FUZZ_RT_OBJ6))\nFUZZ_RT_OBJ8 := $(subst $\\./,rt_fuzz_,$(FUZZ_RT_OBJ7))\nFUZZ_RT_OBJ9 := $(FUZZ_RT_OBJ8:.c=.o)\nFUZZ_RT_OBJ10 := $(THIRD_PARTY_SEQ_PROD_OBJ) $(FUZZ_RT_OBJ9)\nFUZZ_ROUND_TRIP_OBJ := $(FUZZ_RT_OBJ10:.S=.o)\n\nFUZZ_TARGETS :=       \\\n\tsimple_round_trip \\\n\tstream_round_trip \\\n\tblock_round_trip  \\\n\tsimple_decompress \\\n\tstream_decompress \\\n\tblock_decompress  \\\n\tdictionary_round_trip \\\n\tdictionary_decompress \\\n\tzstd_frame_info \\\n\tsimple_compress \\\n\tdictionary_loader \\\n\traw_dictionary_round_trip \\\n\tdictionary_stream_round_trip \\\n\tdecompress_dstSize_tooSmall \\\n\tfse_read_ncount \\\n\tsequence_compression_api \\\n\tseekable_roundtrip \\\n\thuf_round_trip \\\n\thuf_decompress \\\n\tdecompress_cross_format \\\n\tgenerate_sequences\n\n.PHONY: all clean cleanall\nall: libregression.a $(FUZZ_TARGETS)\n\nrt_lib_common_%.o: $(LIB_SRCDIR)/common/%.c\n\t$(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $(FUZZ_ROUND_TRIP_FLAGS) $< -c -o $@\n\nrt_lib_compress_%.o: $(LIB_SRCDIR)/compress/%.c\n\t$(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $(FUZZ_ROUND_TRIP_FLAGS) $< -c -o $@\n\nrt_lib_decompress_%.o: $(LIB_SRCDIR)/decompress/%.c\n\t$(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $(FUZZ_ROUND_TRIP_FLAGS) $< -c -o $@\n\nrt_lib_decompress_%.o: $(LIB_SRCDIR)/decompress/%.S\n\t$(CC) $(FUZZ_CPPFLAGS) $(FUZZ_ASFLAGS) $(FUZZ_ROUND_TRIP_FLAGS) $< -c -o $@\n\nrt_lib_dictBuilder_%.o: $(LIB_SRCDIR)/dictBuilder/%.c\n\t$(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $(FUZZ_ROUND_TRIP_FLAGS) $< -c -o $@\n\nrt_lib_legacy_%.o: $(LIB_SRCDIR)/legacy/%.c\n\t$(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $(FUZZ_ROUND_TRIP_FLAGS) $< -c -o $@\n\nrt_prg_%.o: $(PRGDIR)/%.c\n\t$(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $(FUZZ_ROUND_TRIP_FLAGS) $< -c -o $@\n\nrt_fuzz_%.o: %.c\n\t$(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $(FUZZ_ROUND_TRIP_FLAGS) $< -c -o $@\n\nrt_default_seq_prod_%.o: $(DEFAULT_SEQ_PROD_DIR)/%.c\n\t$(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $(FUZZ_ROUND_TRIP_FLAGS) $< -c -o $@\n\nd_lib_common_%.o: $(LIB_SRCDIR)/common/%.c\n\t$(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $< -c -o $@\n\nd_lib_compress_%.o: $(LIB_SRCDIR)/compress/%.c\n\t$(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $< -c -o $@\n\nd_lib_decompress_%.o: $(LIB_SRCDIR)/decompress/%.c\n\t$(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $< -c -o $@\n\nd_lib_decompress_%.o: $(LIB_SRCDIR)/decompress/%.S\n\t$(CC) $(FUZZ_CPPFLAGS) $(FUZZ_ASFLAGS) $< -c -o $@\n\nd_lib_dictBuilder_%.o: $(LIB_SRCDIR)/dictBuilder/%.c\n\t$(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $< -c -o $@\n\nd_lib_legacy_%.o: $(LIB_SRCDIR)/legacy/%.c\n\t$(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $< -c -o $@\n\nd_prg_%.o: $(PRGDIR)/%.c\n\t$(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $< -c -o $@\n\nd_fuzz_%.o: %.c\n\t$(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $< -c -o $@\n\nd_default_seq_prod_%.o: $(DEFAULT_SEQ_PROD_DIR)/%.c\n\t$(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $< -c -o $@\n\nsimple_round_trip: $(FUZZ_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_simple_round_trip.o\n\t$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_simple_round_trip.o $(LIB_FUZZING_ENGINE) -o $@\n\nstream_round_trip: $(FUZZ_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_stream_round_trip.o\n\t$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_stream_round_trip.o $(LIB_FUZZING_ENGINE) -o $@\n\nblock_round_trip: $(FUZZ_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_block_round_trip.o\n\t$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_block_round_trip.o $(LIB_FUZZING_ENGINE) -o $@\n\nsimple_decompress: $(FUZZ_HEADERS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_simple_decompress.o\n\t$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_simple_decompress.o $(LIB_FUZZING_ENGINE) -o $@\n\nstream_decompress: $(FUZZ_HEADERS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_stream_decompress.o\n\t$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_stream_decompress.o $(LIB_FUZZING_ENGINE) -o $@\n\nblock_decompress: $(FUZZ_HEADERS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_block_decompress.o\n\t$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_block_decompress.o $(LIB_FUZZING_ENGINE) -o $@\n\ndictionary_round_trip: $(FUZZ_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_dictionary_round_trip.o\n\t$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_dictionary_round_trip.o $(LIB_FUZZING_ENGINE) -o $@\n\nraw_dictionary_round_trip: $(FUZZ_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_raw_dictionary_round_trip.o\n\t$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_raw_dictionary_round_trip.o $(LIB_FUZZING_ENGINE) -o $@\n\ndictionary_stream_round_trip: $(FUZZ_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_dictionary_stream_round_trip.o\n\t$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_dictionary_stream_round_trip.o $(LIB_FUZZING_ENGINE) -o $@\n\ndictionary_decompress: $(FUZZ_HEADERS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_dictionary_decompress.o\n\t$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_dictionary_decompress.o $(LIB_FUZZING_ENGINE) -o $@\n\nsimple_compress: $(FUZZ_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_simple_compress.o\n\t$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_simple_compress.o $(LIB_FUZZING_ENGINE) -o $@\n\nzstd_frame_info: $(FUZZ_HEADERS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_zstd_frame_info.o\n\t$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_zstd_frame_info.o $(LIB_FUZZING_ENGINE) -o $@\n\ndictionary_loader: $(FUZZ_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_dictionary_loader.o\n\t$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_dictionary_loader.o $(LIB_FUZZING_ENGINE) -o $@\n\ndecompress_dstSize_tooSmall: $(FUZZ_HEADERS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_decompress_dstSize_tooSmall.o\n\t$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_decompress_dstSize_tooSmall.o $(LIB_FUZZING_ENGINE) -o $@\n\nfse_read_ncount: $(FUZZ_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_fse_read_ncount.o\n\t$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_fse_read_ncount.o $(LIB_FUZZING_ENGINE) -o $@\n\nsequence_compression_api: $(FUZZ_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_sequence_compression_api.o\n\t$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_sequence_compression_api.o $(LIB_FUZZING_ENGINE) -o $@\n\nseekable_roundtrip: $(FUZZ_HEADERS) $(SEEKABLE_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) $(SEEKABLE_OBJS)  rt_fuzz_seekable_roundtrip.o\n\t$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_ROUND_TRIP_OBJ) $(SEEKABLE_OBJS) rt_fuzz_seekable_roundtrip.o $(LIB_FUZZING_ENGINE) -o $@\n\nhuf_round_trip: $(FUZZ_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_huf_round_trip.o\n\t$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_huf_round_trip.o $(LIB_FUZZING_ENGINE) -o $@\n\nhuf_decompress: $(FUZZ_HEADERS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_huf_decompress.o\n\t$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_huf_decompress.o $(LIB_FUZZING_ENGINE) -o $@\n\ndecompress_cross_format: $(FUZZ_HEADERS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_decompress_cross_format.o\n\t$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_decompress_cross_format.o $(LIB_FUZZING_ENGINE) -o $@\n\ngenerate_sequences: $(FUZZ_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_generate_sequences.o\n\t$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_generate_sequences.o $(LIB_FUZZING_ENGINE) -o $@\n\nlibregression.a: $(FUZZ_HEADERS) $(PRGDIR)/util.h $(PRGDIR)/util.c d_fuzz_regression_driver.o\n\t$(AR) $(FUZZ_ARFLAGS) $@ d_fuzz_regression_driver.o\n\ncorpora/%_seed_corpus.zip:\n\t@mkdir -p corpora\n\t$(DOWNLOAD) $@ $(CORPORA_URL_PREFIX)$*_seed_corpus.zip\n\ncorpora/%: corpora/%_seed_corpus.zip\n\tunzip -q $^ -d $@\n\n.PHONY: corpora\ncorpora: $(patsubst %,corpora/%,$(FUZZ_TARGETS))\n\n.PHONY: seedcorpora\nseedcorpora: $(patsubst %,corpora/%_seed_corpus.zip,$(FUZZ_TARGETS))\n\nREGRESSION_TARGET ?= all\nregressiontest: corpora\n\tCC=\"$(CC)\" CXX=\"$(CXX)\" CFLAGS=\"$(CFLAGS)\" CXXFLAGS=\"$(CXXFLAGS)\" LDFLAGS=\"$(LDFLAGS)\" $(PYTHON) ./fuzz.py build $(REGRESSION_TARGET) --debug=$(DEBUGLEVEL)\n\t$(PYTHON) ./fuzz.py regression $(REGRESSION_TARGET)\n\nclean:\n\t@$(RM) *.a *.o $(FUZZ_TARGETS)\n\t@echo Cleaning completed\n\ncleanall:\n\t@$(RM) -r Fuzzer\n\t@$(RM) -r corpora\n\t@echo Cleaning completed\n"
  },
  {
    "path": "tests/fuzz/README.md",
    "content": "# Fuzzing\n\nEach fuzzing target can be built with multiple engines.\nZstd provides a fuzz corpus for each target that can be downloaded with\nthe command:\n\n```\nmake corpora\n```\n\nIt will download each corpus into `./corpora/TARGET`.\n\n## fuzz.py\n\n`fuzz.py` is a helper script for building and running fuzzers.\nRun `./fuzz.py -h` for the commands and run `./fuzz.py COMMAND -h` for\ncommand specific help.\n\n### Generating Data\n\n`fuzz.py` provides a utility to generate seed data for each fuzzer.\n\n```\nmake -C ../tests decodecorpus\n./fuzz.py gen TARGET\n```\n\nBy default it outputs 100 samples, each at most 8KB into `corpora/TARGET-seed`,\nbut that can be configured with the `--number`, `--max-size-log` and `--seed`\nflags.\n\n### Build\nIt respects the usual build environment variables `CC`, `CFLAGS`, etc.\nThe environment variables can be overridden with the corresponding flags\n`--cc`, `--cflags`, etc.\nThe specific fuzzing engine is selected with `LIB_FUZZING_ENGINE` or\n`--lib-fuzzing-engine`, the default is `libregression.a`.\nAlternatively, you can use Clang's built in fuzzing engine with\n`--enable-fuzzer`.\nIt has flags that can easily set up sanitizers `--enable-{a,ub,m}san`, and\ncoverage instrumentation `--enable-coverage`.\nIt sets sane defaults which can be overridden with flags `--debug`,\n`--enable-ubsan-pointer-overflow`, etc.\nRun `./fuzz.py build -h` for help.\n\n### Running Fuzzers\n\n`./fuzz.py` can run `libfuzzer`, `afl`, and `regression` tests.\nSee the help of the relevant command for options.\nFlags not parsed by `fuzz.py` are passed to the fuzzing engine.\nThe command used to run the fuzzer is printed for debugging.\n\nHere's a helpful command to fuzz each target across all cores,\nstopping only if a bug is found:\n```\nfor target in $(./fuzz.py list); do\n    ./fuzz.py libfuzzer $target -jobs=10 -workers=10 -max_total_time=1000 || break;\ndone\n```\nAlternatively, you can fuzz all targets in parallel, using one core per target:\n```\npython3 ./fuzz.py list | xargs -P$(python3 ./fuzz.py list | wc -l) -I__ sh -c \"python3 ./fuzz.py libfuzzer __ 2>&1 | tee __.log\"\n```\nEither way, to double-check that no crashes were found, run `ls corpora/*crash`.\nIf any crashes were found, you can use the hashes to reproduce them.\n\n## LibFuzzer\n\n```\n# Build the fuzz targets\n./fuzz.py build all --enable-fuzzer --enable-asan --enable-ubsan --cc clang --cxx clang++\n# OR equivalently\nCC=clang CXX=clang++ ./fuzz.py build all --enable-fuzzer --enable-asan --enable-ubsan\n# Run the fuzzer\n./fuzz.py libfuzzer TARGET <libfuzzer args like -jobs=4>\n```\n\nwhere `TARGET` could be `simple_decompress`, `stream_round_trip`, etc.\n\n### MSAN\n\nFuzzing with `libFuzzer` and `MSAN` is as easy as:\n\n```\nCC=clang CXX=clang++ ./fuzz.py build all --enable-fuzzer --enable-msan\n./fuzz.py libfuzzer TARGET <libfuzzer args>\n```\n\n`fuzz.py` respects the environment variables / flags `MSAN_EXTRA_CPPFLAGS`,\n`MSAN_EXTRA_CFLAGS`, `MSAN_EXTRA_CXXFLAGS`, `MSAN_EXTRA_LDFLAGS` to easily pass\nthe extra parameters only for MSAN.\n\n## AFL\n\nThe default `LIB_FUZZING_ENGINE` is `libregression.a`, which produces a binary\nthat AFL can use.\n\n```\n# Build the fuzz targets\nCC=afl-clang CXX=afl-clang++ ./fuzz.py build all --enable-asan --enable-ubsan\n# Run the fuzzer without a memory limit because of ASAN\n./fuzz.py afl TARGET -m none\n```\n\n## Regression Testing\n\nThe regression test supports the `all` target to run all the fuzzers in one\ncommand.\n\n```\nCC=clang CXX=clang++ ./fuzz.py build all --enable-asan --enable-ubsan\n./fuzz.py regression all\nCC=clang CXX=clang++ ./fuzz.py build all --enable-msan\n./fuzz.py regression all\n```\n\n## Fuzzing a custom sequence producer plugin\nSequence producer plugin authors can use the zstd fuzzers to stress-test their code.\nSee the documentation in `fuzz_third_party_seq_prod.h` for details.\n\n## Adding a new fuzzer\nThere are several steps involved in adding a new fuzzer harness.\n\n### Build your harness\n1. Create a new your fuzzer harness `tests/fuzz/your_harness.c`.\n\n2. Add your harness to the Makefile\n\n    2.1 Follow [this example](https://github.com/facebook/zstd/blob/e124e39301381de8f323436a3e4c46539747ba24/tests/fuzz/Makefile#L216) if your fuzzer requires both compression and decompression symbols (prefix `rt_`). If your fuzzer only requires decompression symbols, follow [this example](https://github.com/facebook/zstd/blob/6a0052a409e2604bd40354b76b86272b712edd7d/tests/fuzz/Makefile#L194) (prefix `d_`).\n    \n    2.2 Add your target to [`FUZZ_TARGETS`](https://github.com/facebook/zstd/blob/6a0052a409e2604bd40354b76b86272b712edd7d/tests/fuzz/Makefile#L108).\n    \n3. Add your harness to [`fuzz.py`](https://github.com/facebook/zstd/blob/6a0052a409e2604bd40354b76b86272b712edd7d/tests/fuzz/fuzz.py#L48).\n\n### Generate seed data\nFollow the instructions above to generate seed data:\n```\nmake -C ../tests decodecorpus\n./fuzz.py gen your_harness\n```\n\n### Run the harness\nFollow the instructions above to run your harness and fix any crashes:\n```\n./fuzz.py build your_harness --enable-fuzzer --enable-asan --enable-ubsan --cc clang --cxx clang++\n./fuzz.py libfuzzer your_harness\n```\n\n### Minimize and zip the corpus\nAfter running the fuzzer for a while, you will have a large corpus at `tests/fuzz/corpora/your_harness*`.\nThis corpus must be minimized and zipped before uploading to GitHub for regression testing:\n```\n./fuzz.py minimize your_harness\n./fuzz.py zip your_harness \n```\n\n### Upload the zip file to GitHub\nThe previous step should produce a `.zip` file containing the corpus for your new harness.\nThis corpus must be uploaded to GitHub here: https://github.com/facebook/zstd/releases/tag/fuzz-corpora\n\n\n"
  },
  {
    "path": "tests/fuzz/block_decompress.c",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/**\n * This fuzz target attempts to decompress the fuzzed data with the simple\n * decompression function to ensure the decompressor never crashes.\n */\n\n#include \"fuzz_data_producer.h\"\n#define ZSTD_STATIC_LINKING_ONLY\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include \"fuzz_helpers.h\"\n#include \"zstd.h\"\n\nstatic ZSTD_DCtx *dctx = NULL;\nstatic void* rBuf = NULL;\nstatic size_t bufSize = 0;\n\nint LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)\n{\n    size_t const neededBufSize = ZSTD_BLOCKSIZE_MAX;\n    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);\n\n    /* Allocate all buffers and contexts if not already allocated */\n    if (neededBufSize > bufSize) {\n        free(rBuf);\n        rBuf = FUZZ_malloc_rand(neededBufSize, producer);\n        bufSize = neededBufSize;\n    }\n    if (!dctx) {\n        dctx = ZSTD_createDCtx();\n        FUZZ_ASSERT(dctx);\n    }\n    ZSTD_decompressBegin(dctx);\n    ZSTD_decompressBlock(dctx, rBuf, neededBufSize, src, size);\n\n    FUZZ_dataProducer_free(producer);\n\n#ifndef STATEFUL_FUZZING\n    ZSTD_freeDCtx(dctx); dctx = NULL;\n#endif\n    return 0;\n}\n"
  },
  {
    "path": "tests/fuzz/block_round_trip.c",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/**\n * This fuzz target performs a zstd round-trip test (compress & decompress),\n * compares the result with the original, and calls abort() on corruption.\n */\n\n#define ZSTD_STATIC_LINKING_ONLY\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include \"fuzz_helpers.h\"\n#include \"zstd.h\"\n#include \"zstd_helpers.h\"\n#include \"fuzz_data_producer.h\"\n#include \"fuzz_third_party_seq_prod.h\"\n\nstatic ZSTD_CCtx *cctx = NULL;\nstatic ZSTD_DCtx *dctx = NULL;\nstatic void* cBuf = NULL;\nstatic void* rBuf = NULL;\nstatic size_t bufSize = 0;\n\nstatic size_t roundTripTest(void *result, size_t resultCapacity,\n                            void *compressed, size_t compressedCapacity,\n                            const void *src, size_t srcSize,\n                            int cLevel)\n{\n    ZSTD_parameters const params = ZSTD_getParams(cLevel, srcSize, 0);\n    size_t ret = ZSTD_compressBegin_advanced(cctx, NULL, 0, params, srcSize);\n    FUZZ_ZASSERT(ret);\n\n    ret = ZSTD_compressBlock(cctx, compressed, compressedCapacity, src, srcSize);\n    FUZZ_ZASSERT(ret);\n    if (ret == 0) {\n        FUZZ_ASSERT(resultCapacity >= srcSize);\n        if (srcSize > 0) {\n            memcpy(result, src, srcSize);\n        }\n        return srcSize;\n    }\n    ZSTD_decompressBegin(dctx);\n    return ZSTD_decompressBlock(dctx, result, resultCapacity, compressed, ret);\n}\n\nint LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)\n{\n    FUZZ_SEQ_PROD_SETUP();\n\n    /* Give a random portion of src data to the producer, to use for\n    parameter generation. The rest will be used for (de)compression */\n    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);\n    size = FUZZ_dataProducer_reserveDataPrefix(producer);\n\n    int const cLevel = FUZZ_dataProducer_int32Range(producer, kMinClevel, kMaxClevel);\n\n    size_t neededBufSize = size;\n    if (size > ZSTD_BLOCKSIZE_MAX)\n        size = ZSTD_BLOCKSIZE_MAX;\n\n    /* Allocate all buffers and contexts if not already allocated */\n    if (neededBufSize > bufSize || !cBuf || !rBuf) {\n        free(cBuf);\n        free(rBuf);\n        cBuf = FUZZ_malloc(neededBufSize);\n        rBuf = FUZZ_malloc(neededBufSize);\n        bufSize = neededBufSize;\n    }\n    if (!cctx) {\n        cctx = ZSTD_createCCtx();\n        FUZZ_ASSERT(cctx);\n    }\n    if (!dctx) {\n        dctx = ZSTD_createDCtx();\n        FUZZ_ASSERT(dctx);\n    }\n\n    {\n        size_t const result =\n            roundTripTest(rBuf, neededBufSize, cBuf, neededBufSize, src, size,\n              cLevel);\n        FUZZ_ZASSERT(result);\n        FUZZ_ASSERT_MSG(result == size, \"Incorrect regenerated size\");\n        FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, rBuf, size), \"Corruption!\");\n    }\n    FUZZ_dataProducer_free(producer);\n#ifndef STATEFUL_FUZZING\n    ZSTD_freeCCtx(cctx); cctx = NULL;\n    ZSTD_freeDCtx(dctx); dctx = NULL;\n#endif\n    FUZZ_SEQ_PROD_TEARDOWN();\n    return 0;\n}\n"
  },
  {
    "path": "tests/fuzz/decompress_cross_format.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n// This fuzz target validates decompression of magicless-format compressed data.\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include \"fuzz_helpers.h\"\n#define ZSTD_STATIC_LINKING_ONLY\n#include \"zstd.h\"\n#include \"fuzz_data_producer.h\"\n\nstatic ZSTD_DCtx *dctx = NULL;\n\nint LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)\n{\n    // Give a random portion of src data to the producer, to use for parameter generation.\n    // The rest will be interpreted as magicless compressed data.\n    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);\n    size_t magiclessSize = FUZZ_dataProducer_reserveDataPrefix(producer);\n    const uint8_t* const magiclessSrc = src;\n    size_t const dstSize = FUZZ_dataProducer_uint32Range(producer, 0, 10 * size);\n    uint8_t* const standardDst = (uint8_t*)FUZZ_malloc(dstSize);\n    uint8_t* const magiclessDst = (uint8_t*)FUZZ_malloc(dstSize);\n\n    // Create standard-format src from magicless-format src\n    const uint32_t zstd_magic = ZSTD_MAGICNUMBER;\n    size_t standardSize = sizeof(zstd_magic) + magiclessSize;\n    uint8_t* const standardSrc = (uint8_t*)FUZZ_malloc(standardSize);\n    memcpy(standardSrc, &zstd_magic, sizeof(zstd_magic)); // assume fuzzing on little-endian machine\n    memcpy(standardSrc + sizeof(zstd_magic), magiclessSrc, magiclessSize);\n\n    // Truncate to a single frame\n    {\n        const size_t standardFrameCompressedSize = ZSTD_findFrameCompressedSize(standardSrc, standardSize);\n        if (ZSTD_isError(standardFrameCompressedSize)) {\n            goto cleanup_and_return;\n        }\n        standardSize = standardFrameCompressedSize;\n        magiclessSize = standardFrameCompressedSize - sizeof(zstd_magic);\n    }\n\n    // Create DCtx if needed\n    if (!dctx) {\n        dctx = ZSTD_createDCtx();\n        FUZZ_ASSERT(dctx);\n    }\n\n    // Test one-shot decompression\n    {\n        FUZZ_ZASSERT(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters));\n        FUZZ_ZASSERT(ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, ZSTD_f_zstd1));\n        const size_t standardRet = ZSTD_decompressDCtx(\n                                        dctx, standardDst, dstSize, standardSrc, standardSize);\n\n        FUZZ_ZASSERT(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters));\n        FUZZ_ZASSERT(ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, ZSTD_f_zstd1_magicless));\n        const size_t magiclessRet = ZSTD_decompressDCtx(\n                                        dctx, magiclessDst, dstSize, magiclessSrc, magiclessSize);\n\n        // Standard accepts => magicless should accept\n        if (!ZSTD_isError(standardRet)) FUZZ_ZASSERT(magiclessRet);\n\n        // Magicless accepts => standard should accept\n        // NOTE: this is nice-to-have, please disable this check if it is difficult to satisfy.\n        if (!ZSTD_isError(magiclessRet)) FUZZ_ZASSERT(standardRet);\n\n        // If both accept, decompressed size and data should match\n        if (!ZSTD_isError(standardRet) && !ZSTD_isError(magiclessRet)) {\n            FUZZ_ASSERT(standardRet == magiclessRet);\n            if (standardRet > 0) {\n                FUZZ_ASSERT(\n                    memcmp(standardDst, magiclessDst, standardRet) == 0\n                );\n            }\n        }\n    }\n\n    // Test streaming decompression\n    {\n        ZSTD_inBuffer standardIn = { standardSrc, standardSize, 0 };\n        ZSTD_inBuffer magiclessIn = { magiclessSrc, magiclessSize, 0 };\n        ZSTD_outBuffer standardOut = { standardDst, dstSize, 0 };\n        ZSTD_outBuffer magiclessOut = { magiclessDst, dstSize, 0 };\n\n        FUZZ_ZASSERT(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters));\n        FUZZ_ZASSERT(ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, ZSTD_f_zstd1));\n        const size_t standardRet = ZSTD_decompressStream(dctx, &standardOut, &standardIn);\n\n        FUZZ_ZASSERT(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters));\n        FUZZ_ZASSERT(ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, ZSTD_f_zstd1_magicless));\n        const size_t magiclessRet = ZSTD_decompressStream(dctx, &magiclessOut, &magiclessIn);\n\n        // Standard accepts => magicless should accept\n        if (standardRet == 0) FUZZ_ASSERT(magiclessRet == 0);\n\n        // Magicless accepts => standard should accept\n        // NOTE: this is nice-to-have, please disable this check if it is difficult to satisfy.\n        if (magiclessRet == 0) FUZZ_ASSERT(standardRet == 0);\n\n        // If both accept, decompressed size and data should match\n        if (standardRet == 0 && magiclessRet == 0) {\n            FUZZ_ASSERT(standardOut.pos == magiclessOut.pos);\n            if (standardOut.pos > 0) {\n                FUZZ_ASSERT(\n                    memcmp(standardOut.dst, magiclessOut.dst, standardOut.pos) == 0\n                );\n            }\n        }\n    }\n\ncleanup_and_return:\n#ifndef STATEFUL_FUZZING\n    ZSTD_freeDCtx(dctx); dctx = NULL;\n#endif\n    free(standardSrc);\n    free(standardDst);\n    free(magiclessDst);\n    FUZZ_dataProducer_free(producer);\n    return 0;\n}\n"
  },
  {
    "path": "tests/fuzz/decompress_dstSize_tooSmall.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/**\n * This fuzz target attempts to decompress a valid compressed frame into\n * an output buffer that is too small to ensure we always get\n * ZSTD_error_dstSize_tooSmall.\n */\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include \"fuzz_helpers.h\"\n#include \"zstd.h\"\n#include \"zstd_errors.h\"\n#include \"zstd_helpers.h\"\n#include \"fuzz_data_producer.h\"\n#include \"fuzz_third_party_seq_prod.h\"\n\nstatic ZSTD_CCtx *cctx = NULL;\nstatic ZSTD_DCtx *dctx = NULL;\n\nint LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)\n{\n    FUZZ_SEQ_PROD_SETUP();\n\n    /* Give a random portion of src data to the producer, to use for\n    parameter generation. The rest will be used for (de)compression */\n    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);\n    size_t rBufSize = FUZZ_dataProducer_uint32Range(producer, 0, size);\n    size = FUZZ_dataProducer_remainingBytes(producer);\n    /* Ensure the round-trip buffer is too small. */\n    if (rBufSize >= size) {\n        rBufSize = size > 0 ? size - 1 : 0;\n    }\n    size_t const cBufSize = ZSTD_compressBound(size);\n\n    if (!cctx) {\n        cctx = ZSTD_createCCtx();\n        FUZZ_ASSERT(cctx);\n    }\n    if (!dctx) {\n        dctx = ZSTD_createDCtx();\n        FUZZ_ASSERT(dctx);\n    }\n\n    void *cBuf = FUZZ_malloc(cBufSize);\n    void *rBuf = FUZZ_malloc(rBufSize);\n    size_t const cSize = ZSTD_compressCCtx(cctx, cBuf, cBufSize, src, size, 1);\n    FUZZ_ZASSERT(cSize);\n    size_t const rSize = ZSTD_decompressDCtx(dctx, rBuf, rBufSize, cBuf, cSize);\n    if (size == 0) {\n        FUZZ_ASSERT(rSize == 0);\n    } else {\n        FUZZ_ASSERT(ZSTD_isError(rSize));\n        FUZZ_ASSERT(ZSTD_getErrorCode(rSize) == ZSTD_error_dstSize_tooSmall);\n    }\n    free(cBuf);\n    free(rBuf);\n    FUZZ_dataProducer_free(producer);\n#ifndef STATEFUL_FUZZING\n    ZSTD_freeCCtx(cctx); cctx = NULL;\n    ZSTD_freeDCtx(dctx); dctx = NULL;\n#endif\n    FUZZ_SEQ_PROD_TEARDOWN();\n    return 0;\n}\n"
  },
  {
    "path": "tests/fuzz/dictionary_decompress.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/**\n * This fuzz target attempts to decompress the fuzzed data with the dictionary\n * decompression function to ensure the decompressor never crashes. It does not\n * fuzz the dictionary.\n */\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include \"fuzz_helpers.h\"\n#include \"zstd_helpers.h\"\n#include \"fuzz_data_producer.h\"\n#include \"fuzz_third_party_seq_prod.h\"\n\nstatic ZSTD_DCtx *dctx = NULL;\n\nint LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)\n{\n    FUZZ_SEQ_PROD_SETUP();\n\n    /* Give a random portion of src data to the producer, to use for\n    parameter generation. The rest will be used for (de)compression */\n    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);\n    size = FUZZ_dataProducer_reserveDataPrefix(producer);\n\n    FUZZ_dict_t dict;\n    ZSTD_DDict* ddict = NULL;\n\n    if (!dctx) {\n        dctx = ZSTD_createDCtx();\n        FUZZ_ASSERT(dctx);\n    }\n    dict = FUZZ_train(src, size, producer);\n    if (FUZZ_dataProducer_uint32Range(producer, 0, 1) == 0) {\n        ddict = ZSTD_createDDict(dict.buff, dict.size);\n        FUZZ_ASSERT(ddict);\n    } else {\n        if (FUZZ_dataProducer_uint32Range(producer, 0, 1) == 0)\n            FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced(\n                dctx, dict.buff, dict.size,\n                (ZSTD_dictLoadMethod_e)FUZZ_dataProducer_uint32Range(producer, 0, 1),\n                (ZSTD_dictContentType_e)FUZZ_dataProducer_uint32Range(producer, 0, 2)));\n        else\n            FUZZ_ZASSERT(ZSTD_DCtx_refPrefix_advanced(\n                dctx, dict.buff, dict.size,\n                (ZSTD_dictContentType_e)FUZZ_dataProducer_uint32Range(producer, 0, 2)));\n    }\n\n    {\n        size_t const bufSize = FUZZ_dataProducer_uint32Range(producer, 0, 10 * size);\n        void* rBuf = FUZZ_malloc(bufSize);\n        if (ddict) {\n            ZSTD_decompress_usingDDict(dctx, rBuf, bufSize, src, size, ddict);\n        } else {\n            ZSTD_decompressDCtx(dctx, rBuf, bufSize, src, size);\n        }\n        free(rBuf);\n    }\n    free(dict.buff);\n    FUZZ_dataProducer_free(producer);\n    ZSTD_freeDDict(ddict);\n#ifndef STATEFUL_FUZZING\n    ZSTD_freeDCtx(dctx); dctx = NULL;\n#endif\n    FUZZ_SEQ_PROD_TEARDOWN();\n    return 0;\n}\n"
  },
  {
    "path": "tests/fuzz/dictionary_loader.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/**\n * This fuzz target makes sure that whenever a compression dictionary can be\n * loaded, the data can be round tripped.\n */\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include \"fuzz_helpers.h\"\n#include \"zstd_helpers.h\"\n#include \"fuzz_data_producer.h\"\n#include \"fuzz_third_party_seq_prod.h\"\n\n/**\n * Compresses the data and returns the compressed size or an error.\n */\nstatic size_t compress(void* compressed, size_t compressedCapacity,\n                       void const* source, size_t sourceSize,\n                       void const* dict, size_t dictSize,\n                       ZSTD_dictLoadMethod_e dictLoadMethod,\n                       ZSTD_dictContentType_e dictContentType,\n                       int const refPrefix)\n{\n    ZSTD_CCtx* cctx = ZSTD_createCCtx();\n    if (refPrefix)\n        FUZZ_ZASSERT(ZSTD_CCtx_refPrefix_advanced(\n            cctx, dict, dictSize, dictContentType));\n    else\n        FUZZ_ZASSERT(ZSTD_CCtx_loadDictionary_advanced(\n            cctx, dict, dictSize, dictLoadMethod, dictContentType));\n    size_t const compressedSize = ZSTD_compress2(\n            cctx, compressed, compressedCapacity, source, sourceSize);\n    ZSTD_freeCCtx(cctx);\n    return compressedSize;\n}\n\nstatic size_t decompress(void* result, size_t resultCapacity,\n                         void const* compressed, size_t compressedSize,\n                         void const* dict, size_t dictSize,\n                       ZSTD_dictLoadMethod_e dictLoadMethod,\n                         ZSTD_dictContentType_e dictContentType,\n                         int const refPrefix)\n{\n    ZSTD_DCtx* dctx = ZSTD_createDCtx();\n    if (refPrefix)\n        FUZZ_ZASSERT(ZSTD_DCtx_refPrefix_advanced(\n            dctx, dict, dictSize, dictContentType));\n    else\n        FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced(\n            dctx, dict, dictSize, dictLoadMethod, dictContentType));\n    size_t const resultSize = ZSTD_decompressDCtx(\n            dctx, result, resultCapacity, compressed, compressedSize);\n    FUZZ_ZASSERT(resultSize);\n    ZSTD_freeDCtx(dctx);\n    return resultSize;\n}\n\nint LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)\n{\n    FUZZ_SEQ_PROD_SETUP();\n    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);\n    int const refPrefix = FUZZ_dataProducer_uint32Range(producer, 0, 1) != 0;\n    ZSTD_dictLoadMethod_e const dlm =\n    size = FUZZ_dataProducer_uint32Range(producer, 0, 1);\n    ZSTD_dictContentType_e const dct =\n            FUZZ_dataProducer_uint32Range(producer, 0, 2);\n    size = FUZZ_dataProducer_remainingBytes(producer);\n\n    DEBUGLOG(4, \"Dict load method %d\", dlm);\n    DEBUGLOG(4, \"Dict content type %d\", dct);\n    DEBUGLOG(4, \"Dict size %u\", (unsigned)size);\n\n    void* const rBuf = FUZZ_malloc(size);\n    size_t const cBufSize = ZSTD_compressBound(size);\n    void* const cBuf = FUZZ_malloc(cBufSize);\n\n    size_t const cSize =\n            compress(cBuf, cBufSize, src, size, src, size, dlm, dct, refPrefix);\n    /* compression failing is okay */\n    if (ZSTD_isError(cSize)) {\n      FUZZ_ASSERT_MSG(dct != ZSTD_dct_rawContent, \"Raw must always succeed!\");\n      goto out;\n    }\n    size_t const rSize =\n            decompress(rBuf, size, cBuf, cSize, src, size, dlm, dct, refPrefix);\n    FUZZ_ASSERT_MSG(rSize == size, \"Incorrect regenerated size\");\n    FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, rBuf, size), \"Corruption!\");\n\nout:\n    free(cBuf);\n    free(rBuf);\n    FUZZ_dataProducer_free(producer);\n    FUZZ_SEQ_PROD_TEARDOWN();\n    return 0;\n}\n"
  },
  {
    "path": "tests/fuzz/dictionary_round_trip.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/**\n * This fuzz target performs a zstd round-trip test (compress & decompress) with\n * a dictionary, compares the result with the original, and calls abort() on\n * corruption.\n */\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include \"fuzz_helpers.h\"\n#include \"zstd_helpers.h\"\n#include \"fuzz_data_producer.h\"\n#include \"fuzz_third_party_seq_prod.h\"\n\nstatic ZSTD_CCtx* cctx = NULL;\nstatic ZSTD_DCtx* dctx = NULL;\n\nstatic size_t roundTripTest(void* result, size_t resultCapacity,\n                            void* compressed, size_t compressedCapacity,\n                            const void* src, size_t srcSize,\n                            FUZZ_dataProducer_t* producer)\n{\n    ZSTD_dictContentType_e dictContentType = ZSTD_dct_auto;\n    FUZZ_dict_t dict = FUZZ_train(src, srcSize, producer);\n    int const refPrefix = FUZZ_dataProducer_uint32Range(producer, 0, 1) != 0;\n    size_t cSize;\n    if (FUZZ_dataProducer_uint32Range(producer, 0, 15) == 0) {\n        int const cLevel = FUZZ_dataProducer_int32Range(producer, kMinClevel, kMaxClevel);\n\n        cSize = ZSTD_compress_usingDict(cctx,\n                compressed, compressedCapacity,\n                src, srcSize,\n                dict.buff, dict.size,\n                cLevel);\n        FUZZ_ZASSERT(cSize);\n        // Compress a second time and check for determinism\n        {\n            size_t const cSize0 = cSize;\n            XXH64_hash_t const hash0 = XXH64(compressed, cSize, 0);\n            cSize = ZSTD_compress_usingDict(cctx,\n                    compressed, compressedCapacity,\n                    src, srcSize,\n                    dict.buff, dict.size,\n                    cLevel);\n            FUZZ_ASSERT(cSize == cSize0);\n            FUZZ_ASSERT(XXH64(compressed, cSize, 0) == hash0);\n        }\n    } else {\n        size_t remainingBytes;\n        dictContentType = FUZZ_dataProducer_uint32Range(producer, 0, 2);\n        remainingBytes = FUZZ_dataProducer_remainingBytes(producer);\n        FUZZ_setRandomParameters(cctx, srcSize, producer);\n        /* Disable checksum so we can use sizes smaller than compress bound. */\n        FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 0));\n        if (refPrefix)\n            FUZZ_ZASSERT(ZSTD_CCtx_refPrefix_advanced(\n                cctx, dict.buff, dict.size,\n                dictContentType));\n        else\n            FUZZ_ZASSERT(ZSTD_CCtx_loadDictionary_advanced(\n                cctx, dict.buff, dict.size,\n                (ZSTD_dictLoadMethod_e)FUZZ_dataProducer_uint32Range(producer, 0, 1),\n                dictContentType));\n        cSize = ZSTD_compress2(cctx, compressed, compressedCapacity, src, srcSize);\n        FUZZ_ZASSERT(cSize);\n        // Compress a second time and check for determinism\n        {\n            size_t const cSize0 = cSize;\n            XXH64_hash_t const hash0 = XXH64(compressed, cSize, 0);\n            FUZZ_dataProducer_rollBack(producer, remainingBytes);\n            FUZZ_setRandomParameters(cctx, srcSize, producer);\n            FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 0));\n            if (refPrefix)\n                FUZZ_ZASSERT(ZSTD_CCtx_refPrefix_advanced(\n                    cctx, dict.buff, dict.size,\n                    dictContentType));\n            cSize = ZSTD_compress2(cctx, compressed, compressedCapacity, src, srcSize);\n            FUZZ_ASSERT(cSize == cSize0);\n            FUZZ_ASSERT(XXH64(compressed, cSize, 0) == hash0);\n        }\n    }\n    if (refPrefix)\n        FUZZ_ZASSERT(ZSTD_DCtx_refPrefix_advanced(\n            dctx, dict.buff, dict.size,\n            dictContentType));\n    else\n        FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced(\n            dctx, dict.buff, dict.size,\n            (ZSTD_dictLoadMethod_e)FUZZ_dataProducer_uint32Range(producer, 0, 1),\n            dictContentType));\n    {\n        size_t const ret = ZSTD_decompressDCtx(\n                dctx, result, resultCapacity, compressed, cSize);\n        free(dict.buff);\n        return ret;\n    }\n}\n\nint LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)\n{\n    FUZZ_SEQ_PROD_SETUP();\n\n    /* Give a random portion of src data to the producer, to use for\n    parameter generation. The rest will be used for (de)compression */\n    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);\n    size = FUZZ_dataProducer_reserveDataPrefix(producer);\n\n    size_t const rBufSize = size;\n    void* rBuf = FUZZ_malloc(rBufSize);\n    size_t cBufSize = ZSTD_compressBound(size);\n    void *cBuf;\n    /* Half of the time fuzz with a 1 byte smaller output size.\n     * This will still succeed because we force the checksum to be disabled,\n     * giving us 4 bytes of overhead.\n     */\n    cBufSize -= FUZZ_dataProducer_uint32Range(producer, 0, 1);\n    cBuf = FUZZ_malloc(cBufSize);\n\n    if (!cctx) {\n        cctx = ZSTD_createCCtx();\n        FUZZ_ASSERT(cctx);\n    }\n    if (!dctx) {\n        dctx = ZSTD_createDCtx();\n        FUZZ_ASSERT(dctx);\n    }\n\n    {\n        size_t const result =\n            roundTripTest(rBuf, rBufSize, cBuf, cBufSize, src, size, producer);\n        FUZZ_ZASSERT(result);\n        FUZZ_ASSERT_MSG(result == size, \"Incorrect regenerated size\");\n        FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, rBuf, size), \"Corruption!\");\n    }\n    free(rBuf);\n    free(cBuf);\n    FUZZ_dataProducer_free(producer);\n#ifndef STATEFUL_FUZZING\n    ZSTD_freeCCtx(cctx); cctx = NULL;\n    ZSTD_freeDCtx(dctx); dctx = NULL;\n#endif\n    FUZZ_SEQ_PROD_TEARDOWN();\n    return 0;\n}\n"
  },
  {
    "path": "tests/fuzz/dictionary_stream_round_trip.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/**\n * This fuzz target performs a zstd round-trip test (compress & decompress),\n * compares the result with the original, and calls abort() on corruption.\n */\n\n#define ZSTD_STATIC_LINKING_ONLY\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include \"fuzz_helpers.h\"\n#include \"zstd_helpers.h\"\n#include \"fuzz_data_producer.h\"\n#include \"fuzz_third_party_seq_prod.h\"\n\nZSTD_CCtx *cctx = NULL;\nstatic ZSTD_DCtx *dctx = NULL;\nstatic uint8_t* cBuf = NULL;\nstatic uint8_t* rBuf = NULL;\nstatic size_t bufSize = 0;\n\nstatic ZSTD_outBuffer makeOutBuffer(uint8_t *dst, size_t capacity,\n                                    FUZZ_dataProducer_t *producer)\n{\n    ZSTD_outBuffer buffer = { dst, 0, 0 };\n\n    FUZZ_ASSERT(capacity > 0);\n    buffer.size = (FUZZ_dataProducer_uint32Range(producer, 1, capacity));\n    FUZZ_ASSERT(buffer.size <= capacity);\n\n    return buffer;\n}\n\nstatic ZSTD_inBuffer makeInBuffer(const uint8_t **src, size_t *size,\n                                  FUZZ_dataProducer_t *producer)\n{\n    ZSTD_inBuffer buffer = { *src, 0, 0 };\n\n    FUZZ_ASSERT(*size > 0);\n    buffer.size = (FUZZ_dataProducer_uint32Range(producer, 1, *size));\n    FUZZ_ASSERT(buffer.size <= *size);\n    *src += buffer.size;\n    *size -= buffer.size;\n\n    return buffer;\n}\n\nstatic size_t compress(uint8_t *dst, size_t capacity,\n                        const uint8_t *src, size_t srcSize,\n                        const uint8_t* dict, size_t dictSize,\n                        FUZZ_dataProducer_t *producer, int refPrefix,\n                        ZSTD_dictContentType_e dictContentType)\n{\n    size_t dstSize = 0;\n    ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);\n    FUZZ_setRandomParameters(cctx, srcSize, producer);\n\n    /* Disable checksum so we can use sizes smaller than compress bound. */\n    FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 0));\n    if (refPrefix)\n        FUZZ_ZASSERT(ZSTD_CCtx_refPrefix_advanced(\n            cctx, dict, dictSize,\n            dictContentType));\n    else\n        FUZZ_ZASSERT(ZSTD_CCtx_loadDictionary_advanced(\n            cctx, dict, dictSize,\n            (ZSTD_dictLoadMethod_e)FUZZ_dataProducer_uint32Range(producer, 0, 1),\n            dictContentType));\n\n    while (srcSize > 0) {\n        ZSTD_inBuffer in = makeInBuffer(&src, &srcSize, producer);\n        /* Mode controls the action. If mode == -1 we pick a new mode */\n        int mode = -1;\n        while (in.pos < in.size || mode != -1) {\n            ZSTD_outBuffer out = makeOutBuffer(dst, capacity, producer);\n            /* Previous action finished, pick a new mode. */\n            if (mode == -1) mode = FUZZ_dataProducer_uint32Range(producer, 0, 9);\n            switch (mode) {\n                case 0: /* fall-through */\n                case 1: /* fall-through */\n                case 2: {\n                    size_t const ret =\n                        ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush);\n                    FUZZ_ZASSERT(ret);\n                    if (ret == 0)\n                        mode = -1;\n                    break;\n                }\n                case 3: {\n                    size_t ret =\n                        ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end);\n                    FUZZ_ZASSERT(ret);\n                    /* Reset the compressor when the frame is finished */\n                    if (ret == 0) {\n                        ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);\n                        if (FUZZ_dataProducer_uint32Range(producer, 0, 7) == 0) {\n                            size_t const remaining = in.size - in.pos;\n                            FUZZ_setRandomParameters(cctx, remaining, producer);\n                        }\n                        mode = -1;\n                    }\n                    break;\n                }\n                case 4: {\n                    ZSTD_inBuffer nullIn = { NULL, 0, 0 };\n                    ZSTD_outBuffer nullOut = { NULL, 0, 0 };\n                    size_t const ret = ZSTD_compressStream2(cctx, &nullOut, &nullIn, ZSTD_e_continue);\n                    FUZZ_ZASSERT(ret);\n                }\n                /* fall-through */\n                default: {\n                    size_t const ret =\n                        ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue);\n                    FUZZ_ZASSERT(ret);\n                    mode = -1;\n                }\n            }\n            dst += out.pos;\n            dstSize += out.pos;\n            capacity -= out.pos;\n        }\n    }\n    for (;;) {\n        ZSTD_inBuffer in = {NULL, 0, 0};\n        ZSTD_outBuffer out = makeOutBuffer(dst, capacity, producer);\n        size_t const ret = ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end);\n        FUZZ_ZASSERT(ret);\n\n        dst += out.pos;\n        dstSize += out.pos;\n        capacity -= out.pos;\n        if (ret == 0)\n            break;\n    }\n    return dstSize;\n}\n\nint LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)\n{\n    FUZZ_SEQ_PROD_SETUP();\n    size_t neededBufSize;\n\n    /* Give a random portion of src data to the producer, to use for\n    parameter generation. The rest will be used for (de)compression */\n    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);\n    size = FUZZ_dataProducer_reserveDataPrefix(producer);\n\n    neededBufSize = ZSTD_compressBound(size) * 15;\n\n    /* Allocate all buffers and contexts if not already allocated */\n    if (neededBufSize > bufSize) {\n        free(cBuf);\n        free(rBuf);\n        cBuf = (uint8_t*)FUZZ_malloc(neededBufSize);\n        rBuf = (uint8_t*)FUZZ_malloc(neededBufSize);\n        bufSize = neededBufSize;\n    }\n    if (!cctx) {\n        cctx = ZSTD_createCCtx();\n        FUZZ_ASSERT(cctx);\n    }\n    if (!dctx) {\n        dctx = ZSTD_createDCtx();\n        FUZZ_ASSERT(dctx);\n    }\n\n    {\n        ZSTD_dictContentType_e dictContentType = FUZZ_dataProducer_uint32Range(producer, 0, 2);\n        FUZZ_dict_t dict = FUZZ_train(src, size, producer);\n        int const refPrefix = FUZZ_dataProducer_uint32Range(producer, 0, 1) != 0;\n\n        size_t const cSize = compress(cBuf, neededBufSize, src, size, dict.buff, dict.size, producer, refPrefix, dictContentType);\n\n        if (refPrefix)\n            FUZZ_ZASSERT(ZSTD_DCtx_refPrefix_advanced(\n                dctx, dict.buff, dict.size,\n                dictContentType));\n        else\n            FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced(\n                dctx, dict.buff, dict.size,\n                (ZSTD_dictLoadMethod_e)FUZZ_dataProducer_uint32Range(producer, 0, 1),\n                dictContentType));\n        size_t const rSize =\n            ZSTD_decompressDCtx(dctx, rBuf, neededBufSize, cBuf, cSize);\n        FUZZ_ZASSERT(rSize);\n        FUZZ_ASSERT_MSG(rSize == size, \"Incorrect regenerated size\");\n        FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, rBuf, size), \"Corruption!\");\n        free(dict.buff);\n    }\n\n    FUZZ_dataProducer_free(producer);\n#ifndef STATEFUL_FUZZING\n    ZSTD_freeCCtx(cctx); cctx = NULL;\n    ZSTD_freeDCtx(dctx); dctx = NULL;\n#endif\n    FUZZ_SEQ_PROD_TEARDOWN();\n    return 0;\n}\n"
  },
  {
    "path": "tests/fuzz/fse_read_ncount.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/**\n * This fuzz target round trips the FSE normalized count with FSE_writeNCount()\n * and FSE_readNcount() to ensure that it can always round trip correctly.\n */\n\n#define FSE_STATIC_LINKING_ONLY\n#define ZSTD_STATIC_LINKING_ONLY\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include \"fuzz_helpers.h\"\n#include \"zstd_helpers.h\"\n#include \"fuzz_data_producer.h\"\n#include \"fse.h\"\n\nint LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)\n{\n    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);\n\n    /* Pick a random tableLog and maxSymbolValue */\n    unsigned const tableLog = FUZZ_dataProducer_uint32Range(producer, FSE_MIN_TABLELOG, FSE_MAX_TABLELOG);\n    unsigned const maxSymbolValue = FUZZ_dataProducer_uint32Range(producer, 0, 255);\n\n    unsigned remainingWeight = (1u << tableLog) - 1;\n    size_t dataSize;\n    BYTE data[512];\n    short ncount[256];\n\n    /* Randomly fill the normalized count */\n    memset(ncount, 0, sizeof(ncount));\n    {\n        unsigned s;\n        for (s = 0; s < maxSymbolValue && remainingWeight > 0; ++s) {\n            short n = (short)FUZZ_dataProducer_int32Range(producer, -1, remainingWeight);\n            ncount[s] = n;\n            if (n < 0) {\n                remainingWeight -= 1;\n            } else {\n                assert((unsigned)n <= remainingWeight);\n                remainingWeight -= n;\n            }\n        }\n        /* Ensure ncount[maxSymbolValue] != 0 and the sum is (1<<tableLog) */\n        ncount[maxSymbolValue] = remainingWeight + 1;\n        if (ncount[maxSymbolValue] == 1 && FUZZ_dataProducer_uint32Range(producer, 0, 1) == 1) {\n            ncount[maxSymbolValue] = -1;\n        }\n    }\n    /* Write the normalized count */\n    {\n        FUZZ_ASSERT(sizeof(data) >= FSE_NCountWriteBound(maxSymbolValue, tableLog));\n        dataSize = FSE_writeNCount(data, sizeof(data), ncount, maxSymbolValue, tableLog);\n        FUZZ_ZASSERT(dataSize);\n    }\n    /* Read & validate the normalized count */\n    {\n        short rtNcount[256];\n        unsigned rtMaxSymbolValue = 255;\n        unsigned rtTableLog;\n        /* Copy into a buffer with a random amount of random data at the end */\n        size_t const buffSize = (size_t)FUZZ_dataProducer_uint32Range(producer, dataSize, sizeof(data));\n        BYTE* const buff = FUZZ_malloc(buffSize);\n        size_t rtDataSize;\n        memcpy(buff, data, dataSize); \n        {\n            size_t b;\n            for (b = dataSize; b < buffSize; ++b) {\n                buff[b] = (BYTE)FUZZ_dataProducer_uint32Range(producer, 0, 255);\n            }\n        }\n\n        rtDataSize = FSE_readNCount(rtNcount, &rtMaxSymbolValue, &rtTableLog, buff, buffSize);\n        FUZZ_ZASSERT(rtDataSize);\n        FUZZ_ASSERT(rtDataSize == dataSize);\n        FUZZ_ASSERT(rtMaxSymbolValue == maxSymbolValue);\n        FUZZ_ASSERT(rtTableLog == tableLog);\n        {\n            unsigned s;\n            for (s = 0; s <= maxSymbolValue; ++s) {\n                FUZZ_ASSERT(ncount[s] == rtNcount[s]);\n            }\n        }\n        free(buff);\n    }\n\n    FUZZ_dataProducer_free(producer);\n    return 0;\n}\n"
  },
  {
    "path": "tests/fuzz/fuzz.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/**\n * Fuzz target interface.\n * Fuzz targets have some common parameters passed as macros during compilation.\n * Check the documentation for each individual fuzzer for more parameters.\n *\n * @param STATEFUL_FUZZING:\n *        Define this to reuse state between fuzzer runs. This can be useful to\n *        test code paths which are only executed when contexts are reused.\n *        WARNING: Makes reproducing crashes much harder.\n *        Default: Not defined.\n * @param DEBUGLEVEL:\n *        This is a parameter for the zstd library. Defining `DEBUGLEVEL=1`\n *        enables assert() statements in the zstd library. Higher levels enable\n *        logging, so aren't recommended. Defining `DEBUGLEVEL=1` is\n *        recommended.\n * @param MEM_FORCE_MEMORY_ACCESS:\n *        This flag controls how the zstd library accesses unaligned memory.\n *        It can be undefined, or 0 through 2. If it is undefined, it selects\n *        the method to use based on the compiler.\n * @param FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION\n *        This is the canonical flag to enable deterministic builds for fuzzing.\n *        Changes to zstd for fuzzing are gated behind this define.\n *        It is recommended to define this when building zstd for fuzzing.\n * @param FUZZ_THIRD_PARTY_SEQ_PROD\n *        This flag allows sequence producer plugin authors to replace the built-in\n *        default sequence producer with their own code. If you are not a plugin\n *        author, you should not define this flag. See the docs at\n *        fuzz_third_party_seq_prod.h for more information.\n */\n\n#ifndef FUZZ_H\n#define FUZZ_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nint LLVMFuzzerTestOneInput(const uint8_t *src, size_t size);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "tests/fuzz/fuzz.py",
    "content": "#!/usr/bin/env python\n\n# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ##########################################################################\n\nimport argparse\nimport contextlib\nimport os\nimport re\nimport shlex\nimport shutil\nimport subprocess\nimport sys\nimport tempfile\n\n\ndef abs_join(a, *p):\n    return os.path.abspath(os.path.join(a, *p))\n\n\nclass InputType(object):\n    RAW_DATA = 1\n    COMPRESSED_DATA = 2\n    DICTIONARY_DATA = 3\n\n\nclass FrameType(object):\n    ZSTD = 1\n    BLOCK = 2\n\n\nclass TargetInfo(object):\n    def __init__(self, input_type, frame_type=FrameType.ZSTD):\n        self.input_type = input_type\n        self.frame_type = frame_type\n\n\n# Constants\nFUZZ_DIR = os.path.abspath(os.path.dirname(__file__))\nCORPORA_DIR = abs_join(FUZZ_DIR, 'corpora')\nTARGET_INFO = {\n    'simple_round_trip': TargetInfo(InputType.RAW_DATA),\n    'stream_round_trip': TargetInfo(InputType.RAW_DATA),\n    'block_round_trip': TargetInfo(InputType.RAW_DATA, FrameType.BLOCK),\n    'simple_decompress': TargetInfo(InputType.COMPRESSED_DATA),\n    'stream_decompress': TargetInfo(InputType.COMPRESSED_DATA),\n    'block_decompress': TargetInfo(InputType.COMPRESSED_DATA, FrameType.BLOCK),\n    'dictionary_round_trip': TargetInfo(InputType.RAW_DATA),\n    'dictionary_decompress': TargetInfo(InputType.COMPRESSED_DATA),\n    'zstd_frame_info': TargetInfo(InputType.COMPRESSED_DATA),\n    'simple_compress': TargetInfo(InputType.RAW_DATA),\n    'dictionary_loader': TargetInfo(InputType.DICTIONARY_DATA),\n    'raw_dictionary_round_trip': TargetInfo(InputType.RAW_DATA),\n    'dictionary_stream_round_trip': TargetInfo(InputType.RAW_DATA),\n    'decompress_dstSize_tooSmall': TargetInfo(InputType.RAW_DATA),\n    'fse_read_ncount': TargetInfo(InputType.RAW_DATA),\n    'sequence_compression_api': TargetInfo(InputType.RAW_DATA),\n    'seekable_roundtrip': TargetInfo(InputType.RAW_DATA),\n    'huf_round_trip': TargetInfo(InputType.RAW_DATA),\n    'huf_decompress': TargetInfo(InputType.RAW_DATA),\n    'decompress_cross_format': TargetInfo(InputType.RAW_DATA),\n    'generate_sequences': TargetInfo(InputType.RAW_DATA),\n}\nTARGETS = list(TARGET_INFO.keys())\nALL_TARGETS = TARGETS + ['all']\nFUZZ_RNG_SEED_SIZE = 4\n\n# Standard environment variables\nCC = os.environ.get('CC', 'cc')\nCXX = os.environ.get('CXX', 'c++')\nCPPFLAGS = os.environ.get('CPPFLAGS', '')\nCFLAGS = os.environ.get('CFLAGS', '-O3')\nCXXFLAGS = os.environ.get('CXXFLAGS', CFLAGS)\nLDFLAGS = os.environ.get('LDFLAGS', '')\nMFLAGS = os.environ.get('MFLAGS', '-j')\nTHIRD_PARTY_SEQ_PROD_OBJ = os.environ.get('THIRD_PARTY_SEQ_PROD_OBJ', '')\n\n# Fuzzing environment variables\nLIB_FUZZING_ENGINE = os.environ.get('LIB_FUZZING_ENGINE', 'libregression.a')\nAFL_FUZZ = os.environ.get('AFL_FUZZ', 'afl-fuzz')\nDECODECORPUS = os.environ.get('DECODECORPUS',\n                              abs_join(FUZZ_DIR, '..', 'decodecorpus'))\nZSTD = os.environ.get('ZSTD', abs_join(FUZZ_DIR, '..', '..', 'zstd'))\n\n# Sanitizer environment variables\nMSAN_EXTRA_CPPFLAGS = os.environ.get('MSAN_EXTRA_CPPFLAGS', '')\nMSAN_EXTRA_CFLAGS = os.environ.get('MSAN_EXTRA_CFLAGS', '')\nMSAN_EXTRA_CXXFLAGS = os.environ.get('MSAN_EXTRA_CXXFLAGS', '')\nMSAN_EXTRA_LDFLAGS = os.environ.get('MSAN_EXTRA_LDFLAGS', '')\n\n\ndef create(r):\n    d = os.path.abspath(r)\n    if not os.path.isdir(d):\n        os.makedirs(d)\n    return d\n\n\ndef check(r):\n    d = os.path.abspath(r)\n    if not os.path.isdir(d):\n        return None\n    return d\n\n\n@contextlib.contextmanager\ndef tmpdir():\n    dirpath = tempfile.mkdtemp()\n    try:\n        yield dirpath\n    finally:\n        shutil.rmtree(dirpath, ignore_errors=True)\n\n\ndef parse_targets(in_targets):\n    targets = set()\n    for target in in_targets:\n        if not target:\n            continue\n        if target == 'all':\n            targets = targets.union(TARGETS)\n        elif target in TARGETS:\n            targets.add(target)\n        else:\n            raise RuntimeError('{} is not a valid target'.format(target))\n    return list(targets)\n\n\ndef targets_parser(args, description):\n    parser = argparse.ArgumentParser(prog=args.pop(0), description=description)\n    parser.add_argument(\n        'TARGET',\n        nargs='*',\n        type=str,\n        help='Fuzz target(s) to build {{{}}}'.format(', '.join(ALL_TARGETS)))\n    args, extra = parser.parse_known_args(args)\n    args.extra = extra\n\n    args.TARGET = parse_targets(args.TARGET)\n\n    return args\n\n\ndef parse_env_flags(args, flags):\n    \"\"\"\n    Look for flags set by environment variables.\n    \"\"\"\n    san_flags = ','.join(re.findall('-fsanitize=((?:[a-z]+,?)+)', flags))\n    nosan_flags = ','.join(re.findall('-fno-sanitize=((?:[a-z]+,?)+)', flags))\n\n    def set_sanitizer(sanitizer, default, san, nosan):\n        if sanitizer in san and sanitizer in nosan:\n            raise RuntimeError('-fno-sanitize={s} and -fsanitize={s} passed'.\n                               format(s=sanitizer))\n        if sanitizer in san:\n            return True\n        if sanitizer in nosan:\n            return False\n        return default\n\n    san = set(san_flags.split(','))\n    nosan = set(nosan_flags.split(','))\n\n    args.asan = set_sanitizer('address', args.asan, san, nosan)\n    args.msan = set_sanitizer('memory', args.msan, san, nosan)\n    args.ubsan = set_sanitizer('undefined', args.ubsan, san, nosan)\n\n    args.sanitize = args.asan or args.msan or args.ubsan\n\n    return args\n\n\ndef compiler_version(cc, cxx):\n    \"\"\"\n    Determines the compiler and version.\n    Only works for clang and gcc.\n    \"\"\"\n    cc_version_bytes = subprocess.check_output([cc, \"--version\"])\n    cxx_version_bytes = subprocess.check_output([cxx, \"--version\"])\n    compiler = None\n    version = None\n    print(\"{} --version:\\n{}\".format(cc, cc_version_bytes.decode('ascii')))\n    if b'clang' in cc_version_bytes:\n        assert(b'clang' in cxx_version_bytes)\n        compiler = 'clang'\n    elif b'gcc' in cc_version_bytes or b'GCC' in cc_version_bytes:\n        assert(b'gcc' in cxx_version_bytes or b'g++' in cxx_version_bytes)\n        compiler = 'gcc'\n    if compiler is not None:\n        version_regex = b'([0-9]+)\\.([0-9]+)\\.([0-9]+)'\n        version_match = re.search(version_regex, cc_version_bytes)\n        version = tuple(int(version_match.group(i)) for i in range(1, 4))\n    return compiler, version\n\n\ndef overflow_ubsan_flags(cc, cxx):\n    compiler, version = compiler_version(cc, cxx)\n    if compiler == 'gcc' and version < (8, 0, 0):\n        return ['-fno-sanitize=signed-integer-overflow']\n    if compiler == 'gcc' or (compiler == 'clang' and version >= (5, 0, 0)):\n        return ['-fno-sanitize=pointer-overflow']\n    return []\n\n\ndef build_parser(args):\n    description = \"\"\"\n    Cleans the repository and builds a fuzz target (or all).\n    Many flags default to environment variables (default says $X='y').\n    Options that aren't enabling features default to the correct values for\n    zstd.\n    Enable sanitizers with --enable-*san.\n    For regression testing just build.\n    For libFuzzer set LIB_FUZZING_ENGINE and pass --enable-coverage.\n    For AFL set CC and CXX to AFL's compilers and set\n    LIB_FUZZING_ENGINE='libregression.a'.\n    \"\"\"\n    parser = argparse.ArgumentParser(prog=args.pop(0), description=description)\n    parser.add_argument(\n        '--lib-fuzzing-engine',\n        dest='lib_fuzzing_engine',\n        type=str,\n        default=LIB_FUZZING_ENGINE,\n        help=('The fuzzing engine to use e.g. /path/to/libFuzzer.a '\n              \"(default: $LIB_FUZZING_ENGINE='{})\".format(LIB_FUZZING_ENGINE)))\n\n    fuzz_group = parser.add_mutually_exclusive_group()\n    fuzz_group.add_argument(\n        '--enable-coverage',\n        dest='coverage',\n        action='store_true',\n        help='Enable coverage instrumentation (-fsanitize-coverage)')\n    fuzz_group.add_argument(\n        '--enable-fuzzer',\n        dest='fuzzer',\n        action='store_true',\n        help=('Enable clang fuzzer (-fsanitize=fuzzer). When enabled '\n              'LIB_FUZZING_ENGINE is ignored')\n    )\n\n    parser.add_argument(\n        '--enable-asan', dest='asan', action='store_true', help='Enable UBSAN')\n    parser.add_argument(\n        '--enable-ubsan',\n        dest='ubsan',\n        action='store_true',\n        help='Enable UBSAN')\n    parser.add_argument(\n        '--disable-ubsan-pointer-overflow',\n        dest='ubsan_pointer_overflow',\n        action='store_false',\n        help='Disable UBSAN pointer overflow check (known failure)')\n    parser.add_argument(\n        '--enable-msan', dest='msan', action='store_true', help='Enable MSAN')\n    parser.add_argument(\n        '--enable-msan-track-origins', dest='msan_track_origins',\n        action='store_true', help='Enable MSAN origin tracking')\n    parser.add_argument(\n        '--msan-extra-cppflags',\n        dest='msan_extra_cppflags',\n        type=str,\n        default=MSAN_EXTRA_CPPFLAGS,\n        help=\"Extra CPPFLAGS for MSAN (default: $MSAN_EXTRA_CPPFLAGS='{}')\".\n        format(MSAN_EXTRA_CPPFLAGS))\n    parser.add_argument(\n        '--msan-extra-cflags',\n        dest='msan_extra_cflags',\n        type=str,\n        default=MSAN_EXTRA_CFLAGS,\n        help=\"Extra CFLAGS for MSAN (default: $MSAN_EXTRA_CFLAGS='{}')\".format(\n            MSAN_EXTRA_CFLAGS))\n    parser.add_argument(\n        '--msan-extra-cxxflags',\n        dest='msan_extra_cxxflags',\n        type=str,\n        default=MSAN_EXTRA_CXXFLAGS,\n        help=\"Extra CXXFLAGS for MSAN (default: $MSAN_EXTRA_CXXFLAGS='{}')\".\n        format(MSAN_EXTRA_CXXFLAGS))\n    parser.add_argument(\n        '--msan-extra-ldflags',\n        dest='msan_extra_ldflags',\n        type=str,\n        default=MSAN_EXTRA_LDFLAGS,\n        help=\"Extra LDFLAGS for MSAN (default: $MSAN_EXTRA_LDFLAGS='{}')\".\n        format(MSAN_EXTRA_LDFLAGS))\n    parser.add_argument(\n        '--enable-sanitize-recover',\n        dest='sanitize_recover',\n        action='store_true',\n        help='Non-fatal sanitizer errors where possible')\n    parser.add_argument(\n        '--debug',\n        dest='debug',\n        type=int,\n        default=1,\n        help='Set DEBUGLEVEL (default: 1)')\n    parser.add_argument(\n        '--force-memory-access',\n        dest='memory_access',\n        type=int,\n        default=0,\n        help='Set MEM_FORCE_MEMORY_ACCESS (default: 0)')\n    parser.add_argument(\n        '--fuzz-rng-seed-size',\n        dest='fuzz_rng_seed_size',\n        type=int,\n        default=4,\n        help='Set FUZZ_RNG_SEED_SIZE (default: 4)')\n    parser.add_argument(\n        '--disable-fuzzing-mode',\n        dest='fuzzing_mode',\n        action='store_false',\n        help='Do not define FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION')\n    parser.add_argument(\n        '--enable-stateful-fuzzing',\n        dest='stateful_fuzzing',\n        action='store_true',\n        help='Reuse contexts between runs (makes reproduction impossible)')\n    parser.add_argument(\n        '--custom-seq-prod',\n        dest='third_party_seq_prod_obj',\n        type=str,\n        default=THIRD_PARTY_SEQ_PROD_OBJ,\n        help='Path to an object file with symbols for fuzzing your sequence producer plugin.')\n    parser.add_argument(\n        '--cc',\n        dest='cc',\n        type=str,\n        default=CC,\n        help=\"CC (default: $CC='{}')\".format(CC))\n    parser.add_argument(\n        '--cxx',\n        dest='cxx',\n        type=str,\n        default=CXX,\n        help=\"CXX (default: $CXX='{}')\".format(CXX))\n    parser.add_argument(\n        '--cppflags',\n        dest='cppflags',\n        type=str,\n        default=CPPFLAGS,\n        help=\"CPPFLAGS (default: $CPPFLAGS='{}')\".format(CPPFLAGS))\n    parser.add_argument(\n        '--cflags',\n        dest='cflags',\n        type=str,\n        default=CFLAGS,\n        help=\"CFLAGS (default: $CFLAGS='{}')\".format(CFLAGS))\n    parser.add_argument(\n        '--cxxflags',\n        dest='cxxflags',\n        type=str,\n        default=CXXFLAGS,\n        help=\"CXXFLAGS (default: $CXXFLAGS='{}')\".format(CXXFLAGS))\n    parser.add_argument(\n        '--ldflags',\n        dest='ldflags',\n        type=str,\n        default=LDFLAGS,\n        help=\"LDFLAGS (default: $LDFLAGS='{}')\".format(LDFLAGS))\n    parser.add_argument(\n        '--mflags',\n        dest='mflags',\n        type=str,\n        default=MFLAGS,\n        help=\"Extra Make flags (default: $MFLAGS='{}')\".format(MFLAGS))\n    parser.add_argument(\n        'TARGET',\n        nargs='*',\n        type=str,\n        help='Fuzz target(s) to build {{{}}}'.format(', '.join(ALL_TARGETS))\n    )\n    args = parser.parse_args(args)\n    args = parse_env_flags(args, ' '.join(\n        [args.cppflags, args.cflags, args.cxxflags, args.ldflags]))\n\n    # Check option sanity\n    if args.msan and (args.asan or args.ubsan):\n        raise RuntimeError('MSAN may not be used with any other sanitizers')\n    if args.msan_track_origins and not args.msan:\n        raise RuntimeError('--enable-msan-track-origins requires MSAN')\n    if args.sanitize_recover and not args.sanitize:\n        raise RuntimeError('--enable-sanitize-recover but no sanitizers used')\n\n    return args\n\n\ndef build(args):\n    try:\n        args = build_parser(args)\n    except Exception as e:\n        print(e)\n        return 1\n    # The compilation flags we are setting\n    targets = args.TARGET\n    cc = args.cc\n    cxx = args.cxx\n    cppflags = shlex.split(args.cppflags)\n    cflags = shlex.split(args.cflags)\n    ldflags = shlex.split(args.ldflags)\n    cxxflags = shlex.split(args.cxxflags)\n    mflags = shlex.split(args.mflags)\n    # Flags to be added to both cflags and cxxflags\n    common_flags = [\n        '-Wno-error=declaration-after-statement',\n        '-Wno-error=c++-compat',\n        '-Wno-error=deprecated' # C files are sometimes compiled with CXX\n    ]\n\n    cppflags += [\n        '-DDEBUGLEVEL={}'.format(args.debug),\n        '-DMEM_FORCE_MEMORY_ACCESS={}'.format(args.memory_access),\n        '-DFUZZ_RNG_SEED_SIZE={}'.format(args.fuzz_rng_seed_size),\n    ]\n\n    # Set flags for options\n    assert not (args.fuzzer and args.coverage)\n    if args.coverage:\n        common_flags += [\n            '-fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp'\n        ]\n    if args.fuzzer:\n        common_flags += ['-fsanitize=fuzzer']\n        args.lib_fuzzing_engine = ''\n\n    mflags += ['LIB_FUZZING_ENGINE={}'.format(args.lib_fuzzing_engine)]\n\n    if args.sanitize_recover:\n        recover_flags = ['-fsanitize-recover=all']\n    else:\n        recover_flags = ['-fno-sanitize-recover=all']\n    if args.sanitize:\n        common_flags += recover_flags\n\n    if args.msan:\n        msan_flags = ['-fsanitize=memory']\n        if args.msan_track_origins:\n            msan_flags += ['-fsanitize-memory-track-origins']\n        common_flags += msan_flags\n        # Append extra MSAN flags (it might require special setup)\n        cppflags += [args.msan_extra_cppflags]\n        cflags += [args.msan_extra_cflags]\n        cxxflags += [args.msan_extra_cxxflags]\n        ldflags += [args.msan_extra_ldflags]\n\n    if args.asan:\n        common_flags += ['-fsanitize=address']\n\n    if args.ubsan:\n        ubsan_flags = ['-fsanitize=undefined']\n        if not args.ubsan_pointer_overflow:\n            ubsan_flags += overflow_ubsan_flags(cc, cxx)\n        common_flags += ubsan_flags\n\n    if args.stateful_fuzzing:\n        cppflags += ['-DSTATEFUL_FUZZING']\n\n    if args.third_party_seq_prod_obj:\n        cppflags += ['-DFUZZ_THIRD_PARTY_SEQ_PROD']\n        mflags += ['THIRD_PARTY_SEQ_PROD_OBJ={}'.format(args.third_party_seq_prod_obj)]\n\n    if args.fuzzing_mode:\n        cppflags += ['-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION']\n\n    if args.lib_fuzzing_engine == 'libregression.a':\n        targets = ['libregression.a'] + targets\n\n    # Append the common flags\n    cflags += common_flags\n    cxxflags += common_flags\n\n    # Prepare the flags for Make\n    cc_str = \"CC={}\".format(cc)\n    cxx_str = \"CXX={}\".format(cxx)\n    cppflags_str = \"CPPFLAGS={}\".format(' '.join(cppflags))\n    cflags_str = \"CFLAGS={}\".format(' '.join(cflags))\n    cxxflags_str = \"CXXFLAGS={}\".format(' '.join(cxxflags))\n    ldflags_str = \"LDFLAGS={}\".format(' '.join(ldflags))\n\n    # Print the flags\n    print('MFLAGS={}'.format(' '.join(mflags)))\n    print(cc_str)\n    print(cxx_str)\n    print(cppflags_str)\n    print(cflags_str)\n    print(cxxflags_str)\n    print(ldflags_str)\n\n    # Clean and build\n    clean_cmd = ['make', 'clean'] + mflags\n    print(' '.join(clean_cmd))\n    subprocess.check_call(clean_cmd)\n    build_cmd = [\n        'make',\n        '-j',\n        cc_str,\n        cxx_str,\n        cppflags_str,\n        cflags_str,\n        cxxflags_str,\n        ldflags_str,\n    ] + mflags + targets\n    print(' '.join(build_cmd))\n    subprocess.check_call(build_cmd)\n    return 0\n\n\ndef libfuzzer_parser(args):\n    description = \"\"\"\n    Runs a libfuzzer binary.\n    Passes all extra arguments to libfuzzer.\n    The fuzzer should have been build with LIB_FUZZING_ENGINE pointing to\n    libFuzzer.a.\n    Generates output in the CORPORA directory, puts crashes in the ARTIFACT\n    directory, and takes extra input from the SEED directory.\n    To merge AFL's output pass the SEED as AFL's output directory and pass\n    '-merge=1'.\n    \"\"\"\n    parser = argparse.ArgumentParser(prog=args.pop(0), description=description)\n    parser.add_argument(\n        '--corpora',\n        type=str,\n        help='Override the default corpora dir (default: {})'.format(\n            abs_join(CORPORA_DIR, 'TARGET')))\n    parser.add_argument(\n        '--artifact',\n        type=str,\n        help='Override the default artifact dir (default: {})'.format(\n            abs_join(CORPORA_DIR, 'TARGET-crash')))\n    parser.add_argument(\n        '--seed',\n        type=str,\n        help='Override the default seed dir (default: {})'.format(\n            abs_join(CORPORA_DIR, 'TARGET-seed')))\n    parser.add_argument(\n        'TARGET',\n        type=str,\n        help='Fuzz target(s) to build {{{}}}'.format(', '.join(TARGETS)))\n    args, extra = parser.parse_known_args(args)\n    args.extra = extra\n\n    if args.TARGET and args.TARGET not in TARGETS:\n        raise RuntimeError('{} is not a valid target'.format(args.TARGET))\n\n    return args\n\n\ndef libfuzzer(target, corpora=None, artifact=None, seed=None, extra_args=None):\n    if corpora is None:\n        corpora = abs_join(CORPORA_DIR, target)\n    if artifact is None:\n        artifact = abs_join(CORPORA_DIR, '{}-crash'.format(target))\n    if seed is None:\n        seed = abs_join(CORPORA_DIR, '{}-seed'.format(target))\n    if extra_args is None:\n        extra_args = []\n\n    target = abs_join(FUZZ_DIR, target)\n\n    corpora = [create(corpora)]\n    artifact = create(artifact)\n    seed = check(seed)\n\n    corpora += [artifact]\n    if seed is not None:\n        corpora += [seed]\n\n    cmd = [target, '-artifact_prefix={}/'.format(artifact)]\n    cmd += corpora + extra_args\n    print(' '.join(cmd))\n    subprocess.check_call(cmd)\n\n\ndef libfuzzer_cmd(args):\n    try:\n        args = libfuzzer_parser(args)\n    except Exception as e:\n        print(e)\n        return 1\n    libfuzzer(args.TARGET, args.corpora, args.artifact, args.seed, args.extra)\n    return 0\n\n\ndef afl_parser(args):\n    description = \"\"\"\n    Runs an afl-fuzz job.\n    Passes all extra arguments to afl-fuzz.\n    The fuzzer should have been built with CC/CXX set to the AFL compilers,\n    and with LIB_FUZZING_ENGINE='libregression.a'.\n    Takes input from CORPORA and writes output to OUTPUT.\n    Uses AFL_FUZZ as the binary (set from flag or environment variable).\n    \"\"\"\n    parser = argparse.ArgumentParser(prog=args.pop(0), description=description)\n    parser.add_argument(\n        '--corpora',\n        type=str,\n        help='Override the default corpora dir (default: {})'.format(\n            abs_join(CORPORA_DIR, 'TARGET')))\n    parser.add_argument(\n        '--output',\n        type=str,\n        help='Override the default AFL output dir (default: {})'.format(\n            abs_join(CORPORA_DIR, 'TARGET-afl')))\n    parser.add_argument(\n        '--afl-fuzz',\n        type=str,\n        default=AFL_FUZZ,\n        help='AFL_FUZZ (default: $AFL_FUZZ={})'.format(AFL_FUZZ))\n    parser.add_argument(\n        'TARGET',\n        type=str,\n        help='Fuzz target(s) to build {{{}}}'.format(', '.join(TARGETS)))\n    args, extra = parser.parse_known_args(args)\n    args.extra = extra\n\n    if args.TARGET and args.TARGET not in TARGETS:\n        raise RuntimeError('{} is not a valid target'.format(args.TARGET))\n\n    if not args.corpora:\n        args.corpora = abs_join(CORPORA_DIR, args.TARGET)\n    if not args.output:\n        args.output = abs_join(CORPORA_DIR, '{}-afl'.format(args.TARGET))\n\n    return args\n\n\ndef afl(args):\n    try:\n        args = afl_parser(args)\n    except Exception as e:\n        print(e)\n        return 1\n    target = abs_join(FUZZ_DIR, args.TARGET)\n\n    corpora = create(args.corpora)\n    output = create(args.output)\n\n    cmd = [args.afl_fuzz, '-i', corpora, '-o', output] + args.extra\n    cmd += [target, '@@']\n    print(' '.join(cmd))\n    subprocess.call(cmd)\n    return 0\n\n\ndef regression(args):\n    try:\n        description = \"\"\"\n        Runs one or more regression tests.\n        The fuzzer should have been built with\n        LIB_FUZZING_ENGINE='libregression.a'.\n        Takes input from CORPORA.\n        \"\"\"\n        args = targets_parser(args, description)\n    except Exception as e:\n        print(e)\n        return 1\n    for target in args.TARGET:\n        corpora = create(abs_join(CORPORA_DIR, target))\n        target = abs_join(FUZZ_DIR, target)\n        cmd = [target, corpora]\n        print(' '.join(cmd))\n        subprocess.check_call(cmd)\n    return 0\n\n\ndef gen_parser(args):\n    description = \"\"\"\n    Generate a seed corpus appropriate for TARGET with data generated with\n    decodecorpus.\n    The fuzz inputs are prepended with a seed before the zstd data, so the\n    output of decodecorpus shouldn't be used directly.\n    Generates NUMBER samples prepended with FUZZ_RNG_SEED_SIZE random bytes and\n    puts the output in SEED.\n    DECODECORPUS is the decodecorpus binary, and must already be built.\n    \"\"\"\n    parser = argparse.ArgumentParser(prog=args.pop(0), description=description)\n    parser.add_argument(\n        '--number',\n        '-n',\n        type=int,\n        default=100,\n        help='Number of samples to generate')\n    parser.add_argument(\n        '--max-size-log',\n        type=int,\n        default=18,\n        help='Maximum sample size to generate')\n    parser.add_argument(\n        '--seed',\n        type=str,\n        help='Override the default seed dir (default: {})'.format(\n            abs_join(CORPORA_DIR, 'TARGET-seed')))\n    parser.add_argument(\n        '--decodecorpus',\n        type=str,\n        default=DECODECORPUS,\n        help=\"decodecorpus binary (default: $DECODECORPUS='{}')\".format(\n            DECODECORPUS))\n    parser.add_argument(\n        '--zstd',\n        type=str,\n        default=ZSTD,\n        help=\"zstd binary (default: $ZSTD='{}')\".format(ZSTD))\n    parser.add_argument(\n        '--fuzz-rng-seed-size',\n        type=int,\n        default=4,\n        help=\"FUZZ_RNG_SEED_SIZE used for generate the samples (must match)\"\n    )\n    parser.add_argument(\n        'TARGET',\n        type=str,\n        help='Fuzz target(s) to build {{{}}}'.format(', '.join(TARGETS)))\n    args, extra = parser.parse_known_args(args)\n    args.extra = extra\n\n    if args.TARGET and args.TARGET not in TARGETS:\n        raise RuntimeError('{} is not a valid target'.format(args.TARGET))\n\n    if not args.seed:\n        args.seed = abs_join(CORPORA_DIR, '{}-seed'.format(args.TARGET))\n\n    if not os.path.isfile(args.decodecorpus):\n        raise RuntimeError(\"{} is not a file run 'make -C {} decodecorpus'\".\n                           format(args.decodecorpus, abs_join(FUZZ_DIR, '..')))\n\n    return args\n\n\ndef gen(args):\n    try:\n        args = gen_parser(args)\n    except Exception as e:\n        print(e)\n        return 1\n\n    seed = create(args.seed)\n    with tmpdir() as compressed, tmpdir() as decompressed, tmpdir() as dict:\n        info = TARGET_INFO[args.TARGET]\n\n        if info.input_type == InputType.DICTIONARY_DATA:\n            number = max(args.number, 1000)\n        else:\n            number = args.number\n        cmd = [\n            args.decodecorpus,\n            '-n{}'.format(args.number),\n            '-p{}/'.format(compressed),\n            '-o{}'.format(decompressed),\n        ]\n\n        if info.frame_type == FrameType.BLOCK:\n            cmd += [\n                '--gen-blocks',\n                '--max-block-size-log={}'.format(min(args.max_size_log, 17))\n            ]\n        else:\n            cmd += ['--max-content-size-log={}'.format(args.max_size_log)]\n\n        print(' '.join(cmd))\n        subprocess.check_call(cmd)\n\n        if info.input_type == InputType.RAW_DATA:\n            print('using decompressed data in {}'.format(decompressed))\n            samples = decompressed\n        elif info.input_type == InputType.COMPRESSED_DATA:\n            print('using compressed data in {}'.format(compressed))\n            samples = compressed\n        else:\n            assert info.input_type == InputType.DICTIONARY_DATA\n            print('making dictionary data from {}'.format(decompressed))\n            samples = dict\n            min_dict_size_log = 9\n            max_dict_size_log = max(min_dict_size_log + 1, args.max_size_log)\n            for dict_size_log in range(min_dict_size_log, max_dict_size_log):\n                dict_size = 1 << dict_size_log\n                cmd = [\n                    args.zstd,\n                    '--train',\n                    '-r', decompressed,\n                    '--maxdict={}'.format(dict_size),\n                    '-o', abs_join(dict, '{}.zstd-dict'.format(dict_size))\n                ]\n                print(' '.join(cmd))\n                subprocess.check_call(cmd)\n\n        # Copy the samples over and prepend the RNG seeds\n        for name in os.listdir(samples):\n            samplename = abs_join(samples, name)\n            outname = abs_join(seed, name)\n            with open(samplename, 'rb') as sample:\n                with open(outname, 'wb') as out:\n                    CHUNK_SIZE = 131072\n                    chunk = sample.read(CHUNK_SIZE)\n                    while len(chunk) > 0:\n                        out.write(chunk)\n                        chunk = sample.read(CHUNK_SIZE)\n    return 0\n\n\ndef minimize(args):\n    try:\n        description = \"\"\"\n        Runs a libfuzzer fuzzer with -merge=1 to build a minimal corpus in\n        TARGET_seed_corpus. All extra args are passed to libfuzzer.\n        \"\"\"\n        args = targets_parser(args, description)\n    except Exception as e:\n        print(e)\n        return 1\n\n    for target in args.TARGET:\n        # Merge the corpus + anything else into the seed_corpus\n        corpus = abs_join(CORPORA_DIR, target)\n        seed_corpus = abs_join(CORPORA_DIR, \"{}_seed_corpus\".format(target))\n        extra_args = [corpus, \"-merge=1\"] + args.extra\n        libfuzzer(target, corpora=seed_corpus, extra_args=extra_args)\n        seeds = set(os.listdir(seed_corpus))\n        # Copy all crashes directly into the seed_corpus if not already present\n        crashes = abs_join(CORPORA_DIR, '{}-crash'.format(target))\n        for crash in os.listdir(crashes):\n            if crash not in seeds:\n                shutil.copy(abs_join(crashes, crash), seed_corpus)\n                seeds.add(crash)\n\n\ndef zip_cmd(args):\n    try:\n        description = \"\"\"\n        Zips up the seed corpus.\n        \"\"\"\n        args = targets_parser(args, description)\n    except Exception as e:\n        print(e)\n        return 1\n\n    for target in args.TARGET:\n        # Zip the seed_corpus\n        seed_corpus = abs_join(CORPORA_DIR, \"{}_seed_corpus\".format(target))\n        zip_file = \"{}.zip\".format(seed_corpus)\n        cmd = [\"zip\", \"-r\", \"-q\", \"-j\", \"-9\", zip_file, \".\"]\n        print(' '.join(cmd))\n        subprocess.check_call(cmd, cwd=seed_corpus)\n\n\ndef list_cmd(args):\n    print(\"\\n\".join(TARGETS))\n\n\ndef short_help(args):\n    name = args[0]\n    print(\"Usage: {} [OPTIONS] COMMAND [ARGS]...\\n\".format(name))\n\n\ndef help(args):\n    short_help(args)\n    print(\"\\tfuzzing helpers (select a command and pass -h for help)\\n\")\n    print(\"Options:\")\n    print(\"\\t-h, --help\\tPrint this message\")\n    print(\"\")\n    print(\"Commands:\")\n    print(\"\\tbuild\\t\\tBuild a fuzzer\")\n    print(\"\\tlibfuzzer\\tRun a libFuzzer fuzzer\")\n    print(\"\\tafl\\t\\tRun an AFL fuzzer\")\n    print(\"\\tregression\\tRun a regression test\")\n    print(\"\\tgen\\t\\tGenerate a seed corpus for a fuzzer\")\n    print(\"\\tminimize\\tMinimize the test corpora\")\n    print(\"\\tzip\\t\\tZip the minimized corpora up\")\n    print(\"\\tlist\\t\\tList the available targets\")\n\n\ndef main():\n    args = sys.argv\n    if len(args) < 2:\n        help(args)\n        return 1\n    if args[1] == '-h' or args[1] == '--help' or args[1] == '-H':\n        help(args)\n        return 1\n    command = args.pop(1)\n    args[0] = \"{} {}\".format(args[0], command)\n    if command == \"build\":\n        return build(args)\n    if command == \"libfuzzer\":\n        return libfuzzer_cmd(args)\n    if command == \"regression\":\n        return regression(args)\n    if command == \"afl\":\n        return afl(args)\n    if command == \"gen\":\n        return gen(args)\n    if command == \"minimize\":\n        return minimize(args)\n    if command == \"zip\":\n        return zip_cmd(args)\n    if command == \"list\":\n        return list_cmd(args)\n    short_help(args)\n    print(\"Error: No such command {} (pass -h for help)\".format(command))\n    return 1\n\n\nif __name__ == \"__main__\":\n    sys.exit(main())\n"
  },
  {
    "path": "tests/fuzz/fuzz_data_producer.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"fuzz_helpers.h\"\n#include \"fuzz_data_producer.h\"\n\nstruct FUZZ_dataProducer_s{\n  const uint8_t *data;\n  size_t size;\n};\n\nFUZZ_dataProducer_t *FUZZ_dataProducer_create(const uint8_t *data, size_t size) {\n    FUZZ_dataProducer_t *producer = FUZZ_malloc(sizeof(FUZZ_dataProducer_t));\n\n    producer->data = data;\n    producer->size = size;\n    return producer;\n}\n\nvoid FUZZ_dataProducer_free(FUZZ_dataProducer_t *producer) { free(producer); }\n\nuint32_t FUZZ_dataProducer_uint32Range(FUZZ_dataProducer_t *producer, uint32_t min,\n                                  uint32_t max) {\n    uint32_t range = max - min;\n    uint32_t rolling = range;\n    uint32_t result = 0;\n\n    FUZZ_ASSERT(min <= max);\n\n    while (rolling > 0 && producer->size > 0) {\n      uint8_t next = *(producer->data + producer->size - 1);\n      producer->size -= 1;\n      result = (result << 8) | next;\n      rolling >>= 8;\n    }\n\n    if (range == 0xffffffff) {\n      return result;\n    }\n\n    return min + result % (range + 1);\n}\n\nuint32_t FUZZ_dataProducer_uint32(FUZZ_dataProducer_t *producer) {\n    return FUZZ_dataProducer_uint32Range(producer, 0, 0xffffffff);\n}\n\nint32_t FUZZ_dataProducer_int32Range(FUZZ_dataProducer_t *producer,\n                                    int32_t min, int32_t max)\n{\n    FUZZ_ASSERT(min <= max);\n\n    if (min < 0)\n      return (int)FUZZ_dataProducer_uint32Range(producer, 0, max - min) + min;\n\n    return FUZZ_dataProducer_uint32Range(producer, min, max);\n}\n\nsize_t FUZZ_dataProducer_remainingBytes(FUZZ_dataProducer_t *producer){\n    return producer->size;\n}\n\nvoid FUZZ_dataProducer_rollBack(FUZZ_dataProducer_t *producer, size_t remainingBytes)\n{\n    FUZZ_ASSERT(remainingBytes >= producer->size);\n    producer->size = remainingBytes;\n}\n\nint FUZZ_dataProducer_empty(FUZZ_dataProducer_t *producer) {\n    return producer->size == 0;\n}\n\nsize_t FUZZ_dataProducer_contract(FUZZ_dataProducer_t *producer, size_t newSize)\n{\n    const size_t effectiveNewSize = newSize > producer->size ? producer->size : newSize;\n\n    size_t remaining = producer->size - effectiveNewSize;\n    producer->data = producer->data + remaining;\n    producer->size = effectiveNewSize;\n    return remaining;\n}\n\nsize_t FUZZ_dataProducer_reserveDataPrefix(FUZZ_dataProducer_t *producer)\n{\n    size_t producerSliceSize = FUZZ_dataProducer_uint32Range(\n                                  producer, 0, producer->size);\n    return FUZZ_dataProducer_contract(producer, producerSliceSize);\n}\n"
  },
  {
    "path": "tests/fuzz/fuzz_data_producer.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/**\n * Helper APIs for generating random data from input data stream.\n The producer reads bytes from the end of the input and appends them together\n to generate  a random number in the requested range. If it runs out of input\n data, it will keep returning the same value (min) over and over again.\n\n */\n\n#ifndef FUZZ_DATA_PRODUCER_H\n#define FUZZ_DATA_PRODUCER_H\n\n#include <stddef.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n\n\n/* Struct used for maintaining the state of the data */\ntypedef struct FUZZ_dataProducer_s FUZZ_dataProducer_t;\n\n/* Returns a data producer state struct. Use for producer initialization. */\nFUZZ_dataProducer_t *FUZZ_dataProducer_create(const uint8_t *data, size_t size);\n\n/* Frees the data producer */\nvoid FUZZ_dataProducer_free(FUZZ_dataProducer_t *producer);\n\n/* Returns value between [min, max] */\nuint32_t FUZZ_dataProducer_uint32Range(FUZZ_dataProducer_t *producer, uint32_t min,\n                                  uint32_t max);\n\n/* Returns a uint32 value */\nuint32_t FUZZ_dataProducer_uint32(FUZZ_dataProducer_t *producer);\n\n/* Returns a signed value between [min, max] */\nint32_t FUZZ_dataProducer_int32Range(FUZZ_dataProducer_t *producer,\n                                    int32_t min, int32_t max);\n\n/* Returns the size of the remaining bytes of data in the producer */\nsize_t FUZZ_dataProducer_remainingBytes(FUZZ_dataProducer_t *producer);\n\n/* Rolls back the data producer state to have remainingBytes remaining */\nvoid FUZZ_dataProducer_rollBack(FUZZ_dataProducer_t *producer, size_t remainingBytes);\n\n/* Returns true if the data producer is out of bytes */\nint FUZZ_dataProducer_empty(FUZZ_dataProducer_t *producer);\n\n/* Restricts the producer to only the last newSize bytes of data.\nIf newSize > current data size, nothing happens. Returns the number of bytes\nthe producer won't use anymore, after contracting. */\nsize_t FUZZ_dataProducer_contract(FUZZ_dataProducer_t *producer, size_t newSize);\n\n/* Restricts the producer to use only the last X bytes of data, where X is\n a random number in the interval [0, data_size]. Returns the size of the\n remaining data the producer won't use anymore (the prefix). */\nsize_t FUZZ_dataProducer_reserveDataPrefix(FUZZ_dataProducer_t *producer);\n#endif // FUZZ_DATA_PRODUCER_H\n"
  },
  {
    "path": "tests/fuzz/fuzz_helpers.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n#include \"fuzz_helpers.h\"\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <string.h>\n\nvoid* FUZZ_malloc(size_t size)\n{\n    if (size > 0) {\n        void* const mem = malloc(size);\n        FUZZ_ASSERT(mem);\n        return mem;\n    }\n    return NULL;\n}\n\nvoid* FUZZ_malloc_rand(size_t size, FUZZ_dataProducer_t *producer)\n{\n    if (size > 0) {\n        void* const mem = malloc(size);\n        FUZZ_ASSERT(mem);\n        return mem;\n    } else {\n        uintptr_t ptr = 0;\n        /* Return junk pointer 50% of the time */\n        if (FUZZ_dataProducer_uint32Range(producer, 0, 1))\n            ptr += FUZZ_dataProducer_int32Range(producer, -1000000, 1000000);\n        return (void*)ptr;\n    }\n}\n\nint FUZZ_memcmp(void const* lhs, void const* rhs, size_t size)\n{\n    if (size == 0) {\n        return 0;\n    }\n    return memcmp(lhs, rhs, size);\n}\n"
  },
  {
    "path": "tests/fuzz/fuzz_helpers.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/**\n * Helper functions for fuzzing.\n */\n\n#ifndef FUZZ_HELPERS_H\n#define FUZZ_HELPERS_H\n\n#include \"debug.h\"\n#include \"fuzz.h\"\n#include \"xxhash.h\"\n#include \"zstd.h\"\n#include \"fuzz_data_producer.h\"\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define MIN(a, b) ((a) < (b) ? (a) : (b))\n#define MAX(a, b) ((a) > (b) ? (a) : (b))\n\n#define FUZZ_QUOTE_IMPL(str) #str\n#define FUZZ_QUOTE(str) FUZZ_QUOTE_IMPL(str)\n\n/**\n * Asserts for fuzzing that are always enabled.\n */\n#define FUZZ_ASSERT_MSG(cond, msg)                                             \\\n  ((cond) ? (void)0                                                            \\\n          : (fprintf(stderr, \"%s: %u: Assertion: `%s' failed. %s\\n\", __FILE__, \\\n                     __LINE__, FUZZ_QUOTE(cond), (msg)),                       \\\n             abort()))\n#define FUZZ_ASSERT(cond) FUZZ_ASSERT_MSG((cond), \"\");\n#define FUZZ_ZASSERT(code)                                                     \\\n  FUZZ_ASSERT_MSG(!ZSTD_isError(code), ZSTD_getErrorName(code))\n\n#if defined(__GNUC__)\n#define FUZZ_STATIC static __inline __attribute__((unused))\n#elif defined(__cplusplus) ||                                                  \\\n    (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n#define FUZZ_STATIC static inline\n#elif defined(_MSC_VER)\n#define FUZZ_STATIC static __inline\n#else\n#define FUZZ_STATIC static\n#endif\n\n/**\n * malloc except return NULL for zero sized data and FUZZ_ASSERT\n * that malloc doesn't fail.\n */\nvoid* FUZZ_malloc(size_t size);\n\n/**\n * malloc except returns random pointer for zero sized data and FUZZ_ASSERT\n * that malloc doesn't fail.\n * WARNING: Only free the returned pointer if size > 0!\n */\nvoid* FUZZ_malloc_rand(size_t size,  FUZZ_dataProducer_t *producer);\n\n/**\n * memcmp but accepts NULL.\n */\nint FUZZ_memcmp(void const* lhs, void const* rhs, size_t size);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "tests/fuzz/fuzz_third_party_seq_prod.h",
    "content": "/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef EXAMPLE_SEQ_PROD_H\n#define EXAMPLE_SEQ_PROD_H\n\n#define ZSTD_STATIC_LINKING_ONLY\n#include \"zstd.h\"\n\n#include <stdint.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* *** INTERFACE FOR FUZZING THIRD-PARTY SEQUENCE PRODUCER PLUGINS ***\n * Fuzz-testing for the external sequence producer API was introduced in PR #3437.\n * However, the setup in #3437 only allows fuzzers to exercise the implementation of the\n * API itself (the code in the core zstd library which interacts with your plugin).\n *\n * This header defines an interface for plugin authors to link their code into the fuzzer\n * build. Plugin authors can provide an object file implementing the symbols below,\n * and those symbols will replace the default ones provided by #3437.\n *\n * To fuzz your plugin, follow these steps:\n *   - Build your object file with a recent version of clang. Building with gcc is not supported.\n *   - Build your object file using appropriate flags for fuzzing. For example:\n *     `-g -fno-omit-frame-pointer -fsanitize=undefined,address,fuzzer`\n *   - Build the fuzzer binaries with options corresponding to the flags you chose. Use --custom-seq-prod= to pass in your object file:\n *     `./fuzz.py build all --enable-fuzzer --enable-asan --enable-ubsan --cc clang --cxx clang++ --custom-seq-prod=your_object.o`\n *\n * An example implementation of this header is provided at tests/fuzz/seq_prod_fuzz_example/.\n * Use these commands to fuzz with the example code:\n *   $ make corpora\n *   $ make -C seq_prod_fuzz_example/\n *   $ python3 ./fuzz.py build all --enable-fuzzer --enable-asan --enable-ubsan --cc clang --cxx clang++ --custom-seq-prod=seq_prod_fuzz_example/example_seq_prod.o\n *   $ python3 ./fuzz.py libfuzzer simple_round_trip\n */\n\n/* The fuzzer will call this function before each test-case. It should run any\n * setup actions (such as starting a hardware device) needed for fuzzing.\n *\n * The fuzzer will assert() that the return value is zero. To signal an error,\n * please return a non-zero value. */\nsize_t FUZZ_seqProdSetup(void);\n\n/* The fuzzer will call this function after each test-case. It should free\n * resources acquired by FUZZ_seqProdSetup() to prevent leaks across test-cases.\n *\n * The fuzzer will assert() that the return value is zero. To signal an error,\n * please return a non-zero value. */\nsize_t FUZZ_seqProdTearDown(void);\n\n/* The fuzzer will call this function before each test-case, only after calling\n * FUZZ_seqProdSetup(), to obtain a sequence producer state which can be passed\n * into ZSTD_registerSequenceProducer().\n *\n * All compressions which are part of a test-case will share a single sequence\n * producer state. Sharing the state object is safe because the fuzzers currently\n * don't exercise the sequence producer API in multi-threaded scenarios. We may\n * need a new approach in the future to support multi-threaded fuzzing.\n *\n * The fuzzer will assert() that the return value is not NULL. To signal an error,\n * please return NULL. */\nvoid* FUZZ_createSeqProdState(void);\n\n/* The fuzzer will call this function after each test-case. It should free any\n * resources acquired by FUZZ_createSeqProdState().\n *\n * The fuzzer will assert() that the return value is zero. To signal an error,\n * please return a non-zero value. */\nsize_t FUZZ_freeSeqProdState(void* sequenceProducerState);\n\n/* This is the sequence producer function you would like to fuzz! It will receive\n * the void* returned by FUZZ_createSeqProdState() on each invocation. */\nsize_t FUZZ_thirdPartySeqProd(void* sequenceProducerState,\n                              ZSTD_Sequence* outSeqs, size_t outSeqsCapacity,\n                              const void* src, size_t srcSize,\n                              const void* dict, size_t dictSize,\n                              int compressionLevel,\n                              size_t windowSize);\n\n/* These macros are internal helpers. You do not need to worry about them. */\n#ifdef FUZZ_THIRD_PARTY_SEQ_PROD\n#define FUZZ_SEQ_PROD_SETUP()                                                  \\\n  do {                                                                         \\\n    FUZZ_ASSERT(FUZZ_seqProdSetup() == 0);                                     \\\n    FUZZ_seqProdState = FUZZ_createSeqProdState();                             \\\n    FUZZ_ASSERT(FUZZ_seqProdState != NULL);                                    \\\n  } while (0)\n#else\n#define FUZZ_SEQ_PROD_SETUP()\n#endif\n\n#ifdef FUZZ_THIRD_PARTY_SEQ_PROD\n#define FUZZ_SEQ_PROD_TEARDOWN()                                               \\\n  do {                                                                         \\\n    FUZZ_ASSERT(FUZZ_freeSeqProdState(FUZZ_seqProdState) == 0);                \\\n    FUZZ_ASSERT(FUZZ_seqProdTearDown() == 0);                                  \\\n  } while (0)\n#else\n#define FUZZ_SEQ_PROD_TEARDOWN()\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* EXAMPLE_SEQ_PROD_H */\n"
  },
  {
    "path": "tests/fuzz/generate_sequences.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#define ZSTD_STATIC_LINKING_ONLY\n\n#include <stddef.h>\n#include <stdint.h>\n#include <string.h>\n#include <stdlib.h>\n\n#include \"fuzz_data_producer.h\"\n#include \"fuzz_helpers.h\"\n#include \"zstd_helpers.h\"\n\n/**\n * This fuzz target ensures that ZSTD_generateSequences() does not crash and\n * if it succeeds that ZSTD_compressSequences() round trips.\n */\n\nstatic void testRoundTrip(ZSTD_CCtx* cctx, ZSTD_Sequence const* seqs, size_t nbSeqs, const void* src, size_t srcSize) {\n  /* Compress the sequences with block delimiters */\n  const size_t compressBound = ZSTD_compressBound(srcSize);\n  void* dst = FUZZ_malloc(compressBound);\n  FUZZ_ASSERT(dst);\n\n  size_t compressedSize = ZSTD_compressSequences(cctx, dst, compressBound, seqs, nbSeqs, src, srcSize);\n  FUZZ_ZASSERT(compressedSize);\n\n  void* decompressed = FUZZ_malloc(srcSize);\n  FUZZ_ASSERT(srcSize == 0 || decompressed);\n  size_t decompressedSize = ZSTD_decompress(decompressed, srcSize, dst, compressedSize);\n  FUZZ_ZASSERT(decompressedSize);\n  FUZZ_ASSERT(decompressedSize == srcSize);\n  if (srcSize != 0) {\n    FUZZ_ASSERT(!memcmp(src, decompressed, srcSize));\n  }\n\n  free(decompressed);\n  free(dst);\n}\n\nint LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {\n\n  FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(data, size);\n  size = FUZZ_dataProducer_reserveDataPrefix(producer);\n\n  ZSTD_CCtx* cctx = ZSTD_createCCtx();\n  FUZZ_ASSERT(cctx);\n\n  const size_t seqsCapacity = FUZZ_dataProducer_uint32Range(producer, 0, 2 * ZSTD_sequenceBound(size));\n  ZSTD_Sequence* seqs = (ZSTD_Sequence*)FUZZ_malloc(sizeof(ZSTD_Sequence) * seqsCapacity);\n  FUZZ_ASSERT(seqsCapacity == 0 || seqs);\n\n  FUZZ_setRandomParameters(cctx, size, producer);\n  FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, ZSTD_c_targetCBlockSize, 0));\n  FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 0));\n\n  const size_t nbSeqs = ZSTD_generateSequences(cctx, seqs, seqsCapacity, data, size);\n  if (ZSTD_isError(nbSeqs)) {\n    /* Allowed to error if the destination is too small */\n    if (ZSTD_getErrorCode(nbSeqs) == ZSTD_error_dstSize_tooSmall) {\n        FUZZ_ASSERT(seqsCapacity < ZSTD_sequenceBound(size));\n    }\n  } else {\n    /* Ensure we round trip with and without block delimiters*/\n\n    FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters));\n    testRoundTrip(cctx, seqs, nbSeqs, data, size);\n\n    const size_t nbMergedSeqs = ZSTD_mergeBlockDelimiters(seqs, nbSeqs);\n    FUZZ_ASSERT(nbMergedSeqs <= nbSeqs);\n    FUZZ_ZASSERT(ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only));\n    FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, ZSTD_sf_noBlockDelimiters));\n    testRoundTrip(cctx, seqs, nbMergedSeqs, data, size);\n  }\n\n  free(seqs);\n  ZSTD_freeCCtx(cctx);\n  FUZZ_dataProducer_free(producer);\n  return 0;\n}\n"
  },
  {
    "path": "tests/fuzz/huf_decompress.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/**\n * This fuzz target performs a zstd round-trip test (compress & decompress),\n * compares the result with the original, and calls abort() on corruption.\n */\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include \"common/cpu.h\"\n#include \"common/huf.h\"\n#include \"fuzz_helpers.h\"\n#include \"fuzz_data_producer.h\"\n\nint LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)\n{\n    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);\n    /* Select random parameters: #streams, X1 or X2 decoding, bmi2 */\n    int const streams = FUZZ_dataProducer_int32Range(producer, 0, 1);\n    int const symbols = FUZZ_dataProducer_int32Range(producer, 0, 1);\n    int const flags = 0\n        | (ZSTD_cpuid_bmi2(ZSTD_cpuid()) && FUZZ_dataProducer_int32Range(producer, 0, 1) ? HUF_flags_bmi2 : 0)\n        | (FUZZ_dataProducer_int32Range(producer, 0, 1) ? HUF_flags_optimalDepth : 0)\n        | (FUZZ_dataProducer_int32Range(producer, 0, 1) ? HUF_flags_preferRepeat : 0)\n        | (FUZZ_dataProducer_int32Range(producer, 0, 1) ? HUF_flags_suspectUncompressible : 0)\n        | (FUZZ_dataProducer_int32Range(producer, 0, 1) ? HUF_flags_disableAsm : 0)\n        | (FUZZ_dataProducer_int32Range(producer, 0, 1) ? HUF_flags_disableFast : 0);\n    /* Select a random cBufSize - it may be too small */\n    size_t const dBufSize = FUZZ_dataProducer_uint32Range(producer, 0, 8 * size + 500);\n    size_t const maxTableLog = FUZZ_dataProducer_uint32Range(producer, 1, HUF_TABLELOG_MAX);\n    HUF_DTable* dt = (HUF_DTable*)FUZZ_malloc(HUF_DTABLE_SIZE(maxTableLog) * sizeof(HUF_DTable));\n    size_t const wkspSize = HUF_WORKSPACE_SIZE;\n    void* wksp = FUZZ_malloc(wkspSize);\n    void* dBuf = FUZZ_malloc(dBufSize);\n    dt[0] = maxTableLog * 0x01000001;\n    size = FUZZ_dataProducer_remainingBytes(producer);\n\n    if (symbols == 0) {\n        size_t const err = HUF_readDTableX1_wksp(dt, src, size, wksp, wkspSize, flags);\n        if (ZSTD_isError(err))\n            goto _out;\n    } else {\n        size_t const err = HUF_readDTableX2_wksp(dt, src, size, wksp, wkspSize, flags);\n        if (ZSTD_isError(err))\n            goto _out;\n    }\n    if (streams == 0)\n        HUF_decompress1X_usingDTable(dBuf, dBufSize, src, size, dt, flags);\n    else\n        HUF_decompress4X_usingDTable(dBuf, dBufSize, src, size, dt, flags);\n\n_out:\n    free(dt);\n    free(wksp);\n    free(dBuf);\n    FUZZ_dataProducer_free(producer);\n    return 0;\n}\n"
  },
  {
    "path": "tests/fuzz/huf_round_trip.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/**\n * This fuzz target performs a zstd round-trip test (compress & decompress),\n * compares the result with the original, and calls abort() on corruption.\n */\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include \"common/cpu.h\"\n#include \"compress/hist.h\"\n#include \"common/huf.h\"\n#include \"fuzz_helpers.h\"\n#include \"fuzz_data_producer.h\"\n#include \"common/bits.h\"\n\nstatic size_t adjustTableLog(size_t tableLog, size_t maxSymbol)\n{\n    size_t const alphabetSize = maxSymbol + 1;\n    size_t minTableLog = ZSTD_highbit32(alphabetSize) + 1;\n    if ((alphabetSize & (alphabetSize - 1)) != 0) {\n        ++minTableLog;\n    }\n    assert(minTableLog <= 9);\n    if (tableLog < minTableLog)\n        return minTableLog;\n    else\n        return tableLog;\n}\n\nint LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)\n{\n    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);\n    /* Select random parameters: #streams, X1 or X2 decoding, bmi2 */\n    int const streams = FUZZ_dataProducer_int32Range(producer, 0, 1);\n    int const symbols = FUZZ_dataProducer_int32Range(producer, 0, 1);\n    int const flags = 0\n        | (ZSTD_cpuid_bmi2(ZSTD_cpuid()) && FUZZ_dataProducer_int32Range(producer, 0, 1) ? HUF_flags_bmi2 : 0)\n        | (FUZZ_dataProducer_int32Range(producer, 0, 1) ? HUF_flags_optimalDepth : 0)\n        | (FUZZ_dataProducer_int32Range(producer, 0, 1) ? HUF_flags_preferRepeat : 0)\n        | (FUZZ_dataProducer_int32Range(producer, 0, 1) ? HUF_flags_suspectUncompressible : 0)\n        | (FUZZ_dataProducer_int32Range(producer, 0, 1) ? HUF_flags_disableAsm : 0)\n        | (FUZZ_dataProducer_int32Range(producer, 0, 1) ? HUF_flags_disableFast : 0);\n    /* Select a random cBufSize - it may be too small */\n    size_t const cBufSize = FUZZ_dataProducer_uint32Range(producer, 0, 4 * size);\n    /* Select a random tableLog - we'll adjust it up later */\n    size_t tableLog = FUZZ_dataProducer_uint32Range(producer, 1, 12);\n    size_t const kMaxSize = 256 * 1024;\n    size = FUZZ_dataProducer_remainingBytes(producer);\n    if (size > kMaxSize)\n        size = kMaxSize;\n\n    if (size <= 1) {\n        FUZZ_dataProducer_free(producer);\n        return 0;\n    }\n\n    uint32_t maxSymbol = 255;\n\n    U32 count[256];\n    size_t const mostFrequent = HIST_count(count, &maxSymbol, src, size);\n    FUZZ_ZASSERT(mostFrequent);\n    if (mostFrequent == size) {\n        /* RLE */\n        FUZZ_dataProducer_free(producer);\n        return 0;\n\n    }\n    FUZZ_ASSERT(maxSymbol <= 255);\n    tableLog = adjustTableLog(tableLog, maxSymbol);\n\n    size_t const wkspSize = HUF_WORKSPACE_SIZE;\n    void* wksp = FUZZ_malloc(wkspSize);\n    void* rBuf = FUZZ_malloc(size);\n    void* cBuf = FUZZ_malloc(cBufSize);\n    HUF_CElt* ct = (HUF_CElt*)FUZZ_malloc(HUF_CTABLE_SIZE(maxSymbol));\n    HUF_DTable* dt = (HUF_DTable*)FUZZ_malloc(HUF_DTABLE_SIZE(tableLog) * sizeof(HUF_DTable));\n    dt[0] = tableLog * 0x01000001;\n\n    tableLog = HUF_optimalTableLog(tableLog, size, maxSymbol, wksp, wkspSize, ct, count, flags);\n    FUZZ_ASSERT(tableLog <= 12);\n    tableLog = HUF_buildCTable_wksp(ct, count, maxSymbol, tableLog, wksp, wkspSize);\n    FUZZ_ZASSERT(tableLog);\n    size_t const tableSize = HUF_writeCTable_wksp(cBuf, cBufSize, ct, maxSymbol, tableLog, wksp, wkspSize);\n    if (ERR_isError(tableSize)) {\n        /* Errors on uncompressible data or cBufSize too small */\n        goto _out;\n    }\n    FUZZ_ZASSERT(tableSize);\n    if (symbols == 0) {\n        FUZZ_ZASSERT(HUF_readDTableX1_wksp(dt, cBuf, tableSize, wksp, wkspSize, flags));\n    } else {\n        size_t const ret = HUF_readDTableX2_wksp(dt, cBuf, tableSize, wksp, wkspSize, flags);\n        if (ERR_getErrorCode(ret) == ZSTD_error_tableLog_tooLarge) {\n            FUZZ_ZASSERT(HUF_readDTableX1_wksp(dt, cBuf, tableSize, wksp, wkspSize, flags));\n        } else {\n            FUZZ_ZASSERT(ret);\n        }\n    }\n\n    size_t cSize;\n    size_t rSize;\n    if (streams == 0) {\n        cSize = HUF_compress1X_usingCTable(cBuf, cBufSize, src, size, ct, flags);\n        FUZZ_ZASSERT(cSize);\n        if (cSize != 0)\n            rSize = HUF_decompress1X_usingDTable(rBuf, size, cBuf, cSize, dt, flags);\n    } else {\n        cSize = HUF_compress4X_usingCTable(cBuf, cBufSize, src, size, ct, flags);\n        FUZZ_ZASSERT(cSize);\n        if (cSize != 0)\n            rSize = HUF_decompress4X_usingDTable(rBuf, size, cBuf, cSize, dt, flags);\n    }\n    if (cSize != 0) {\n        FUZZ_ZASSERT(rSize);\n        FUZZ_ASSERT_MSG(rSize == size, \"Incorrect regenerated size\");\n        FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, rBuf, size), \"Corruption!\");\n    }\n_out:\n    free(rBuf);\n    free(cBuf);\n    free(ct);\n    free(dt);\n    free(wksp);\n    FUZZ_dataProducer_free(producer);\n    return 0;\n}\n"
  },
  {
    "path": "tests/fuzz/raw_dictionary_round_trip.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/**\n * This fuzz target performs a zstd round-trip test (compress & decompress) with\n * a raw content dictionary, compares the result with the original, and calls\n * abort() on corruption.\n */\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include \"fuzz_helpers.h\"\n#include \"zstd_helpers.h\"\n#include \"fuzz_data_producer.h\"\n#include \"fuzz_third_party_seq_prod.h\"\n\nstatic ZSTD_CCtx *cctx = NULL;\nstatic ZSTD_DCtx *dctx = NULL;\n\nstatic size_t roundTripTest(void *result, size_t resultCapacity,\n                            void *compressed, size_t compressedCapacity,\n                            const void *src, size_t srcSize,\n                            const void *dict, size_t dictSize,\n                            FUZZ_dataProducer_t *producer)\n{\n    ZSTD_dictContentType_e const dictContentType = ZSTD_dct_rawContent;\n    int const refPrefix = FUZZ_dataProducer_uint32Range(producer, 0, 1) != 0;\n    size_t cSize;\n\n    FUZZ_setRandomParameters(cctx, srcSize, producer);\n    /* Disable checksum so we can use sizes smaller than compress bound. */\n    FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 0));\n    if (refPrefix)\n        FUZZ_ZASSERT(ZSTD_CCtx_refPrefix_advanced(\n            cctx, dict, dictSize,\n            ZSTD_dct_rawContent));\n    else\n        FUZZ_ZASSERT(ZSTD_CCtx_loadDictionary_advanced(\n            cctx, dict, dictSize,\n            (ZSTD_dictLoadMethod_e)FUZZ_dataProducer_uint32Range(producer, 0, 1),\n            ZSTD_dct_rawContent));\n    cSize = ZSTD_compress2(cctx, compressed, compressedCapacity, src, srcSize);\n    FUZZ_ZASSERT(cSize);\n\n    if (refPrefix)\n        FUZZ_ZASSERT(ZSTD_DCtx_refPrefix_advanced(\n            dctx, dict, dictSize,\n            dictContentType));\n    else\n        FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced(\n            dctx, dict, dictSize,\n            (ZSTD_dictLoadMethod_e)FUZZ_dataProducer_uint32Range(producer, 0, 1),\n            dictContentType));\n    {\n        size_t const ret = ZSTD_decompressDCtx(\n                dctx, result, resultCapacity, compressed, cSize);\n        return ret;\n    }\n}\n\nint LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)\n{\n    FUZZ_SEQ_PROD_SETUP();\n\n    /* Give a random portion of src data to the producer, to use for\n    parameter generation. The rest will be used for (de)compression */\n    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);\n    size = FUZZ_dataProducer_reserveDataPrefix(producer);\n\n    uint8_t const* const srcBuf = src;\n    size_t const srcSize = FUZZ_dataProducer_uint32Range(producer, 0, size);\n    uint8_t const* const dictBuf = srcBuf + srcSize;\n    size_t const dictSize = size - srcSize;\n    size_t const decompSize = srcSize;\n    void* const decompBuf = FUZZ_malloc(decompSize);\n    size_t compSize = ZSTD_compressBound(srcSize);\n    void* compBuf;\n    /* Half of the time fuzz with a 1 byte smaller output size.\n     * This will still succeed because we force the checksum to be disabled,\n     * giving us 4 bytes of overhead.\n     */\n    compSize -= FUZZ_dataProducer_uint32Range(producer, 0, 1);\n    compBuf = FUZZ_malloc(compSize);\n\n    if (!cctx) {\n        cctx = ZSTD_createCCtx();\n        FUZZ_ASSERT(cctx);\n    }\n    if (!dctx) {\n        dctx = ZSTD_createDCtx();\n        FUZZ_ASSERT(dctx);\n    }\n\n    {\n        size_t const result =\n            roundTripTest(decompBuf, decompSize, compBuf, compSize, srcBuf, srcSize, dictBuf, dictSize, producer);\n        FUZZ_ZASSERT(result);\n        FUZZ_ASSERT_MSG(result == srcSize, \"Incorrect regenerated size\");\n        FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, decompBuf, srcSize), \"Corruption!\");\n    }\n    free(decompBuf);\n    free(compBuf);\n    FUZZ_dataProducer_free(producer);\n#ifndef STATEFUL_FUZZING\n    ZSTD_freeCCtx(cctx); cctx = NULL;\n    ZSTD_freeDCtx(dctx); dctx = NULL;\n#endif\n    FUZZ_SEQ_PROD_TEARDOWN();\n    return 0;\n}\n"
  },
  {
    "path": "tests/fuzz/regression_driver.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"fuzz.h\"\n#include \"fuzz_helpers.h\"\n#include \"util.h\"\n#include <stddef.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n\nint main(int argc, char const **argv) {\n  size_t const kMaxFileSize = (size_t)1 << 27;\n  int const kFollowLinks = 1;\n  FileNamesTable* files;\n  const char** const fnTable = argv + 1;\n  uint8_t *buffer = NULL;\n  size_t bufferSize = 0;\n  unsigned i;\n  unsigned numFilesTested = 0;\n  int ret = 0;\n\n  {\n    unsigned const numFiles = (unsigned)(argc - 1);\n#ifdef UTIL_HAS_CREATEFILELIST\n    files = UTIL_createExpandedFNT(fnTable, numFiles, kFollowLinks);\n#else\n    files = UTIL_createFNT_fromROTable(fnTable, numFiles);\n    assert(numFiles == files->tableSize);\n#endif\n  }\n  if (!files) {\n    fprintf(stderr, \"ERROR: Failed to create file names table\\n\");\n    return 1;\n  }\n  if (files->tableSize == 0)\n    fprintf(stderr, \"WARNING: No files passed to %s\\n\", argv[0]);\n  for (i = 0; i < files->tableSize; ++i) {\n    char const *fileName = files->fileNames[i];\n    size_t const fileSize = UTIL_getFileSize(fileName);\n    size_t readSize;\n    FILE *file;\n\n    DEBUGLOG(3, \"Running %s\", fileName);\n\n    /* Check that it is a regular file, and that the fileSize is valid.\n     * If it is not a regular file, then it may have been deleted since we\n     * constructed the list, so just skip it, but return an error exit code.\n     */\n    if (!UTIL_isRegularFile(fileName)) {\n      ret = 1;\n      continue;\n    }\n    FUZZ_ASSERT_MSG(fileSize <= kMaxFileSize, fileName);\n    /* Ensure we have a large enough buffer allocated */\n    if (fileSize > bufferSize) {\n      free(buffer);\n      buffer = (uint8_t *)malloc(fileSize);\n      FUZZ_ASSERT_MSG(buffer, fileName);\n      bufferSize = fileSize;\n    }\n    /* Open the file */\n    file = fopen(fileName, \"rb\");\n    FUZZ_ASSERT_MSG(file, fileName);\n    /* Read the file */\n    readSize = fread(buffer, 1, fileSize, file);\n    FUZZ_ASSERT_MSG(readSize == fileSize, fileName);\n    /* Close the file */\n    fclose(file);\n    /* Run the fuzz target */\n    LLVMFuzzerTestOneInput(buffer, fileSize);\n    ++numFilesTested;\n  }\n  fprintf(stderr, \"Tested %u files: \", numFilesTested);\n  if (ret == 0) {\n    fprintf(stderr, \"Success!\\n\");\n  } else {\n    fprintf(stderr, \"Failure!\\n\");\n  }\n  free(buffer);\n  UTIL_freeFileNamesTable(files);\n  return ret;\n}\n"
  },
  {
    "path": "tests/fuzz/seekable_roundtrip.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"zstd.h\"\n#include \"zstd_seekable.h\"\n#include \"fuzz_helpers.h\"\n#include \"fuzz_data_producer.h\"\n\nstatic ZSTD_seekable *stream = NULL;\nstatic ZSTD_seekable_CStream *zscs = NULL;\nstatic const size_t kSeekableOverheadSize = ZSTD_seekTableFooterSize;\n\nint LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)\n{\n    /* Give a random portion of src data to the producer, to use for\n    parameter generation. The rest will be used for (de)compression */\n    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);\n    size = FUZZ_dataProducer_reserveDataPrefix(producer);\n    size_t const compressedBufferSize = ZSTD_compressBound(size) + kSeekableOverheadSize;\n    uint8_t* compressedBuffer = (uint8_t*)malloc(compressedBufferSize);\n    uint8_t* decompressedBuffer = (uint8_t*)malloc(size);\n\n    int const cLevel = FUZZ_dataProducer_int32Range(producer, ZSTD_minCLevel(), ZSTD_maxCLevel());\n    unsigned const checksumFlag = FUZZ_dataProducer_int32Range(producer, 0, 1);\n    size_t const uncompressedSize = FUZZ_dataProducer_uint32Range(producer, 0, size);\n    size_t const offset = FUZZ_dataProducer_uint32Range(producer, 0, size - uncompressedSize);\n    size_t seekSize;\n\n    if (!zscs) {\n        zscs = ZSTD_seekable_createCStream();\n        FUZZ_ASSERT(zscs);\n    }\n    if (!stream) {\n        stream = ZSTD_seekable_create();\n        FUZZ_ASSERT(stream);\n    }\n\n    {   /* Perform a compression */\n        size_t const initStatus = ZSTD_seekable_initCStream(zscs, cLevel, checksumFlag, size);\n        size_t endStatus;\n        ZSTD_outBuffer out = { .dst=compressedBuffer, .pos=0, .size=compressedBufferSize };\n        ZSTD_inBuffer  in  = { .src=src, .pos=0, .size=size };\n        FUZZ_ASSERT(!ZSTD_isError(initStatus));\n\n        do {\n            size_t cSize = ZSTD_seekable_compressStream(zscs, &out, &in);\n            FUZZ_ASSERT(!ZSTD_isError(cSize));\n        } while (in.pos != in.size);\n\n        FUZZ_ASSERT(in.pos == in.size);\n        endStatus = ZSTD_seekable_endStream(zscs, &out);\n        FUZZ_ASSERT(!ZSTD_isError(endStatus));\n        seekSize = out.pos;\n    }\n\n    {   /* Decompress at an offset */\n        size_t const initStatus = ZSTD_seekable_initBuff(stream, compressedBuffer, seekSize);\n        size_t decompressedBytesTotal = 0;\n        size_t dSize;\n\n        FUZZ_ZASSERT(initStatus);\n        do {\n            dSize = ZSTD_seekable_decompress(stream, decompressedBuffer, uncompressedSize, offset);\n            FUZZ_ASSERT(!ZSTD_isError(dSize));\n            decompressedBytesTotal += dSize;\n        } while (decompressedBytesTotal < uncompressedSize && dSize > 0);\n        FUZZ_ASSERT(decompressedBytesTotal == uncompressedSize);\n    }\n\n    FUZZ_ASSERT_MSG(!FUZZ_memcmp(src+offset, decompressedBuffer, uncompressedSize), \"Corruption!\");\n\n    free(decompressedBuffer);\n    free(compressedBuffer);\n    FUZZ_dataProducer_free(producer);\n\n#ifndef STATEFUL_FUZZING\n    ZSTD_seekable_free(stream); stream = NULL;\n    ZSTD_seekable_freeCStream(zscs); zscs = NULL;\n#endif\n    return 0;\n}\n"
  },
  {
    "path": "tests/fuzz/seq_prod_fuzz_example/Makefile",
    "content": "# Copyright (c) Yann Collet, Meta Platforms, Inc.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n\nCC = clang\nCFLAGS = -g -fno-omit-frame-pointer -fsanitize=undefined,address,fuzzer -I../ -I../../../lib/\n\n.PHONY: default\ndefault: example_seq_prod.o\n\nexample_seq_prod.o: example_seq_prod.c\n\t$(CC) -c $(CFLAGS) $^ -o $@\n"
  },
  {
    "path": "tests/fuzz/seq_prod_fuzz_example/README.md",
    "content": "# Fuzzing a Custom Sequence Producer Plugin\nThis directory contains example code for using a custom sequence producer in the zstd fuzzers.\n\nYou can build and run the code in this directory using these commands:\n```\n$ make corpora\n$ make -C seq_prod_fuzz_example/\n$ python3 ./fuzz.py build all --enable-fuzzer --enable-asan --enable-ubsan --cc clang --cxx clang++ --custom-seq-prod=seq_prod_fuzz_example/example_seq_prod.o\n$ python3 ./fuzz.py libfuzzer simple_round_trip\n```\n\nSee `../fuzz_third_party_seq_prod.h` and `../README.md` for more information on zstd fuzzing.\n"
  },
  {
    "path": "tests/fuzz/seq_prod_fuzz_example/example_seq_prod.c",
    "content": "/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"fuzz_third_party_seq_prod.h\"\n\n#include <assert.h>\n#include <stdlib.h>\n#include <string.h>\n\n_Thread_local size_t threadLocalState;\n\nsize_t FUZZ_seqProdSetup(void) {\n    threadLocalState = 0;\n    return 0;\n}\n\nsize_t FUZZ_seqProdTearDown(void) {\n    return 0;\n}\n\nvoid* FUZZ_createSeqProdState(void) {\n    return calloc(1, sizeof(size_t));\n}\n\nsize_t FUZZ_freeSeqProdState(void* state) {\n    free(state);\n    return 0;\n}\n\nsize_t FUZZ_thirdPartySeqProd(\n    void* sequenceProducerState,\n    ZSTD_Sequence* outSeqs, size_t outSeqsCapacity,\n    const void* src, size_t srcSize,\n    const void* dict, size_t dictSize,\n    int compressionLevel,\n    size_t windowSize\n) {\n    /* Try to catch unsafe use of the shared state */\n    size_t* const sharedStatePtr = (size_t*)sequenceProducerState;\n    assert(*sharedStatePtr == threadLocalState);\n    (*sharedStatePtr)++; threadLocalState++;\n\n    /* Check that fallback is enabled when FUZZ_THIRD_PARTY_SEQ_PROD is defined */\n    return ZSTD_SEQUENCE_PRODUCER_ERROR;\n}\n"
  },
  {
    "path": "tests/fuzz/sequence_compression_api.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/**\n * This fuzz target performs a zstd round-trip test by generating an arbitrary\n * array of sequences, generating the associated source buffer, calling\n * ZSTD_compressSequences(), and then decompresses and compares the result with\n * the original generated source buffer.\n */\n\n#define ZSTD_STATIC_LINKING_ONLY\n#include \"zstd_errors.h\"\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <time.h>\n#include \"fuzz_helpers.h\"\n#include \"zstd_helpers.h\"\n#include \"fuzz_data_producer.h\"\n#include \"fuzz_third_party_seq_prod.h\"\n\nstatic ZSTD_CCtx* cctx = NULL;\nstatic ZSTD_DCtx* dctx = NULL;\nstatic void* literalsBuffer = NULL;\nstatic void* generatedSrc = NULL;\nstatic ZSTD_Sequence* generatedSequences = NULL;\n\nstatic void* dictBuffer = NULL;\nstatic ZSTD_CDict* cdict = NULL;\nstatic ZSTD_DDict* ddict = NULL;\n\n#define ZSTD_FUZZ_GENERATED_SRC_MAXSIZE (1 << 20) /* Allow up to 1MB generated data */\n#define ZSTD_FUZZ_GENERATED_LITERALS_SIZE (1 << 20) /* Fixed size 1MB literals buffer */\n#define ZSTD_FUZZ_MATCHLENGTH_MAXSIZE (1 << 18) /* Allow up to 256KB matches */\n#define ZSTD_FUZZ_GENERATED_DICT_MAXSIZE (1 << ZSTD_WINDOWLOG_MAX_32) /* Allow up to 1 << ZSTD_WINDOWLOG_MAX_32 dictionary */\n#define ZSTD_FUZZ_MAX_NBSEQ (1 << 17) /* Maximum of 128K sequences */\n\n/* Deterministic random number generator */\n#define FUZZ_RDG_rotl32(x,r) ((x << r) | (x >> (32 - r)))\nstatic uint32_t FUZZ_RDG_rand(uint32_t* src)\n{\n    static const uint32_t prime1 = 2654435761U;\n    static const uint32_t prime2 = 2246822519U;\n    uint32_t rand32 = *src;\n    rand32 *= prime1;\n    rand32 ^= prime2;\n    rand32  = FUZZ_RDG_rotl32(rand32, 13);\n    *src = rand32;\n    return rand32 >> 5;\n}\n\n/* Make a pseudorandom string - this simple function exists to avoid\n * taking a dependency on datagen.h to have RDG_genBuffer().\n */\nstatic char* generatePseudoRandomString(char* str, size_t size, FUZZ_dataProducer_t* producer) {\n    const char charset[] = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJK1234567890!@#$^&*()_\";\n    uint32_t seed = FUZZ_dataProducer_uint32(producer);\n    if (size) {\n        for (size_t n = 0; n < size; n++) {\n            int key = FUZZ_RDG_rand(&seed) % (int) (sizeof charset - 1);\n            str[n] = charset[key];\n        }\n    }\n    return str;\n}\n\n/* Returns size of source buffer */\nstatic size_t decodeSequences(void* dst, size_t nbSequences,\n                              size_t literalsSize,\n                              const void* dict, size_t dictSize,\n                              ZSTD_SequenceFormat_e mode)\n{\n    const uint8_t* litPtr = literalsBuffer;\n    const uint8_t* const litBegin = literalsBuffer;\n    const uint8_t* const litEnd = litBegin + literalsSize;\n    const uint8_t* dictPtr = dict;\n    uint8_t* op = dst;\n    const uint8_t* const oend = (uint8_t*)dst + ZSTD_FUZZ_GENERATED_SRC_MAXSIZE;\n    size_t generatedSrcBufferSize = 0;\n    size_t bytesWritten = 0;\n\n    for (size_t i = 0; i < nbSequences; ++i) {\n        /* block boundary */\n        if (generatedSequences[i].offset == 0)\n            FUZZ_ASSERT(generatedSequences[i].matchLength == 0);\n\n        if (litPtr + generatedSequences[i].litLength > litEnd) {\n            litPtr = litBegin;\n        }\n        memcpy(op, litPtr, generatedSequences[i].litLength);\n        bytesWritten += generatedSequences[i].litLength;\n        op += generatedSequences[i].litLength;\n        litPtr += generatedSequences[i].litLength;\n\n        /* Copy over the match */\n        {   size_t matchLength = generatedSequences[i].matchLength;\n            size_t j = 0;\n            size_t k = 0;\n            if (dictSize != 0) {\n                if (generatedSequences[i].offset > bytesWritten) { /* Offset goes into the dictionary */\n                    size_t dictOffset = generatedSequences[i].offset - bytesWritten;\n                    size_t matchInDict = MIN(matchLength, dictOffset);\n                    for (; k < matchInDict; ++k) {\n                        op[k] = dictPtr[dictSize - dictOffset + k];\n                    }\n                    matchLength -= matchInDict;\n                    op += matchInDict;\n                }\n            }\n            for (; j < matchLength; ++j) {\n                op[j] = op[(ptrdiff_t)(j - generatedSequences[i].offset)];\n            }\n            op += j;\n            FUZZ_ASSERT(generatedSequences[i].matchLength == j + k);\n            bytesWritten += generatedSequences[i].matchLength;\n        }\n    }\n    generatedSrcBufferSize = bytesWritten;\n    FUZZ_ASSERT(litPtr <= litEnd);\n    if (mode == ZSTD_sf_noBlockDelimiters) {\n        const uint32_t lastLLSize = (uint32_t)(litEnd - litPtr);\n        if (lastLLSize <= (uint32_t)(oend - op)) {\n            memcpy(op, litPtr, lastLLSize);\n            generatedSrcBufferSize += lastLLSize;\n    }   }\n    return generatedSrcBufferSize;\n}\n\n/* Returns nb sequences generated\n * Note : random sequences are always valid in ZSTD_sf_noBlockDelimiters mode.\n * However, it can fail with ZSTD_sf_explicitBlockDelimiters,\n * due to potential lack of space in\n */\nstatic size_t generateRandomSequences(FUZZ_dataProducer_t* producer,\n                                      size_t literalsSizeLimit, size_t dictSize,\n                                      size_t windowLog, ZSTD_SequenceFormat_e mode)\n{\n    const uint32_t repCode = 0;  /* not used by sequence ingestion api */\n    size_t windowSize = 1ULL << windowLog;\n    size_t blockSizeMax = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);\n    uint32_t matchLengthMax = ZSTD_FUZZ_MATCHLENGTH_MAXSIZE;\n    uint32_t bytesGenerated = 0;\n    uint32_t nbSeqGenerated = 0;\n    uint32_t isFirstSequence = 1;\n    uint32_t blockSize = 0;\n\n    if (mode == ZSTD_sf_explicitBlockDelimiters) {\n        /* ensure that no sequence can be larger than one block */\n        literalsSizeLimit = MIN(literalsSizeLimit, blockSizeMax/2);\n        matchLengthMax = MIN(matchLengthMax, (uint32_t)blockSizeMax/2);\n    }\n\n    while ( nbSeqGenerated < ZSTD_FUZZ_MAX_NBSEQ - 3 /* extra room for explicit delimiters */\n         && bytesGenerated < ZSTD_FUZZ_GENERATED_SRC_MAXSIZE\n         && !FUZZ_dataProducer_empty(producer)) {\n        uint32_t matchLength;\n        uint32_t matchBound = matchLengthMax;\n        uint32_t offset;\n        uint32_t offsetBound;\n        const uint32_t minLitLength = (isFirstSequence && (dictSize == 0));\n        const uint32_t litLength = FUZZ_dataProducer_uint32Range(producer, minLitLength, (uint32_t)literalsSizeLimit);\n        bytesGenerated += litLength;\n        if (bytesGenerated > ZSTD_FUZZ_GENERATED_SRC_MAXSIZE) {\n            break;\n        }\n        offsetBound = (bytesGenerated > windowSize) ? (uint32_t)windowSize : bytesGenerated + (uint32_t)dictSize;\n        offset = FUZZ_dataProducer_uint32Range(producer, 1, offsetBound);\n        if (dictSize > 0 && bytesGenerated <= windowSize) {\n            /* Prevent match length from being such that it would be associated with an offset too large\n             * from the decoder's perspective. If not possible (match would be too small),\n             * then reduce the offset if necessary.\n             */\n            const size_t bytesToReachWindowSize = windowSize - bytesGenerated;\n            if (bytesToReachWindowSize < ZSTD_MINMATCH_MIN) {\n                const uint32_t newOffsetBound = offsetBound > windowSize ? (uint32_t)windowSize : offsetBound;\n                offset = FUZZ_dataProducer_uint32Range(producer, 1, newOffsetBound);\n            } else {\n                matchBound = MIN(matchLengthMax, (uint32_t)bytesToReachWindowSize);\n            }\n        }\n        matchLength = FUZZ_dataProducer_uint32Range(producer, ZSTD_MINMATCH_MIN, matchBound);\n        bytesGenerated += matchLength;\n        if (bytesGenerated > ZSTD_FUZZ_GENERATED_SRC_MAXSIZE) {\n            break;\n        }\n        {   ZSTD_Sequence seq = {offset, litLength, matchLength, repCode};\n            const uint32_t lastLits = FUZZ_dataProducer_uint32Range(producer, 0, litLength);\n            #define SPLITPROB 6000\n            #define SPLITMARK 5234\n            const int split = (FUZZ_dataProducer_uint32Range(producer, 0, SPLITPROB) == SPLITMARK);\n            if (mode == ZSTD_sf_explicitBlockDelimiters) {\n                const size_t seqSize = seq.litLength + seq.matchLength;\n                if (blockSize + seqSize > blockSizeMax) {  /* reaching limit : must end block now */\n                    const ZSTD_Sequence endBlock = {0, 0, 0, 0};\n                    generatedSequences[nbSeqGenerated++] = endBlock;\n                    blockSize = (uint32_t)seqSize;\n                }\n                if (split) {\n                    const ZSTD_Sequence endBlock = {0, lastLits, 0, 0};\n                    generatedSequences[nbSeqGenerated++] = endBlock;\n                    assert(lastLits <= seq.litLength);\n                    seq.litLength -= lastLits;\n                    blockSize = (uint32_t)(seqSize - lastLits);\n                } else {\n                    blockSize += seqSize;\n                }\n            }\n            generatedSequences[nbSeqGenerated++] = seq;\n            isFirstSequence = 0;\n        }\n    }\n\n    if (mode == ZSTD_sf_explicitBlockDelimiters) {\n        /* always end sequences with a block delimiter */\n        const ZSTD_Sequence endBlock = {0, 0, 0, 0};\n        assert(nbSeqGenerated < ZSTD_FUZZ_MAX_NBSEQ);\n        generatedSequences[nbSeqGenerated++] = endBlock;\n    }\n    return nbSeqGenerated;\n}\n\nstatic size_t\ntransferLiterals(void* dst, size_t dstCapacity, const ZSTD_Sequence* seqs, size_t nbSeqs, const void* src, size_t srcSize)\n{\n    size_t n;\n    char* op = dst;\n    char* const oend = op + dstCapacity;\n    const char* ip = src;\n    const char* const iend = ip + srcSize;\n    for (n=0; n<nbSeqs; n++) {\n        size_t litLen = seqs[n].litLength;\n        size_t mlen = seqs[n].matchLength;\n        assert(op + litLen < oend); (void)oend;\n        assert(ip + litLen + mlen <= iend); (void)iend;\n        memcpy(op, ip, litLen);\n        op += litLen;\n        ip += litLen + mlen;\n    }\n    assert(oend - op >= 8);\n    return (size_t)(op - (char*)dst);\n}\n\nstatic size_t roundTripTest_compressSequencesAndLiterals(\n                    void* result, size_t resultCapacity,\n                    void* compressed, size_t compressedCapacity,\n                    const void* src, size_t srcSize,\n                    const ZSTD_Sequence* seqs, size_t nbSeqs)\n{\n    size_t const litCapacity = srcSize + 8;\n    void* literals = malloc(litCapacity);\n    size_t cSize, litSize;\n\n    assert(literals);\n    litSize = transferLiterals(literals, litCapacity, seqs, nbSeqs, src, srcSize);\n\n    cSize = ZSTD_compressSequencesAndLiterals(cctx,\n                                compressed, compressedCapacity,\n                                   seqs, nbSeqs,\n                                   literals, litSize, litCapacity, srcSize);\n    free(literals);\n    if (ZSTD_getErrorCode(cSize) == ZSTD_error_cannotProduce_uncompressedBlock) {\n        /* Valid scenario : ZSTD_compressSequencesAndLiterals cannot generate uncompressed blocks */\n        return 0;\n    }\n    if (ZSTD_getErrorCode(cSize) == ZSTD_error_dstSize_tooSmall) {\n        /* Valid scenario : in explicit delimiter mode,\n         * it might be possible for the compressed size to outgrow dstCapacity.\n         * In which case, it's still a valid fuzzer scenario,\n         * but no roundtrip shall be possible */\n        return 0;\n    }\n\n    /* round-trip */\n    FUZZ_ZASSERT(cSize);\n    {   size_t const dSize = ZSTD_decompressDCtx(dctx, result, resultCapacity, compressed, cSize);\n        FUZZ_ZASSERT(dSize);\n        FUZZ_ASSERT_MSG(dSize == srcSize, \"Incorrect regenerated size\");\n        FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, result, srcSize), \"Corruption!\");\n        return dSize;\n    }\n}\n\nstatic size_t roundTripTest(void* result, size_t resultCapacity,\n                            void* compressed, size_t compressedCapacity,\n                            const void* src, size_t srcSize,\n                            const ZSTD_Sequence* seqs, size_t nbSeqs,\n                            unsigned hasDict,\n                            ZSTD_SequenceFormat_e mode)\n{\n    size_t cSize;\n    size_t dSize;\n\n    if (hasDict) {\n        FUZZ_ZASSERT(ZSTD_CCtx_refCDict(cctx, cdict));\n        FUZZ_ZASSERT(ZSTD_DCtx_refDDict(dctx, ddict));\n    }\n\n    {   int blockMode, validation;\n        /* compressSequencesAndLiterals() only supports explicitBlockDelimiters and no validation */\n        FUZZ_ZASSERT(ZSTD_CCtx_getParameter(cctx, ZSTD_c_blockDelimiters, &blockMode));\n        FUZZ_ZASSERT(ZSTD_CCtx_getParameter(cctx, ZSTD_c_validateSequences, &validation));\n        if ((blockMode == ZSTD_sf_explicitBlockDelimiters) && (!validation)) {\n            FUZZ_ZASSERT(roundTripTest_compressSequencesAndLiterals(result, resultCapacity, compressed, compressedCapacity, src, srcSize, seqs, nbSeqs));\n        }\n    }\n\n    cSize = ZSTD_compressSequences(cctx, compressed, compressedCapacity,\n                                   seqs, nbSeqs,\n                                   src, srcSize);\n    if ( (ZSTD_getErrorCode(cSize) == ZSTD_error_dstSize_tooSmall)\n      && (mode == ZSTD_sf_explicitBlockDelimiters) ) {\n        /* Valid scenario : in explicit delimiter mode,\n         * it might be possible for the compressed size to outgrow dstCapacity.\n         * In which case, it's still a valid fuzzer scenario,\n         * but no roundtrip shall be possible */\n        return 0;\n    }\n    /* round-trip */\n    FUZZ_ZASSERT(cSize);\n    dSize = ZSTD_decompressDCtx(dctx, result, resultCapacity, compressed, cSize);\n    FUZZ_ZASSERT(dSize);\n    FUZZ_ASSERT_MSG(dSize == srcSize, \"Incorrect regenerated size\");\n    FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, result, srcSize), \"Corruption!\");\n    return dSize;\n}\n\nint LLVMFuzzerTestOneInput(const uint8_t* src, size_t size)\n{\n    FUZZ_SEQ_PROD_SETUP();\n\n    void* rBuf;\n    size_t rBufSize;\n    void* cBuf;\n    size_t cBufSize;\n    size_t generatedSrcSize;\n    size_t nbSequences;\n    size_t dictSize = 0;\n    unsigned hasDict;\n    unsigned wLog;\n    int cLevel;\n    ZSTD_SequenceFormat_e mode;\n\n    FUZZ_dataProducer_t* const producer = FUZZ_dataProducer_create(src, size);\n    FUZZ_ASSERT(producer);\n\n    if (!cctx) {\n        cctx = ZSTD_createCCtx();\n        FUZZ_ASSERT(cctx);\n    }\n    if (!dctx) {\n        dctx = ZSTD_createDCtx();\n        FUZZ_ASSERT(dctx);\n    }\n\n    /* Generate window log first so we don't generate offsets too large */\n    wLog = FUZZ_dataProducer_uint32Range(producer, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);\n    cLevel = FUZZ_dataProducer_int32Range(producer, -3, 22);\n    mode = (ZSTD_SequenceFormat_e)FUZZ_dataProducer_int32Range(producer, 0, 1);\n\n    ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n    ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 0);\n    ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, cLevel);\n    ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, (int)wLog);\n    ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, ZSTD_MINMATCH_MIN);\n    ZSTD_CCtx_setParameter(cctx, ZSTD_c_validateSequences, 1);\n    ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, (int)mode);\n    ZSTD_CCtx_setParameter(cctx, ZSTD_c_forceAttachDict, ZSTD_dictForceAttach);\n\n    if (!literalsBuffer) {\n        literalsBuffer = FUZZ_malloc(ZSTD_FUZZ_GENERATED_LITERALS_SIZE);\n        FUZZ_ASSERT(literalsBuffer);\n        literalsBuffer = generatePseudoRandomString(literalsBuffer, ZSTD_FUZZ_GENERATED_LITERALS_SIZE, producer);\n    }\n\n    if (!dictBuffer) { /* Generate global dictionary buffer */\n        ZSTD_compressionParameters cParams;\n\n        /* Generate a large dictionary buffer */\n        dictBuffer = calloc(ZSTD_FUZZ_GENERATED_DICT_MAXSIZE, 1);\n        FUZZ_ASSERT(dictBuffer);\n\n        /* Create global cdict and ddict */\n        cParams = ZSTD_getCParams(1, ZSTD_FUZZ_GENERATED_SRC_MAXSIZE, ZSTD_FUZZ_GENERATED_DICT_MAXSIZE);\n        cParams.minMatch = ZSTD_MINMATCH_MIN;\n        cParams.hashLog = ZSTD_HASHLOG_MIN;\n        cParams.chainLog = ZSTD_CHAINLOG_MIN;\n\n        cdict = ZSTD_createCDict_advanced(dictBuffer, ZSTD_FUZZ_GENERATED_DICT_MAXSIZE, ZSTD_dlm_byRef, ZSTD_dct_rawContent, cParams, ZSTD_defaultCMem);\n        ddict = ZSTD_createDDict_advanced(dictBuffer, ZSTD_FUZZ_GENERATED_DICT_MAXSIZE, ZSTD_dlm_byRef, ZSTD_dct_rawContent, ZSTD_defaultCMem);\n        FUZZ_ASSERT(cdict);\n        FUZZ_ASSERT(ddict);\n    }\n\n    FUZZ_ASSERT(cdict);\n    FUZZ_ASSERT(ddict);\n\n    hasDict = FUZZ_dataProducer_uint32Range(producer, 0, 1);\n    if (hasDict) {\n        dictSize = ZSTD_FUZZ_GENERATED_DICT_MAXSIZE;\n    }\n\n    if (!generatedSequences) {\n        generatedSequences = FUZZ_malloc(sizeof(ZSTD_Sequence)*ZSTD_FUZZ_MAX_NBSEQ);\n    }\n    if (!generatedSrc) {\n        generatedSrc = FUZZ_malloc(ZSTD_FUZZ_GENERATED_SRC_MAXSIZE);\n    }\n\n    nbSequences = generateRandomSequences(producer, ZSTD_FUZZ_GENERATED_LITERALS_SIZE, dictSize, wLog, mode);\n    generatedSrcSize = decodeSequences(generatedSrc, nbSequences, ZSTD_FUZZ_GENERATED_LITERALS_SIZE, dictBuffer, dictSize, mode);\n\n    /* Note : in explicit block delimiters mode,\n     * the fuzzer might generate a lot of small blocks.\n     * In which case, the final compressed size might be > ZSTD_compressBound().\n     * This is still a valid scenario fuzzer though, which makes it possible to check under-sized dstCapacity.\n     * The test just doesn't roundtrip. */\n    cBufSize = ZSTD_compressBound(generatedSrcSize);\n    cBuf = FUZZ_malloc(cBufSize);\n\n    rBufSize = generatedSrcSize;\n    rBuf = FUZZ_malloc(rBufSize);\n\n    {   const size_t result = roundTripTest(rBuf, rBufSize,\n                                        cBuf, cBufSize,\n                                        generatedSrc, generatedSrcSize,\n                                        generatedSequences, nbSequences,\n                                        hasDict, mode);\n        FUZZ_ASSERT(result <= generatedSrcSize);  /* can be 0 when no round-trip */\n    }\n\n    free(rBuf);\n    free(cBuf);\n    FUZZ_dataProducer_free(producer);\n#ifndef STATEFUL_FUZZING\n    ZSTD_freeCCtx(cctx); cctx = NULL;\n    ZSTD_freeDCtx(dctx); dctx = NULL;\n    free(generatedSequences); generatedSequences = NULL;\n    free(generatedSrc); generatedSrc = NULL;\n    free(literalsBuffer); literalsBuffer = NULL;\n#endif\n    FUZZ_SEQ_PROD_TEARDOWN();\n    return 0;\n}\n"
  },
  {
    "path": "tests/fuzz/simple_compress.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/**\n * This fuzz target attempts to compress the fuzzed data with the simple\n * compression function with an output buffer that may be too small to\n * ensure that the compressor never crashes.\n */\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include \"fuzz_helpers.h\"\n#include \"zstd.h\"\n#include \"zstd_errors.h\"\n#include \"zstd_helpers.h\"\n#include \"fuzz_data_producer.h\"\n#include \"fuzz_third_party_seq_prod.h\"\n\nstatic ZSTD_CCtx *cctx = NULL;\n\nint LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)\n{\n    FUZZ_SEQ_PROD_SETUP();\n\n    /* Give a random portion of src data to the producer, to use for\n    parameter generation. The rest will be used for (de)compression */\n    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);\n    size = FUZZ_dataProducer_reserveDataPrefix(producer);\n\n    size_t const maxSize = ZSTD_compressBound(size);\n    size_t const bufSize = FUZZ_dataProducer_uint32Range(producer, 0, maxSize);\n\n    int const cLevel = FUZZ_dataProducer_int32Range(producer, kMinClevel, kMaxClevel);\n\n    if (!cctx) {\n        cctx = ZSTD_createCCtx();\n        FUZZ_ASSERT(cctx);\n    }\n\n    void *rBuf = FUZZ_malloc(bufSize);\n    size_t const ret = ZSTD_compressCCtx(cctx, rBuf, bufSize, src, size, cLevel);\n    if (ZSTD_isError(ret)) {\n        FUZZ_ASSERT(ZSTD_getErrorCode(ret) == ZSTD_error_dstSize_tooSmall);\n    }\n    free(rBuf);\n    FUZZ_dataProducer_free(producer);\n#ifndef STATEFUL_FUZZING\n    ZSTD_freeCCtx(cctx); cctx = NULL;\n#endif\n    FUZZ_SEQ_PROD_TEARDOWN();\n    return 0;\n}\n"
  },
  {
    "path": "tests/fuzz/simple_decompress.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/**\n * This fuzz target attempts to decompress the fuzzed data with the simple\n * decompression function to ensure the decompressor never crashes.\n */\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <stdio.h>\n\n#define ZSTD_STATIC_LINKING_ONLY\n\n#include \"fuzz_helpers.h\"\n#include \"zstd.h\"\n#include \"fuzz_data_producer.h\"\n\nstatic ZSTD_DCtx *dctx = NULL;\n\nint LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)\n{\n    /* Give a random portion of src data to the producer, to use for\n    parameter generation. The rest will be used for (de)compression */\n    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);\n    size = FUZZ_dataProducer_reserveDataPrefix(producer);\n\n    if (!dctx) {\n        dctx = ZSTD_createDCtx();\n        FUZZ_ASSERT(dctx);\n    }\n\n    {\n        size_t const bufSize = FUZZ_dataProducer_uint32Range(producer, 0, 10 * size);\n        void *rBuf = FUZZ_malloc(bufSize);\n        size_t const dSize = ZSTD_decompressDCtx(dctx, rBuf, bufSize, src, size);\n        if (!ZSTD_isError(dSize)) {\n            /* If decompression was successful, the content size from the frame header(s) should be valid. */\n            unsigned long long const expectedSize = ZSTD_findDecompressedSize(src, size);\n            FUZZ_ASSERT(expectedSize != ZSTD_CONTENTSIZE_ERROR);\n            FUZZ_ASSERT(expectedSize == ZSTD_CONTENTSIZE_UNKNOWN || expectedSize == dSize);\n        }\n        free(rBuf);\n    }\n\n    FUZZ_dataProducer_free(producer);\n\n#ifndef STATEFUL_FUZZING\n    ZSTD_freeDCtx(dctx); dctx = NULL;\n#endif\n    return 0;\n}\n"
  },
  {
    "path": "tests/fuzz/simple_round_trip.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/**\n * This fuzz target performs a zstd round-trip test (compress & decompress),\n * compares the result with the original, and calls abort() on corruption.\n */\n\n#define ZSTD_STATIC_LINKING_ONLY\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include \"fuzz_helpers.h\"\n#include \"zstd_helpers.h\"\n#include \"fuzz_data_producer.h\"\n#include \"fuzz_third_party_seq_prod.h\"\n\nstatic ZSTD_CCtx *cctx = NULL;\nstatic ZSTD_DCtx *dctx = NULL;\n\nstatic size_t getDecompressionMargin(void const* compressed, size_t cSize, size_t srcSize, int hasSmallBlocks, int maxBlockSize)\n{\n    size_t margin = ZSTD_decompressionMargin(compressed, cSize);\n    if (!hasSmallBlocks) {\n        /* The macro should be correct in this case, but it may be smaller\n         * because of e.g. block splitting, so take the smaller of the two.\n         */\n        ZSTD_FrameHeader zfh;\n        size_t marginM;\n        FUZZ_ZASSERT(ZSTD_getFrameHeader(&zfh, compressed, cSize));\n        if (maxBlockSize == 0) {\n            maxBlockSize = zfh.blockSizeMax;\n        } else {\n            maxBlockSize = MIN(maxBlockSize, (int)zfh.blockSizeMax);\n        }\n        marginM = ZSTD_DECOMPRESSION_MARGIN(srcSize, maxBlockSize);\n        if (marginM < margin)\n            margin = marginM;\n    }\n    return margin;\n}\n\nstatic size_t roundTripTest(void *result, size_t resultCapacity,\n                            void *compressed, size_t compressedCapacity,\n                            const void *src, size_t srcSize,\n                            FUZZ_dataProducer_t *producer)\n{\n    size_t cSize;\n    size_t dSize;\n    int targetCBlockSize = 0;\n    int maxBlockSize = 0;\n    if (FUZZ_dataProducer_uint32Range(producer, 0, 1)) {\n        size_t const remainingBytes = FUZZ_dataProducer_remainingBytes(producer);\n        FUZZ_setRandomParameters(cctx, srcSize, producer);\n        cSize = ZSTD_compress2(cctx, compressed, compressedCapacity, src, srcSize);\n        FUZZ_ZASSERT(cSize);\n        FUZZ_ZASSERT(ZSTD_CCtx_getParameter(cctx, ZSTD_c_targetCBlockSize, &targetCBlockSize));\n        FUZZ_ZASSERT(ZSTD_CCtx_getParameter(cctx, ZSTD_c_maxBlockSize, &maxBlockSize));\n        // Compress a second time and check for determinism\n        {\n            size_t const cSize0 = cSize;\n            XXH64_hash_t const hash0 = XXH64(compressed, cSize, 0);\n            FUZZ_dataProducer_rollBack(producer, remainingBytes);\n            FUZZ_setRandomParameters(cctx, srcSize, producer);\n            cSize = ZSTD_compress2(cctx, compressed, compressedCapacity, src, srcSize);\n            FUZZ_ASSERT(cSize == cSize0);\n            FUZZ_ASSERT(XXH64(compressed, cSize, 0) == hash0);\n        }\n    } else {\n        int const cLevel = FUZZ_dataProducer_int32Range(producer, kMinClevel, kMaxClevel);\n        cSize = ZSTD_compressCCtx(\n            cctx, compressed, compressedCapacity, src, srcSize, cLevel);\n        FUZZ_ZASSERT(cSize);\n        // Compress a second time and check for determinism\n        {\n            size_t const cSize0 = cSize;\n            XXH64_hash_t const hash0 = XXH64(compressed, cSize, 0);\n            cSize = ZSTD_compressCCtx(\n                cctx, compressed, compressedCapacity, src, srcSize, cLevel);\n            FUZZ_ASSERT(cSize == cSize0);\n            FUZZ_ASSERT(XXH64(compressed, cSize, 0) == hash0);\n        }\n    }\n    if (FUZZ_dataProducer_uint32Range(producer, 0, 1)) {\n        FUZZ_ZASSERT(ZSTD_DCtx_setParameter(dctx, ZSTD_d_maxBlockSize, maxBlockSize));\n    }\n    dSize = ZSTD_decompressDCtx(dctx, result, resultCapacity, compressed, cSize);\n    FUZZ_ZASSERT(dSize);\n    FUZZ_ASSERT_MSG(dSize == srcSize, \"Incorrect regenerated size\");\n    FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, result, dSize), \"Corruption!\");\n\n    {\n        size_t margin = getDecompressionMargin(compressed, cSize, srcSize, targetCBlockSize, maxBlockSize);\n        size_t const outputSize = srcSize + margin;\n        char* const output = (char*)FUZZ_malloc(outputSize);\n        char* const input = output + outputSize - cSize;\n        FUZZ_ASSERT(outputSize >= cSize);\n        memcpy(input, compressed, cSize);\n\n        dSize = ZSTD_decompressDCtx(dctx, output, outputSize, input, cSize);\n        FUZZ_ZASSERT(dSize);\n        FUZZ_ASSERT_MSG(dSize == srcSize, \"Incorrect regenerated size\");\n        FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, output, srcSize), \"Corruption!\");\n\n        free(output);\n    }\n\n    /* When superblock is enabled make sure we don't expand the block more than expected.\n     * NOTE: This test is currently disabled because superblock mode can arbitrarily\n     * expand the block in the worst case. Once superblock mode has been improved we can\n     * re-enable this test.\n     */\n    if (0 && targetCBlockSize != 0) {\n        size_t normalCSize;\n        FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, ZSTD_c_targetCBlockSize, 0));\n        normalCSize = ZSTD_compress2(cctx, compressed, compressedCapacity, src, srcSize);\n        FUZZ_ZASSERT(normalCSize);\n        {\n            size_t const bytesPerBlock = 3 /* block header */\n                + 5 /* Literal header */\n                + 6 /* Huffman jump table */\n                + 3 /* number of sequences */\n                + 1 /* symbol compression modes */;\n            size_t const expectedExpansion = bytesPerBlock * (1 + (normalCSize / MAX(1, targetCBlockSize)));\n            size_t const allowedExpansion = (srcSize >> 3) + 5 * expectedExpansion + 10;\n            FUZZ_ASSERT(cSize <= normalCSize + allowedExpansion);\n        }\n    }\n    return dSize;\n}\n\nint LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)\n{\n    FUZZ_SEQ_PROD_SETUP();\n\n    size_t const rBufSize = size;\n    void* rBuf = FUZZ_malloc(rBufSize);\n    size_t cBufSize = ZSTD_compressBound(size);\n    void* cBuf;\n\n    /* Give a random portion of src data to the producer, to use for\n    parameter generation. The rest will be used for (de)compression */\n    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);\n    size = FUZZ_dataProducer_reserveDataPrefix(producer);\n\n    /* Half of the time fuzz with a 1 byte smaller output size.\n     * This will still succeed because we don't use a dictionary, so the dictID\n     * field is empty, giving us 4 bytes of overhead.\n     */\n    cBufSize -= FUZZ_dataProducer_uint32Range(producer, 0, 1);\n\n    cBuf = FUZZ_malloc(cBufSize);\n\n    if (!cctx) {\n        cctx = ZSTD_createCCtx();\n        FUZZ_ASSERT(cctx);\n    }\n    if (!dctx) {\n        dctx = ZSTD_createDCtx();\n        FUZZ_ASSERT(dctx);\n    }\n\n    roundTripTest(rBuf, rBufSize, cBuf, cBufSize, src, size, producer);\n    free(rBuf);\n    free(cBuf);\n    FUZZ_dataProducer_free(producer);\n#ifndef STATEFUL_FUZZING\n    ZSTD_freeCCtx(cctx); cctx = NULL;\n    ZSTD_freeDCtx(dctx); dctx = NULL;\n#endif\n    FUZZ_SEQ_PROD_TEARDOWN();\n    return 0;\n}\n"
  },
  {
    "path": "tests/fuzz/stream_decompress.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/**\n * This fuzz target attempts to decompress the fuzzed data with the simple\n * decompression function to ensure the decompressor never crashes.\n */\n\n#define ZSTD_STATIC_LINKING_ONLY\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include \"fuzz_helpers.h\"\n#include \"zstd.h\"\n#include \"fuzz_data_producer.h\"\n\nstatic ZSTD_DStream *dstream = NULL;\nuint32_t seed;\n\nstatic ZSTD_outBuffer makeOutBuffer(FUZZ_dataProducer_t *producer, void* buf, size_t bufSize)\n{\n  ZSTD_outBuffer buffer = { buf, 0, 0 };\n\n  if (FUZZ_dataProducer_empty(producer)) {\n    buffer.size = bufSize;\n  } else {\n    buffer.size = (FUZZ_dataProducer_uint32Range(producer, 0, bufSize));\n  }\n  FUZZ_ASSERT(buffer.size <= bufSize);\n\n  if (buffer.size == 0) {\n    buffer.dst = NULL;\n  }\n\n  return buffer;\n}\n\nstatic ZSTD_inBuffer makeInBuffer(const uint8_t **src, size_t *size,\n                                  FUZZ_dataProducer_t *producer)\n{\n  ZSTD_inBuffer buffer = { *src, 0, 0 };\n\n  FUZZ_ASSERT(*size > 0);\n  if (FUZZ_dataProducer_empty(producer)) {\n    buffer.size = *size;\n  } else {\n    buffer.size = (FUZZ_dataProducer_uint32Range(producer, 0, *size));\n  }\n  FUZZ_ASSERT(buffer.size <= *size);\n  *src += buffer.size;\n  *size -= buffer.size;\n\n  if (buffer.size == 0) {\n    buffer.src = NULL;\n  }\n\n  return buffer;\n}\n\nint LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)\n{\n    /* Give a random portion of src data to the producer, to use for\n    parameter generation. The rest will be used for (de)compression */\n    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);\n    int stableOutBuffer;\n    ZSTD_outBuffer out;\n    void* buf;\n    size_t bufSize;\n    size = FUZZ_dataProducer_reserveDataPrefix(producer);\n    bufSize = MAX(10 * size, ZSTD_BLOCKSIZE_MAX);\n\n    /* Allocate all buffers and contexts if not already allocated */\n    buf = FUZZ_malloc(bufSize);\n\n    if (!dstream) {\n        dstream = ZSTD_createDStream();\n        FUZZ_ASSERT(dstream);\n    } else {\n        FUZZ_ZASSERT(ZSTD_DCtx_reset(dstream, ZSTD_reset_session_only));\n    }\n\n    stableOutBuffer = FUZZ_dataProducer_uint32Range(producer, 0, 10) == 5;\n    if (stableOutBuffer) {\n      FUZZ_ZASSERT(ZSTD_DCtx_setParameter(dstream, ZSTD_d_stableOutBuffer, 1));\n      out.dst = buf;\n      out.size = bufSize;\n      out.pos = 0;\n    } else {\n      out = makeOutBuffer(producer, buf, bufSize);\n    }\n\n    while (size > 0) {\n        ZSTD_inBuffer in = makeInBuffer(&src, &size, producer);\n        do {\n            size_t const rc = ZSTD_decompressStream(dstream, &out, &in);\n            if (ZSTD_isError(rc)) goto error;\n            if (out.pos == out.size) {\n                if (stableOutBuffer) goto error;\n                out = makeOutBuffer(producer, buf, bufSize);\n            }\n        } while (in.pos != in.size);\n    }\n\nerror:\n#ifndef STATEFUL_FUZZING\n    ZSTD_freeDStream(dstream); dstream = NULL;\n#endif\n    FUZZ_dataProducer_free(producer);\n    free(buf);\n    return 0;\n}\n"
  },
  {
    "path": "tests/fuzz/stream_round_trip.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/**\n * This fuzz target performs a zstd round-trip test (compress & decompress),\n * compares the result with the original, and calls abort() on corruption.\n */\n\n#define ZSTD_STATIC_LINKING_ONLY\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include \"fuzz_helpers.h\"\n#include \"zstd_helpers.h\"\n#include \"fuzz_data_producer.h\"\n#include \"fuzz_third_party_seq_prod.h\"\n\nZSTD_CCtx *cctx = NULL;\nstatic ZSTD_DCtx *dctx = NULL;\nstatic uint8_t* cBuf = NULL;\nstatic uint8_t* rBuf = NULL;\nstatic size_t bufSize = 0;\n\nstatic ZSTD_outBuffer makeOutBuffer(uint8_t *dst, size_t capacity,\n                                    FUZZ_dataProducer_t *producer)\n{\n    ZSTD_outBuffer buffer = { dst, 0, 0 };\n\n    FUZZ_ASSERT(capacity > 0);\n    buffer.size = (FUZZ_dataProducer_uint32Range(producer, 1, capacity));\n    FUZZ_ASSERT(buffer.size <= capacity);\n\n    return buffer;\n}\n\nstatic ZSTD_inBuffer makeInBuffer(const uint8_t **src, size_t *size,\n                                  FUZZ_dataProducer_t *producer)\n{\n    ZSTD_inBuffer buffer = { *src, 0, 0 };\n\n    FUZZ_ASSERT(*size > 0);\n    buffer.size = (FUZZ_dataProducer_uint32Range(producer, 1, *size));\n    FUZZ_ASSERT(buffer.size <= *size);\n    *src += buffer.size;\n    *size -= buffer.size;\n\n    return buffer;\n}\n\nstatic size_t compress(uint8_t *dst, size_t capacity,\n                       const uint8_t *src, size_t srcSize,\n                     FUZZ_dataProducer_t *producer)\n{\n    size_t dstSize = 0;\n    ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);\n    FUZZ_setRandomParameters(cctx, srcSize, producer);\n    int maxBlockSize;\n    FUZZ_ZASSERT(ZSTD_CCtx_getParameter(cctx, ZSTD_c_maxBlockSize, &maxBlockSize));\n\n    while (srcSize > 0) {\n        ZSTD_inBuffer in = makeInBuffer(&src, &srcSize, producer);\n        /* Mode controls the action. If mode == -1 we pick a new mode */\n        int mode = -1;\n        while (in.pos < in.size || mode != -1) {\n            ZSTD_outBuffer out = makeOutBuffer(dst, capacity, producer);\n            /* Previous action finished, pick a new mode. */\n            if (mode == -1) mode = FUZZ_dataProducer_uint32Range(producer, 0, 9);\n            switch (mode) {\n                case 0: /* fall-through */\n                case 1: /* fall-through */\n                case 2: {\n                    size_t const ret =\n                        ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush);\n                    FUZZ_ZASSERT(ret);\n                    if (ret == 0)\n                        mode = -1;\n                    break;\n                }\n                case 3: {\n                    size_t ret =\n                        ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end);\n                    FUZZ_ZASSERT(ret);\n                    /* Reset the compressor when the frame is finished */\n                    if (ret == 0) {\n                        ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);\n                        if (FUZZ_dataProducer_uint32Range(producer, 0, 7) == 0) {\n                            size_t const remaining = in.size - in.pos;\n                            FUZZ_setRandomParameters(cctx, remaining, producer);\n                            /* Always use the same maxBlockSize */\n                            FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, maxBlockSize));\n                        }\n                        mode = -1;\n                    }\n                    break;\n                }\n                case 4: {\n                    ZSTD_inBuffer nullIn = { NULL, 0, 0 };\n                    ZSTD_outBuffer nullOut = { NULL, 0, 0 };\n                    size_t const ret = ZSTD_compressStream2(cctx, &nullOut, &nullIn, ZSTD_e_continue);\n                    FUZZ_ZASSERT(ret);\n                }\n                /* fall-through */\n                default: {\n                    size_t const ret =\n                        ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue);\n                    FUZZ_ZASSERT(ret);\n                    mode = -1;\n                }\n            }\n            dst += out.pos;\n            dstSize += out.pos;\n            capacity -= out.pos;\n        }\n    }\n    for (;;) {\n        ZSTD_inBuffer in = {NULL, 0, 0};\n        ZSTD_outBuffer out = makeOutBuffer(dst, capacity, producer);\n        size_t const ret = ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end);\n        FUZZ_ZASSERT(ret);\n\n        dst += out.pos;\n        dstSize += out.pos;\n        capacity -= out.pos;\n        if (ret == 0)\n            break;\n    }\n    return dstSize;\n}\n\nstatic size_t decompress(void* dst, size_t dstCapacity, void const* src, size_t srcSize, FUZZ_dataProducer_t* producer)\n{\n    ZSTD_inBuffer in = {src, srcSize, 0};\n    ZSTD_outBuffer out = {dst, dstCapacity, 0};\n    int maxBlockSize;\n    FUZZ_ZASSERT(ZSTD_CCtx_getParameter(cctx, ZSTD_c_maxBlockSize, &maxBlockSize));\n    if (FUZZ_dataProducer_uint32Range(producer, 0, 1)) {\n        FUZZ_ZASSERT(ZSTD_DCtx_setParameter(dctx, ZSTD_d_maxBlockSize, maxBlockSize));\n    }\n    while (in.pos < in.size) {\n        size_t const ret = ZSTD_decompressStream(dctx, &out, &in);\n        FUZZ_ZASSERT(ret);\n        FUZZ_ASSERT(ret == 0);\n    }\n    return out.pos;\n}\n\nint LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)\n{\n    FUZZ_SEQ_PROD_SETUP();\n    size_t neededBufSize;\n\n    /* Give a random portion of src data to the producer, to use for\n    parameter generation. The rest will be used for (de)compression */\n    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);\n    size = FUZZ_dataProducer_reserveDataPrefix(producer);\n\n    neededBufSize = ZSTD_compressBound(size) * 15;\n\n    /* Allocate all buffers and contexts if not already allocated */\n    if (neededBufSize > bufSize) {\n        free(cBuf);\n        free(rBuf);\n        cBuf = (uint8_t*)FUZZ_malloc(neededBufSize);\n        rBuf = (uint8_t*)FUZZ_malloc(neededBufSize);\n        bufSize = neededBufSize;\n    }\n    if (!cctx) {\n        cctx = ZSTD_createCCtx();\n        FUZZ_ASSERT(cctx);\n    }\n    if (!dctx) {\n        dctx = ZSTD_createDCtx();\n        FUZZ_ASSERT(dctx);\n    }\n\n    {\n        size_t const cSize = compress(cBuf, neededBufSize, src, size, producer);\n        size_t const rSize = decompress(rBuf, neededBufSize, cBuf, cSize, producer);\n        FUZZ_ZASSERT(rSize);\n        FUZZ_ASSERT_MSG(rSize == size, \"Incorrect regenerated size\");\n        FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, rBuf, size), \"Corruption!\");\n\n        /* Test in-place decompression (note the macro doesn't work in this case) */\n        {\n            size_t const margin = ZSTD_decompressionMargin(cBuf, cSize);\n            size_t const outputSize = size + margin;\n            char* const output = (char*)FUZZ_malloc(outputSize);\n            char* const input = output + outputSize - cSize;\n            size_t dSize;\n            FUZZ_ASSERT(outputSize >= cSize);\n            memcpy(input, cBuf, cSize);\n\n            dSize = ZSTD_decompressDCtx(dctx, output, outputSize, input, cSize);\n            FUZZ_ZASSERT(dSize);\n            FUZZ_ASSERT_MSG(dSize == size, \"Incorrect regenerated size\");\n            FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, output, size), \"Corruption!\");\n\n            free(output);\n        }\n    }\n\n    FUZZ_dataProducer_free(producer);\n#ifndef STATEFUL_FUZZING\n    ZSTD_freeCCtx(cctx); cctx = NULL;\n    ZSTD_freeDCtx(dctx); dctx = NULL;\n#endif\n    FUZZ_SEQ_PROD_TEARDOWN();\n    return 0;\n}\n"
  },
  {
    "path": "tests/fuzz/zstd_frame_info.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/**\n * This fuzz target fuzzes all of the helper functions that consume compressed\n * input.\n */\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include \"fuzz_helpers.h\"\n#include \"zstd_helpers.h\"\n\nint LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)\n{\n    ZSTD_FrameHeader zfh;\n    if (size == 0) {\n        src = NULL;\n   }\n    /* You can fuzz any helper functions here that are fast, and take zstd\n     * compressed data as input. E.g. don't expect the input to be a dictionary,\n     * so don't fuzz ZSTD_getDictID_fromDict().\n     */\n    ZSTD_getFrameContentSize(src, size);\n    ZSTD_getDecompressedSize(src, size);\n    ZSTD_findFrameCompressedSize(src, size);\n    ZSTD_getDictID_fromFrame(src, size);\n    ZSTD_findDecompressedSize(src, size);\n    ZSTD_decompressBound(src, size);\n    ZSTD_frameHeaderSize(src, size);\n    ZSTD_isFrame(src, size);\n    ZSTD_getFrameHeader(&zfh, src, size);\n    ZSTD_getFrameHeader_advanced(&zfh, src, size, ZSTD_f_zstd1);\n    return 0;\n}\n"
  },
  {
    "path": "tests/fuzz/zstd_helpers.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#define ZSTD_STATIC_LINKING_ONLY\n#define ZDICT_STATIC_LINKING_ONLY\n\n#include <string.h>\n\n#include \"zstd_helpers.h\"\n#include \"fuzz_helpers.h\"\n#include \"zstd.h\"\n#include \"zdict.h\"\n#include \"sequence_producer.h\"\n#include \"fuzz_third_party_seq_prod.h\"\n\nconst int kMinClevel = -3;\nconst int kMaxClevel = 19;\n\nvoid* FUZZ_seqProdState = NULL;\n\nstatic void set(ZSTD_CCtx *cctx, ZSTD_cParameter param, int value)\n{\n    FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, param, value));\n}\n\nstatic unsigned produceParamValue(unsigned min, unsigned max,\n                                  FUZZ_dataProducer_t *producer) {\n    return FUZZ_dataProducer_uint32Range(producer, min, max);\n}\n\nstatic void setRand(ZSTD_CCtx *cctx, ZSTD_cParameter param, unsigned min,\n                    unsigned max, FUZZ_dataProducer_t *producer) {\n    unsigned const value = produceParamValue(min, max, producer);\n    set(cctx, param, value);\n}\n\nZSTD_compressionParameters FUZZ_randomCParams(size_t srcSize, FUZZ_dataProducer_t *producer)\n{\n    /* Select compression parameters */\n    ZSTD_compressionParameters cParams;\n    cParams.windowLog = FUZZ_dataProducer_uint32Range(producer, ZSTD_WINDOWLOG_MIN, 15);\n    cParams.hashLog = FUZZ_dataProducer_uint32Range(producer, ZSTD_HASHLOG_MIN, 15);\n    cParams.chainLog = FUZZ_dataProducer_uint32Range(producer, ZSTD_CHAINLOG_MIN, 16);\n    cParams.searchLog = FUZZ_dataProducer_uint32Range(producer, ZSTD_SEARCHLOG_MIN, 9);\n    cParams.minMatch = FUZZ_dataProducer_uint32Range(producer, ZSTD_MINMATCH_MIN,\n                                          ZSTD_MINMATCH_MAX);\n    cParams.targetLength = FUZZ_dataProducer_uint32Range(producer, 0, 512);\n    cParams.strategy = FUZZ_dataProducer_uint32Range(producer, ZSTD_STRATEGY_MIN, ZSTD_STRATEGY_MAX);\n    return ZSTD_adjustCParams(cParams, srcSize, 0);\n}\n\nZSTD_frameParameters FUZZ_randomFParams(FUZZ_dataProducer_t *producer)\n{\n    /* Select frame parameters */\n    ZSTD_frameParameters fParams;\n    fParams.contentSizeFlag = FUZZ_dataProducer_uint32Range(producer, 0, 1);\n    fParams.checksumFlag = FUZZ_dataProducer_uint32Range(producer, 0, 1);\n    fParams.noDictIDFlag = FUZZ_dataProducer_uint32Range(producer, 0, 1);\n    return fParams;\n}\n\nZSTD_parameters FUZZ_randomParams(size_t srcSize, FUZZ_dataProducer_t *producer)\n{\n    ZSTD_parameters params;\n    params.cParams = FUZZ_randomCParams(srcSize, producer);\n    params.fParams = FUZZ_randomFParams(producer);\n    return params;\n}\n\nstatic void setSequenceProducerParams(ZSTD_CCtx *cctx, FUZZ_dataProducer_t *producer) {\n#ifdef FUZZ_THIRD_PARTY_SEQ_PROD\n    ZSTD_registerSequenceProducer(\n        cctx,\n        FUZZ_seqProdState,\n        FUZZ_thirdPartySeqProd\n    );\n#else\n    ZSTD_registerSequenceProducer(\n        cctx,\n        NULL,\n        simpleSequenceProducer\n    );\n#endif\n\n#ifdef FUZZ_THIRD_PARTY_SEQ_PROD\n    FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableSeqProducerFallback, 1));\n#else\n    setRand(cctx, ZSTD_c_enableSeqProducerFallback, 0, 1, producer);\n#endif\n    FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 0));\n    FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_disable));\n}\n\nvoid FUZZ_setRandomParameters(ZSTD_CCtx *cctx, size_t srcSize, FUZZ_dataProducer_t *producer)\n{\n    ZSTD_compressionParameters cParams = FUZZ_randomCParams(srcSize, producer);\n    set(cctx, ZSTD_c_windowLog, cParams.windowLog);\n    set(cctx, ZSTD_c_hashLog, cParams.hashLog);\n    set(cctx, ZSTD_c_chainLog, cParams.chainLog);\n    set(cctx, ZSTD_c_searchLog, cParams.searchLog);\n    set(cctx, ZSTD_c_minMatch, cParams.minMatch);\n    set(cctx, ZSTD_c_targetLength, cParams.targetLength);\n    set(cctx, ZSTD_c_strategy, cParams.strategy);\n    /* Select frame parameters */\n    setRand(cctx, ZSTD_c_contentSizeFlag, 0, 1, producer);\n    setRand(cctx, ZSTD_c_checksumFlag, 0, 1, producer);\n    setRand(cctx, ZSTD_c_dictIDFlag, 0, 1, producer);\n    /* Select long distance matching parameters */\n    setRand(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_auto, ZSTD_ps_disable, producer);\n    setRand(cctx, ZSTD_c_ldmHashLog, ZSTD_HASHLOG_MIN, 16, producer);\n    setRand(cctx, ZSTD_c_ldmMinMatch, ZSTD_LDM_MINMATCH_MIN,\n            ZSTD_LDM_MINMATCH_MAX, producer);\n    setRand(cctx, ZSTD_c_ldmBucketSizeLog, 0, ZSTD_LDM_BUCKETSIZELOG_MAX,\n            producer);\n    setRand(cctx, ZSTD_c_ldmHashRateLog, ZSTD_LDM_HASHRATELOG_MIN,\n            ZSTD_LDM_HASHRATELOG_MAX, producer);\n    /* Set misc parameters */\n#ifndef ZSTD_MULTITHREAD\n    // To reproduce with or without ZSTD_MULTITHREAD, we are going to use\n    // the same amount of entropy.\n    unsigned const nbWorkers_value = produceParamValue(0, 2, producer);\n    unsigned const rsyncable_value = produceParamValue(0, 1, producer);\n    (void)nbWorkers_value;\n    (void)rsyncable_value;\n    set(cctx, ZSTD_c_nbWorkers, 0);\n    set(cctx, ZSTD_c_rsyncable, 0);\n#else\n    setRand(cctx, ZSTD_c_nbWorkers, 0, 2, producer);\n    setRand(cctx, ZSTD_c_rsyncable, 0, 1, producer);\n#endif\n    setRand(cctx, ZSTD_c_useRowMatchFinder, 0, 2, producer);\n    setRand(cctx, ZSTD_c_enableDedicatedDictSearch, 0, 1, producer);\n    setRand(cctx, ZSTD_c_forceMaxWindow, 0, 1, producer);\n    setRand(cctx, ZSTD_c_literalCompressionMode, 0, 2, producer);\n    setRand(cctx, ZSTD_c_forceAttachDict, 0, 2, producer);\n    setRand(cctx, ZSTD_c_blockSplitterLevel, 0, ZSTD_BLOCKSPLITTER_LEVEL_MAX, producer);\n    setRand(cctx, ZSTD_c_splitAfterSequences, 0, 2, producer);\n    setRand(cctx, ZSTD_c_deterministicRefPrefix, 0, 1, producer);\n    setRand(cctx, ZSTD_c_prefetchCDictTables, 0, 2, producer);\n    setRand(cctx, ZSTD_c_maxBlockSize, ZSTD_BLOCKSIZE_MAX_MIN, ZSTD_BLOCKSIZE_MAX, producer);\n    setRand(cctx, ZSTD_c_validateSequences, 0, 1, producer);\n    setRand(cctx, ZSTD_c_repcodeResolution, 0, 2, producer);\n    if (FUZZ_dataProducer_uint32Range(producer, 0, 1) == 0) {\n      setRand(cctx, ZSTD_c_srcSizeHint, ZSTD_SRCSIZEHINT_MIN, 2 * srcSize, producer);\n    }\n    if (FUZZ_dataProducer_uint32Range(producer, 0, 1) == 0) {\n      setRand(cctx, ZSTD_c_targetCBlockSize, ZSTD_TARGETCBLOCKSIZE_MIN, ZSTD_TARGETCBLOCKSIZE_MAX, producer);\n    }\n\n#ifdef FUZZ_THIRD_PARTY_SEQ_PROD\n    setSequenceProducerParams(cctx, producer);\n#else\n    if (FUZZ_dataProducer_uint32Range(producer, 0, 10) == 1) {\n        setSequenceProducerParams(cctx, producer);\n    } else {\n        ZSTD_registerSequenceProducer(cctx, NULL, NULL);\n    }\n#endif\n}\n\nFUZZ_dict_t FUZZ_train(void const* src, size_t srcSize, FUZZ_dataProducer_t *producer)\n{\n    size_t const dictSize = MAX(srcSize / 8, 1024);\n    size_t const totalSampleSize = dictSize * 11;\n    FUZZ_dict_t dict = { FUZZ_malloc(dictSize), dictSize };\n    char* const samples = (char*)FUZZ_malloc(totalSampleSize);\n    unsigned nbSamples = 100;\n    size_t* const samplesSizes = (size_t*)FUZZ_malloc(sizeof(size_t) * nbSamples);\n    size_t pos = 0;\n    size_t sample = 0;\n    ZDICT_fastCover_params_t params;\n\n    for (sample = 0; sample < nbSamples; ++sample) {\n      size_t const remaining = totalSampleSize - pos;\n      size_t const offset = FUZZ_dataProducer_uint32Range(producer, 0, MAX(srcSize, 1) - 1);\n      size_t const limit = MIN(srcSize - offset, remaining);\n      size_t const toCopy = MIN(limit, remaining / (nbSamples - sample));\n      memcpy(samples + pos, (const char*)src + offset, toCopy);\n      pos += toCopy;\n      samplesSizes[sample] = toCopy;\n    }\n    memset(samples + pos, 0, totalSampleSize - pos);\n\n    memset(&params, 0, sizeof(params));\n    params.accel = 5;\n    params.k = 40;\n    params.d = 8;\n    params.f = 14;\n    params.zParams.compressionLevel = 1;\n    dict.size = ZDICT_trainFromBuffer_fastCover(dict.buff, dictSize,\n        samples, samplesSizes, nbSamples, params);\n    if (ZSTD_isError(dict.size)) {\n        free(dict.buff);\n        memset(&dict, 0, sizeof(dict));\n    }\n\n    free(samplesSizes);\n    free(samples);\n\n    return dict;\n}\n"
  },
  {
    "path": "tests/fuzz/zstd_helpers.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n/**\n * Helper functions for fuzzing.\n */\n\n#ifndef ZSTD_HELPERS_H\n#define ZSTD_HELPERS_H\n\n#define ZSTD_STATIC_LINKING_ONLY\n\n#include \"zstd.h\"\n#include \"zstd_errors.h\"\n#include \"fuzz_data_producer.h\"\n#include <stdint.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern const int kMinClevel;\nextern const int kMaxClevel;\n\nvoid FUZZ_setRandomParameters(ZSTD_CCtx *cctx, size_t srcSize, FUZZ_dataProducer_t *producer);\n\nZSTD_compressionParameters FUZZ_randomCParams(size_t srcSize, FUZZ_dataProducer_t *producer);\nZSTD_frameParameters FUZZ_randomFParams(FUZZ_dataProducer_t *producer);\nZSTD_parameters FUZZ_randomParams(size_t srcSize, FUZZ_dataProducer_t *producer);\n\ntypedef struct {\n  void* buff;\n  size_t size;\n} FUZZ_dict_t;\n\n/* Quickly train a dictionary from a source for fuzzing.\n * NOTE: Don't use this to train production dictionaries, it is only optimized\n * for speed, and doesn't care about dictionary quality.\n */\nFUZZ_dict_t FUZZ_train(void const* src, size_t srcSize, FUZZ_dataProducer_t *producer);\n\n#ifdef FUZZ_THIRD_PARTY_SEQ_PROD\nextern void* FUZZ_seqProdState;\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* ZSTD_HELPERS_H */\n"
  },
  {
    "path": "tests/fuzzer.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/*-************************************\n*  Compiler specific\n**************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  define _CRT_SECURE_NO_WARNINGS   /* fgets */\n#  pragma warning(disable : 4127)   /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4204)   /* disable: C4204: non-constant aggregate initializer */\n#endif\n\n\n/*-************************************\n*  Includes\n**************************************/\n#include <stdlib.h>       /* free */\n#include <stdio.h>        /* fgets, sscanf */\n#include <string.h>       /* strcmp */\n#include <time.h>         /* time(), time_t */\n#undef NDEBUG             /* always enable assert() */\n#include <assert.h>\n#define ZSTD_STATIC_LINKING_ONLY  /* ZSTD_compressContinue, ZSTD_compressBlock */\n#include \"debug.h\"        /* DEBUG_STATIC_ASSERT */\n#include \"fse.h\"\n#define ZSTD_DISABLE_DEPRECATE_WARNINGS /* No deprecation warnings, we still test some deprecated functions */\n#include \"zstd.h\"         /* ZSTD_VERSION_STRING */\n#include \"zstd_errors.h\"  /* ZSTD_getErrorCode */\n#define ZDICT_STATIC_LINKING_ONLY\n#include \"zdict.h\"        /* ZDICT_trainFromBuffer */\n#include \"mem.h\"\n#include \"datagen.h\"      /* RDG_genBuffer */\n#define XXH_STATIC_LINKING_ONLY   /* XXH64_state_t */\n#include \"xxhash.h\"       /* XXH64 */\n#include \"timefn.h\"       /* SEC_TO_MICRO, UTIL_time_t, UTIL_TIME_INITIALIZER, UTIL_clockSpanMicro, UTIL_getTime */\n/* must be included after util.h, due to ERROR macro redefinition issue on Visual Studio */\n#include \"zstd_internal.h\" /* ZSTD_WORKSPACETOOLARGE_MAXDURATION, ZSTD_WORKSPACETOOLARGE_FACTOR, KB, MB */\n#include \"threading.h\"    /* ZSTD_pthread_create, ZSTD_pthread_join */\n#include \"compress/hist.h\" /* HIST_count_wksp */\n#include \"compress/zstd_compress_internal.h\" /* ZSTD_get1BlockSummary */\n\n\n/*-************************************\n*  Macros\n**************************************/\n#define COUNTOF(array)    (sizeof(array) / sizeof(*(array)))\n\n\n/*-************************************\n*  Constants\n**************************************/\n#define GB *(1U<<30)\n\nstatic const int FUZ_compressibility_default = 50;\nstatic const int nbTestsDefault = 30000;\n\n\n/*-************************************\n*  Display Macros\n**************************************/\n#define DISPLAY(...)          fprintf(stderr, __VA_ARGS__)\n#define DISPLAYLEVEL(l, ...)  if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); }\nstatic U32 g_displayLevel = 2;\n\nstatic const U64 g_refreshRate = SEC_TO_MICRO / 6;\nstatic UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER;\n\n#define DISPLAYUPDATE(l, ...) \\\n    if (g_displayLevel>=l) { \\\n        if ((UTIL_clockSpanMicro(g_displayClock) > g_refreshRate) || (g_displayLevel>=4)) \\\n        { g_displayClock = UTIL_getTime(); DISPLAY(__VA_ARGS__); \\\n        if (g_displayLevel>=4) fflush(stderr); } \\\n    }\n\n\n/*-*******************************************************\n*  Compile time test\n*********************************************************/\n#undef MIN\n#undef MAX\n/* Declaring the function, to avoid -Wmissing-prototype */\nvoid FUZ_bug976(void);\nvoid FUZ_bug976(void)\n{   /* these constants shall not depend on MIN() macro */\n    DEBUG_STATIC_ASSERT(ZSTD_HASHLOG_MAX < 31);\n    DEBUG_STATIC_ASSERT(ZSTD_CHAINLOG_MAX < 31);\n}\n\n\n/*-*******************************************************\n*  Internal functions\n*********************************************************/\n#define MIN(a,b) ((a)<(b)?(a):(b))\n#define MAX(a,b) ((a)>(b)?(a):(b))\n\n#define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r)))\nstatic U32 FUZ_rand(U32* src)\n{\n    static const U32 prime1 = 2654435761U;\n    static const U32 prime2 = 2246822519U;\n    U32 rand32 = *src;\n    rand32 *= prime1;\n    rand32 += prime2;\n    rand32  = FUZ_rotl32(rand32, 13);\n    *src = rand32;\n    return rand32 >> 5;\n}\n\nstatic U32 FUZ_highbit32(U32 v32)\n{\n    unsigned nbBits = 0;\n    if (v32==0) return 0;\n    while (v32) v32 >>= 1, nbBits++;\n    return nbBits;\n}\n\n\n/*=============================================\n*   Test macros\n=============================================*/\n#define CHECK(fn)  { if(!(fn)) { DISPLAYLEVEL(1, \"Error : test (%s) failed \\n\", #fn); exit(1); } }\n\n#define CHECK_Z(f) {                          \\\n    size_t const err = f;                     \\\n    if (ZSTD_isError(err)) {                  \\\n        DISPLAY(\"Error => %s : %s \",          \\\n                #f, ZSTD_getErrorName(err));  \\\n        exit(1);                              \\\n}   }\n\n#define CHECK_VAR(var, fn)  var = fn; if (ZSTD_isError(var)) { DISPLAYLEVEL(1, \"%s : fails : %s \\n\", #fn, ZSTD_getErrorName(var)); exit(1); }\n#define CHECK_NEWV(var, fn)  size_t const CHECK_VAR(var, fn)\n#define CHECKPLUS(var, fn, more)  { CHECK_NEWV(var, fn); more; }\n\n#define CHECK_OP(op, lhs, rhs) {                                  \\\n    if (!((lhs) op (rhs))) {                                      \\\n        DISPLAY(\"Error L%u => FAILED %s %s %s \", __LINE__, #lhs, #op, #rhs);  \\\n         exit(1);                                                 \\\n    }                                                             \\\n}\n#define CHECK_EQ(lhs, rhs) CHECK_OP(==, lhs, rhs)\n#define CHECK_LT(lhs, rhs) CHECK_OP(<, lhs, rhs)\n\n\n/*=============================================\n*   Memory Tests\n=============================================*/\n#if defined(__APPLE__) && defined(__MACH__)\n\n#include <malloc/malloc.h>    /* malloc_size */\n\ntypedef struct {\n    unsigned long long totalMalloc;\n    size_t currentMalloc;\n    size_t peakMalloc;\n    unsigned nbMalloc;\n    unsigned nbFree;\n} mallocCounter_t;\n\nstatic const mallocCounter_t INIT_MALLOC_COUNTER = { 0, 0, 0, 0, 0 };\n\nstatic void* FUZ_mallocDebug(void* counter, size_t size)\n{\n    mallocCounter_t* const mcPtr = (mallocCounter_t*)counter;\n    void* const ptr = malloc(size);\n    if (ptr==NULL) return NULL;\n    DISPLAYLEVEL(4, \"allocating %u KB => effectively %u KB \\n\",\n        (unsigned)(size >> 10), (unsigned)(malloc_size(ptr) >> 10));  /* OS-X specific */\n    mcPtr->totalMalloc += size;\n    mcPtr->currentMalloc += size;\n    if (mcPtr->currentMalloc > mcPtr->peakMalloc)\n        mcPtr->peakMalloc = mcPtr->currentMalloc;\n    mcPtr->nbMalloc += 1;\n    return ptr;\n}\n\nstatic void FUZ_freeDebug(void* counter, void* address)\n{\n    mallocCounter_t* const mcPtr = (mallocCounter_t*)counter;\n    DISPLAYLEVEL(4, \"freeing %u KB \\n\", (unsigned)(malloc_size(address) >> 10));\n    mcPtr->nbFree += 1;\n    mcPtr->currentMalloc -= malloc_size(address);  /* OS-X specific */\n    free(address);\n}\n\nstatic void FUZ_displayMallocStats(mallocCounter_t count)\n{\n    DISPLAYLEVEL(3, \"peak:%6u KB,  nbMallocs:%2u, total:%6u KB \\n\",\n        (unsigned)(count.peakMalloc >> 10),\n        count.nbMalloc,\n        (unsigned)(count.totalMalloc >> 10));\n}\n\nstatic int FUZ_mallocTests_internal(unsigned seed, double compressibility, unsigned part,\n                void* inBuffer, size_t inSize, void* outBuffer, size_t outSize)\n{\n    /* test only played in verbose mode, as they are long */\n    if (g_displayLevel<3) return 0;\n\n    /* Create compressible noise */\n    if (!inBuffer || !outBuffer) {\n        DISPLAY(\"Not enough memory, aborting\\n\");\n        exit(1);\n    }\n    RDG_genBuffer(inBuffer, inSize, compressibility, 0. /*auto*/, seed);\n\n    /* simple compression tests */\n    if (part <= 1)\n    {   int compressionLevel;\n        for (compressionLevel=1; compressionLevel<=6; compressionLevel++) {\n            mallocCounter_t malcount = INIT_MALLOC_COUNTER;\n            ZSTD_customMem const cMem = { FUZ_mallocDebug, FUZ_freeDebug, &malcount };\n            ZSTD_CCtx* const cctx = ZSTD_createCCtx_advanced(cMem);\n            CHECK_Z( ZSTD_compressCCtx(cctx, outBuffer, outSize, inBuffer, inSize, compressionLevel) );\n            ZSTD_freeCCtx(cctx);\n            DISPLAYLEVEL(3, \"compressCCtx level %i : \", compressionLevel);\n            FUZ_displayMallocStats(malcount);\n    }   }\n\n    /* streaming compression tests */\n    if (part <= 2)\n    {   int compressionLevel;\n        for (compressionLevel=1; compressionLevel<=6; compressionLevel++) {\n            mallocCounter_t malcount = INIT_MALLOC_COUNTER;\n            ZSTD_customMem const cMem = { FUZ_mallocDebug, FUZ_freeDebug, &malcount };\n            ZSTD_CCtx* const cstream = ZSTD_createCStream_advanced(cMem);\n            ZSTD_outBuffer out = { outBuffer, outSize, 0 };\n            ZSTD_inBuffer in = { inBuffer, inSize, 0 };\n            CHECK_Z( ZSTD_initCStream(cstream, compressionLevel) );\n            CHECK_Z( ZSTD_compressStream(cstream, &out, &in) );\n            CHECK_Z( ZSTD_endStream(cstream, &out) );\n            ZSTD_freeCStream(cstream);\n            DISPLAYLEVEL(3, \"compressStream level %i : \", compressionLevel);\n            FUZ_displayMallocStats(malcount);\n    }   }\n\n    /* advanced MT API test */\n    if (part <= 3)\n    {   int nbThreads;\n        for (nbThreads=1; nbThreads<=4; nbThreads++) {\n            int compressionLevel;\n            for (compressionLevel=1; compressionLevel<=6; compressionLevel++) {\n                mallocCounter_t malcount = INIT_MALLOC_COUNTER;\n                ZSTD_customMem const cMem = { FUZ_mallocDebug, FUZ_freeDebug, &malcount };\n                ZSTD_CCtx* const cctx = ZSTD_createCCtx_advanced(cMem);\n                CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, compressionLevel) );\n                CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, nbThreads) );\n                CHECK_Z( ZSTD_compress2(cctx, outBuffer, outSize, inBuffer, inSize) );\n                ZSTD_freeCCtx(cctx);\n                DISPLAYLEVEL(3, \"compress_generic,-T%i,end level %i : \",\n                                nbThreads, compressionLevel);\n                FUZ_displayMallocStats(malcount);\n    }   }   }\n\n    /* advanced MT streaming API test */\n    if (part <= 4)\n    {   int nbThreads;\n        for (nbThreads=1; nbThreads<=4; nbThreads++) {\n            int compressionLevel;\n            for (compressionLevel=1; compressionLevel<=6; compressionLevel++) {\n                mallocCounter_t malcount = INIT_MALLOC_COUNTER;\n                ZSTD_customMem const cMem = { FUZ_mallocDebug, FUZ_freeDebug, &malcount };\n                ZSTD_CCtx* const cctx = ZSTD_createCCtx_advanced(cMem);\n                ZSTD_outBuffer out = { outBuffer, outSize, 0 };\n                ZSTD_inBuffer in = { inBuffer, inSize, 0 };\n                CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, compressionLevel) );\n                CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, nbThreads) );\n                CHECK_Z( ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue) );\n                while ( ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end) ) {}\n                ZSTD_freeCCtx(cctx);\n                DISPLAYLEVEL(3, \"compress_generic,-T%i,continue level %i : \",\n                                nbThreads, compressionLevel);\n                FUZ_displayMallocStats(malcount);\n    }   }   }\n\n    return 0;\n}\n\nstatic int FUZ_mallocTests(unsigned seed, double compressibility, unsigned part)\n{\n    size_t const inSize = 64 MB + 16 MB + 4 MB + 1 MB + 256 KB + 64 KB; /* 85.3 MB */\n    size_t const outSize = ZSTD_compressBound(inSize);\n    void* const inBuffer = malloc(inSize);\n    void* const outBuffer = malloc(outSize);\n    int result;\n\n    /* Create compressible noise */\n    if (!inBuffer || !outBuffer) {\n        DISPLAY(\"Not enough memory, aborting \\n\");\n        exit(1);\n    }\n\n    result = FUZ_mallocTests_internal(seed, compressibility, part,\n                    inBuffer, inSize, outBuffer, outSize);\n\n    free(inBuffer);\n    free(outBuffer);\n    return result;\n}\n\n#else\n\nstatic int FUZ_mallocTests(unsigned seed, double compressibility, unsigned part)\n{\n    (void)seed; (void)compressibility; (void)part;\n    return 0;\n}\n\n#endif\n\nstatic void FUZ_decodeSequences(BYTE* dst, ZSTD_Sequence* seqs, size_t seqsSize,\n                                BYTE* src, size_t size, ZSTD_SequenceFormat_e format)\n{\n    size_t i;\n    size_t j;\n    for(i = 0; i < seqsSize; ++i) {\n        assert(dst + seqs[i].litLength + seqs[i].matchLength <= dst + size);\n        assert(src + seqs[i].litLength + seqs[i].matchLength <= src + size);\n        if (format == ZSTD_sf_noBlockDelimiters) {\n            assert(seqs[i].matchLength != 0 || seqs[i].offset != 0);\n        }\n\n        memcpy(dst, src, seqs[i].litLength);\n        dst += seqs[i].litLength;\n        src += seqs[i].litLength;\n        size -= seqs[i].litLength;\n\n        if (seqs[i].offset != 0) {\n            for (j = 0; j < seqs[i].matchLength; ++j)\n                dst[j] = dst[(ptrdiff_t)(j - seqs[i].offset)];\n            dst += seqs[i].matchLength;\n            src += seqs[i].matchLength;\n            size -= seqs[i].matchLength;\n        }\n    }\n    if (format == ZSTD_sf_noBlockDelimiters) {\n        memcpy(dst, src, size);\n    }\n}\n\nstatic size_t FUZ_getLitSize(const ZSTD_Sequence* seqs, size_t nbSeqs)\n{\n    size_t n, litSize = 0;\n    assert(seqs != NULL);\n    for (n=0; n<nbSeqs; n++) {\n        litSize += seqs[n].litLength;\n    }\n    return litSize;\n}\n\nstatic void\nFUZ_transferLiterals(void* dst, size_t dstCapacity,\n                const void* src, size_t srcSize,\n                const ZSTD_Sequence* seqs, size_t nbSeqs)\n{\n    size_t n;\n    const char* ip = (const char*)src;\n    char* op = (char*)dst;\n    size_t const litSize = FUZ_getLitSize(seqs, nbSeqs);\n    assert(litSize <= dstCapacity);\n    for (n=0; n<nbSeqs; n++) {\n        size_t const ll = seqs[n].litLength;\n        memcpy(op, ip, ll);\n        op += ll;\n        ip += ll + seqs[n].matchLength;\n    }\n    assert((size_t)(ip - (const char*)src) == srcSize);\n}\n\n#ifdef ZSTD_MULTITHREAD\n\ntypedef struct {\n    ZSTD_CCtx* cctx;\n    ZSTD_threadPool* pool;\n    void* CNBuffer;\n    size_t CNBuffSize;\n    void* compressedBuffer;\n    size_t compressedBufferSize;\n    void* decodedBuffer;\n    int err;\n} threadPoolTests_compressionJob_payload;\n\nstatic void* threadPoolTests_compressionJob(void* payload) {\n    threadPoolTests_compressionJob_payload* args = (threadPoolTests_compressionJob_payload*)payload;\n    size_t cSize;\n    if (ZSTD_isError(ZSTD_CCtx_refThreadPool(args->cctx, args->pool))) args->err = 1;\n    cSize = ZSTD_compress2(args->cctx, args->compressedBuffer, args->compressedBufferSize, args->CNBuffer, args->CNBuffSize);\n    if (ZSTD_isError(cSize)) args->err = 1;\n    if (ZSTD_isError(ZSTD_decompress(args->decodedBuffer, args->CNBuffSize, args->compressedBuffer, cSize))) args->err = 1;\n    return payload;\n}\n\nstatic int threadPoolTests(void) {\n    int testResult = 0;\n    size_t err;\n\n    size_t const CNBuffSize = 5 MB;\n    void* const CNBuffer = malloc(CNBuffSize);\n    size_t const compressedBufferSize = ZSTD_compressBound(CNBuffSize);\n    void* const compressedBuffer = malloc(compressedBufferSize);\n    void* const decodedBuffer = malloc(CNBuffSize);\n\n    size_t const kPoolNumThreads = 8;\n\n    RDG_genBuffer(CNBuffer, CNBuffSize, 0.5, 0.5, 0);\n\n    DISPLAYLEVEL(3, \"thread pool test : threadPool reuse roundtrips: \");\n    {\n        ZSTD_CCtx* cctx = ZSTD_createCCtx();\n        ZSTD_threadPool* pool = ZSTD_createThreadPool(kPoolNumThreads);\n\n        size_t nbThreads = 1;\n        for (; nbThreads <= kPoolNumThreads; ++nbThreads) {\n            ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n            ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, (int)nbThreads);\n            err = ZSTD_CCtx_refThreadPool(cctx, pool);\n            if (ZSTD_isError(err)) {\n                DISPLAYLEVEL(3, \"refThreadPool error!\\n\");\n                ZSTD_freeCCtx(cctx);\n                goto _output_error;\n            }\n            err = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);\n            if (ZSTD_isError(err)) {\n                DISPLAYLEVEL(3, \"Compression error!\\n\");\n                ZSTD_freeCCtx(cctx);\n                goto _output_error;\n            }\n            err = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, err);\n            if (ZSTD_isError(err)) {\n                DISPLAYLEVEL(3, \"Decompression error!\\n\");\n                ZSTD_freeCCtx(cctx);\n                goto _output_error;\n            }\n        }\n\n        ZSTD_freeCCtx(cctx);\n        ZSTD_freeThreadPool(pool);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"thread pool test : threadPool simultaneous usage: \");\n    {\n        void* const decodedBuffer2 = malloc(CNBuffSize);\n        void* const compressedBuffer2 = malloc(compressedBufferSize);\n        ZSTD_threadPool* pool = ZSTD_createThreadPool(kPoolNumThreads);\n        ZSTD_CCtx* cctx1 = ZSTD_createCCtx();\n        ZSTD_CCtx* cctx2 = ZSTD_createCCtx();\n\n        ZSTD_pthread_t t1;\n        ZSTD_pthread_t t2;\n        threadPoolTests_compressionJob_payload p1 = {cctx1, pool, CNBuffer, CNBuffSize,\n                                                     compressedBuffer, compressedBufferSize, decodedBuffer, 0 /* err */};\n        threadPoolTests_compressionJob_payload p2 = {cctx2, pool, CNBuffer, CNBuffSize,\n                                                     compressedBuffer2, compressedBufferSize, decodedBuffer2, 0 /* err */};\n\n        ZSTD_CCtx_setParameter(cctx1, ZSTD_c_nbWorkers, 2);\n        ZSTD_CCtx_setParameter(cctx2, ZSTD_c_nbWorkers, 2);\n        ZSTD_CCtx_refThreadPool(cctx1, pool);\n        ZSTD_CCtx_refThreadPool(cctx2, pool);\n\n        ZSTD_pthread_create(&t1, NULL, threadPoolTests_compressionJob, &p1);\n        ZSTD_pthread_create(&t2, NULL, threadPoolTests_compressionJob, &p2);\n        ZSTD_pthread_join(t1);\n        ZSTD_pthread_join(t2);\n\n        assert(!memcmp(decodedBuffer, decodedBuffer2, CNBuffSize));\n        free(decodedBuffer2);\n        free(compressedBuffer2);\n\n        ZSTD_freeThreadPool(pool);\n        ZSTD_freeCCtx(cctx1);\n        ZSTD_freeCCtx(cctx2);\n\n        if (p1.err || p2.err) goto _output_error;\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n_end:\n    free(CNBuffer);\n    free(compressedBuffer);\n    free(decodedBuffer);\n    return testResult;\n\n_output_error:\n    testResult = 1;\n    DISPLAY(\"Error detected in Unit tests ! \\n\");\n    goto _end;\n}\n#endif /* ZSTD_MULTITHREAD */\n\n/*=============================================\n*   Unit tests\n=============================================*/\n\nstatic void test_compressBound(unsigned tnb)\n{\n    DISPLAYLEVEL(3, \"test%3u : compressBound : \", tnb);\n\n    /* check ZSTD_compressBound == ZSTD_COMPRESSBOUND\n     * for a large range of known valid values */\n    DEBUG_STATIC_ASSERT(sizeof(size_t) >= 4);\n    {   int s;\n        for (s=0; s<30; s++) {\n            size_t const w = (size_t)1 << s;\n            CHECK_EQ(ZSTD_compressBound(w), ZSTD_COMPRESSBOUND(w));\n    }   }\n\n    /* Ensure error if srcSize too big */\n    {   size_t const w = ZSTD_MAX_INPUT_SIZE + 1;\n        CHECK(ZSTD_isError(ZSTD_compressBound(w))); /* must fail */\n        CHECK_EQ(ZSTD_COMPRESSBOUND(w), 0);\n    }\n\n    DISPLAYLEVEL(3, \"OK \\n\");\n}\n\nstatic void test_decompressBound(unsigned tnb)\n{\n    DISPLAYLEVEL(3, \"test%3u : decompressBound : \", tnb);\n\n    /* Simple compression, with size : should provide size; */\n    {   const char example[] = \"abcd\";\n        char cBuffer[ZSTD_COMPRESSBOUND(sizeof(example))];\n        size_t const cSize = ZSTD_compress(cBuffer, sizeof(cBuffer), example, sizeof(example), 0);\n        CHECK_Z(cSize);\n        CHECK_EQ(ZSTD_decompressBound(cBuffer, cSize), (unsigned long long)sizeof(example));\n    }\n\n    /* Simple small compression without size : should provide 1 block size */\n    {   char cBuffer[ZSTD_COMPRESSBOUND(0)];\n        ZSTD_outBuffer out = { cBuffer, sizeof(cBuffer), 0 };\n        ZSTD_inBuffer in = { NULL, 0, 0 };\n        ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        assert(cctx);\n        CHECK_Z( ZSTD_initCStream(cctx, 0) );\n        CHECK_Z( ZSTD_compressStream(cctx, &out, &in) );\n        CHECK_EQ( ZSTD_endStream(cctx, &out), 0 );\n        CHECK_EQ( ZSTD_decompressBound(cBuffer, out.pos), ZSTD_BLOCKSIZE_MAX );\n        ZSTD_freeCCtx(cctx);\n    }\n\n    /* Attempt to overflow 32-bit intermediate multiplication result\n     * This requires dBound >= 4 GB, aka 2^32.\n     * This requires 2^32 / 2^17 = 2^15 blocks\n     * => create 2^15 blocks (can be empty, or just 1 byte). */\n    {   const char input[] = \"a\";\n        size_t const nbBlocks = (1 << 15) + 1;\n        size_t blockNb;\n        size_t const outCapacity = 1 << 18; /* large margin */\n        char* const outBuffer = malloc (outCapacity);\n        ZSTD_outBuffer out = { outBuffer, outCapacity, 0 };\n        ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        assert(cctx);\n        assert(outBuffer);\n        CHECK_Z( ZSTD_initCStream(cctx, 0) );\n        for (blockNb=0; blockNb<nbBlocks; blockNb++) {\n            ZSTD_inBuffer in = { input, sizeof(input), 0 };\n            CHECK_Z( ZSTD_compressStream(cctx, &out, &in) );\n            CHECK_EQ( ZSTD_flushStream(cctx, &out), 0 );\n        }\n        CHECK_EQ( ZSTD_endStream(cctx, &out), 0 );\n        CHECK( ZSTD_decompressBound(outBuffer, out.pos) > 0x100000000ULL /* 4 GB */ );\n        ZSTD_freeCCtx(cctx);\n        free(outBuffer);\n    }\n\n    DISPLAYLEVEL(3, \"OK \\n\");\n}\n\nstatic unsigned test_histCountWksp(unsigned seed, unsigned testNb)\n{\n    static const unsigned symLowLimits[] =  {   0,  27,   0,   0,  27,  42,   0,   0, 27, 42, 27, 42 };\n    static const unsigned symHighLimits[] = { 255, 255, 210, 110,  42,  42, 210, 110, 42, 42, 42, 42 };\n    static const unsigned symMaxLimits[] =  { 255, 255, 255, 255, 255, 255, 230, 130, 99, 99, 42, 42 };\n    static const size_t inputSizes[] = { 3367, 1761, 893, 117 };\n    unsigned workspace[HIST_WKSP_SIZE_U32];\n    size_t res, i, is, il;\n\n    DISPLAYLEVEL(3, \"test%3u : HIST_count_wksp with empty source : \", testNb++);\n    {\n        /* With NULL source UBSan of older Clang could fail: applying zero offset to null pointer. */\n        static const unsigned char source[4] = { 0 };\n        unsigned count[1] = { 0 };\n        unsigned maxSym = 0;\n        res = HIST_count_wksp(count, &maxSym, source, 0, workspace, sizeof(workspace));\n        CHECK_EQ(res, 0);\n        CHECK_EQ(maxSym, 0);\n        CHECK_EQ(count[0], 0);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n#if HIST_WKSP_SIZE_U32\n    DISPLAYLEVEL(3, \"test%3u : HIST_count_wksp with small workspace : \", testNb++);\n    {\n        unsigned count[1] = { 0 };\n        unsigned maxSym = 0;\n        res = HIST_count_wksp(count, &maxSym, NULL, 0, workspace, sizeof(workspace) - 1);\n        CHECK_EQ(res, ERROR(workSpace_tooSmall));\n        CHECK_EQ(maxSym, 0);\n        CHECK_EQ(count[0], 0);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3u : HIST_count_wksp with wrong workspace alignment : \", testNb++);\n    {\n        unsigned count[1] = { 0 };\n        unsigned maxSym = 0;\n        res = HIST_count_wksp(count, &maxSym, NULL, 0, (unsigned*)(void*)((char*)workspace + 1), sizeof(workspace));\n        CHECK_EQ(res, ERROR(GENERIC));\n        CHECK_EQ(maxSym, 0);\n        CHECK_EQ(count[0], 0);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n#endif\n\n    DISPLAYLEVEL(3, \"test%3u : HIST_count_wksp with symbol out of range, small size : \", testNb++);\n    {\n        /* For less elements HIST_count_parallel_wksp would fail. */\n        static const unsigned char source[4] = { 1, 4, 0, 2 };\n        static const unsigned expected[6] = { 0 };\n        unsigned count[6] = { 0 };\n        unsigned maxSym = 2;\n        res = HIST_count_wksp(count, &maxSym, source, sizeof(source), workspace, sizeof(workspace));\n        CHECK_EQ(res, ERROR(maxSymbolValue_tooSmall));\n        CHECK_EQ(maxSym, 2);\n        for (i = 0; i < COUNTOF(expected); ++i) CHECK_EQ(count[i], expected[i]);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3u : HIST_count_wksp with symbol out of range, medium size : \", testNb++);\n    {\n        unsigned char source[3407];\n        unsigned count[6] = { 0 };\n        unsigned maxSym = 2;\n        for (i = 0; i < COUNTOF(source); ++i) {\n            source[i] = (48271 * (i + 1)) & 3;\n        }\n        res = HIST_count_wksp(count, &maxSym, source, sizeof(source), workspace, sizeof(workspace));\n        CHECK_EQ(res, ERROR(maxSymbolValue_tooSmall));\n        CHECK_EQ(maxSym, 2);\n        for (i = 0; i < COUNTOF(count); ++i) CHECK_EQ(count[i], 0);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    for (il = 0; il < COUNTOF(symMaxLimits); ++il) {\n        unsigned symMax = symMaxLimits[il];\n        unsigned symLow = symLowLimits[il];\n        unsigned symHigh = symHighLimits[il];\n        unsigned symRange = symHigh - symLow + 1;\n\n        for (is = 0; is < COUNTOF(inputSizes); ++is) {\n            unsigned char source[4000];\n            size_t inputSize = inputSizes[is];\n            assert(inputSize <= sizeof(source));\n            DISPLAYLEVEL(3, \"test%3u : HIST_count_wksp test in [%u..%u], symMax: %u, inputSize: %u : \",\n                         testNb++, symLow, symHigh, symMax, (unsigned)inputSize);\n            {\n                unsigned count[260] = { 0 };\n                unsigned expected[COUNTOF(count)] = { 0 };\n                unsigned maxSym = symMax;\n                unsigned realMaxSym = symMax;\n                unsigned maxCount = 0;\n                for (i = 0; i < inputSize; ++i) {\n                    unsigned prng = (48271 * (i + seed)) % symRange + symLow;\n                    source[i] = (unsigned char)prng;\n                    ++expected[prng];\n                }\n                /* for basic buffer overwrite checks */\n                for (i = maxSym + 1; i < COUNTOF(count); ++i) expected[i] = count[i] = ~0u;\n                for (i = 0; i <= maxSym; ++i) maxCount = MAX(maxCount, expected[i]);\n                for (i = realMaxSym; i > 0; --i) {\n                    if (expected[i]) break;\n                    --realMaxSym;\n                }\n                res = HIST_count_wksp(count, &maxSym, source, inputSize, workspace, sizeof(workspace));\n                CHECK_EQ(res, maxCount);\n                CHECK_EQ(maxSym, realMaxSym);\n                for (i = 0; i < COUNTOF(expected); ++i) CHECK_EQ(count[i], expected[i]);\n            }\n            DISPLAYLEVEL(3, \"OK \\n\");\n        }\n    }\n\n    return testNb;\n}\n\nstatic void test_setCParams(unsigned tnb)\n{\n    ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n    ZSTD_compressionParameters cparams;\n    assert(cctx);\n\n    DISPLAYLEVEL(3, \"test%3u : ZSTD_CCtx_setCParams : \", tnb);\n\n    /* valid cparams */\n    cparams = ZSTD_getCParams(1, 0, 0);\n    CHECK_Z(ZSTD_CCtx_setCParams(cctx, cparams));\n\n    /* invalid cparams (must fail) */\n    cparams.windowLog = 99;\n    CHECK(ZSTD_isError(ZSTD_CCtx_setCParams(cctx, cparams)));\n\n    free(cctx);\n    DISPLAYLEVEL(3, \"OK \\n\");\n}\n\nstatic void test_blockSplitter_incompressibleExpansionProtection(unsigned testNb, unsigned seed)\n{\n    DISPLAYLEVEL(3, \"test%3i : Check block splitter doesn't oversplit incompressible data (seed %u): \", testNb, seed);\n    {   ZSTD_CCtx* cctx = ZSTD_createCCtx();\n        size_t const srcSize = 256 * 1024; /* needs to be at least 2 blocks */\n        void* incompressible = malloc(srcSize);\n        size_t const dstCapacity = ZSTD_compressBound(srcSize);\n        void* cBuffer = malloc(dstCapacity);\n        size_t const chunkSize = 8 KB;\n        size_t const nbChunks = srcSize / chunkSize;\n        size_t chunkNb, cSizeNoSplit, cSizeWithSplit;\n        assert(cctx != NULL);\n        assert(incompressible != NULL);\n        assert(cBuffer != NULL);\n\n        /* let's fill input with random noise (incompressible) */\n        RDG_genBuffer(incompressible, srcSize, 0.0, 0.0, seed);\n\n        /* this pattern targets the fastest _byChunk variant's sampling (level 3).\n         * manually checked that, without the @savings protection, it would over-split.\n         */\n        for (chunkNb=0; chunkNb<nbChunks; chunkNb++) {\n            BYTE* const p = (BYTE*)incompressible + chunkNb * chunkSize;\n            size_t const samplingRate = 43;\n            int addOrRemove = chunkNb % 2;\n            size_t n;\n            for (n=0; n<chunkSize; n+=samplingRate) {\n                if (addOrRemove) {\n                    p[n] &= 0x80;\n                } else {\n                    p[n] |= 0x80;\n                }\n            }\n        }\n\n        /* run first without splitting */\n        ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockSplitterLevel, 1 /* no split */);\n        cSizeNoSplit = ZSTD_compress2(cctx, cBuffer, dstCapacity, incompressible, srcSize);\n\n        /* run with sample43 splitter, check it's still the same */\n        ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockSplitterLevel, 3 /* sample43, fastest _byChunk variant */);\n        cSizeWithSplit = ZSTD_compress2(cctx, cBuffer, dstCapacity, incompressible, srcSize);\n\n        if (cSizeWithSplit != cSizeNoSplit) {\n            DISPLAYLEVEL(1, \"invalid compressed size: cSizeWithSplit %u != %u cSizeNoSplit \\n\",\n                    (unsigned)cSizeWithSplit, (unsigned)cSizeNoSplit);\n            abort();\n        }\n        DISPLAYLEVEL(4, \"compressed size: cSizeWithSplit %u == %u cSizeNoSplit : \",\n                (unsigned)cSizeWithSplit, (unsigned)cSizeNoSplit);\n\n        free(incompressible);\n        free(cBuffer);\n        ZSTD_freeCCtx(cctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n}\n\nsize_t convertSequences_noRepcodes(SeqDef* dstSeqs, const ZSTD_Sequence* inSeqs,\n    size_t nbSequences);\n\nstatic size_t convertSequences_noRepcodes_ref(\n    SeqDef* dstSeqs,\n    const ZSTD_Sequence* inSeqs,\n    size_t nbSequences)\n{\n    size_t longLen = 0;\n    size_t n;\n    for (n=0; n<nbSequences; n++) {\n        dstSeqs[n].offBase = OFFSET_TO_OFFBASE(inSeqs[n].offset);\n        dstSeqs[n].litLength = (U16)inSeqs[n].litLength;\n        dstSeqs[n].mlBase = (U16)(inSeqs[n].matchLength - MINMATCH);\n        /* Check for long length > 65535. */\n        if (UNLIKELY(inSeqs[n].matchLength > 65535+MINMATCH)) {\n            assert(longLen == 0);\n            longLen = n + 1;\n        }\n        if (UNLIKELY(inSeqs[n].litLength > 65535)) {\n            assert(longLen == 0);\n            longLen = n + nbSequences + 1;\n        }\n    }\n    return longLen;\n}\n\nstatic unsigned test_convertSequences_noRepcodes(unsigned seed, unsigned testNb)\n{\n    ZSTD_Sequence nsrc[12];\n    SeqDef ndst[12], rdst[12];\n    size_t ref, ret, i, j;\n\n    seed += 0xDEADBEEF;\n    for (i = 0; i < COUNTOF(nsrc); ++i) {\n        seed = 48271 * ((unsigned)i + seed);\n        nsrc[i].offset = (seed & 0xFFFF) | 1;   /* Offset shall not be zero. */\n        seed = 48271 * ((unsigned)i + seed);\n        nsrc[i].litLength = seed & 0xFFFF;\n        seed = 48271 * ((unsigned)i + seed);\n        nsrc[i].matchLength = (seed & 0xFFFFFF) % (65536 + MINMATCH);\n        seed = 48271 * ((unsigned)i + seed);\n        nsrc[i].rep = seed & 0xFF;\n    }\n\n    /* For near overflow and proper negative value handling. */\n    nsrc[5].matchLength = 65535 + MINMATCH;\n    nsrc[6].litLength = 65535;\n    nsrc[6].matchLength = 0;\n    nsrc[7].litLength = 0;\n    nsrc[7].matchLength = MINMATCH;\n\n    for (i = 0; i <= COUNTOF(nsrc); ++i) {\n        DISPLAYLEVEL(3, \"test%3u : convertSequences_noRepcodes with %u inputs : \",\n                     testNb++, (unsigned)i);\n        memset(ndst, 0, sizeof(ndst));\n        memset(rdst, 0, sizeof(rdst));\n        ref = convertSequences_noRepcodes_ref(rdst, nsrc, i);\n        ret = convertSequences_noRepcodes(ndst, nsrc, i);\n        CHECK_EQ(ret, ref);\n        CHECK_EQ(memcmp(rdst, ndst, sizeof(ndst)), 0);\n        DISPLAYLEVEL(3, \"OK \\n\");\n    }\n\n    nsrc[7].matchLength = 65536 + MINMATCH;\n    for (i = 8; i <= COUNTOF(nsrc); ++i) {\n        DISPLAYLEVEL(3, \"test%3u : convertSequences_noRepcodes with %u inputs and \"\n                     \"matchLength overflow : \",\n                     testNb++, (unsigned)i);\n        memset(ndst, 0, sizeof(ndst));\n        memset(rdst, 0, sizeof(rdst));\n        ref = convertSequences_noRepcodes_ref(rdst, nsrc, i);\n        ret = convertSequences_noRepcodes(ndst, nsrc, i);\n        CHECK_EQ(ret, ref);\n        CHECK_EQ(memcmp(rdst, ndst, sizeof(ndst)), 0);\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        assert(COUNTOF(nsrc) > 8);\n        for (j = 4; j < 8; ++j) {\n            DISPLAYLEVEL(3, \"test%3u : convertSequences_noRepcodes with %u inputs and \"\n                         \"matchLength overflow #%u : \",\n                         testNb++, (unsigned)i, (unsigned)(i - j));\n            memset(ndst, 0, sizeof(ndst));\n            memset(rdst, 0, sizeof(rdst));\n            ref = convertSequences_noRepcodes_ref(rdst, nsrc + j, i - j);\n            ret = convertSequences_noRepcodes(ndst, nsrc + j, i - j);\n            CHECK_EQ(ret, ref);\n            CHECK_EQ(memcmp(rdst, ndst, sizeof(ndst)), 0);\n            DISPLAYLEVEL(3, \"OK \\n\");\n        }\n    }\n    nsrc[7].matchLength = 1;\n\n    nsrc[7].litLength = 65536;\n    for (i = 8; i <= COUNTOF(nsrc); ++i) {\n        DISPLAYLEVEL(3, \"test%3u : convertSequences_noRepcodes with %u inputs and \"\n                     \"litLength overflow: \",\n                     testNb++, (unsigned)i);\n        memset(ndst, 0, sizeof(ndst));\n        memset(rdst, 0, sizeof(rdst));\n        ref = convertSequences_noRepcodes_ref(rdst, nsrc, i);\n        ret = convertSequences_noRepcodes(ndst, nsrc, i);\n        CHECK_EQ(ret, ref);\n        CHECK_EQ(memcmp(rdst, ndst, sizeof(ndst)), 0);\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        assert(COUNTOF(nsrc) > 8);\n        for (j = 4; j < 8; ++j) {\n            DISPLAYLEVEL(3, \"test%3u : convertSequences_noRepcodes with %u inputs and \"\n                         \"litLength overflow #%u: \",\n                         testNb++, (unsigned)i, (unsigned)(i - j));\n            memset(ndst, 0, sizeof(ndst));\n            memset(rdst, 0, sizeof(rdst));\n            ref = convertSequences_noRepcodes_ref(rdst, nsrc + j, i - j);\n            ret = convertSequences_noRepcodes(ndst, nsrc + j, i - j);\n            CHECK_EQ(ret, ref);\n            CHECK_EQ(memcmp(rdst, ndst, sizeof(ndst)), 0);\n            DISPLAYLEVEL(3, \"OK \\n\");\n        }\n    }\n\n    return testNb;\n}\n\nstatic unsigned test_get1BlockSummary(unsigned testNb)\n{\n    static const ZSTD_Sequence nseqs[] = {\n        { 10, 2, 4, 1 },\n        { 20, 3, 5, 2 },\n        { 30, 6, 8, 3 },\n        { 40, 7, 9, 4 },\n        { 50, 10, 12, 5 },\n        { 60, 11, 13, 6 },\n        { 0,  14, 0, 7 },\n        { 70, 15, 17, 8 },\n        { 80, 16, 18, 9 },\n        { 90, 19, 21, 1 },\n        { 99, 20, 22, 2 },\n    };\n    static const BlockSummary blocks[] = {\n        { 7, 104, 53 },\n        { 6, 98, 51 },\n        { 5, 90, 48 },\n        { 4, 76, 42 },\n        { 3, 60, 35 },\n        { 2, 38, 25 },\n        { 1, 14, 14 },\n    };\n    size_t i;\n\n    DISPLAYLEVEL(3, \"test%3u : ZSTD_get1BlockSummary with empty array : \", testNb++);\n    {\n        BlockSummary bs = ZSTD_get1BlockSummary(nseqs, 0);\n        CHECK_EQ(bs.nbSequences, ERROR(externalSequences_invalid));\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3u : ZSTD_get1BlockSummary with 1 literal only : \", testNb++);\n    {\n        static const ZSTD_Sequence seqs[] = { { 0, 5, 0, 0 } };\n        BlockSummary bs = ZSTD_get1BlockSummary(seqs, 1);\n        CHECK_EQ(bs.nbSequences, 1);\n        CHECK_EQ(bs.litSize, 5);\n        CHECK_EQ(bs.blockSize, 5);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3u : ZSTD_get1BlockSummary with no terminator : \", testNb++);\n    {\n        static const ZSTD_Sequence seqs[] = { { 10, 2, 4, 0 }, { 20, 3, 5, 0 } };\n        BlockSummary bs = ZSTD_get1BlockSummary(seqs, 2);\n        CHECK_EQ(bs.nbSequences, ERROR(externalSequences_invalid));\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3u : ZSTD_get1BlockSummary with rep ignored : \", testNb++);\n    {\n        static const ZSTD_Sequence seqs[] = {\n            { 10, 2, 4, 2 },\n            { 10, 3, 5, 2 },\n            { 0, 7, 0, 3 },\n        };\n        BlockSummary bs = ZSTD_get1BlockSummary(seqs, 3);\n        CHECK_EQ(bs.nbSequences, 3);\n        CHECK_EQ(bs.litSize, 2 + 3 + 7);\n        CHECK_EQ(bs.blockSize, (4 + 5) + (2 + 3 + 7));\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    assert(COUNTOF(nseqs) > COUNTOF(blocks));\n    for (i = 0; i < COUNTOF(blocks); ++i) {\n        BlockSummary bs;\n        DISPLAYLEVEL(3, \"test%3u : ZSTD_get1BlockSummary with %u inputs : \",\n                     testNb++, (unsigned)(COUNTOF(nseqs) - i));\n        bs = ZSTD_get1BlockSummary(nseqs + i, COUNTOF(nseqs) - i);\n        CHECK_EQ(bs.nbSequences, blocks[i].nbSequences);\n        CHECK_EQ(bs.litSize, blocks[i].litSize);\n        CHECK_EQ(bs.blockSize, blocks[i].blockSize);\n        DISPLAYLEVEL(3, \"OK \\n\");\n    }\n\n    return testNb;\n}\n\n/* ============================================================= */\n\nstatic int basicUnitTests(U32 const seed, double compressibility)\n{\n    size_t const CNBuffSize = 5 MB;\n    void* const CNBuffer = malloc(CNBuffSize);\n    size_t const compressedBufferSize = ZSTD_compressBound(CNBuffSize);\n    void* const compressedBuffer = malloc(compressedBufferSize);\n    void* const decodedBuffer = malloc(CNBuffSize);\n    int testResult = 0;\n    unsigned testNb=0;\n    size_t cSize;\n\n    /* Create compressible noise */\n    if (!CNBuffer || !compressedBuffer || !decodedBuffer) {\n        DISPLAY(\"Not enough memory, aborting\\n\");\n        testResult = 1;\n        goto _end;\n    }\n    RDG_genBuffer(CNBuffer, CNBuffSize, compressibility, 0., seed);\n\n    /* Basic tests */\n    DISPLAYLEVEL(3, \"test%3u : ZSTD_getErrorName : \", testNb++);\n    {   const char* errorString = ZSTD_getErrorName(0);\n        DISPLAYLEVEL(3, \"OK : %s \\n\", errorString);\n    }\n\n    DISPLAYLEVEL(3, \"test%3u : ZSTD_getErrorName with wrong value : \", testNb++);\n    {   const char* errorString = ZSTD_getErrorName(499);\n        DISPLAYLEVEL(3, \"OK : %s \\n\", errorString);\n    }\n\n    DISPLAYLEVEL(3, \"test%3u : min compression level : \", testNb++);\n    {   int const mcl = ZSTD_minCLevel();\n        DISPLAYLEVEL(3, \"%i (OK) \\n\", mcl);\n    }\n\n    DISPLAYLEVEL(3, \"test%3u : default compression level : \", testNb++);\n    {   int const defaultCLevel = ZSTD_defaultCLevel();\n        if (defaultCLevel != ZSTD_CLEVEL_DEFAULT) goto _output_error;\n        DISPLAYLEVEL(3, \"%i (OK) \\n\", defaultCLevel);\n    }\n\n    DISPLAYLEVEL(3, \"test%3u : ZSTD_versionNumber : \", testNb++);\n    {   unsigned const vn = ZSTD_versionNumber();\n        DISPLAYLEVEL(3, \"%u (OK) \\n\", vn);\n    }\n\n    test_compressBound(testNb++);\n\n    test_decompressBound(testNb++);\n\n    test_setCParams(testNb++);\n\n    DISPLAYLEVEL(3, \"test%3u : ZSTD_adjustCParams : \", testNb++);\n    {\n        ZSTD_compressionParameters params;\n        memset(&params, 0, sizeof(params));\n        params.windowLog = 10;\n        params.hashLog = 19;\n        params.chainLog = 19;\n        params = ZSTD_adjustCParams(params, 1000, 100000);\n        if (params.hashLog != 18) goto _output_error;\n        if (params.chainLog != 17) goto _output_error;\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    testNb = test_histCountWksp(seed, testNb);\n\n    DISPLAYLEVEL(3, \"test%3u : compress %u bytes : \", testNb++, (unsigned)CNBuffSize);\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        if (cctx==NULL) goto _output_error;\n        CHECK_VAR(cSize, ZSTD_compressCCtx(cctx,\n                            compressedBuffer, compressedBufferSize,\n                            CNBuffer, CNBuffSize, 1) );\n        DISPLAYLEVEL(3, \"OK (%u bytes : %.2f%%)\\n\", (unsigned)cSize, (double)cSize/CNBuffSize*100);\n\n        DISPLAYLEVEL(3, \"test%3i : size of cctx for level 1 : \", testNb++);\n        {   size_t const cctxSize = ZSTD_sizeof_CCtx(cctx);\n            DISPLAYLEVEL(3, \"%u bytes \\n\", (unsigned)cctxSize);\n        }\n        ZSTD_freeCCtx(cctx);\n    }\n\n    DISPLAYLEVEL(3, \"test%3i : decompress skippable frame -8 size : \", testNb++);\n    {\n       char const skippable8[] = \"\\x50\\x2a\\x4d\\x18\\xf8\\xff\\xff\\xff\";\n       size_t const size = ZSTD_decompress(NULL, 0, skippable8, 8);\n       if (!ZSTD_isError(size)) goto _output_error;\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_getFrameContentSize test : \", testNb++);\n    {   unsigned long long const rSize = ZSTD_getFrameContentSize(compressedBuffer, cSize);\n        if (rSize != CNBuffSize) goto _output_error;\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_getDecompressedSize test : \", testNb++);\n    {   unsigned long long const rSize = ZSTD_getDecompressedSize(compressedBuffer, cSize);\n        if (rSize != CNBuffSize) goto _output_error;\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_findDecompressedSize test : \", testNb++);\n    {   unsigned long long const rSize = ZSTD_findDecompressedSize(compressedBuffer, cSize);\n        if (rSize != CNBuffSize) goto _output_error;\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : tight ZSTD_decompressBound test : \", testNb++);\n    {\n        unsigned long long bound = ZSTD_decompressBound(compressedBuffer, cSize);\n        if (bound != CNBuffSize) goto _output_error;\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_decompressBound test with invalid srcSize : \", testNb++);\n    {\n        unsigned long long bound = ZSTD_decompressBound(compressedBuffer, cSize - 1);\n        if (bound != ZSTD_CONTENTSIZE_ERROR) goto _output_error;\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : decompress %u bytes : \", testNb++, (unsigned)CNBuffSize);\n    { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize);\n      if (r != CNBuffSize) goto _output_error; }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : decompress %u bytes with Huffman assembly disabled : \", testNb++, (unsigned)CNBuffSize);\n    {\n        ZSTD_DCtx* dctx = ZSTD_createDCtx();\n        size_t r;\n        CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_disableHuffmanAssembly, 1));\n        r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize);\n        if (r != CNBuffSize || memcmp(decodedBuffer, CNBuffer, CNBuffSize)) goto _output_error;\n        ZSTD_freeDCtx(dctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : check decompressed result : \", testNb++);\n    {   size_t u;\n        for (u=0; u<CNBuffSize; u++) {\n            if (((BYTE*)decodedBuffer)[u] != ((BYTE*)CNBuffer)[u]) goto _output_error;\n    }   }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3u : invalid endDirective : \", testNb++);\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        ZSTD_inBuffer inb = { CNBuffer, CNBuffSize, 0 };\n        ZSTD_outBuffer outb = { compressedBuffer, compressedBufferSize, 0 };\n        if (cctx==NULL) goto _output_error;\n        CHECK( ZSTD_isError( ZSTD_compressStream2(cctx, &outb, &inb, (ZSTD_EndDirective) 3) ) );  /* must fail */\n        CHECK( ZSTD_isError( ZSTD_compressStream2(cctx, &outb, &inb, (ZSTD_EndDirective)-1) ) );  /* must fail */\n        ZSTD_freeCCtx(cctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_checkCParams : \", testNb++);\n    {\n        ZSTD_parameters params = ZSTD_getParams(3, 0, 0);\n        assert(!ZSTD_checkCParams(params.cParams));\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_createDCtx_advanced and ZSTD_sizeof_DCtx: \", testNb++);\n    {\n        ZSTD_DCtx* const dctx = ZSTD_createDCtx_advanced(ZSTD_defaultCMem);\n        assert(dctx != NULL);\n        assert(ZSTD_sizeof_DCtx(dctx) != 0);\n        ZSTD_freeDCtx(dctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : misc unaccounted for zstd symbols : \", testNb++);\n    {\n        /* %p takes a void*. In ISO C, it's illegal to cast a function pointer\n         * to a data pointer. (Although in POSIX you're required to be allowed\n         * to do it...) So we have to fall back to our trusty friend memcpy. */\n        unsigned (* const funcptr_getDictID)(const ZSTD_DDict* ddict) =\n            ZSTD_getDictID_fromDDict;\n        ZSTD_DStream* (* const funcptr_createDStream)(\n            ZSTD_customMem customMem) = ZSTD_createDStream_advanced;\n        void (* const funcptr_copyDCtx)(\n            ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx) = ZSTD_copyDCtx;\n        ZSTD_nextInputType_e (* const funcptr_nextInputType)(ZSTD_DCtx* dctx) =\n            ZSTD_nextInputType;\n        const void *voidptr_getDictID;\n        const void *voidptr_createDStream;\n        const void *voidptr_copyDCtx;\n        const void *voidptr_nextInputType;\n        DEBUG_STATIC_ASSERT(sizeof(funcptr_getDictID) == sizeof(voidptr_getDictID));\n        memcpy(\n            (void*)&voidptr_getDictID,\n            (const void*)&funcptr_getDictID,\n            sizeof(void*));\n        memcpy(\n            (void*)&voidptr_createDStream,\n            (const void*)&funcptr_createDStream,\n            sizeof(void*));\n        memcpy(\n            (void*)&voidptr_copyDCtx,\n            (const void*)&funcptr_copyDCtx,\n            sizeof(void*));\n        memcpy(\n            (void*)&voidptr_nextInputType,\n            (const void*)&funcptr_nextInputType,\n            sizeof(void*));\n        DISPLAYLEVEL(3, \"%p \", voidptr_getDictID);\n        DISPLAYLEVEL(3, \"%p \", voidptr_createDStream);\n        DISPLAYLEVEL(3, \"%p \", voidptr_copyDCtx);\n        DISPLAYLEVEL(3, \"%p \", voidptr_nextInputType);\n    }\n    DISPLAYLEVEL(3, \": OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : decompress with null dict : \", testNb++);\n    {   ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL);\n        {   size_t const r = ZSTD_decompress_usingDict(dctx,\n                                                    decodedBuffer, CNBuffSize,\n                                                    compressedBuffer, cSize,\n                                                    NULL, 0);\n            if (r != CNBuffSize) goto _output_error;\n        }\n        ZSTD_freeDCtx(dctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : decompress with null DDict : \", testNb++);\n    {   ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL);\n        {   size_t const r = ZSTD_decompress_usingDDict(dctx,\n                                                    decodedBuffer, CNBuffSize,\n                                                    compressedBuffer, cSize,\n                                                    NULL);\n            if (r != CNBuffSize) goto _output_error;\n        }\n        ZSTD_freeDCtx(dctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : decompress with 1 missing byte : \", testNb++);\n    { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize-1);\n      if (!ZSTD_isError(r)) goto _output_error;\n      if (ZSTD_getErrorCode((size_t)r) != ZSTD_error_srcSize_wrong) goto _output_error; }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : decompress with 1 too much byte : \", testNb++);\n    { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize+1);\n      if (!ZSTD_isError(r)) goto _output_error;\n      if (ZSTD_getErrorCode(r) != ZSTD_error_srcSize_wrong) goto _output_error; }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : decompress too large input : \", testNb++);\n    { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, compressedBufferSize);\n      if (!ZSTD_isError(r)) goto _output_error;\n      if (ZSTD_getErrorCode(r) != ZSTD_error_srcSize_wrong) goto _output_error; }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : decompress into NULL buffer : \", testNb++);\n    { size_t const r = ZSTD_decompress(NULL, 0, compressedBuffer, compressedBufferSize);\n      if (!ZSTD_isError(r)) goto _output_error;\n      if (ZSTD_getErrorCode(r) != ZSTD_error_dstSize_tooSmall) goto _output_error; }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : decompress with corrupted checksum : \", testNb++);\n    {   /* create compressed buffer with checksumming enabled */\n        ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        if (!cctx) {\n            DISPLAY(\"Not enough memory, aborting\\n\");\n            testResult = 1;\n            goto _end;\n        }\n        CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1) );\n        CHECK_VAR(cSize, ZSTD_compress2(cctx,\n                            compressedBuffer, compressedBufferSize,\n                            CNBuffer, CNBuffSize) );\n        ZSTD_freeCCtx(cctx);\n    }\n    {   /* copy the compressed buffer and corrupt the checksum */\n        size_t r;\n        ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n        if (!dctx) {\n            DISPLAY(\"Not enough memory, aborting\\n\");\n            testResult = 1;\n            goto _end;\n        }\n\n        ((char*)compressedBuffer)[cSize-1] += 1;\n        r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize);\n        if (!ZSTD_isError(r)) goto _output_error;\n        if (ZSTD_getErrorCode(r) != ZSTD_error_checksum_wrong) goto _output_error;\n\n        CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_forceIgnoreChecksum, ZSTD_d_ignoreChecksum));\n        r = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize-1);\n        if (!ZSTD_isError(r)) goto _output_error;   /* wrong checksum size should still throw error */\n        r = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);\n        if (ZSTD_isError(r)) goto _output_error;\n\n        ZSTD_freeDCtx(dctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_decompressBound test with content size missing : \", testNb++);\n    {   /* create compressed buffer with content size missing */\n        ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_contentSizeFlag, 0) );\n        CHECK_VAR(cSize, ZSTD_compress2(cctx,\n                            compressedBuffer, compressedBufferSize,\n                            CNBuffer, CNBuffSize) );\n        ZSTD_freeCCtx(cctx);\n    }\n    {   /* ensure frame content size is missing */\n        ZSTD_FrameHeader zfh;\n        size_t const ret = ZSTD_getFrameHeader(&zfh, compressedBuffer, compressedBufferSize);\n        if (ret != 0 || zfh.frameContentSize !=  ZSTD_CONTENTSIZE_UNKNOWN) goto _output_error;\n    }\n    {   /* ensure CNBuffSize <= decompressBound */\n        unsigned long long const bound = ZSTD_decompressBound(compressedBuffer, compressedBufferSize);\n        if (CNBuffSize > bound) goto _output_error;\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3d: check DCtx size is reduced after many oversized calls : \", testNb++);\n    {\n        size_t const largeFrameSrcSize = 200;\n        size_t const smallFrameSrcSize = 10;\n        size_t const nbFrames = 256;\n\n        size_t i = 0, consumed = 0, produced = 0, prevDCtxSize = 0;\n        int sizeReduced = 0;\n\n        BYTE* const dst = (BYTE*)compressedBuffer;\n        ZSTD_DCtx* dctx = ZSTD_createDCtx();\n\n        /* create a large frame and then a bunch of small frames */\n        size_t srcSize = ZSTD_compress((void*)dst,\n            compressedBufferSize, CNBuffer, largeFrameSrcSize, 3);\n        for (i = 0; i < nbFrames; i++)\n            srcSize += ZSTD_compress((void*)(dst + srcSize),\n                compressedBufferSize - srcSize, CNBuffer,\n                smallFrameSrcSize, 3);\n\n        /* decompressStream and make sure that dctx size was reduced at least once */\n        while (consumed < srcSize) {\n            ZSTD_inBuffer in = {(void*)(dst + consumed), MIN(1, srcSize - consumed), 0};\n            ZSTD_outBuffer out = {(BYTE*)CNBuffer + produced, CNBuffSize - produced, 0};\n            ZSTD_decompressStream(dctx, &out, &in);\n            consumed += in.pos;\n            produced += out.pos;\n\n            /* success! size was reduced from the previous frame */\n            if (prevDCtxSize > ZSTD_sizeof_DCtx(dctx))\n                sizeReduced = 1;\n\n            prevDCtxSize = ZSTD_sizeof_DCtx(dctx);\n        }\n\n        assert(sizeReduced);\n\n        ZSTD_freeDCtx(dctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    {\n        ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        ZSTD_CDict* const cdict = ZSTD_createCDict(CNBuffer, 100, 1);\n        ZSTD_parameters const params = ZSTD_getParams(1, 0, 0);\n        CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_format, ZSTD_f_zstd1_magicless) );\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_compressCCtx() doesn't use advanced parameters\", testNb++);\n        CHECK_Z(ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, NULL, 0, 1));\n        if (MEM_readLE32(compressedBuffer) != ZSTD_MAGICNUMBER) goto _output_error;\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_compress_usingDict() doesn't use advanced parameters: \", testNb++);\n        CHECK_Z(ZSTD_compress_usingDict(cctx, compressedBuffer, compressedBufferSize, NULL, 0, NULL, 0, 1));\n        if (MEM_readLE32(compressedBuffer) != ZSTD_MAGICNUMBER) goto _output_error;\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_compress_usingCDict() doesn't use advanced parameters: \", testNb++);\n        CHECK_Z(ZSTD_compress_usingCDict(cctx, compressedBuffer, compressedBufferSize, NULL, 0, cdict));\n        if (MEM_readLE32(compressedBuffer) != ZSTD_MAGICNUMBER) goto _output_error;\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_compress_advanced() doesn't use advanced parameters: \", testNb++);\n        CHECK_Z(ZSTD_compress_advanced(cctx, compressedBuffer, compressedBufferSize, NULL, 0, NULL, 0, params));\n        if (MEM_readLE32(compressedBuffer) != ZSTD_MAGICNUMBER) goto _output_error;\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_compress_usingCDict_advanced() doesn't use advanced parameters: \", testNb++);\n        CHECK_Z(ZSTD_compress_usingCDict_advanced(cctx, compressedBuffer, compressedBufferSize, NULL, 0, cdict, params.fParams));\n        if (MEM_readLE32(compressedBuffer) != ZSTD_MAGICNUMBER) goto _output_error;\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        ZSTD_freeCDict(cdict);\n        ZSTD_freeCCtx(cctx);\n    }\n\n    DISPLAYLEVEL(3, \"test%3i : maxBlockSize = 2K\", testNb++);\n    {\n        ZSTD_CCtx* cctx = ZSTD_createCCtx();\n        ZSTD_DCtx* dctx = ZSTD_createDCtx();\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, 2048));\n        CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_maxBlockSize, 2048));\n\n        cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);\n        CHECK_Z(cSize);\n        CHECK_Z(ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize));\n\n        CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_maxBlockSize, 1024));\n        CHECK(ZSTD_isError(ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize)));\n\n        ZSTD_freeDCtx(dctx);\n        ZSTD_freeCCtx(cctx);\n    }\n\n    DISPLAYLEVEL(3, \"test%3i : ldm fill dict out-of-bounds check\", testNb++);\n    {\n        ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n\n        size_t const size = (1U << 10);\n        size_t const dstCapacity = ZSTD_compressBound(size);\n        void* dict = (void*)malloc(size);\n        void* src = (void*)malloc(size);\n        void* dst = (void*)malloc(dstCapacity);\n\n        RDG_genBuffer(dict, size, 0.5, 0.5, seed);\n        RDG_genBuffer(src, size, 0.5, 0.5, seed);\n\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable));\n        assert(!ZSTD_isError(ZSTD_compress_usingDict(cctx, dst, dstCapacity, src, size, dict, size, 3)));\n\n        ZSTD_freeCCtx(cctx);\n        free(dict);\n        free(src);\n        free(dst);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : ldm hashRateLog > windowLog underflow check : \", testNb++);\n    {\n        /* Test that when windowLog < hashRateLog, we don't get excessive memory usage\n         * due to underflow in hashLog calculation (windowLog - hashRateLog). */\n        ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n\n        size_t const size = (1U << 10); // 1 KB\n        size_t const dstCapacity = ZSTD_compressBound(size);\n        void* src = (void*)malloc(size);\n        void* dst = (void*)malloc(dstCapacity);\n\n        RDG_genBuffer(src, size, 0.5, 0.5, seed);\n\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_ldmHashLog, 0)); \n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 12));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_ldmHashRateLog, 13));\n\n        CHECK_Z(ZSTD_compress2(cctx, dst, dstCapacity, src, size));\n\n        {   size_t const cctxSize = ZSTD_sizeof_CCtx(cctx);\n            DISPLAYLEVEL(3, \"CCtx size: %u bytes \", (unsigned)cctxSize);\n            CHECK_LT(cctxSize, 50 MB);\n        }\n\n        ZSTD_freeCCtx(cctx);\n        free(src);\n        free(dst);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : testing dict compression with enableLdm and forceMaxWindow : \", testNb++);\n    {\n        ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n        void* dict = (void*)malloc(CNBuffSize);\n        int nbWorkers;\n\n        for (nbWorkers = 0; nbWorkers < 3; ++nbWorkers) {\n            RDG_genBuffer(dict, CNBuffSize, 0.5, 0.5, seed);\n            RDG_genBuffer(CNBuffer, CNBuffSize, 0.6, 0.6, seed);\n\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, nbWorkers));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_forceMaxWindow, 1));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable));\n            CHECK_Z(ZSTD_CCtx_refPrefix(cctx, dict, CNBuffSize));\n            cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);\n            CHECK_Z(cSize);\n            CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, dict, CNBuffSize));\n        }\n\n        ZSTD_freeCCtx(cctx);\n        ZSTD_freeDCtx(dctx);\n        free(dict);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : testing dict compression for determinism : \", testNb++);\n    {\n        size_t const testSize = 1024;\n        ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n        char* dict = (char*)malloc(2 * testSize);\n        int ldmEnabled, level;\n\n        RDG_genBuffer(dict, testSize, 0.5, 0.5, seed);\n        RDG_genBuffer(CNBuffer, testSize, 0.6, 0.6, seed);\n        memcpy(dict + testSize, CNBuffer, testSize);\n        for (level = 1; level <= 5; ++level) {\n            for (ldmEnabled = ZSTD_ps_enable; ldmEnabled <= ZSTD_ps_disable; ++ldmEnabled) {\n                size_t cSize0;\n                XXH64_hash_t compressedChecksum0;\n\n                CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1));\n                CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, level));\n                CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ldmEnabled));\n                CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_deterministicRefPrefix, 1));\n\n                CHECK_Z(ZSTD_CCtx_refPrefix(cctx, dict, testSize));\n                cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, testSize);\n                CHECK_Z(cSize);\n                CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, testSize, compressedBuffer, cSize, dict, testSize));\n\n                cSize0 = cSize;\n                compressedChecksum0 = XXH64(compressedBuffer, cSize, 0);\n\n                CHECK_Z(ZSTD_CCtx_refPrefix(cctx, dict, testSize));\n                cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, dict + testSize, testSize);\n                CHECK_Z(cSize);\n\n                if (cSize != cSize0) goto _output_error;\n                if (XXH64(compressedBuffer, cSize, 0) != compressedChecksum0) goto _output_error;\n            }\n        }\n\n        ZSTD_freeCCtx(cctx);\n        ZSTD_freeDCtx(dctx);\n        free(dict);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : LDM + opt parser with small uncompressible block \", testNb++);\n    {   ZSTD_CCtx* cctx = ZSTD_createCCtx();\n        ZSTD_DCtx* dctx = ZSTD_createDCtx();\n        size_t const srcSize = 300 KB;\n        size_t const flushSize = 128 KB + 5;\n        size_t const dstSize = ZSTD_compressBound(srcSize);\n        char* src = (char*)CNBuffer;\n        char* dst = (char*)compressedBuffer;\n\n        ZSTD_outBuffer out = { dst, dstSize, 0 };\n        ZSTD_inBuffer in = { src, flushSize, 0 };\n\n        if (!cctx || !dctx) {\n            DISPLAY(\"Not enough memory, aborting\\n\");\n            testResult = 1;\n            goto _end;\n        }\n\n        RDG_genBuffer(src, srcSize, 0.5, 0.5, seed);\n        /* Force an LDM to exist that crosses block boundary into uncompressible block */\n        memcpy(src + 125 KB, src, 3 KB + 5);\n\n        /* Enable MT, LDM, and opt parser */\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 1));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 19));\n\n        /* Flushes a block of 128 KB and block of 5 bytes */\n        CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush));\n\n        /* Compress the rest */\n        in.size = 300 KB;\n        CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));\n\n        CHECK_Z(ZSTD_decompress(decodedBuffer, CNBuffSize, dst, out.pos));\n\n        ZSTD_freeCCtx(cctx);\n        ZSTD_freeDCtx(dctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : testing ldm dictionary gets invalidated : \", testNb++);\n    {\n        ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n        void* dict = (void*)malloc(CNBuffSize);\n        size_t const kWindowLog = 10;\n        size_t const kWindowSize = (size_t)1 << kWindowLog;\n        size_t const dictSize = kWindowSize * 10;\n        size_t const srcSize1 = kWindowSize / 2;\n        size_t const srcSize2 = kWindowSize * 10;\n\n        CHECK(cctx!=NULL);\n        CHECK(dctx!=NULL);\n        CHECK(dict!=NULL);\n        if (CNBuffSize < dictSize) goto _output_error;\n\n        RDG_genBuffer(dict, dictSize, 0.5, 0.5, seed);\n        RDG_genBuffer(CNBuffer, srcSize1 + srcSize2, 0.5, 0.5, seed);\n\n        /* Enable checksum to verify round trip. */\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1));\n        /* Disable content size to skip single-pass decompression. */\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_contentSizeFlag, 0));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, (int)kWindowLog));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_ldmMinMatch, 32));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_ldmHashRateLog, 1));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_ldmHashLog, 16));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_ldmBucketSizeLog, 3));\n\n        /* Round trip once with a dictionary. */\n        CHECK_Z(ZSTD_CCtx_refPrefix(cctx, dict, dictSize));\n        cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, srcSize1);\n        CHECK_Z(cSize);\n        CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, dict, dictSize));\n\n        cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, srcSize2);\n        /* Streaming decompression to catch out of bounds offsets. */\n        {\n            ZSTD_inBuffer in = {compressedBuffer, cSize, 0};\n            ZSTD_outBuffer out = {decodedBuffer, CNBuffSize, 0};\n            size_t const dSize = ZSTD_decompressStream(dctx, &out, &in);\n            CHECK_Z(dSize);\n            if (dSize != 0) goto _output_error;\n        }\n\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 2));\n        /* Round trip once with a dictionary. */\n        CHECK_Z(ZSTD_CCtx_refPrefix(cctx, dict, dictSize));\n        {   ZSTD_inBuffer in = {CNBuffer, srcSize1, 0};\n            ZSTD_outBuffer out = {compressedBuffer, compressedBufferSize, 0};\n            CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush));\n            CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));\n            cSize = out.pos;\n        }\n        CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, dict, dictSize));\n\n        {   ZSTD_inBuffer in = {CNBuffer, srcSize2, 0};\n            ZSTD_outBuffer out = {compressedBuffer, compressedBufferSize, 0};\n            CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush));\n            CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));\n            cSize = out.pos;\n        }\n        /* Streaming decompression to catch out of bounds offsets. */\n        {   ZSTD_inBuffer in = {compressedBuffer, cSize, 0};\n            ZSTD_outBuffer out = {decodedBuffer, CNBuffSize, 0};\n            size_t const dSize = ZSTD_decompressStream(dctx, &out, &in);\n            CHECK_Z(dSize);\n            if (dSize != 0) goto _output_error;\n        }\n\n        ZSTD_freeCCtx(cctx);\n        ZSTD_freeDCtx(dctx);\n        free(dict);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* Note: this test takes 0.5 seconds to run */\n    DISPLAYLEVEL(3, \"test%3i : testing refPrefx vs refPrefx + ldm (size comparison) : \", testNb++);\n    {\n        /* test a big buffer so that ldm can take effect */\n        size_t const size = 100 MB;\n        int const windowLog = 27;\n        size_t const dstSize = ZSTD_compressBound(size);\n\n        void* dict = (void*)malloc(size);\n        void* src = (void*)malloc(size);\n        void* dst = (void*)malloc(dstSize);\n        void* recon = (void*)malloc(size);\n\n        size_t refPrefixCompressedSize = 0;\n        size_t refPrefixLdmCompressedSize = 0;\n        size_t reconSize = 0;\n\n        ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n\n        /* make dict and src the same uncompressible data */\n        RDG_genBuffer(src, size, 0, 0, seed);\n        memcpy(dict, src, size);\n        assert(!memcmp(dict, src, size));\n\n        /* set level 1 and windowLog to cover src */\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, windowLog));\n\n        /* compress on level 1 using just refPrefix and no ldm */\n        ZSTD_CCtx_refPrefix(cctx, dict, size);\n        refPrefixCompressedSize = ZSTD_compress2(cctx, dst, dstSize, src, size);\n        assert(!ZSTD_isError(refPrefixCompressedSize));\n\n        /* test round trip just refPrefix */\n        ZSTD_DCtx_refPrefix(dctx, dict, size);\n        reconSize = ZSTD_decompressDCtx(dctx, recon, size, dst, refPrefixCompressedSize);\n        assert(!ZSTD_isError(reconSize));\n        assert(reconSize == size);\n        assert(!memcmp(recon, src, size));\n\n        /* compress on level 1 using refPrefix and ldm */\n        ZSTD_CCtx_refPrefix(cctx, dict, size);;\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable))\n        refPrefixLdmCompressedSize = ZSTD_compress2(cctx, dst, dstSize, src, size);\n        assert(!ZSTD_isError(refPrefixLdmCompressedSize));\n\n        /* test round trip refPrefix + ldm*/\n        ZSTD_DCtx_refPrefix(dctx, dict, size);\n        reconSize = ZSTD_decompressDCtx(dctx, recon, size, dst, refPrefixLdmCompressedSize);\n        assert(!ZSTD_isError(reconSize));\n        assert(reconSize == size);\n        assert(!memcmp(recon, src, size));\n\n        /* make sure that refPrefixCompressedSize is significantly greater */\n        assert(refPrefixCompressedSize > 10 * refPrefixLdmCompressedSize);\n        /* make sure the ldm compressed size is less than 1% of original */\n        assert((double)refPrefixLdmCompressedSize / (double)size < 0.01);\n\n        ZSTD_freeDCtx(dctx);\n        ZSTD_freeCCtx(cctx);\n        free(recon);\n        free(dict);\n        free(src);\n        free(dst);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : in-place decompression : \", testNb++);\n    cSize = ZSTD_compress(compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize, -ZSTD_BLOCKSIZE_MAX);\n    CHECK_Z(cSize);\n    CHECK_LT(CNBuffSize, cSize);\n    {\n        size_t const margin = ZSTD_decompressionMargin(compressedBuffer, cSize);\n        size_t const outputSize = (CNBuffSize + margin);\n        char* output = malloc(outputSize);\n        char* input = output + outputSize - cSize;\n        CHECK_LT(cSize, CNBuffSize + margin);\n        CHECK(output != NULL);\n        CHECK_Z(margin);\n        CHECK(margin <= ZSTD_DECOMPRESSION_MARGIN(CNBuffSize, ZSTD_BLOCKSIZE_MAX));\n        memcpy(input, compressedBuffer, cSize);\n\n        {\n            size_t const dSize = ZSTD_decompress(output, outputSize, input, cSize);\n            CHECK_Z(dSize);\n            CHECK_EQ(dSize, CNBuffSize);\n        }\n        CHECK(!memcmp(output, CNBuffer, CNBuffSize));\n        free(output);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : in-place decompression with 2 frames : \", testNb++);\n    cSize = ZSTD_compress(compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize / 3, -ZSTD_BLOCKSIZE_MAX);\n    CHECK_Z(cSize);\n    {\n        size_t const cSize2 = ZSTD_compress((char*)compressedBuffer + cSize, compressedBufferSize - cSize, (char const*)CNBuffer + (CNBuffSize / 3), CNBuffSize / 3, -ZSTD_BLOCKSIZE_MAX);\n        CHECK_Z(cSize2);\n        cSize += cSize2;\n    }\n    {\n        size_t const srcSize = (CNBuffSize / 3) * 2;\n        size_t const margin = ZSTD_decompressionMargin(compressedBuffer, cSize);\n        size_t const outputSize = (CNBuffSize + margin);\n        char* output = malloc(outputSize);\n        char* input = output + outputSize - cSize;\n        CHECK_LT(cSize, CNBuffSize + margin);\n        CHECK(output != NULL);\n        CHECK_Z(margin);\n        memcpy(input, compressedBuffer, cSize);\n\n        {\n            size_t const dSize = ZSTD_decompress(output, outputSize, input, cSize);\n            CHECK_Z(dSize);\n            CHECK_EQ(dSize, srcSize);\n        }\n        CHECK(!memcmp(output, CNBuffer, srcSize));\n        free(output);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : Check block splitter with 64K literal length : \", testNb++);\n    {   ZSTD_CCtx* cctx = ZSTD_createCCtx();\n        size_t const srcSize = 256 * 1024;\n        U32 const compressibleLenU32 = 32 * 1024 / 4;\n        U32 const blockSizeU32 = 128 * 1024 / 4;\n        U32 const litLenU32 = 64 * 1024 / 4;\n        U32* data = (U32*)malloc(srcSize);\n        size_t dSize;\n\n        if (data == NULL || cctx == NULL) goto _output_error;\n\n        /* Generate data without any matches */\n        RDG_genBuffer(data, srcSize, 0.0, 0.01, 2654435761U);\n        /* Generate 32K of compressible data */\n        RDG_genBuffer(data, compressibleLenU32 * 4, 0.5, 0.5, 0xcafebabe);\n\n        /* Add a match of offset=12, length=8 at idx=16, 32, 48, 64  */\n        data[compressibleLenU32 + 0] = 0xFFFFFFFF;\n        data[compressibleLenU32 + 1] = 0xEEEEEEEE;\n        data[compressibleLenU32 + 4] = 0xFFFFFFFF;\n        data[compressibleLenU32 + 5] = 0xEEEEEEEE;\n\n        /* Add a match of offset=16, length=8 at idx=64K + 64.\n         * This generates a sequence with llen=64K, and repeat code 1.\n         * The block splitter thought this was ll0, and corrupted the\n         * repeat offset history.\n         */\n        data[compressibleLenU32 + litLenU32 + 2 + 0] = 0xDDDDDDDD;\n        data[compressibleLenU32 + litLenU32 + 2 + 1] = 0xCCCCCCCC;\n        data[compressibleLenU32 + litLenU32 + 2 + 4] = 0xDDDDDDDD;\n        data[compressibleLenU32 + litLenU32 + 2 + 5] = 0xCCCCCCCC;\n\n        /* Add a match of offset=16, length=8 at idx=128K + 16.\n         * This should generate a sequence with repeat code = 1.\n         * But the block splitters mistake caused zstd to generate\n         * repeat code = 2, corrupting the data.\n         */\n        data[blockSizeU32] = 0xBBBBBBBB;\n        data[blockSizeU32 + 1] = 0xAAAAAAAA;\n        data[blockSizeU32 + 4] = 0xBBBBBBBB;\n        data[blockSizeU32 + 5] = 0xAAAAAAAA;\n\n        /* Generate a golden file from this data in case datagen changes and\n         * doesn't generate the exact same data. We will also test this golden file.\n         */\n        if (0) {\n            FILE* f = fopen(\"golden-compression/PR-3517-block-splitter-corruption-test\", \"wb\");\n            fwrite(data, 1, srcSize, f);\n            fclose(f);\n        }\n\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 19));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, 7));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_splitAfterSequences, ZSTD_ps_enable));\n\n        cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, data, srcSize);\n        CHECK_Z(cSize);\n        dSize = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize);\n        CHECK_Z(dSize);\n        CHECK_EQ(dSize, srcSize);\n        CHECK(!memcmp(decodedBuffer, data, srcSize));\n\n        free(data);\n        ZSTD_freeCCtx(cctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    test_blockSplitter_incompressibleExpansionProtection(testNb++, seed);\n\n    DISPLAYLEVEL(3, \"test%3d : superblock uncompressible data: too many nocompress superblocks : \", testNb++);\n    {\n        ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        const BYTE* src = (BYTE*)CNBuffer; BYTE* dst = (BYTE*)compressedBuffer;\n        size_t srcSize = 321656; size_t dstCapacity = ZSTD_compressBound(srcSize);\n\n        /* This is the number of bytes to stream before ending. This value\n         * was obtained by trial and error :/. */\n\n        const size_t streamCompressThreshold = 161792;\n        const size_t streamCompressDelta = 1024;\n\n        /* The first 1/5 of the buffer is compressible and the last 4/5 is\n         * uncompressible. This is an approximation of the type of data\n         * the fuzzer generated to catch this bug. Streams like this were making\n         * zstd generate noCompress superblocks (which are larger than the src\n         * they come from). Do this enough times, and we'll run out of room\n         * and throw a dstSize_tooSmall error. */\n\n        const size_t compressiblePartSize = srcSize/5;\n        const size_t uncompressiblePartSize = srcSize-compressiblePartSize;\n        RDG_genBuffer(CNBuffer, compressiblePartSize, 0.5, 0.5, seed);\n        RDG_genBuffer((BYTE*)CNBuffer+compressiblePartSize, uncompressiblePartSize, 0, 0, seed);\n\n        /* Setting target block size so that superblock is used */\n\n        assert(cctx != NULL);\n        ZSTD_CCtx_setParameter(cctx, ZSTD_c_targetCBlockSize, 81);\n\n        {   size_t read;\n            for (read = 0; read < streamCompressThreshold; read += streamCompressDelta) {\n                ZSTD_inBuffer in = {src, streamCompressDelta, 0};\n                ZSTD_outBuffer out = {dst, dstCapacity, 0};\n                CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue));\n                CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));\n                src += streamCompressDelta; srcSize -= streamCompressDelta;\n                dst += out.pos; dstCapacity -= out.pos;\n        }   }\n\n        /* This is trying to catch a dstSize_tooSmall error */\n\n        {   ZSTD_inBuffer in = {src, srcSize, 0};\n            ZSTD_outBuffer out = {dst, dstCapacity, 0};\n            CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));\n        }\n        ZSTD_freeCCtx(cctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3d: superblock with no literals : \", testNb++);\n    /* Generate the same data 20 times over */\n    {   size_t const avgChunkSize = CNBuffSize / 20;\n        size_t b;\n        for (b = 0; b < CNBuffSize; b += avgChunkSize) {\n            size_t const chunkSize = MIN(CNBuffSize - b, avgChunkSize);\n            RDG_genBuffer((char*)CNBuffer + b, chunkSize, compressibility, 0. /* auto */, seed);\n    }   }\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        size_t const normalCSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);\n        size_t const allowedExpansion = (CNBuffSize * 3 / 1000);\n        size_t superCSize;\n        CHECK_Z(normalCSize);\n        ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 19);\n        ZSTD_CCtx_setParameter(cctx, ZSTD_c_targetCBlockSize, 1000);\n        superCSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);\n        CHECK_Z(superCSize);\n        if (superCSize > normalCSize + allowedExpansion) {\n            DISPLAYLEVEL(1, \"Superblock too big: %u > %u + %u \\n\", (U32)superCSize, (U32)normalCSize, (U32)allowedExpansion);\n            goto _output_error;\n        }\n        ZSTD_freeCCtx(cctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    RDG_genBuffer(CNBuffer, CNBuffSize, compressibility, 0. /*auto*/, seed);\n    DISPLAYLEVEL(3, \"test%3d: superblock enough room for checksum : \", testNb++)\n    /* This tests whether or not we leave enough room for the checksum at the end\n     * of the dst buffer. The bug that motivated this test was found by the\n     * stream_round_trip fuzzer but this crashes for the same reason and is\n     * far more compact than re-creating the stream_round_trip fuzzer's code path */\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        ZSTD_CCtx_setParameter(cctx, ZSTD_c_targetCBlockSize, 64);\n        assert(!ZSTD_isError(ZSTD_compress2(cctx, compressedBuffer, 1339, CNBuffer, 1278)));\n        ZSTD_freeCCtx(cctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : compress a NULL input with each level : \", testNb++);\n    {   int level = -1;\n        ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        if (!cctx) goto _output_error;\n        for (level = -1; level <= ZSTD_maxCLevel(); ++level) {\n          CHECK_Z( ZSTD_compress(compressedBuffer, compressedBufferSize, NULL, 0, level) );\n          CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, level) );\n          CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, NULL, 0) );\n        }\n        ZSTD_freeCCtx(cctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3d : check CCtx size after compressing empty input : \", testNb++);\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        size_t const r = ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, NULL, 0, 19);\n        if (ZSTD_isError(r)) goto _output_error;\n        if (ZSTD_sizeof_CCtx(cctx) > (1U << 20)) goto _output_error;\n        ZSTD_freeCCtx(cctx);\n        cSize = r;\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3d : decompress empty frame into NULL : \", testNb++);\n    {   size_t const r = ZSTD_decompress(NULL, 0, compressedBuffer, cSize);\n        if (ZSTD_isError(r)) goto _output_error;\n        if (r != 0) goto _output_error;\n    }\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        ZSTD_outBuffer output;\n        if (cctx==NULL) goto _output_error;\n        output.dst = compressedBuffer;\n        output.size = compressedBufferSize;\n        output.pos = 0;\n        CHECK_Z( ZSTD_initCStream(cctx, 1) );    /* content size unknown */\n        CHECK_Z( ZSTD_flushStream(cctx, &output) );   /* ensure no possibility to \"concatenate\" and determine the content size */\n        CHECK_Z( ZSTD_endStream(cctx, &output) );\n        ZSTD_freeCCtx(cctx);\n        /* single scan decompression */\n        {   size_t const r = ZSTD_decompress(NULL, 0, compressedBuffer, output.pos);\n            if (ZSTD_isError(r)) goto _output_error;\n            if (r != 0) goto _output_error;\n        }\n        /* streaming decompression */\n        {   ZSTD_DCtx* const dstream = ZSTD_createDStream();\n            ZSTD_inBuffer dinput;\n            ZSTD_outBuffer doutput;\n            size_t ipos;\n            if (dstream==NULL) goto _output_error;\n            dinput.src = compressedBuffer;\n            dinput.size = 0;\n            dinput.pos = 0;\n            doutput.dst = NULL;\n            doutput.size = 0;\n            doutput.pos = 0;\n            CHECK_Z ( ZSTD_initDStream(dstream) );\n            for (ipos=1; ipos<=output.pos; ipos++) {\n                dinput.size = ipos;\n                CHECK_Z ( ZSTD_decompressStream(dstream, &doutput, &dinput) );\n            }\n            if (doutput.pos != 0) goto _output_error;\n            ZSTD_freeDStream(dstream);\n        }\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3d : reuse CCtx with expanding block size : \", testNb++);\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        ZSTD_parameters const params = ZSTD_getParams(1, ZSTD_CONTENTSIZE_UNKNOWN, 0);\n        assert(params.fParams.contentSizeFlag == 1);  /* block size will be adapted if pledgedSrcSize is enabled */\n        CHECK_Z( ZSTD_compressBegin_advanced(cctx, NULL, 0, params, 1 /*pledgedSrcSize*/) );\n        CHECK_Z( ZSTD_compressEnd(cctx, compressedBuffer, compressedBufferSize, CNBuffer, 1) ); /* creates a block size of 1 */\n\n        CHECK_Z( ZSTD_compressBegin_advanced(cctx, NULL, 0, params, ZSTD_CONTENTSIZE_UNKNOWN) );  /* reuse same parameters */\n        {   size_t const inSize = 2* 128 KB;\n            size_t const outSize = ZSTD_compressBound(inSize);\n            CHECK_Z( ZSTD_compressEnd(cctx, compressedBuffer, outSize, CNBuffer, inSize) );\n            /* will fail if blockSize is not resized */\n        }\n        ZSTD_freeCCtx(cctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3d : re-using a CCtx should compress the same : \", testNb++);\n    {   size_t const sampleSize = 30;\n        int i;\n        for (i=0; i<20; i++)\n            ((char*)CNBuffer)[i] = (char)i;   /* ensure no match during initial section */\n        memcpy((char*)CNBuffer + 20, CNBuffer, 10);   /* create one match, starting from beginning of sample, which is the difficult case (see #1241) */\n        for (i=1; i<=19; i++) {\n            ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n            size_t size1, size2;\n            DISPLAYLEVEL(5, \"l%i \", i);\n            size1 = ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, CNBuffer, sampleSize, i);\n            CHECK_Z(size1);\n\n            size2 = ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, CNBuffer, sampleSize, i);\n            CHECK_Z(size2);\n            CHECK_EQ(size1, size2);\n\n            CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, i) );\n            size2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, sampleSize);\n            CHECK_Z(size2);\n            CHECK_EQ(size1, size2);\n\n            size2 = ZSTD_compress2(cctx, compressedBuffer, ZSTD_compressBound(sampleSize) - 1, CNBuffer, sampleSize);  /* force streaming, as output buffer is not large enough to guarantee success */\n            CHECK_Z(size2);\n            CHECK_EQ(size1, size2);\n\n            {   ZSTD_inBuffer inb;\n                ZSTD_outBuffer outb;\n                inb.src = CNBuffer;\n                inb.pos = 0;\n                inb.size = sampleSize;\n                outb.dst = compressedBuffer;\n                outb.pos = 0;\n                outb.size = ZSTD_compressBound(sampleSize) - 1;  /* force streaming, as output buffer is not large enough to guarantee success */\n                CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_end) );\n                assert(inb.pos == inb.size);\n                CHECK_EQ(size1, outb.pos);\n            }\n\n            ZSTD_freeCCtx(cctx);\n        }\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3d : btultra2 & 1st block : \", testNb++);\n    {   size_t const sampleSize = 1024;\n        ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        ZSTD_inBuffer inb;\n        ZSTD_outBuffer outb;\n        inb.src = CNBuffer;\n        inb.pos = 0;\n        inb.size = 0;\n        outb.dst = compressedBuffer;\n        outb.pos = 0;\n        outb.size = compressedBufferSize;\n        CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, ZSTD_maxCLevel()) );\n\n        inb.size = sampleSize;   /* start with something, so that context is already used */\n        CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_end) );   /* will break internal assert if stats_init is not disabled */\n        assert(inb.pos == inb.size);\n        outb.pos = 0;     /* cancel output */\n\n        CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(cctx, sampleSize) );\n        inb.size = 4;   /* too small size : compression will be skipped */\n        inb.pos = 0;\n        CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_flush) );\n        assert(inb.pos == inb.size);\n\n        inb.size += 5;   /* too small size : compression will be skipped */\n        CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_flush) );\n        assert(inb.pos == inb.size);\n\n        inb.size += 11;   /* small enough to attempt compression */\n        CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_flush) );\n        assert(inb.pos == inb.size);\n\n        assert(inb.pos < sampleSize);\n        inb.size = sampleSize;   /* large enough to trigger stats_init, but no longer at beginning */\n        CHECK_Z( ZSTD_compressStream2(cctx, &outb, &inb, ZSTD_e_end) );   /* will break internal assert if stats_init is not disabled */\n        assert(inb.pos == inb.size);\n        ZSTD_freeCCtx(cctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3d : ZSTD_CCtx_getParameter() : \", testNb++);\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        ZSTD_outBuffer out = {NULL, 0, 0};\n        ZSTD_inBuffer in = {NULL, 0, 0};\n        int value;\n\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value));\n        CHECK_EQ(value, 3);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value));\n        CHECK_EQ(value, 0);\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, ZSTD_HASHLOG_MIN));\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value));\n        CHECK_EQ(value, 3);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value));\n        CHECK_EQ(value, ZSTD_HASHLOG_MIN);\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 7));\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value));\n        CHECK_EQ(value, 7);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value));\n        CHECK_EQ(value, ZSTD_HASHLOG_MIN);\n        /* Start a compression job */\n        ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value));\n        CHECK_EQ(value, 7);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value));\n        CHECK_EQ(value, ZSTD_HASHLOG_MIN);\n        /* Reset the CCtx */\n        ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value));\n        CHECK_EQ(value, 7);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value));\n        CHECK_EQ(value, ZSTD_HASHLOG_MIN);\n        /* Reset the parameters */\n        ZSTD_CCtx_reset(cctx, ZSTD_reset_parameters);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_compressionLevel, &value));\n        CHECK_EQ(value, 3);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value));\n        CHECK_EQ(value, 0);\n\n        ZSTD_freeCCtx(cctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3d : ZSTD_CCtx_setCParams() : \", testNb++);\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        int value;\n        ZSTD_compressionParameters cparams = ZSTD_getCParams(1, 0, 0);\n        cparams.strategy = (ZSTD_strategy)-1; /* set invalid value, on purpose */\n        /* Set invalid cParams == error out, and no change. */\n        CHECK(ZSTD_isError(ZSTD_CCtx_setCParams(cctx, cparams)));\n\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_windowLog, &value));\n        CHECK_EQ(value, 0);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_chainLog, &value));\n        CHECK_EQ(value, 0);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value));\n        CHECK_EQ(value, 0);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_searchLog, &value));\n        CHECK_EQ(value, 0);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_minMatch, &value));\n        CHECK_EQ(value, 0);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_targetLength, &value));\n        CHECK_EQ(value, 0);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_strategy, &value));\n        CHECK_EQ(value, 0);\n\n        cparams = ZSTD_getCParams(12, 0, 0);\n        CHECK_Z(ZSTD_CCtx_setCParams(cctx, cparams));\n\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_windowLog, &value));\n        CHECK_EQ(value, (int)cparams.windowLog);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_chainLog, &value));\n        CHECK_EQ(value, (int)cparams.chainLog);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value));\n        CHECK_EQ(value, (int)cparams.hashLog);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_searchLog, &value));\n        CHECK_EQ(value, (int)cparams.searchLog);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_minMatch, &value));\n        CHECK_EQ(value, (int)cparams.minMatch);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_targetLength, &value));\n        CHECK_EQ(value, (int)cparams.targetLength);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_strategy, &value));\n        CHECK_EQ(value, (int)cparams.strategy);\n\n        ZSTD_freeCCtx(cctx);\n    }\n\n    DISPLAYLEVEL(3, \"test%3d : ZSTD_CCtx_setFParams() : \", testNb++);\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        int value;\n        ZSTD_frameParameters fparams = {0, 1, 1};\n\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_contentSizeFlag, &value));\n        CHECK_EQ(value, 1);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_checksumFlag, &value));\n        CHECK_EQ(value, 0);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_dictIDFlag, &value));\n        CHECK_EQ(value, 1);\n\n        CHECK_Z(ZSTD_CCtx_setFParams(cctx, fparams));\n\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_contentSizeFlag, &value));\n        CHECK_EQ(value, fparams.contentSizeFlag);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_checksumFlag, &value));\n        CHECK_EQ(value, fparams.checksumFlag);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_dictIDFlag, &value));\n        CHECK_EQ(value, !fparams.noDictIDFlag);\n\n        ZSTD_freeCCtx(cctx);\n    }\n\n    DISPLAYLEVEL(3, \"test%3d : ZSTD_CCtx_setParams() : \", testNb++);\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        int value;\n        ZSTD_parameters params = ZSTD_getParams(1, 0, 0);\n        params.cParams.strategy = (ZSTD_strategy)-1; /* set invalid value, on purpose */\n        /* Set invalid params == error out, and no change. */\n        CHECK(ZSTD_isError(ZSTD_CCtx_setParams(cctx, params)));\n\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_windowLog, &value));\n        CHECK_EQ(value, 0);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_chainLog, &value));\n        CHECK_EQ(value, 0);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value));\n        CHECK_EQ(value, 0);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_searchLog, &value));\n        CHECK_EQ(value, 0);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_minMatch, &value));\n        CHECK_EQ(value, 0);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_targetLength, &value));\n        CHECK_EQ(value, 0);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_strategy, &value));\n        CHECK_EQ(value, 0);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_contentSizeFlag, &value));\n        CHECK_EQ(value, 1);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_checksumFlag, &value));\n        CHECK_EQ(value, 0);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_dictIDFlag, &value));\n        CHECK_EQ(value, 1);\n\n        params = ZSTD_getParams(12, 0, 0);\n        params.fParams.contentSizeFlag = 0;\n        params.fParams.checksumFlag = 1;\n        params.fParams.noDictIDFlag = 1;\n        CHECK_Z(ZSTD_CCtx_setParams(cctx, params));\n\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_windowLog, &value));\n        CHECK_EQ(value, (int)params.cParams.windowLog);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_chainLog, &value));\n        CHECK_EQ(value, (int)params.cParams.chainLog);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_hashLog, &value));\n        CHECK_EQ(value, (int)params.cParams.hashLog);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_searchLog, &value));\n        CHECK_EQ(value, (int)params.cParams.searchLog);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_minMatch, &value));\n        CHECK_EQ(value, (int)params.cParams.minMatch);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_targetLength, &value));\n        CHECK_EQ(value, (int)params.cParams.targetLength);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_strategy, &value));\n        CHECK_EQ(value, (int)params.cParams.strategy);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_contentSizeFlag, &value));\n        CHECK_EQ(value, params.fParams.contentSizeFlag);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_checksumFlag, &value));\n        CHECK_EQ(value, params.fParams.checksumFlag);\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_dictIDFlag, &value));\n        CHECK_EQ(value, !params.fParams.noDictIDFlag);\n\n        ZSTD_freeCCtx(cctx);\n    }\n\n    DISPLAYLEVEL(3, \"test%3d : ldm conditionally enabled by default doesn't change cctx params: \", testNb++);\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        ZSTD_outBuffer out = {NULL, 0, 0};\n        ZSTD_inBuffer in = {NULL, 0, 0};\n        int value;\n\n        /* Even if LDM will be enabled by default in the applied params (since wlog >= 27 and strategy >= btopt),\n         * we should not modify the actual parameter specified by the user within the CCtx\n         */\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 27));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_strategy, ZSTD_btopt));\n\n        CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue));\n        CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_enableLongDistanceMatching, &value));\n        CHECK_EQ(value, 0);\n\n        ZSTD_freeCCtx(cctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* this test is really too long, and should be made faster */\n    DISPLAYLEVEL(3, \"test%3d : overflow protection with large windowLog : \", testNb++);\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        ZSTD_parameters params = ZSTD_getParams(-999, ZSTD_CONTENTSIZE_UNKNOWN, 0);\n        size_t const nbCompressions = ((1U << 31) / CNBuffSize) + 2;   /* ensure U32 overflow protection is triggered */\n        size_t cnb;\n        assert(cctx != NULL);\n        params.fParams.contentSizeFlag = 0;\n        params.cParams.windowLog = ZSTD_WINDOWLOG_MAX;\n        for (cnb = 0; cnb < nbCompressions; ++cnb) {\n            DISPLAYLEVEL(6, \"run %u / %u \\n\", (unsigned)cnb, (unsigned)nbCompressions);\n            CHECK_Z( ZSTD_compressBegin_advanced(cctx, NULL, 0, params, ZSTD_CONTENTSIZE_UNKNOWN) );  /* reuse same parameters */\n            CHECK_Z( ZSTD_compressEnd(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize) );\n        }\n        ZSTD_freeCCtx(cctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3d : size down context : \", testNb++);\n    {   ZSTD_CCtx* const largeCCtx = ZSTD_createCCtx();\n        assert(largeCCtx != NULL);\n        CHECK_Z( ZSTD_compressBegin(largeCCtx, 19) );   /* streaming implies ZSTD_CONTENTSIZE_UNKNOWN, which maximizes memory usage */\n        CHECK_Z( ZSTD_compressEnd(largeCCtx, compressedBuffer, compressedBufferSize, CNBuffer, 1) );\n        {   size_t const largeCCtxSize = ZSTD_sizeof_CCtx(largeCCtx);   /* size of context must be measured after compression */\n            {   ZSTD_CCtx* const smallCCtx = ZSTD_createCCtx();\n                assert(smallCCtx != NULL);\n                CHECK_Z(ZSTD_compressCCtx(smallCCtx, compressedBuffer, compressedBufferSize, CNBuffer, 1, 1));\n                {   size_t const smallCCtxSize = ZSTD_sizeof_CCtx(smallCCtx);\n                    DISPLAYLEVEL(5, \"(large) %uKB > 32*%uKB (small) : \",\n                                (unsigned)(largeCCtxSize>>10), (unsigned)(smallCCtxSize>>10));\n                    assert(largeCCtxSize > 32* smallCCtxSize);  /* note : \"too large\" definition is handled within zstd_compress.c .\n                                                                 * make this test case extreme, so that it doesn't depend on a possibly fluctuating definition */\n                }\n                ZSTD_freeCCtx(smallCCtx);\n            }\n            {   U32 const maxNbAttempts = 1100;   /* nb of usages before triggering size down is handled within zstd_compress.c.\n                                                   * currently defined as 128x, but could be adjusted in the future.\n                                                   * make this test long enough so that it's not too much tied to the current definition within zstd_compress.c */\n                unsigned u;\n                for (u=0; u<maxNbAttempts; u++) {\n                    CHECK_Z(ZSTD_compressCCtx(largeCCtx, compressedBuffer, compressedBufferSize, CNBuffer, 1, 1));\n                    if (ZSTD_sizeof_CCtx(largeCCtx) < largeCCtxSize) break;   /* sized down */\n                }\n                DISPLAYLEVEL(5, \"size down after %u attempts : \", u);\n                if (u==maxNbAttempts) goto _output_error;   /* no sizedown happened */\n            }\n        }\n        ZSTD_freeCCtx(largeCCtx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* Static CCtx tests */\n#define STATIC_CCTX_LEVEL 4\n    DISPLAYLEVEL(3, \"test%3i : create static CCtx for level %u : \", testNb++, STATIC_CCTX_LEVEL);\n    {   size_t const staticCStreamSize = ZSTD_estimateCStreamSize(STATIC_CCTX_LEVEL);\n        void* const staticCCtxBuffer = malloc(staticCStreamSize);\n        size_t const staticDCtxSize = ZSTD_estimateDCtxSize();\n        void* const staticDCtxBuffer = malloc(staticDCtxSize);\n        DISPLAYLEVEL(4, \"CStream size = %u, \", (U32)staticCStreamSize);\n        if (staticCCtxBuffer==NULL || staticDCtxBuffer==NULL) {\n            free(staticCCtxBuffer);\n            free(staticDCtxBuffer);\n            DISPLAY(\"Not enough memory, aborting\\n\");\n            testResult = 1;\n            goto _end;\n        }\n        {   size_t const smallInSize = 32 KB;\n            ZSTD_compressionParameters const cparams_small = ZSTD_getCParams(STATIC_CCTX_LEVEL, smallInSize, 0);\n            size_t const smallCCtxSize = ZSTD_estimateCCtxSize_usingCParams(cparams_small);\n            size_t const staticCCtxSize = ZSTD_estimateCCtxSize(STATIC_CCTX_LEVEL);\n            ZSTD_CCtx* staticCCtx = ZSTD_initStaticCCtx(staticCCtxBuffer, smallCCtxSize);\n            ZSTD_DCtx* const staticDCtx = ZSTD_initStaticDCtx(staticDCtxBuffer, staticDCtxSize);\n            DISPLAYLEVEL(4, \"Full CCtx size = %u, \", (U32)staticCCtxSize);\n            DISPLAYLEVEL(4, \"CCtx for 32 KB = %u, \", (U32)smallCCtxSize);\n            if ((staticCCtx==NULL) || (staticDCtx==NULL)) goto _output_error;\n            DISPLAYLEVEL(3, \"OK \\n\");\n\n            DISPLAYLEVEL(3, \"test%3i : compress small input with small static CCtx : \", testNb++);\n            CHECK_VAR(cSize, ZSTD_compressCCtx(staticCCtx,\n                                  compressedBuffer, compressedBufferSize,\n                                  CNBuffer, smallInSize, STATIC_CCTX_LEVEL) );\n            DISPLAYLEVEL(3, \"OK (%u bytes : %.2f%%)\\n\",\n                            (unsigned)cSize, (double)cSize/smallInSize*100);\n\n            DISPLAYLEVEL(3, \"test%3i : compress large input with small static CCtx (must fail) : \", testNb++);\n            {   size_t const r = ZSTD_compressCCtx(staticCCtx,\n                                  compressedBuffer, compressedBufferSize,\n                                  CNBuffer, CNBuffSize, STATIC_CCTX_LEVEL);\n                if (ZSTD_getErrorCode((size_t)r) != ZSTD_error_memory_allocation) goto _output_error;\n            }\n            DISPLAYLEVEL(3, \"OK \\n\");\n\n            DISPLAYLEVEL(3, \"test%3i : resize context to full CCtx size : \", testNb++);\n            staticCCtx = ZSTD_initStaticCStream(staticCCtxBuffer, staticCCtxSize);\n            DISPLAYLEVEL(4, \"staticCCtxBuffer = %p,  staticCCtx = %p , \", staticCCtxBuffer, (void*)staticCCtx);\n            if (staticCCtx == NULL) goto _output_error;\n            DISPLAYLEVEL(3, \"OK \\n\");\n\n            DISPLAYLEVEL(3, \"test%3i : compress large input with static CCtx : \", testNb++);\n            CHECK_VAR(cSize, ZSTD_compressCCtx(staticCCtx,\n                                  compressedBuffer, compressedBufferSize,\n                                  CNBuffer, CNBuffSize, STATIC_CCTX_LEVEL) );\n            DISPLAYLEVEL(3, \"OK (%u bytes : %.2f%%)\\n\",\n                            (unsigned)cSize, (double)cSize/CNBuffSize*100);\n\n            DISPLAYLEVEL(3, \"test%3i : compress small input often enough to trigger context reduce : \", testNb++);\n            {   int nbc;\n                assert(staticCCtxSize > smallCCtxSize * ZSTD_WORKSPACETOOLARGE_FACTOR);  /* ensure size down scenario */\n                assert(CNBuffSize > smallInSize + ZSTD_WORKSPACETOOLARGE_MAXDURATION + 3);\n                for (nbc=0; nbc<ZSTD_WORKSPACETOOLARGE_MAXDURATION+2; nbc++) {\n                    CHECK_Z(ZSTD_compressCCtx(staticCCtx,\n                                  compressedBuffer, compressedBufferSize,\n                                  (char*)CNBuffer + nbc, smallInSize,\n                                  STATIC_CCTX_LEVEL) );\n            }   }\n            DISPLAYLEVEL(3, \"OK \\n\")\n\n            DISPLAYLEVEL(3, \"test%3i : init CCtx for level %u : \", testNb++, STATIC_CCTX_LEVEL);\n            CHECK_Z( ZSTD_compressBegin(staticCCtx, STATIC_CCTX_LEVEL) );\n            DISPLAYLEVEL(3, \"OK \\n\");\n\n            DISPLAYLEVEL(3, \"test%3i : compression again with static CCtx : \", testNb++);\n            CHECK_VAR(cSize, ZSTD_compressCCtx(staticCCtx,\n                                  compressedBuffer, compressedBufferSize,\n                                  CNBuffer, CNBuffSize, STATIC_CCTX_LEVEL) );\n            DISPLAYLEVEL(3, \"OK (%u bytes : %.2f%%)\\n\",\n                            (unsigned)cSize, (double)cSize/CNBuffSize*100);\n\n            DISPLAYLEVEL(3, \"test%3i : simple decompression test with static DCtx : \", testNb++);\n            { size_t const r = ZSTD_decompressDCtx(staticDCtx,\n                                                decodedBuffer, CNBuffSize,\n                                                compressedBuffer, cSize);\n              if (r != CNBuffSize) goto _output_error; }\n            DISPLAYLEVEL(3, \"OK \\n\");\n\n            DISPLAYLEVEL(3, \"test%3i : check decompressed result : \", testNb++);\n            if (memcmp(decodedBuffer, CNBuffer, CNBuffSize)) goto _output_error;\n            DISPLAYLEVEL(3, \"OK \\n\");\n\n            DISPLAYLEVEL(3, \"test%3i : init CCtx for too large level (must fail) : \", testNb++);\n            { size_t const r = ZSTD_compressBegin(staticCCtx, ZSTD_maxCLevel());\n              if (!ZSTD_isError(r)) goto _output_error; }\n            DISPLAYLEVEL(3, \"OK \\n\");\n\n            DISPLAYLEVEL(3, \"test%3i : init CCtx for small level %u (should work again) : \", testNb++, 1);\n            CHECK_Z( ZSTD_compressBegin(staticCCtx, 1) );\n            DISPLAYLEVEL(3, \"OK \\n\");\n\n            DISPLAYLEVEL(3, \"test%3i : use CStream on CCtx-sized static context (should fail) : \", testNb++);\n            CHECK_Z( ZSTD_initCStream(staticCCtx, STATIC_CCTX_LEVEL) ); /* note : doesn't allocate */\n            {   ZSTD_outBuffer output = { compressedBuffer, compressedBufferSize, 0 };\n                ZSTD_inBuffer input = { CNBuffer, CNBuffSize, 0 };\n                size_t const r = ZSTD_compressStream(staticCCtx, &output, &input); /* now allocates, should fail */\n                if (!ZSTD_isError(r)) goto _output_error;\n            }\n            DISPLAYLEVEL(3, \"OK \\n\");\n\n            DISPLAYLEVEL(3, \"test%3i : resize context to CStream size, then stream compress : \", testNb++);\n            staticCCtx = ZSTD_initStaticCStream(staticCCtxBuffer, staticCStreamSize);\n            assert(staticCCtx != NULL);\n            CHECK_Z( ZSTD_initCStream(staticCCtx, STATIC_CCTX_LEVEL) ); /* note : doesn't allocate */\n            {   ZSTD_outBuffer output = { compressedBuffer, compressedBufferSize, 0 };\n                ZSTD_inBuffer input = { CNBuffer, CNBuffSize, 0 };\n                CHECK_Z( ZSTD_compressStream(staticCCtx, &output, &input) );\n            }\n            DISPLAYLEVEL(3, \"OK \\n\");\n\n            DISPLAYLEVEL(3, \"test%3i : CStream for small level %u : \", testNb++, 1);\n            CHECK_Z( ZSTD_initCStream(staticCCtx, 1) ); /* note : doesn't allocate */\n            {   ZSTD_outBuffer output = { compressedBuffer, compressedBufferSize, 0 };\n                ZSTD_inBuffer input = { CNBuffer, CNBuffSize, 0 };\n                CHECK_Z( ZSTD_compressStream(staticCCtx, &output, &input) );\n            }\n            DISPLAYLEVEL(3, \"OK \\n\");\n\n            DISPLAYLEVEL(3, \"test%3i : init static CStream with dictionary (should fail) : \", testNb++);\n            { size_t const r = ZSTD_initCStream_usingDict(staticCCtx, CNBuffer, 64 KB, 1);\n              if (!ZSTD_isError(r)) goto _output_error; }\n            DISPLAYLEVEL(3, \"OK \\n\");\n\n            DISPLAYLEVEL(3, \"test%3i : use DStream on DCtx-sized static context (should fail) : \", testNb++);\n            CHECK_Z( ZSTD_initDStream(staticDCtx) );\n            {   ZSTD_outBuffer output = { decodedBuffer, CNBuffSize, 0 };\n                ZSTD_inBuffer input = { compressedBuffer, ZSTD_FRAMEHEADERSIZE_MAX+1, 0 };\n                size_t const r = ZSTD_decompressStream(staticDCtx, &output, &input);\n                if (!ZSTD_isError(r)) goto _output_error;\n            }\n            DISPLAYLEVEL(3, \"OK \\n\");\n\n            DISPLAYLEVEL(3, \"test%3i : test estimation functions with default cctx params : \", testNb++);\n            {\n                // Test ZSTD_estimateCCtxSize_usingCCtxParams\n                {\n                    ZSTD_CCtx_params* params = ZSTD_createCCtxParams();\n                    size_t const cctxSizeDefault = ZSTD_estimateCCtxSize_usingCCtxParams(params);\n                    staticCCtx = ZSTD_initStaticCCtx(staticCCtxBuffer, cctxSizeDefault);\n                    CHECK_VAR(cSize, ZSTD_compressCCtx(staticCCtx,\n                                    compressedBuffer, compressedBufferSize,\n                                    CNBuffer, CNBuffSize, 3));\n\n                    {\n                        size_t const r = ZSTD_decompressDCtx(staticDCtx,\n                                                    decodedBuffer, CNBuffSize,\n                                                    compressedBuffer, cSize);\n                                                                        if (r != CNBuffSize) goto _output_error;\n                        if (memcmp(decodedBuffer, CNBuffer, CNBuffSize)) goto _output_error;\n                    }\n                    ZSTD_freeCCtxParams(params);\n                }\n\n                // Test ZSTD_estimateCStreamSize_usingCCtxParams\n                  {\n                    ZSTD_CCtx_params* params = ZSTD_createCCtxParams();\n                    size_t const cctxSizeDefault = ZSTD_estimateCStreamSize_usingCCtxParams(params);\n                    staticCCtx = ZSTD_initStaticCCtx(staticCCtxBuffer, cctxSizeDefault);\n                    CHECK_VAR(cSize, ZSTD_compressCCtx(staticCCtx,\n                                    compressedBuffer, compressedBufferSize,\n                                    CNBuffer, CNBuffSize, 3) );\n\n                    {\n                        size_t const r = ZSTD_decompressDCtx(staticDCtx,\n                                                    decodedBuffer, CNBuffSize,\n                                                    compressedBuffer, cSize);\n                                                                        if (r != CNBuffSize) goto _output_error;\n                        if (memcmp(decodedBuffer, CNBuffer, CNBuffSize)) goto _output_error;\n                    }\n                    ZSTD_freeCCtxParams(params);\n                }\n            }\n            DISPLAYLEVEL(3, \"OK \\n\");\n\n            DISPLAYLEVEL(3, \"test%3i : test estimation functions with maxBlockSize = 0 : \", testNb++);\n            {\n                // Test ZSTD_estimateCCtxSize_usingCCtxParams\n                {\n                    ZSTD_CCtx_params* params = ZSTD_createCCtxParams();\n                    size_t cctxSizeDefault;\n                    CHECK_Z(ZSTD_CCtxParams_setParameter(params, ZSTD_c_maxBlockSize, 0));\n                    cctxSizeDefault = ZSTD_estimateCCtxSize_usingCCtxParams(params);\n                    staticCCtx = ZSTD_initStaticCCtx(staticCCtxBuffer, cctxSizeDefault);\n                    CHECK_VAR(cSize, ZSTD_compressCCtx(staticCCtx,\n                                    compressedBuffer, compressedBufferSize,\n                                    CNBuffer, CNBuffSize, 3) );\n\n                    {\n                        size_t const r = ZSTD_decompressDCtx(staticDCtx,\n                                                    decodedBuffer, CNBuffSize,\n                                                    compressedBuffer, cSize);\n                                                                        if (r != CNBuffSize) goto _output_error;\n                        if (memcmp(decodedBuffer, CNBuffer, CNBuffSize)) goto _output_error;\n                    }\n                    ZSTD_freeCCtxParams(params);\n                }\n\n                // Test ZSTD_estimateCStreamSize_usingCCtxParams\n                  {\n                    ZSTD_CCtx_params* params = ZSTD_createCCtxParams();\n                    size_t cctxSizeDefault;\n                    CHECK_Z(ZSTD_CCtxParams_setParameter(params, ZSTD_c_maxBlockSize, 0));\n                    cctxSizeDefault = ZSTD_estimateCStreamSize_usingCCtxParams(params);\n                    staticCCtx = ZSTD_initStaticCCtx(staticCCtxBuffer, cctxSizeDefault);\n                    CHECK_VAR(cSize, ZSTD_compressCCtx(staticCCtx,\n                                    compressedBuffer, compressedBufferSize,\n                                    CNBuffer, CNBuffSize, 3) );\n\n                    {\n                        size_t const r = ZSTD_decompressDCtx(staticDCtx,\n                                                    decodedBuffer, CNBuffSize,\n                                                    compressedBuffer, cSize);\n                                                                        if (r != CNBuffSize) goto _output_error;\n                        if (memcmp(decodedBuffer, CNBuffer, CNBuffSize)) goto _output_error;\n                    }\n                    ZSTD_freeCCtxParams(params);\n                }\n            }\n            DISPLAYLEVEL(3, \"OK \\n\");\n\n            DISPLAYLEVEL(3, \"test%3i : estimation functions with LDM enabled (issue #4590) : \", testNb++);\n            {\n                /* ZSTD_estimateCCtxSize_usingCCtxParams must adjust zeroed-out\n                 * LDM parameters when LDM is enabled, to avoid division by zero\n                 * in ZSTD_ldm_getMaxNbSeq. */\n                ZSTD_CCtx_params* params = ZSTD_createCCtxParams();\n                size_t cctxSize;\n                CHECK_Z(ZSTD_CCtxParams_setParameter(params, ZSTD_c_compressionLevel, 22));\n                CHECK_Z(ZSTD_CCtxParams_setParameter(params, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable));\n                cctxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params);\n                if (ZSTD_isError(cctxSize)) goto _output_error;\n                if (cctxSize == 0) goto _output_error;\n                cctxSize = ZSTD_estimateCStreamSize_usingCCtxParams(params);\n                if (ZSTD_isError(cctxSize)) goto _output_error;\n                if (cctxSize == 0) goto _output_error;\n                ZSTD_freeCCtxParams(params);\n            }\n            DISPLAYLEVEL(3, \"OK \\n\");\n        }\n        free(staticCCtxBuffer);\n        free(staticDCtxBuffer);\n    }\n\n    DISPLAYLEVEL(3, \"test%3i : Static context sizes for negative levels : \", testNb++);\n    {   size_t const cctxSizeN1 = ZSTD_estimateCCtxSize(-1);\n        size_t const cctxSizeP1 = ZSTD_estimateCCtxSize(1);\n        size_t const cstreamSizeN1 = ZSTD_estimateCStreamSize(-1);\n        size_t const cstreamSizeP1 = ZSTD_estimateCStreamSize(1);\n\n        if (!(0 < cctxSizeN1 && cctxSizeN1 <= cctxSizeP1)) goto _output_error;\n        if (!(0 < cstreamSizeN1 && cstreamSizeN1 <= cstreamSizeP1)) goto _output_error;\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n\n    /* ZSTDMT simple MT compression test */\n    DISPLAYLEVEL(3, \"test%3i : create ZSTDMT CCtx : \", testNb++);\n    {   ZSTD_CCtx* const mtctx = ZSTD_createCCtx();\n        if (mtctx==NULL) {\n            DISPLAY(\"mtctx : not enough memory, aborting \\n\");\n            testResult = 1;\n            goto _end;\n        }\n        CHECK_Z( ZSTD_CCtx_setParameter(mtctx, ZSTD_c_nbWorkers, 2) );\n        CHECK_Z( ZSTD_CCtx_setParameter(mtctx, ZSTD_c_compressionLevel, 1) );\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3u : compress %u bytes with 2 threads : \", testNb++, (unsigned)CNBuffSize);\n        CHECK_VAR(cSize, ZSTD_compress2(mtctx,\n                                compressedBuffer, compressedBufferSize,\n                                CNBuffer, CNBuffSize) );\n        DISPLAYLEVEL(3, \"OK (%u bytes : %.2f%%)\\n\", (unsigned)cSize, (double)cSize/CNBuffSize*100);\n\n        DISPLAYLEVEL(3, \"test%3i : decompressed size test : \", testNb++);\n        {   unsigned long long const rSize = ZSTD_getFrameContentSize(compressedBuffer, cSize);\n            if (rSize != CNBuffSize)  {\n                DISPLAY(\"ZSTD_getFrameContentSize incorrect : %u != %u \\n\", (unsigned)rSize, (unsigned)CNBuffSize);\n                goto _output_error;\n        }   }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : decompress %u bytes : \", testNb++, (unsigned)CNBuffSize);\n        { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize);\n          if (r != CNBuffSize) goto _output_error; }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : check decompressed result : \", testNb++);\n        {   size_t u;\n            for (u=0; u<CNBuffSize; u++) {\n                if (((BYTE*)decodedBuffer)[u] != ((BYTE*)CNBuffer)[u]) goto _output_error;\n        }   }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : compress -T2 with checksum : \", testNb++);\n        CHECK_Z( ZSTD_CCtx_setParameter(mtctx, ZSTD_c_checksumFlag, 1) );\n        CHECK_Z( ZSTD_CCtx_setParameter(mtctx, ZSTD_c_contentSizeFlag, 1) );\n        CHECK_Z( ZSTD_CCtx_setParameter(mtctx, ZSTD_c_overlapLog, 3) );\n        CHECK_VAR(cSize, ZSTD_compress2(mtctx,\n                                compressedBuffer, compressedBufferSize,\n                                CNBuffer, CNBuffSize) );\n        DISPLAYLEVEL(3, \"OK (%u bytes : %.2f%%)\\n\", (unsigned)cSize, (double)cSize/CNBuffSize*100);\n\n        DISPLAYLEVEL(3, \"test%3i : decompress %u bytes : \", testNb++, (unsigned)CNBuffSize);\n        { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize);\n          if (r != CNBuffSize) goto _output_error; }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        ZSTD_freeCCtx(mtctx);\n    }\n\n    DISPLAYLEVEL(3, \"test%3u : compress empty string and decompress with small window log : \", testNb++);\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n        char out[32];\n        if (cctx == NULL || dctx == NULL) goto _output_error;\n        CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_contentSizeFlag, 0) );\n        CHECK_VAR(cSize, ZSTD_compress2(cctx, out, sizeof(out), NULL, 0) );\n        DISPLAYLEVEL(3, \"OK (%u bytes)\\n\", (unsigned)cSize);\n\n        CHECK_Z( ZSTD_DCtx_setParameter(dctx, ZSTD_d_windowLogMax, 10) );\n        {   char const* outPtr = out;\n            ZSTD_inBuffer inBuffer = { outPtr, cSize, 0 };\n            ZSTD_outBuffer outBuffer = { NULL, 0, 0 };\n            size_t dSize;\n            CHECK_VAR(dSize, ZSTD_decompressStream(dctx, &outBuffer, &inBuffer) );\n            if (dSize != 0) goto _output_error;\n        }\n\n        ZSTD_freeDCtx(dctx);\n        ZSTD_freeCCtx(cctx);\n    }\n\n    DISPLAYLEVEL(3, \"test%3i : compress with block splitting : \", testNb++)\n    {   ZSTD_CCtx* cctx = ZSTD_createCCtx();\n        CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_splitAfterSequences, ZSTD_ps_enable) );\n        cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);\n        CHECK_Z(cSize);\n        ZSTD_freeCCtx(cctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : compress -T2 with/without literals compression : \", testNb++)\n    {   ZSTD_CCtx* cctx = ZSTD_createCCtx();\n        size_t cSize1, cSize2;\n        CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1) );\n        CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 2) );\n        cSize1 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);\n        CHECK_Z(cSize1);\n        CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_literalCompressionMode, ZSTD_ps_disable) );\n        cSize2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);\n        CHECK_Z(cSize2);\n        CHECK_LT(cSize1, cSize2);\n        ZSTD_freeCCtx(cctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : Multithreaded ZSTD_compress2() with rsyncable : \", testNb++)\n    {   ZSTD_CCtx* cctx = ZSTD_createCCtx();\n        /* Set rsyncable and don't give the ZSTD_compressBound(CNBuffSize) so\n         * ZSTDMT is forced to not take the shortcut.\n         */\n        CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1) );\n        CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 1) );\n        CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_rsyncable, 1) );\n        CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize - 1, CNBuffer, CNBuffSize) );\n        ZSTD_freeCCtx(cctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : setting multithreaded parameters : \", testNb++)\n    {   ZSTD_CCtx_params* params = ZSTD_createCCtxParams();\n        int const jobSize = 512 KB;\n        int value;\n        /* Check that the overlap log and job size are unset. */\n        CHECK_Z( ZSTD_CCtxParams_getParameter(params, ZSTD_c_overlapLog, &value) );\n        CHECK_EQ(value, 0);\n        CHECK_Z( ZSTD_CCtxParams_getParameter(params, ZSTD_c_jobSize, &value) );\n        CHECK_EQ(value, 0);\n        /* Set and check the overlap log and job size. */\n        CHECK_Z( ZSTD_CCtxParams_setParameter(params, ZSTD_c_overlapLog, 5) );\n        CHECK_Z( ZSTD_CCtxParams_setParameter(params, ZSTD_c_jobSize, jobSize) );\n        CHECK_Z( ZSTD_CCtxParams_getParameter(params, ZSTD_c_overlapLog, &value) );\n        CHECK_EQ(value, 5);\n        CHECK_Z( ZSTD_CCtxParams_getParameter(params, ZSTD_c_jobSize, &value) );\n        CHECK_EQ(value, jobSize);\n        /* Set the number of workers and check the overlap log and job size. */\n        CHECK_Z( ZSTD_CCtxParams_setParameter(params, ZSTD_c_nbWorkers, 2) );\n        CHECK_Z( ZSTD_CCtxParams_getParameter(params, ZSTD_c_overlapLog, &value) );\n        CHECK_EQ(value, 5);\n        CHECK_Z( ZSTD_CCtxParams_getParameter(params, ZSTD_c_jobSize, &value) );\n        CHECK_EQ(value, jobSize);\n        ZSTD_freeCCtxParams(params);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* Simple API multiframe test */\n    DISPLAYLEVEL(3, \"test%3i : compress multiple frames : \", testNb++);\n    {   size_t off = 0;\n        int i;\n        int const segs = 4;\n        /* only use the first half so we don't push against size limit of compressedBuffer */\n        size_t const segSize = (CNBuffSize / 2) / segs;\n\n        const U32 skipLen = 129 KB;\n        char* const skipBuff = (char*)malloc(skipLen);\n        assert(skipBuff != NULL);\n        memset(skipBuff, 0, skipLen);\n        for (i = 0; i < segs; i++) {\n            CHECK_NEWV(r, ZSTD_compress(\n                            (BYTE*)compressedBuffer + off, CNBuffSize - off,\n                            (BYTE*)CNBuffer + segSize * (size_t)i, segSize,\n                            5) );\n            off += r;\n            if (i == segs/2) {\n                /* insert skippable frame */\n                size_t const skippableSize =\n                    ZSTD_writeSkippableFrame((BYTE*)compressedBuffer + off, compressedBufferSize,\n                                             skipBuff, skipLen, seed % 15);\n                CHECK_Z(skippableSize);\n                off += skippableSize;\n            }\n        }\n        cSize = off;\n        free(skipBuff);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : get decompressed size of multiple frames : \", testNb++);\n    {   unsigned long long const r = ZSTD_findDecompressedSize(compressedBuffer, cSize);\n        if (r != CNBuffSize / 2) goto _output_error; }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : get tight decompressed bound of multiple frames : \", testNb++);\n    {   unsigned long long const bound = ZSTD_decompressBound(compressedBuffer, cSize);\n        if (bound != CNBuffSize / 2) goto _output_error; }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : decompress multiple frames : \", testNb++);\n    {   CHECK_NEWV(r, ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize));\n        if (r != CNBuffSize / 2) goto _output_error; }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : check decompressed result : \", testNb++);\n    if (memcmp(decodedBuffer, CNBuffer, CNBuffSize / 2) != 0) goto _output_error;\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* Simple API skippable frame test */\n    DISPLAYLEVEL(3, \"test%3i : read/write a skippable frame : \", testNb++);\n    {   U32 i;\n        unsigned readMagic;\n        unsigned long long receivedSize;\n        size_t skippableSize;\n        const U32 skipLen = 129 KB;\n        char* const skipBuff = (char*)malloc(skipLen);\n        assert(skipBuff != NULL);\n        for (i = 0; i < skipLen; i++)\n            skipBuff[i] = (char) ((seed + i) % 256);\n        skippableSize = ZSTD_writeSkippableFrame(\n                                compressedBuffer, compressedBufferSize,\n                                skipBuff, skipLen, seed % 15);\n        CHECK_Z(skippableSize);\n        CHECK_EQ(1, ZSTD_isSkippableFrame(compressedBuffer, skippableSize));\n        receivedSize = ZSTD_readSkippableFrame(decodedBuffer, CNBuffSize, &readMagic, compressedBuffer, skippableSize);\n        CHECK_EQ(skippableSize, receivedSize + ZSTD_SKIPPABLEHEADERSIZE);\n        CHECK_EQ(seed % 15, readMagic);\n        if (memcmp(decodedBuffer, skipBuff, skipLen) != 0) goto _output_error;\n\n        free(skipBuff);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : read/write an empty skippable frame : \", testNb++);\n    {\n        unsigned readMagic;\n        unsigned long long receivedSize;\n        size_t skippableSize;\n        skippableSize = ZSTD_writeSkippableFrame(\n                                compressedBuffer, compressedBufferSize,\n                                CNBuffer, 0, seed % 15);\n        CHECK_EQ(ZSTD_SKIPPABLEHEADERSIZE, skippableSize);\n        CHECK_EQ(1, ZSTD_isSkippableFrame(compressedBuffer, skippableSize));\n        receivedSize = ZSTD_readSkippableFrame(NULL, 0, &readMagic, compressedBuffer, skippableSize);\n        CHECK_EQ(skippableSize, receivedSize + ZSTD_SKIPPABLEHEADERSIZE);\n        CHECK_EQ(seed % 15, readMagic);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* Dictionary and CCtx Duplication tests */\n    {   ZSTD_CCtx* const ctxOrig = ZSTD_createCCtx();\n        ZSTD_CCtx* const ctxDuplicated = ZSTD_createCCtx();\n        ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n        static const size_t dictSize = 551;\n        assert(dctx != NULL); assert(ctxOrig != NULL); assert(ctxDuplicated != NULL);\n\n        DISPLAYLEVEL(3, \"test%3i : copy context too soon : \", testNb++);\n        { size_t const copyResult = ZSTD_copyCCtx(ctxDuplicated, ctxOrig, 0);\n          if (!ZSTD_isError(copyResult)) goto _output_error; }   /* error must be detected */\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : load dictionary into context : \", testNb++);\n        CHECK_Z( ZSTD_compressBegin_usingDict(ctxOrig, CNBuffer, dictSize, 2) );\n        CHECK_Z( ZSTD_copyCCtx(ctxDuplicated, ctxOrig, 0) ); /* Begin_usingDict implies unknown srcSize, so match that */\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : compress with flat dictionary : \", testNb++);\n        cSize = 0;\n        CHECKPLUS(r, ZSTD_compressEnd(ctxOrig,\n                                      compressedBuffer, compressedBufferSize,\n                         (const char*)CNBuffer + dictSize, CNBuffSize - dictSize),\n                  cSize += r);\n        DISPLAYLEVEL(3, \"OK (%u bytes : %.2f%%)\\n\", (unsigned)cSize, (double)cSize/CNBuffSize*100);\n\n        DISPLAYLEVEL(3, \"test%3i : frame built with flat dictionary should be decompressible : \", testNb++);\n        CHECKPLUS(r, ZSTD_decompress_usingDict(dctx,\n                                       decodedBuffer, CNBuffSize,\n                                       compressedBuffer, cSize,\n                                       CNBuffer, dictSize),\n                  if (r != CNBuffSize - dictSize) goto _output_error);\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : compress with duplicated context : \", testNb++);\n        {   size_t const cSizeOrig = cSize;\n            cSize = 0;\n            CHECKPLUS(r, ZSTD_compressEnd(ctxDuplicated,\n                                    compressedBuffer, compressedBufferSize,\n                       (const char*)CNBuffer + dictSize, CNBuffSize - dictSize),\n                      cSize += r);\n            if (cSize != cSizeOrig) goto _output_error;   /* should be identical ==> same size */\n        }\n        DISPLAYLEVEL(3, \"OK (%u bytes : %.2f%%)\\n\", (unsigned)cSize, (double)cSize/CNBuffSize*100);\n\n        DISPLAYLEVEL(3, \"test%3i : frame built with duplicated context should be decompressible : \", testNb++);\n        CHECKPLUS(r, ZSTD_decompress_usingDict(dctx,\n                                           decodedBuffer, CNBuffSize,\n                                           compressedBuffer, cSize,\n                                           CNBuffer, dictSize),\n                  if (r != CNBuffSize - dictSize) goto _output_error);\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : decompress with DDict : \", testNb++);\n        {   ZSTD_DDict* const ddict = ZSTD_createDDict(CNBuffer, dictSize);\n            size_t const r = ZSTD_decompress_usingDDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, ddict);\n            if (r != CNBuffSize - dictSize) goto _output_error;\n            DISPLAYLEVEL(3, \"OK (size of DDict : %u) \\n\", (unsigned)ZSTD_sizeof_DDict(ddict));\n            ZSTD_freeDDict(ddict);\n        }\n\n        DISPLAYLEVEL(3, \"test%3i : decompress with static DDict : \", testNb++);\n        {   size_t const ddictBufferSize = ZSTD_estimateDDictSize(dictSize, ZSTD_dlm_byCopy);\n            void* const ddictBuffer = malloc(ddictBufferSize);\n            if (ddictBuffer == NULL) goto _output_error;\n            {   const ZSTD_DDict* const ddict = ZSTD_initStaticDDict(ddictBuffer, ddictBufferSize, CNBuffer, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto);\n                size_t const r = ZSTD_decompress_usingDDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, ddict);\n                if (r != CNBuffSize - dictSize) goto _output_error;\n            }\n            free(ddictBuffer);\n            DISPLAYLEVEL(3, \"OK (size of static DDict : %u) \\n\", (unsigned)ddictBufferSize);\n        }\n\n        DISPLAYLEVEL(3, \"test%3i : check content size on duplicated context : \", testNb++);\n        {   size_t const testSize = CNBuffSize / 3;\n            CHECK_Z( ZSTD_compressBegin(ctxOrig, ZSTD_defaultCLevel()) );\n            CHECK_Z( ZSTD_copyCCtx(ctxDuplicated, ctxOrig, testSize) );\n\n            CHECK_VAR(cSize, ZSTD_compressEnd(ctxDuplicated, compressedBuffer, ZSTD_compressBound(testSize),\n                                          (const char*)CNBuffer + dictSize, testSize) );\n            {   ZSTD_FrameHeader zfh;\n                if (ZSTD_getFrameHeader(&zfh, compressedBuffer, cSize)) goto _output_error;\n                if ((zfh.frameContentSize != testSize) && (zfh.frameContentSize != 0)) goto _output_error;\n        }   }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n#if !defined(ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR) \\\n && !defined(ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR) \\\n && !defined(ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR) \\\n && !defined(ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR) \\\n && !defined(ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR) \\\n && !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR) \\\n && !defined(ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR) \\\n && !defined(ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR)\n        /* Note : these tests should be replaced by proper regression tests,\n         *         but existing ones do not focus on small data + dictionary + all levels.\n         */\n        if ((int)(compressibility * 100 + 0.1) == FUZ_compressibility_default) { /* test only valid with known input */\n            size_t const flatdictSize = 22 KB;\n            size_t const contentSize = 9 KB;\n            const void* const dict = (const char*)CNBuffer;\n            const void* const contentStart = (const char*)dict + flatdictSize;\n            /* These upper bounds are generally within a few bytes of the compressed size */\n            size_t target_nodict_cSize[22+1] = { 3840, 3770, 3870, 3830, 3770,\n                                                 3770, 3770, 3770, 3750, 3750,\n                                                 3742, 3675, 3674, 3665, 3664,\n                                                 3663, 3662, 3661, 3660, 3660,\n                                                 3660, 3660, 3660 };\n            size_t const target_wdict_cSize[22+1] =  { 2830, 2896, 2893, 2840, 2950,\n                                                       2950, 2950, 2925, 2900, 2892,\n                                                       2910, 2910, 2910, 2780, 2775,\n                                                       2765, 2760, 2755, 2754, 2753,\n                                                       2753, 2753, 2753 };\n            int l = 1;\n            int const maxLevel = ZSTD_maxCLevel();\n            /* clevels with strategies that support rowhash on small inputs */\n            int rowLevel = 4;\n            int const rowLevelEnd = 8;\n\n            DISPLAYLEVEL(3, \"test%3i : flat-dictionary efficiency test : \\n\", testNb++);\n            assert(maxLevel == 22);\n            RDG_genBuffer(CNBuffer, flatdictSize + contentSize, compressibility, 0., seed);\n            DISPLAYLEVEL(4, \"content hash : %016llx;  dict hash : %016llx \\n\",\n                        (unsigned long long)XXH64(contentStart, contentSize, 0),\n                        (unsigned long long)XXH64(dict, flatdictSize, 0));\n\n            for ( ; l <= maxLevel; l++) {\n                size_t const nodict_cSize = ZSTD_compress(compressedBuffer, compressedBufferSize,\n                                                          contentStart, contentSize, l);\n                if (nodict_cSize > target_nodict_cSize[l]) {\n                    DISPLAYLEVEL(1, \"error : compression at level %i worse than expected (%u > %u) \\n\",\n                                    l, (unsigned)nodict_cSize, (unsigned)target_nodict_cSize[l]);\n                    goto _output_error;\n                }\n                DISPLAYLEVEL(4, \"level %i : max expected %u >= reached %u \\n\",\n                                l, (unsigned)target_nodict_cSize[l], (unsigned)nodict_cSize);\n            }\n            for ( l=1 ; l <= maxLevel; l++) {\n                size_t const wdict_cSize = ZSTD_compress_usingDict(ctxOrig,\n                                                          compressedBuffer, compressedBufferSize,\n                                                          contentStart, contentSize,\n                                                          dict, flatdictSize,\n                                                          l);\n                if (wdict_cSize > target_wdict_cSize[l]) {\n                    DISPLAYLEVEL(1, \"error : compression with dictionary at level %i worse than expected (%u > %u) \\n\",\n                                    l, (unsigned)wdict_cSize, (unsigned)target_wdict_cSize[l]);\n                    goto _output_error;\n                }\n                DISPLAYLEVEL(4, \"level %i with dictionary : max expected %u >= reached %u \\n\",\n                                l, (unsigned)target_wdict_cSize[l], (unsigned)wdict_cSize);\n            }\n            /* Compression with ZSTD_compress2 and row match finder force enabled.\n             * Give some slack for force-enabled row matchfinder since we're on a small input (9KB)\n             */\n            for ( ; rowLevel <= rowLevelEnd; ++rowLevel) target_nodict_cSize[rowLevel] += 5;\n            for (l=1 ; l <= maxLevel; l++) {\n                ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n                size_t nodict_cSize;\n                ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, l);\n                ZSTD_CCtx_setParameter(cctx, ZSTD_c_useRowMatchFinder, ZSTD_ps_enable);\n                nodict_cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize,\n                                                           contentStart, contentSize);\n                if (nodict_cSize > target_nodict_cSize[l]) {\n                    DISPLAYLEVEL(1, \"error : compression with compress2 at level %i worse than expected (%u > %u) \\n\",\n                                    l, (unsigned)nodict_cSize, (unsigned)target_nodict_cSize[l]);\n                    ZSTD_freeCCtx(cctx);\n                    goto _output_error;\n                }\n                DISPLAYLEVEL(4, \"level %i with compress2 : max expected %u >= reached %u \\n\",\n                                l, (unsigned)target_nodict_cSize[l], (unsigned)nodict_cSize);\n                ZSTD_freeCCtx(cctx);\n            }\n            /* Dict compression with DMS */\n            for ( l=1 ; l <= maxLevel; l++) {\n                size_t wdict_cSize;\n                CHECK_Z( ZSTD_CCtx_loadDictionary(ctxOrig, dict, flatdictSize) );\n                CHECK_Z( ZSTD_CCtx_setParameter(ctxOrig, ZSTD_c_compressionLevel, l) );\n                CHECK_Z( ZSTD_CCtx_setParameter(ctxOrig, ZSTD_c_enableDedicatedDictSearch, 0) );\n                CHECK_Z( ZSTD_CCtx_setParameter(ctxOrig, ZSTD_c_forceAttachDict, ZSTD_dictForceAttach) );\n                CHECK_Z( ZSTD_CCtx_setParameter(ctxOrig, ZSTD_c_prefetchCDictTables, seed % 3) );\n                wdict_cSize = ZSTD_compress2(ctxOrig, compressedBuffer, compressedBufferSize, contentStart, contentSize);\n                if (wdict_cSize > target_wdict_cSize[l]) {\n                    DISPLAYLEVEL(1, \"error : compression with dictionary and compress2 at level %i worse than expected (%u > %u) \\n\",\n                                    l, (unsigned)wdict_cSize, (unsigned)target_wdict_cSize[l]);\n                    goto _output_error;\n                }\n                DISPLAYLEVEL(4, \"level %i with dictionary and compress2 : max expected %u >= reached %u \\n\",\n                                l, (unsigned)target_wdict_cSize[l], (unsigned)wdict_cSize);\n            }\n\n            DISPLAYLEVEL(4, \"compression efficiency tests OK \\n\");\n        }\n#endif\n\n        ZSTD_freeCCtx(ctxOrig);\n        ZSTD_freeCCtx(ctxDuplicated);\n        ZSTD_freeDCtx(dctx);\n    }\n\n    /* Dictionary and dictBuilder tests */\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        size_t const dictBufferCapacity = 16 KB;\n        void* const dictBuffer = malloc(dictBufferCapacity);\n        size_t const totalSampleSize = 1 MB;\n        size_t const sampleUnitSize = 8 KB;\n        U32 const nbSamples = (U32)(totalSampleSize / sampleUnitSize);\n        size_t* const samplesSizes = (size_t*) malloc(nbSamples * sizeof(size_t));\n        size_t dictSize;\n        U32 dictID;\n        size_t dictHeaderSize;\n        size_t dictBufferFixedSize = 144;\n        unsigned char const dictBufferFixed[144] = {0x37, 0xa4, 0x30, 0xec, 0x63, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x1f,\n                                                    0x0f, 0x00, 0x28, 0xe5, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n                                                    0x00, 0x80, 0x0f, 0x9e, 0x0f, 0x00, 0x00, 0x24, 0x40, 0x80, 0x00, 0x01,\n                                                    0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0xde, 0x08,\n                                                    0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,\n                                                    0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,\n                                                    0x08, 0x08, 0x08, 0x08, 0xbc, 0xe1, 0x4b, 0x92, 0x0e, 0xb4, 0x7b, 0x18,\n                                                    0x86, 0x61, 0x18, 0xc6, 0x18, 0x63, 0x8c, 0x31, 0xc6, 0x18, 0x63, 0x8c,\n                                                    0x31, 0x66, 0x66, 0x66, 0x66, 0xb6, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x04,\n                                                    0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x73, 0x6f, 0x64, 0x61,\n                                                    0x6c, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x72, 0x74, 0x6f, 0x72, 0x20, 0x65,\n                                                    0x6c, 0x65, 0x69, 0x66, 0x65, 0x6e, 0x64, 0x2e, 0x20, 0x41, 0x6c, 0x69};\n\n        if (dictBuffer==NULL || samplesSizes==NULL) {\n            free(dictBuffer);\n            free(samplesSizes);\n            goto _output_error;\n        }\n\n        DISPLAYLEVEL(3, \"test%3i : dictBuilder on cyclic data : \", testNb++);\n        assert(compressedBufferSize >= totalSampleSize);\n        { U32 u; for (u=0; u<totalSampleSize; u++) ((BYTE*)decodedBuffer)[u] = (BYTE)u; }\n        { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }\n        {   size_t const sDictSize = ZDICT_trainFromBuffer(dictBuffer, dictBufferCapacity,\n                                         decodedBuffer, samplesSizes, nbSamples);\n            if (ZDICT_isError(sDictSize)) goto _output_error;\n            DISPLAYLEVEL(3, \"OK, created dictionary of size %u \\n\", (unsigned)sDictSize);\n        }\n\n        DISPLAYLEVEL(3, \"test%3i : dictBuilder : \", testNb++);\n        { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }\n        dictSize = ZDICT_trainFromBuffer(dictBuffer, dictBufferCapacity,\n                                         CNBuffer, samplesSizes, nbSamples);\n        if (ZDICT_isError(dictSize)) goto _output_error;\n        DISPLAYLEVEL(3, \"OK, created dictionary of size %u \\n\", (unsigned)dictSize);\n\n        DISPLAYLEVEL(3, \"test%3i : Multithreaded COVER dictBuilder : \", testNb++);\n        { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }\n        {   ZDICT_cover_params_t coverParams;\n            memset(&coverParams, 0, sizeof(coverParams));\n            coverParams.steps = 8;\n            coverParams.nbThreads = 4;\n            dictSize = ZDICT_optimizeTrainFromBuffer_cover(\n                dictBuffer, dictBufferCapacity,\n                CNBuffer, samplesSizes, nbSamples/8,  /* less samples for faster tests */\n                &coverParams);\n            if (ZDICT_isError(dictSize)) goto _output_error;\n        }\n        DISPLAYLEVEL(3, \"OK, created dictionary of size %u \\n\", (unsigned)dictSize);\n\n        DISPLAYLEVEL(3, \"test%3i : COVER dictBuilder with shrinkDict: \", testNb++);\n        { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }\n        {   ZDICT_cover_params_t coverParams;\n            memset(&coverParams, 0, sizeof(coverParams));\n            coverParams.steps = 8;\n            coverParams.nbThreads = 4;\n            coverParams.shrinkDict = 1;\n            coverParams.shrinkDictMaxRegression = 1;\n            dictSize = ZDICT_optimizeTrainFromBuffer_cover(\n                dictBuffer, dictBufferCapacity,\n                CNBuffer, samplesSizes, nbSamples/8,  /* less samples for faster tests */\n                &coverParams);\n            if (ZDICT_isError(dictSize)) goto _output_error;\n        }\n        DISPLAYLEVEL(3, \"OK, created dictionary of size %u \\n\", (unsigned)dictSize);\n\n        DISPLAYLEVEL(3, \"test%3i : Multithreaded FASTCOVER dictBuilder : \", testNb++);\n        { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }\n        {   ZDICT_fastCover_params_t fastCoverParams;\n            memset(&fastCoverParams, 0, sizeof(fastCoverParams));\n            fastCoverParams.steps = 8;\n            fastCoverParams.nbThreads = 4;\n            dictSize = ZDICT_optimizeTrainFromBuffer_fastCover(\n                dictBuffer, dictBufferCapacity,\n                CNBuffer, samplesSizes, nbSamples,\n                &fastCoverParams);\n            if (ZDICT_isError(dictSize)) goto _output_error;\n        }\n        DISPLAYLEVEL(3, \"OK, created dictionary of size %u \\n\", (unsigned)dictSize);\n\n        DISPLAYLEVEL(3, \"test%3i : FASTCOVER dictBuilder with shrinkDict: \", testNb++);\n        { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }\n        {   ZDICT_fastCover_params_t fastCoverParams;\n            memset(&fastCoverParams, 0, sizeof(fastCoverParams));\n            fastCoverParams.steps = 8;\n            fastCoverParams.nbThreads = 4;\n            fastCoverParams.shrinkDict = 1;\n            fastCoverParams.shrinkDictMaxRegression = 1;\n            dictSize = ZDICT_optimizeTrainFromBuffer_fastCover(\n                dictBuffer, dictBufferCapacity,\n                CNBuffer, samplesSizes, nbSamples,\n                &fastCoverParams);\n            if (ZDICT_isError(dictSize)) goto _output_error;\n        }\n        DISPLAYLEVEL(3, \"OK, created dictionary of size %u \\n\", (unsigned)dictSize);\n\n        DISPLAYLEVEL(3, \"test%3i : check dictID : \", testNb++);\n        dictID = ZDICT_getDictID(dictBuffer, dictSize);\n        if (dictID==0) goto _output_error;\n        DISPLAYLEVEL(3, \"OK : %u \\n\", (unsigned)dictID);\n\n        DISPLAYLEVEL(3, \"test%3i : check dict header size no error : \", testNb++);\n        dictHeaderSize = ZDICT_getDictHeaderSize(dictBuffer, dictSize);\n        if (dictHeaderSize==0) goto _output_error;\n        DISPLAYLEVEL(3, \"OK : %u \\n\", (unsigned)dictHeaderSize);\n\n        DISPLAYLEVEL(3, \"test%3i : check dict header size correctness : \", testNb++);\n        {   dictHeaderSize = ZDICT_getDictHeaderSize(dictBufferFixed, dictBufferFixedSize);\n            if (dictHeaderSize != 115) goto _output_error;\n        }\n        DISPLAYLEVEL(3, \"OK : %u \\n\", (unsigned)dictHeaderSize);\n\n        DISPLAYLEVEL(3, \"test%3i : compress with dictionary : \", testNb++);\n        cSize = ZSTD_compress_usingDict(cctx, compressedBuffer, compressedBufferSize,\n                                        CNBuffer, CNBuffSize,\n                                        dictBuffer, dictSize, 4);\n        if (ZSTD_isError(cSize)) goto _output_error;\n        DISPLAYLEVEL(3, \"OK (%u bytes : %.2f%%)\\n\", (unsigned)cSize, (double)cSize/CNBuffSize*100);\n\n        DISPLAYLEVEL(3, \"test%3i : retrieve dictID from dictionary : \", testNb++);\n        {   U32 const did = ZSTD_getDictID_fromDict(dictBuffer, dictSize);\n            if (did != dictID) goto _output_error;   /* non-conformant (content-only) dictionary */\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : retrieve dictID from frame : \", testNb++);\n        {   U32 const did = ZSTD_getDictID_fromFrame(compressedBuffer, cSize);\n            if (did != dictID) goto _output_error;   /* non-conformant (content-only) dictionary */\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : frame built with dictionary should be decompressible : \", testNb++);\n        {   ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL);\n            CHECKPLUS(r, ZSTD_decompress_usingDict(dctx,\n                                           decodedBuffer, CNBuffSize,\n                                           compressedBuffer, cSize,\n                                           dictBuffer, dictSize),\n                      if (r != CNBuffSize) goto _output_error);\n            ZSTD_freeDCtx(dctx);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : estimate CDict size : \", testNb++);\n        {   ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize);\n            size_t const estimatedSize = ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byRef);\n            DISPLAYLEVEL(3, \"OK : %u \\n\", (unsigned)estimatedSize);\n        }\n\n        DISPLAYLEVEL(3, \"test%3i : compress with CDict \", testNb++);\n        {   ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize);\n            ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictSize,\n                                            ZSTD_dlm_byRef, ZSTD_dct_auto,\n                                            cParams, ZSTD_defaultCMem);\n            assert(cdict != NULL);\n            DISPLAYLEVEL(3, \"(size : %u) : \", (unsigned)ZSTD_sizeof_CDict(cdict));\n            assert(ZSTD_getDictID_fromDict(dictBuffer, dictSize) == ZSTD_getDictID_fromCDict(cdict));\n            cSize = ZSTD_compress_usingCDict(cctx, compressedBuffer, compressedBufferSize,\n                                                 CNBuffer, CNBuffSize, cdict);\n            ZSTD_freeCDict(cdict);\n            if (ZSTD_isError(cSize)) goto _output_error;\n        }\n        DISPLAYLEVEL(3, \"OK (%u bytes : %.2f%%)\\n\", (unsigned)cSize, (double)cSize/CNBuffSize*100);\n\n        DISPLAYLEVEL(3, \"test%3i : retrieve dictID from frame : \", testNb++);\n        {   U32 const did = ZSTD_getDictID_fromFrame(compressedBuffer, cSize);\n            if (did != dictID) goto _output_error;   /* non-conformant (content-only) dictionary */\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : frame built with dictionary should be decompressible : \", testNb++);\n        {   ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL);\n            CHECKPLUS(r, ZSTD_decompress_usingDict(dctx,\n                                           decodedBuffer, CNBuffSize,\n                                           compressedBuffer, cSize,\n                                           dictBuffer, dictSize),\n                      if (r != CNBuffSize) goto _output_error);\n            ZSTD_freeDCtx(dctx);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : compress with static CDict : \", testNb++);\n        {   int const maxLevel = ZSTD_maxCLevel();\n            int level;\n            for (level = 1; level <= maxLevel; ++level) {\n                ZSTD_compressionParameters const cParams = ZSTD_getCParams(level, CNBuffSize, dictSize);\n                size_t const cdictSize = ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy);\n                void* const cdictBuffer = malloc(cdictSize);\n                if (cdictBuffer==NULL) goto _output_error;\n                {   const ZSTD_CDict* const cdict = ZSTD_initStaticCDict(\n                                                cdictBuffer, cdictSize,\n                                                dictBuffer, dictSize,\n                                                ZSTD_dlm_byCopy, ZSTD_dct_auto,\n                                                cParams);\n                    if (cdict == NULL) {\n                        DISPLAY(\"ZSTD_initStaticCDict failed \");\n                        goto _output_error;\n                    }\n                    cSize = ZSTD_compress_usingCDict(cctx,\n                                    compressedBuffer, compressedBufferSize,\n                                    CNBuffer, MIN(10 KB, CNBuffSize), cdict);\n                    if (ZSTD_isError(cSize)) {\n                        DISPLAY(\"ZSTD_compress_usingCDict failed \");\n                        goto _output_error;\n                }   }\n                free(cdictBuffer);\n        }   }\n        DISPLAYLEVEL(3, \"OK (%u bytes : %.2f%%)\\n\", (unsigned)cSize, (double)cSize/CNBuffSize*100);\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_compress_usingCDict_advanced, no contentSize, no dictID : \", testNb++);\n        {   ZSTD_frameParameters const fParams = { 0 /* frameSize */, 1 /* checksum */, 1 /* noDictID*/ };\n            ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize);\n            ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, cParams, ZSTD_defaultCMem);\n            assert(cdict != NULL);\n            cSize = ZSTD_compress_usingCDict_advanced(cctx,\n                                                      compressedBuffer, compressedBufferSize,\n                                                      CNBuffer, CNBuffSize,\n                                                      cdict, fParams);\n            ZSTD_freeCDict(cdict);\n            if (ZSTD_isError(cSize)) goto _output_error;\n        }\n        DISPLAYLEVEL(3, \"OK (%u bytes : %.2f%%)\\n\", (unsigned)cSize, (double)cSize/CNBuffSize*100);\n\n        DISPLAYLEVEL(3, \"test%3i : try retrieving contentSize from frame : \", testNb++);\n        {   U64 const contentSize = ZSTD_getFrameContentSize(compressedBuffer, cSize);\n            if (contentSize != ZSTD_CONTENTSIZE_UNKNOWN) goto _output_error;\n        }\n        DISPLAYLEVEL(3, \"OK (unknown)\\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : frame built without dictID should be decompressible : \", testNb++);\n        {   ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n            assert(dctx != NULL);\n            CHECKPLUS(r, ZSTD_decompress_usingDict(dctx,\n                                           decodedBuffer, CNBuffSize,\n                                           compressedBuffer, cSize,\n                                           dictBuffer, dictSize),\n                      if (r != CNBuffSize) goto _output_error);\n            ZSTD_freeDCtx(dctx);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_compress_advanced, no dictID : \", testNb++);\n        {   ZSTD_parameters p = ZSTD_getParams(3, CNBuffSize, dictSize);\n            p.fParams.noDictIDFlag = 1;\n            cSize = ZSTD_compress_advanced(cctx, compressedBuffer, compressedBufferSize,\n                                           CNBuffer, CNBuffSize,\n                                           dictBuffer, dictSize, p);\n            if (ZSTD_isError(cSize)) goto _output_error;\n        }\n        DISPLAYLEVEL(3, \"OK (%u bytes : %.2f%%)\\n\", (unsigned)cSize, (double)cSize/CNBuffSize*100);\n\n        DISPLAYLEVEL(3, \"test%3i : frame built without dictID should be decompressible : \", testNb++);\n        {   ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL);\n            CHECKPLUS(r, ZSTD_decompress_usingDict(dctx,\n                                           decodedBuffer, CNBuffSize,\n                                           compressedBuffer, cSize,\n                                           dictBuffer, dictSize),\n                      if (r != CNBuffSize) goto _output_error);\n            ZSTD_freeDCtx(dctx);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : dictionary containing only header should return error : \", testNb++);\n        {   ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n            assert(dctx != NULL);\n            {   const size_t ret = ZSTD_decompress_usingDict(\n                    dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize,\n                    \"\\x37\\xa4\\x30\\xec\\x11\\x22\\x33\\x44\", 8);\n                if (ZSTD_getErrorCode(ret) != ZSTD_error_dictionary_corrupted)\n                    goto _output_error;\n            }\n            ZSTD_freeDCtx(dctx);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3d : bufferless api with cdict : \", testNb++);\n        {   ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, 1);\n            ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n            ZSTD_frameParameters const fParams = { 0, 1, 0 };\n            size_t cBlockSize;\n            cSize = 0;\n            CHECK_Z(ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, ZSTD_CONTENTSIZE_UNKNOWN));\n            cBlockSize = ZSTD_compressContinue(cctx, (char*)compressedBuffer + cSize, compressedBufferSize - cSize, CNBuffer, 1000);\n            CHECK_Z(cBlockSize);\n            cSize += cBlockSize;\n            cBlockSize = ZSTD_compressEnd(cctx, (char*)compressedBuffer + cSize, compressedBufferSize - cSize, (char const*)CNBuffer + 2000, 1000);\n            CHECK_Z(cBlockSize);\n            cSize += cBlockSize;\n\n            CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, dictBuffer, dictSize));\n\n            ZSTD_freeCDict(cdict);\n            ZSTD_freeDCtx(dctx);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : Building cdict w/ ZSTD_dct_fullDict on a good dictionary : \", testNb++);\n        {   ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize);\n            ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_fullDict, cParams, ZSTD_defaultCMem);\n            if (cdict==NULL) goto _output_error;\n            ZSTD_freeCDict(cdict);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : Building cdict w/ ZSTD_dct_fullDict on a rawContent (must fail) : \", testNb++);\n        {   ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize);\n            ZSTD_CDict* const cdict = ZSTD_createCDict_advanced((const char*)dictBuffer+1, dictSize-1, ZSTD_dlm_byRef, ZSTD_dct_fullDict, cParams, ZSTD_defaultCMem);\n            if (cdict!=NULL) goto _output_error;\n            ZSTD_freeCDict(cdict);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        {   char* rawDictBuffer = (char*)malloc(dictSize);\n            assert(rawDictBuffer);\n            memcpy(rawDictBuffer, (char*)dictBuffer + 2, dictSize - 2);\n            memset(rawDictBuffer + dictSize - 2, 0, 2);\n            MEM_writeLE32((char*)rawDictBuffer, ZSTD_MAGIC_DICTIONARY);\n\n            DISPLAYLEVEL(3, \"test%3i : Loading rawContent starting with dict header w/ ZSTD_dct_auto should fail : \", testNb++);\n            {\n                size_t ret;\n                /* Either operation is allowed to fail, but one must fail. */\n                ret = ZSTD_CCtx_loadDictionary_advanced(\n                        cctx, (const char*)rawDictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto);\n                if (!ZSTD_isError(ret)) {\n                    ret = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100));\n                    if (!ZSTD_isError(ret)) goto _output_error;\n                }\n            }\n            DISPLAYLEVEL(3, \"OK \\n\");\n\n            DISPLAYLEVEL(3, \"test%3i : Loading rawContent starting with dict header w/ ZSTD_dct_rawContent should pass : \", testNb++);\n            {\n                size_t ret;\n                ret = ZSTD_CCtx_loadDictionary_advanced(\n                        cctx, (const char*)rawDictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_rawContent);\n                if (ZSTD_isError(ret)) goto _output_error;\n                ret = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100));\n                if (ZSTD_isError(ret)) goto _output_error;\n            }\n            DISPLAYLEVEL(3, \"OK \\n\");\n\n            DISPLAYLEVEL(3, \"test%3i : Testing non-attached CDict with ZSTD_dct_rawContent : \", testNb++);\n            {   size_t const srcSize = MIN(CNBuffSize, 100);\n                ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n                /* Force the dictionary to be reloaded in raw content mode */\n                CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_forceAttachDict, ZSTD_dictForceLoad));\n                CHECK_Z(ZSTD_CCtx_loadDictionary_advanced(cctx, rawDictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_rawContent));\n                cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, srcSize);\n                CHECK_Z(cSize);\n            }\n            DISPLAYLEVEL(3, \"OK \\n\");\n\n            free(rawDictBuffer);\n        }\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_CCtx_refCDict() then set parameters : \", testNb++);\n        {   ZSTD_CDict* const cdict = ZSTD_createCDict(CNBuffer, dictSize, 1);\n            ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n            CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1) );\n            CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, 12 ));\n            CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) );\n            CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1) );\n            CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, 12 ));\n            ZSTD_freeCDict(cdict);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : Loading dictionary before setting parameters is the same as loading after : \", testNb++);\n        {\n            size_t size1, size2;\n            ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n            CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 7) );\n            CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, CNBuffer, MIN(CNBuffSize, 10 KB)) );\n            size1 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));\n            if (ZSTD_isError(size1)) goto _output_error;\n\n            ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n            CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, CNBuffer, MIN(CNBuffSize, 10 KB)) );\n            CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 7) );\n            size2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));\n            if (ZSTD_isError(size2)) goto _output_error;\n\n            if (size1 != size2) goto _output_error;\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : Loading a dictionary clears the prefix : \", testNb++);\n        {\n            CHECK_Z( ZSTD_CCtx_refPrefix(cctx, (const char*)dictBuffer, dictSize) );\n            CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, (const char*)dictBuffer, dictSize) );\n            CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : Loading a dictionary clears the cdict : \", testNb++);\n        {\n            ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, 1);\n            CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) );\n            CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, (const char*)dictBuffer, dictSize) );\n            CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );\n            ZSTD_freeCDict(cdict);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : Loading a cdict clears the prefix : \", testNb++);\n        {\n            ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, 1);\n            CHECK_Z( ZSTD_CCtx_refPrefix(cctx, (const char*)dictBuffer, dictSize) );\n            CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) );\n            CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );\n            ZSTD_freeCDict(cdict);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : Loading a cdict clears the dictionary : \", testNb++);\n        {\n            ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, 1);\n            CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, (const char*)dictBuffer, dictSize) );\n            CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) );\n            CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );\n            ZSTD_freeCDict(cdict);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : Loading a prefix clears the dictionary : \", testNb++);\n        {\n            CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, (const char*)dictBuffer, dictSize) );\n            CHECK_Z( ZSTD_CCtx_refPrefix(cctx, (const char*)dictBuffer, dictSize) );\n            CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : Loading a prefix clears the cdict : \", testNb++);\n        {\n            ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, 1);\n            CHECK_Z( ZSTD_CCtx_refCDict(cctx, cdict) );\n            CHECK_Z( ZSTD_CCtx_refPrefix(cctx, (const char*)dictBuffer, dictSize) );\n            CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100)) );\n            ZSTD_freeCDict(cdict);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : Loaded dictionary persists across reset session : \", testNb++);\n        {\n            size_t size1, size2;\n            ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n            CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, CNBuffer, MIN(CNBuffSize, 10 KB)) );\n            size1 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));\n            if (ZSTD_isError(size1)) goto _output_error;\n\n            ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);\n            size2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));\n            if (ZSTD_isError(size2)) goto _output_error;\n\n            if (size1 != size2) goto _output_error;\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : Loaded dictionary is cleared after resetting parameters : \", testNb++);\n        {\n            size_t size1, size2;\n            ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n            CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, CNBuffer, MIN(CNBuffSize, 10 KB)) );\n            size1 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));\n            if (ZSTD_isError(size1)) goto _output_error;\n\n            ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n            size2 = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));\n            if (ZSTD_isError(size2)) goto _output_error;\n\n            if (size1 == size2) goto _output_error;\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n        CHECK_Z( ZSTD_CCtx_loadDictionary(cctx, dictBuffer, dictSize) );\n        cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBuffSize, 100 KB));\n        CHECK_Z(cSize);\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_decompressDCtx() with dictionary : \", testNb++);\n        {\n            ZSTD_DCtx* dctx = ZSTD_createDCtx();\n            size_t ret;\n            /* We should fail to decompress without a dictionary. */\n            ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);\n            ret = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);\n            if (!ZSTD_isError(ret)) goto _output_error;\n            /* We should succeed to decompress with the dictionary. */\n            ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);\n            CHECK_Z( ZSTD_DCtx_loadDictionary(dctx, dictBuffer, dictSize) );\n            CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) );\n            /* The dictionary should persist across calls. */\n            CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) );\n            /* When we reset the context the dictionary is cleared. */\n            ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);\n            ret = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);\n            if (!ZSTD_isError(ret)) goto _output_error;\n            ZSTD_freeDCtx(dctx);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_decompressDCtx() with ddict : \", testNb++);\n        {\n            ZSTD_DCtx* dctx = ZSTD_createDCtx();\n            ZSTD_DDict* ddict = ZSTD_createDDict(dictBuffer, dictSize);\n            size_t ret;\n            /* We should succeed to decompress with the ddict. */\n            ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);\n            CHECK_Z( ZSTD_DCtx_refDDict(dctx, ddict) );\n            CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) );\n            /* The ddict should persist across calls. */\n            CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) );\n            /* When we reset the context the ddict is cleared. */\n            ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);\n            ret = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);\n            if (!ZSTD_isError(ret)) goto _output_error;\n            ZSTD_freeDCtx(dctx);\n            ZSTD_freeDDict(ddict);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_decompressDCtx() with prefix : \", testNb++);\n        {\n            ZSTD_DCtx* dctx = ZSTD_createDCtx();\n            size_t ret;\n            /* We should succeed to decompress with the prefix. */\n            ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);\n            CHECK_Z( ZSTD_DCtx_refPrefix_advanced(dctx, dictBuffer, dictSize, ZSTD_dct_auto) );\n            CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) );\n            /* The prefix should be cleared after the first compression. */\n            ret = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);\n            if (!ZSTD_isError(ret)) goto _output_error;\n            ZSTD_freeDCtx(dctx);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_fast attach dictionary with hashLog = 25 and chainLog = 25 : \", testNb++);\n        {\n            ZSTD_CCtx_params* cctxParams = ZSTD_createCCtxParams();\n            ZSTD_customMem customMem = {NULL, NULL, NULL};\n            ZSTD_DCtx* dctx = ZSTD_createDCtx();\n            ZSTD_CDict* cdict;\n            CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_strategy, ZSTD_fast));\n            /* Set windowLog to 25 so hash/chain logs don't get sized down */\n            CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_windowLog, 25));\n            CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_hashLog, 25));\n            CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_chainLog, 25));\n            /* Set srcSizeHint to 2^25 so hash/chain logs don't get sized down */\n            CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_srcSizeHint, 1u << 25));\n            cdict = ZSTD_createCDict_advanced2(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, cctxParams, customMem);\n            CHECK_Z(ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_forceAttachDict, ZSTD_dictForceAttach));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1));\n            CHECK_Z(ZSTD_CCtx_refCDict(cctx, cdict));\n            cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);\n            CHECK_Z(cSize);\n            CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, dictBuffer, dictSize));\n            ZSTD_freeCDict(cdict);\n            ZSTD_freeDCtx(dctx);\n            ZSTD_freeCCtxParams(cctxParams);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_dfast attach dictionary with hashLog = 25 and chainLog = 25 : \", testNb++);\n        {\n            ZSTD_CCtx_params* cctxParams = ZSTD_createCCtxParams();\n            ZSTD_customMem customMem = {NULL, NULL, NULL};\n            ZSTD_DCtx* dctx = ZSTD_createDCtx();\n            ZSTD_CDict* cdict;\n            CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_strategy, ZSTD_dfast));\n            /* Set windowLog to 25 so hash/chain logs don't get sized down */\n            CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_windowLog, 25));\n            CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_hashLog, 25));\n            CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_chainLog, 25));\n            /* Set srcSizeHint to 2^25 so hash/chain logs don't get sized down */\n            CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_srcSizeHint, 1u << 25));\n            cdict = ZSTD_createCDict_advanced2(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, cctxParams, customMem);\n            CHECK_Z(ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_forceAttachDict, ZSTD_dictForceAttach));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1));\n            CHECK_Z(ZSTD_CCtx_refCDict(cctx, cdict));\n            cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);\n            CHECK_Z(cSize);\n            CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, dictBuffer, dictSize));\n            ZSTD_freeCDict(cdict);\n            ZSTD_freeDCtx(dctx);\n            ZSTD_freeCCtxParams(cctxParams);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_lazy attach dictionary with hashLog = 29 and searchLog = 4 : \", testNb++);\n        if (MEM_64bits()) {\n            ZSTD_CCtx_params* cctxParams = ZSTD_createCCtxParams();\n            ZSTD_customMem customMem = {NULL, NULL, NULL};\n            ZSTD_DCtx* dctx = ZSTD_createDCtx();\n            ZSTD_CDict* cdict;\n            CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_strategy, ZSTD_lazy));\n            /* Force enable row based match finder, and disable dedicated dict search. */\n            CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_useRowMatchFinder, ZSTD_ps_enable));\n            CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_enableDedicatedDictSearch, 0));\n            CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_searchLog, 4));\n            /* Set windowLog to 29 so hash/chain logs don't get sized down */\n            CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_windowLog, 29));\n            CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_hashLog, 29));\n            /* Set srcSizeHint to 2^29 so hash/chain logs don't get sized down */\n            CHECK_Z(ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_srcSizeHint, 1u << 29));\n            cdict = ZSTD_createCDict_advanced2(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, cctxParams, customMem);\n            CHECK_Z(ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_forceAttachDict, ZSTD_dictForceAttach));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1));\n            CHECK_Z(ZSTD_CCtx_refCDict(cctx, cdict));\n            cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);\n            CHECK_Z(cSize);\n            CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, dictBuffer, dictSize));\n            ZSTD_freeCDict(cdict);\n            ZSTD_freeDCtx(dctx);\n            ZSTD_freeCCtxParams(cctxParams);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : Dictionary with non-default repcodes : \", testNb++);\n        { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }\n        dictSize = ZDICT_trainFromBuffer(dictBuffer, dictSize,\n                                         CNBuffer, samplesSizes, nbSamples);\n        if (ZDICT_isError(dictSize)) goto _output_error;\n        /* Set all the repcodes to non-default */\n        {\n            BYTE* dictPtr = (BYTE*)dictBuffer;\n            BYTE* dictLimit = dictPtr + dictSize - 12;\n            /* Find the repcodes */\n            while (dictPtr < dictLimit &&\n                   (MEM_readLE32(dictPtr) != 1 || MEM_readLE32(dictPtr + 4) != 4 ||\n                    MEM_readLE32(dictPtr + 8) != 8)) {\n                ++dictPtr;\n            }\n            if (dictPtr >= dictLimit) goto _output_error;\n            MEM_writeLE32(dictPtr + 0, 10);\n            MEM_writeLE32(dictPtr + 4, 10);\n            MEM_writeLE32(dictPtr + 8, 10);\n            /* Set the last 8 bytes to 'x' */\n            memset((BYTE*)dictBuffer + dictSize - 8, 'x', 8);\n        }\n        /* The optimal parser checks all the repcodes.\n         * Make sure at least one is a match >= targetLength so that it is\n         * immediately chosen. This will make sure that the compressor and\n         * decompressor agree on at least one of the repcodes.\n         */\n        {   size_t dSize;\n            BYTE data[1024];\n            ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n            ZSTD_compressionParameters const cParams = ZSTD_getCParams(19, CNBuffSize, dictSize);\n            ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictSize,\n                                            ZSTD_dlm_byRef, ZSTD_dct_auto,\n                                            cParams, ZSTD_defaultCMem);\n            assert(dctx != NULL); assert(cdict != NULL);\n            memset(data, 'x', sizeof(data));\n            cSize = ZSTD_compress_usingCDict(cctx, compressedBuffer, compressedBufferSize,\n                                             data, sizeof(data), cdict);\n            ZSTD_freeCDict(cdict);\n            if (ZSTD_isError(cSize)) { DISPLAYLEVEL(5, \"Compression error %s : \", ZSTD_getErrorName(cSize)); goto _output_error; }\n            dSize = ZSTD_decompress_usingDict(dctx, decodedBuffer, sizeof(data), compressedBuffer, cSize, dictBuffer, dictSize);\n            if (ZSTD_isError(dSize)) { DISPLAYLEVEL(5, \"Decompression error %s : \", ZSTD_getErrorName(dSize)); goto _output_error; }\n            if (memcmp(data, decodedBuffer, sizeof(data))) { DISPLAYLEVEL(5, \"Data corruption : \"); goto _output_error; }\n            ZSTD_freeDCtx(dctx);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_decompressDCtx() with multiple ddicts : \", testNb++);\n        {\n            const size_t numDicts = 128;\n            const size_t numFrames = 4;\n            size_t i;\n            ZSTD_DCtx* dctx = ZSTD_createDCtx();\n            ZSTD_DDict** ddictTable = (ZSTD_DDict**)malloc(sizeof(ZSTD_DDict*)*numDicts);\n            ZSTD_CDict** cdictTable = (ZSTD_CDict**)malloc(sizeof(ZSTD_CDict*)*numDicts);\n            U32 dictIDSeed = seed;\n            /* Create new compressed buffer that will hold frames with differing dictIDs */\n            char* dictBufferMulti = (char*)malloc(sizeof(char) * dictBufferFixedSize);  /* Modifiable copy of fixed full dict buffer */\n\n            ZSTD_memcpy(dictBufferMulti, dictBufferFixed, dictBufferFixedSize);\n            /* Create a bunch of DDicts with random dict IDs */\n            for (i = 0; i < numDicts; ++i) {\n                U32 currDictID = FUZ_rand(&dictIDSeed);\n                MEM_writeLE32(dictBufferMulti+ZSTD_FRAMEIDSIZE, currDictID);\n                ddictTable[i] = ZSTD_createDDict(dictBufferMulti, dictBufferFixedSize);\n                cdictTable[i] = ZSTD_createCDict(dictBufferMulti, dictBufferFixedSize, 3);\n                if (!ddictTable[i] || !cdictTable[i] || ZSTD_getDictID_fromCDict(cdictTable[i]) != ZSTD_getDictID_fromDDict(ddictTable[i])) {\n                    goto _output_error;\n                }\n            }\n            /* Compress a few frames using random CDicts */\n            {\n                size_t off = 0;\n                /* only use the first half so we don't push against size limit of compressedBuffer */\n                size_t const segSize = (CNBuffSize / 2) / numFrames;\n                for (i = 0; i < numFrames; i++) {\n                    size_t dictIdx = FUZ_rand(&dictIDSeed) % numDicts;\n                    ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n                    {   CHECK_NEWV(r, ZSTD_compress_usingCDict(cctx,\n                                    (BYTE*)compressedBuffer + off, CNBuffSize - off,\n                                    (BYTE*)CNBuffer + segSize * (size_t)i, segSize,\n                                    cdictTable[dictIdx]));\n                        off += r;\n                    }\n                }\n                cSize = off;\n            }\n\n            /* We should succeed to decompression even though different dicts were used on different frames */\n            ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);\n            ZSTD_DCtx_setParameter(dctx, ZSTD_d_refMultipleDDicts, ZSTD_rmd_refMultipleDDicts);\n            /* Reference every single ddict we made */\n            for (i = 0; i < numDicts; ++i) {\n                CHECK_Z( ZSTD_DCtx_refDDict(dctx, ddictTable[i]));\n            }\n            CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) );\n            /* Streaming decompression should also work */\n            {\n                ZSTD_inBuffer in = {compressedBuffer, cSize, 0};\n                ZSTD_outBuffer out = {decodedBuffer, CNBuffSize, 0};\n                while (in.pos < in.size) {\n                    CHECK_Z(ZSTD_decompressStream(dctx, &out, &in));\n                }\n            }\n            ZSTD_freeDCtx(dctx);\n            for (i = 0; i < numDicts; ++i) {\n                ZSTD_freeCDict(cdictTable[i]);\n                ZSTD_freeDDict(ddictTable[i]);\n            }\n            free(dictBufferMulti);\n            free(ddictTable);\n            free(cdictTable);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        ZSTD_freeCCtx(cctx);\n        free(dictBuffer);\n        free(samplesSizes);\n    }\n\n    /* COVER dictionary builder tests */\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        size_t dictSize = 16 KB;\n        size_t optDictSize = dictSize;\n        void* dictBuffer = malloc(dictSize);\n        size_t const totalSampleSize = 1 MB;\n        size_t const sampleUnitSize = 8 KB;\n        U32 const nbSamples = (U32)(totalSampleSize / sampleUnitSize);\n        size_t* const samplesSizes = (size_t*) malloc(nbSamples * sizeof(size_t));\n        U32 seed32 = seed;\n        ZDICT_cover_params_t params;\n        U32 dictID;\n\n        if (dictBuffer==NULL || samplesSizes==NULL) {\n            free(dictBuffer);\n            free(samplesSizes);\n            goto _output_error;\n        }\n\n        DISPLAYLEVEL(3, \"test%3i : ZDICT_trainFromBuffer_cover : \", testNb++);\n        { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }\n        memset(&params, 0, sizeof(params));\n        params.d = 1 + (FUZ_rand(&seed32) % 16);\n        params.k = params.d + (FUZ_rand(&seed32) % 256);\n        dictSize = ZDICT_trainFromBuffer_cover(dictBuffer, dictSize,\n                                               CNBuffer, samplesSizes, nbSamples,\n                                               params);\n        if (ZDICT_isError(dictSize)) goto _output_error;\n        DISPLAYLEVEL(3, \"OK, created dictionary of size %u \\n\", (unsigned)dictSize);\n\n        DISPLAYLEVEL(3, \"test%3i : check dictID : \", testNb++);\n        dictID = ZDICT_getDictID(dictBuffer, dictSize);\n        if (dictID==0) goto _output_error;\n        DISPLAYLEVEL(3, \"OK : %u \\n\", (unsigned)dictID);\n\n        DISPLAYLEVEL(3, \"test%3i : ZDICT_optimizeTrainFromBuffer_cover : \", testNb++);\n        memset(&params, 0, sizeof(params));\n        params.steps = 4;\n        optDictSize = ZDICT_optimizeTrainFromBuffer_cover(dictBuffer, optDictSize,\n                                                          CNBuffer, samplesSizes,\n                                                          nbSamples / 4, &params);\n        if (ZDICT_isError(optDictSize)) goto _output_error;\n        DISPLAYLEVEL(3, \"OK, created dictionary of size %u \\n\", (unsigned)optDictSize);\n\n        DISPLAYLEVEL(3, \"test%3i : check dictID : \", testNb++);\n        dictID = ZDICT_getDictID(dictBuffer, optDictSize);\n        if (dictID==0) goto _output_error;\n        DISPLAYLEVEL(3, \"OK : %u \\n\", (unsigned)dictID);\n\n        ZSTD_freeCCtx(cctx);\n        free(dictBuffer);\n        free(samplesSizes);\n    }\n\n    /* Decompression defense tests */\n    DISPLAYLEVEL(3, \"test%3i : Check input length for magic number : \", testNb++);\n    { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, CNBuffer, 3);   /* too small input */\n      if (!ZSTD_isError(r)) goto _output_error;\n      if (ZSTD_getErrorCode(r) != ZSTD_error_srcSize_wrong) goto _output_error; }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : Check magic Number : \", testNb++);\n    ((char*)(CNBuffer))[0] = 1;\n    { size_t const r = ZSTD_decompress(decodedBuffer, CNBuffSize, CNBuffer, 4);\n      if (!ZSTD_isError(r)) goto _output_error; }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* content size verification test */\n    DISPLAYLEVEL(3, \"test%3i : Content size verification : \", testNb++);\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        size_t const srcSize = 5000;\n        size_t const wrongSrcSize = (srcSize + 1000);\n        ZSTD_parameters params = ZSTD_getParams(1, wrongSrcSize, 0);\n        params.fParams.contentSizeFlag = 1;\n        CHECK_Z( ZSTD_compressBegin_advanced(cctx, NULL, 0, params, wrongSrcSize) );\n        {   size_t const result = ZSTD_compressEnd(cctx, decodedBuffer, CNBuffSize, CNBuffer, srcSize);\n            if (!ZSTD_isError(result)) goto _output_error;\n            if (ZSTD_getErrorCode(result) != ZSTD_error_srcSize_wrong) goto _output_error;\n            DISPLAYLEVEL(3, \"OK : %s \\n\", ZSTD_getErrorName(result));\n        }\n        ZSTD_freeCCtx(cctx);\n    }\n\n    /* negative compression level test : ensure simple API and advanced API produce same result */\n    DISPLAYLEVEL(3, \"test%3i : negative compression level : \", testNb++);\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        size_t const srcSize = CNBuffSize / 5;\n        int const compressionLevel = -1;\n\n        assert(cctx != NULL);\n        {   size_t const cSize_1pass = ZSTD_compress(compressedBuffer, compressedBufferSize,\n                                                     CNBuffer, srcSize, compressionLevel);\n            if (ZSTD_isError(cSize_1pass)) goto _output_error;\n\n            CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, compressionLevel) );\n            {   size_t const compressionResult = ZSTD_compress2(cctx,\n                                    compressedBuffer, compressedBufferSize,\n                                    CNBuffer, srcSize);\n                DISPLAYLEVEL(5, \"simple=%u vs %u=advanced : \", (unsigned)cSize_1pass, (unsigned)compressionResult);\n                if (ZSTD_isError(compressionResult)) goto _output_error;\n                if (compressionResult != cSize_1pass) goto _output_error;\n        }   }\n        ZSTD_freeCCtx(cctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* parameters order test */\n    {   size_t const inputSize = CNBuffSize / 2;\n        U64 xxh64;\n\n        {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n            DISPLAYLEVEL(3, \"test%3i : parameters in order : \", testNb++);\n            assert(cctx != NULL);\n            CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 2) );\n            CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable) );\n            CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 18) );\n            {   size_t const compressedSize = ZSTD_compress2(cctx,\n                                compressedBuffer, ZSTD_compressBound(inputSize),\n                                CNBuffer, inputSize);\n                CHECK_Z(compressedSize);\n                cSize = compressedSize;\n                xxh64 = XXH64(compressedBuffer, compressedSize, 0);\n            }\n            DISPLAYLEVEL(3, \"OK (compress : %u -> %u bytes)\\n\", (unsigned)inputSize, (unsigned)cSize);\n            ZSTD_freeCCtx(cctx);\n        }\n\n        {   ZSTD_CCtx* cctx = ZSTD_createCCtx();\n            DISPLAYLEVEL(3, \"test%3i : parameters disordered : \", testNb++);\n            CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 18) );\n            CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable) );\n            CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 2) );\n            {   size_t const result = ZSTD_compress2(cctx,\n                                compressedBuffer, ZSTD_compressBound(inputSize),\n                                CNBuffer, inputSize);\n                CHECK_Z(result);\n                if (result != cSize) goto _output_error;   /* must result in same compressed result, hence same size */\n                if (XXH64(compressedBuffer, result, 0) != xxh64) goto _output_error;  /* must result in exactly same content, hence same hash */\n                DISPLAYLEVEL(3, \"OK (compress : %u -> %u bytes)\\n\", (unsigned)inputSize, (unsigned)result);\n            }\n            ZSTD_freeCCtx(cctx);\n        }\n    }\n\n    /* advanced parameters for decompression */\n    {   ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n        assert(dctx != NULL);\n\n        DISPLAYLEVEL(3, \"test%3i : get dParameter bounds \", testNb++);\n        {   ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);\n            CHECK_Z(bounds.error);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : wrong dParameter : \", testNb++);\n        {   size_t const sr = ZSTD_DCtx_setParameter(dctx, (ZSTD_dParameter)999999, 0);\n            if (!ZSTD_isError(sr)) goto _output_error;\n        }\n        {   ZSTD_bounds const bounds = ZSTD_dParam_getBounds((ZSTD_dParameter)999998);\n            if (!ZSTD_isError(bounds.error)) goto _output_error;\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : out of bound dParameter : \", testNb++);\n        {   size_t const sr = ZSTD_DCtx_setParameter(dctx, ZSTD_d_windowLogMax, 9999);\n            if (!ZSTD_isError(sr)) goto _output_error;\n        }\n        {   size_t const sr = ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (ZSTD_format_e)888);\n            if (!ZSTD_isError(sr)) goto _output_error;\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        ZSTD_freeDCtx(dctx);\n    }\n\n\n    /* custom formats tests */\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n        size_t const inputSize = CNBuffSize / 2;   /* won't cause pb with small dict size */\n        assert(dctx != NULL); assert(cctx != NULL);\n\n        /* basic block compression */\n        DISPLAYLEVEL(3, \"test%3i : magic-less format test : \", testNb++);\n        CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_format, ZSTD_f_zstd1_magicless) );\n        {   ZSTD_inBuffer in = { CNBuffer, inputSize, 0 };\n            ZSTD_outBuffer out = { compressedBuffer, ZSTD_compressBound(inputSize), 0 };\n            size_t const result = ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end);\n            if (result != 0) goto _output_error;\n            if (in.pos != in.size) goto _output_error;\n            cSize = out.pos;\n        }\n        DISPLAYLEVEL(3, \"OK (compress : %u -> %u bytes)\\n\", (unsigned)inputSize, (unsigned)cSize);\n\n        DISPLAYLEVEL(3, \"test%3i : decompress normally (should fail) : \", testNb++);\n        {   size_t const decodeResult = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);\n            if (ZSTD_getErrorCode(decodeResult) != ZSTD_error_prefix_unknown) goto _output_error;\n            DISPLAYLEVEL(3, \"OK : %s \\n\", ZSTD_getErrorName(decodeResult));\n        }\n\n        DISPLAYLEVEL(3, \"test%3i : decompress of magic-less frame : \", testNb++);\n        ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);\n        CHECK_Z( ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, ZSTD_f_zstd1_magicless) );\n        {   ZSTD_FrameHeader zfh;\n            size_t const zfhrt = ZSTD_getFrameHeader_advanced(&zfh, compressedBuffer, cSize, ZSTD_f_zstd1_magicless);\n            if (zfhrt != 0) goto _output_error;\n        }\n        /* one shot */\n        {   size_t const result = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);\n            if (result != inputSize) goto _output_error;\n            DISPLAYLEVEL(3, \"one-shot OK, \");\n        }\n        /* streaming */\n        {   ZSTD_inBuffer in = { compressedBuffer, cSize, 0 };\n            ZSTD_outBuffer out = { decodedBuffer, CNBuffSize, 0 };\n            size_t const result = ZSTD_decompressStream(dctx, &out, &in);\n            if (result != 0) goto _output_error;\n            if (in.pos != in.size) goto _output_error;\n            if (out.pos != inputSize) goto _output_error;\n            DISPLAYLEVEL(3, \"streaming OK : regenerated %u bytes \\n\", (unsigned)out.pos);\n        }\n\n        /* basic block compression */\n        DISPLAYLEVEL(3, \"test%3i : empty magic-less format test : \", testNb++);\n        CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_format, ZSTD_f_zstd1_magicless) );\n        {   ZSTD_inBuffer in = { CNBuffer, 0, 0 };\n            ZSTD_outBuffer out = { compressedBuffer, ZSTD_compressBound(0), 0 };\n            size_t const result = ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end);\n            if (result != 0) goto _output_error;\n            if (in.pos != in.size) goto _output_error;\n            cSize = out.pos;\n        }\n        DISPLAYLEVEL(3, \"OK (compress : %u -> %u bytes)\\n\", (unsigned)0, (unsigned)cSize);\n\n        DISPLAYLEVEL(3, \"test%3i : decompress of empty magic-less frame : \", testNb++);\n        ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);\n        CHECK_Z( ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, ZSTD_f_zstd1_magicless) );\n        /* one shot */\n        {   size_t const result = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);\n            if (result != 0) goto _output_error;\n            DISPLAYLEVEL(3, \"one-shot OK, \");\n        }\n        /* streaming */\n        {   ZSTD_inBuffer in = { compressedBuffer, cSize, 0 };\n            ZSTD_outBuffer out = { decodedBuffer, CNBuffSize, 0 };\n            size_t const result = ZSTD_decompressStream(dctx, &out, &in);\n            if (result != 0) goto _output_error;\n            if (in.pos != in.size) goto _output_error;\n            if (out.pos != 0) goto _output_error;\n            DISPLAYLEVEL(3, \"streaming OK : regenerated %u bytes \\n\", (unsigned)out.pos);\n        }\n\n        ZSTD_freeCCtx(cctx);\n        ZSTD_freeDCtx(dctx);\n    }\n\n    DISPLAYLEVEL(3, \"test%3i : Decompression parameter reset test : \", testNb++);\n    {\n        ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n        /* Attempt to future proof this to new parameters. */\n        int const maxParam = 2000;\n        int param;\n        if (ZSTD_d_experimentalParam3 > maxParam) goto _output_error;\n        for (param = 0; param < maxParam; ++param) {\n            ZSTD_dParameter dParam = (ZSTD_dParameter)param;\n            ZSTD_bounds bounds = ZSTD_dParam_getBounds(dParam);\n            int value1;\n            int value2;\n            int check;\n            if (ZSTD_isError(bounds.error))\n                continue;\n            CHECK_Z(ZSTD_DCtx_getParameter(dctx, dParam, &value1));\n            value2 = (value1 != bounds.lowerBound) ? bounds.lowerBound : bounds.upperBound;\n            CHECK_Z(ZSTD_DCtx_setParameter(dctx, dParam, value2));\n            CHECK_Z(ZSTD_DCtx_getParameter(dctx, dParam, &check));\n            if (check != value2) goto _output_error;\n            CHECK_Z(ZSTD_DCtx_reset(dctx, ZSTD_reset_parameters));\n            CHECK_Z(ZSTD_DCtx_getParameter(dctx, dParam, &check));\n            if (check != value1) goto _output_error;\n        }\n        ZSTD_freeDCtx(dctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* block API tests */\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n        static const size_t dictSize = 65 KB;\n        static const size_t blockSize = 100 KB;   /* won't cause pb with small dict size */\n        size_t cSize2;\n        assert(cctx != NULL); assert(dctx != NULL);\n\n        /* basic block compression */\n        DISPLAYLEVEL(3, \"test%3i : Block compression test : \", testNb++);\n        CHECK_Z( ZSTD_compressBegin(cctx, 5) );\n        CHECK_Z( ZSTD_getBlockSize(cctx) >= blockSize);\n        CHECK_VAR(cSize, ZSTD_compressBlock(cctx, compressedBuffer, ZSTD_compressBound(blockSize), CNBuffer, blockSize) );\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : Block decompression test : \", testNb++);\n        CHECK_Z( ZSTD_decompressBegin(dctx) );\n        { CHECK_NEWV(r, ZSTD_decompressBlock(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize) );\n          if (r != blockSize) goto _output_error; }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        /* very long stream of block compression */\n        DISPLAYLEVEL(3, \"test%3i : Huge block streaming compression test : \", testNb++);\n        CHECK_Z( ZSTD_compressBegin(cctx, -199) );  /* we just want to quickly overflow internal U32 index */\n        CHECK_Z( ZSTD_getBlockSize(cctx) >= blockSize);\n        {   U64 const toCompress = 5000000000ULL;   /* > 4 GB */\n            U64 compressed = 0;\n            while (compressed < toCompress) {\n                size_t const blockCSize = ZSTD_compressBlock(cctx, compressedBuffer, ZSTD_compressBound(blockSize), CNBuffer, blockSize);\n                assert(blockCSize != 0);\n                if (ZSTD_isError(blockCSize)) goto _output_error;\n                compressed += blockCSize;\n        }   }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        /* dictionary block compression */\n        DISPLAYLEVEL(3, \"test%3i : Dictionary Block compression test : \", testNb++);\n        CHECK_Z( ZSTD_compressBegin_usingDict(cctx, CNBuffer, dictSize, 5) );\n        CHECK_VAR(cSize,  ZSTD_compressBlock(cctx, compressedBuffer, ZSTD_compressBound(blockSize), (char*)CNBuffer+dictSize, blockSize));\n        RDG_genBuffer((char*)CNBuffer+dictSize+blockSize, blockSize, 0.0, 0.0, seed);  /* create a non-compressible second block */\n        { CHECK_NEWV(r, ZSTD_compressBlock(cctx, (char*)compressedBuffer+cSize, ZSTD_compressBound(blockSize), (char*)CNBuffer+dictSize+blockSize, blockSize) );  /* for cctx history consistency */\n          assert(r == 0); /* non-compressible block */ }\n        memcpy((char*)compressedBuffer+cSize, (char*)CNBuffer+dictSize+blockSize, blockSize);   /* send non-compressed block (without header) */\n        CHECK_VAR(cSize2, ZSTD_compressBlock(cctx, (char*)compressedBuffer+cSize+blockSize, ZSTD_compressBound(blockSize),\n                                                   (char*)CNBuffer+dictSize+2*blockSize, blockSize));\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : Dictionary Block decompression test : \", testNb++);\n        CHECK_Z( ZSTD_decompressBegin_usingDict(dctx, CNBuffer, dictSize) );\n        {   CHECK_NEWV( r, ZSTD_decompressBlock(dctx, decodedBuffer, blockSize, compressedBuffer, cSize) );\n            if (r != blockSize) {\n                DISPLAYLEVEL(1, \"ZSTD_decompressBlock() with _usingDict() fails : %u, instead of %u expected \\n\", (unsigned)r, (unsigned)blockSize);\n                goto _output_error;\n        }   }\n        memcpy((char*)decodedBuffer+blockSize, (char*)compressedBuffer+cSize, blockSize);\n        ZSTD_insertBlock(dctx, (char*)decodedBuffer+blockSize, blockSize);   /* insert non-compressed block into dctx history */\n        {   CHECK_NEWV( r, ZSTD_decompressBlock(dctx, (char*)decodedBuffer+2*blockSize, blockSize, (char*)compressedBuffer+cSize+blockSize, cSize2) );\n            if (r != blockSize) {\n                DISPLAYLEVEL(1, \"ZSTD_decompressBlock() with _usingDict() and after insertBlock() fails : %u, instead of %u expected \\n\", (unsigned)r, (unsigned)blockSize);\n                goto _output_error;\n        }   }\n        assert(memcpy((char*)CNBuffer+dictSize, decodedBuffer, blockSize*3));  /* ensure regenerated content is identical to origin */\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : Block compression with CDict : \", testNb++);\n        {   ZSTD_CDict* const cdict = ZSTD_createCDict(CNBuffer, dictSize, 3);\n            if (cdict==NULL) goto _output_error;\n            CHECK_Z( ZSTD_compressBegin_usingCDict(cctx, cdict) );\n            CHECK_Z( ZSTD_compressBlock(cctx, compressedBuffer, ZSTD_compressBound(blockSize), (char*)CNBuffer+dictSize, blockSize) );\n            ZSTD_freeCDict(cdict);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        ZSTD_freeCCtx(cctx);\n        ZSTD_freeDCtx(dctx);\n    }\n\n    /* rle detection test: must compress better blocks with a single identical byte repeated */\n    {   size_t sampleSize = 0;\n        size_t maxCompressedSize = 46; /* block 1, 2: compressed, block 3: RLE, zstd 1.4.4 */\n        DISPLAYLEVEL(3, \"test%3i : RLE detection test : \", testNb++);\n        memset((char*)CNBuffer+sampleSize, 'B', 256 KB - 2);\n        sampleSize += 256 KB - 2;\n        memset((char*)CNBuffer+sampleSize, 'A', 100 KB);\n        sampleSize += 100 KB;\n        cSize = ZSTD_compress(compressedBuffer, ZSTD_compressBound(sampleSize), CNBuffer, sampleSize, 1);\n        if (ZSTD_isError(cSize) || cSize > maxCompressedSize) {\n            DISPLAYLEVEL(4, \"error: cSize %u > %u expected ! \\n\", (unsigned)cSize, (unsigned)maxCompressedSize);\n            goto _output_error;\n        }\n        { CHECK_NEWV(regenSize, ZSTD_decompress(decodedBuffer, sampleSize, compressedBuffer, cSize));\n          if (regenSize!=sampleSize) goto _output_error; }\n        DISPLAYLEVEL(3, \"OK \\n\");\n    }\n\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_generateSequences decode from sequences test : \", testNb++);\n    {\n        size_t srcSize = 150 KB;\n        BYTE* src = (BYTE*)CNBuffer;\n        BYTE* decoded = (BYTE*)compressedBuffer;\n\n        ZSTD_CCtx* cctx = ZSTD_createCCtx();\n        ZSTD_Sequence* seqs = (ZSTD_Sequence*)malloc(srcSize * sizeof(ZSTD_Sequence));\n        size_t seqsSize;\n\n        if (seqs == NULL) goto _output_error;\n        assert(cctx != NULL);\n        ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 19);\n        /* Populate src with random data */\n        RDG_genBuffer(CNBuffer, srcSize, compressibility, 0.5, seed);\n\n        /* Test with block delimiters roundtrip */\n        seqsSize = ZSTD_generateSequences(cctx, seqs, srcSize, src, srcSize);\n        CHECK_Z(seqsSize);\n        FUZ_decodeSequences(decoded, seqs, seqsSize, src, srcSize, ZSTD_sf_explicitBlockDelimiters);\n        assert(!memcmp(CNBuffer, compressedBuffer, srcSize));\n\n        /* Test no block delimiters roundtrip */\n        seqsSize = ZSTD_mergeBlockDelimiters(seqs, seqsSize);\n        CHECK_Z(seqsSize);\n        FUZ_decodeSequences(decoded, seqs, seqsSize, src, srcSize, ZSTD_sf_noBlockDelimiters);\n        assert(!memcmp(CNBuffer, compressedBuffer, srcSize));\n\n        ZSTD_freeCCtx(cctx);\n        free(seqs);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_generateSequences too small output buffer : \", testNb++);\n    {\n        const size_t seqsCapacity = 10;\n        const size_t srcSize = 150 KB;\n        const BYTE* src = (BYTE*)CNBuffer;\n\n        ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        ZSTD_Sequence* const seqs = (ZSTD_Sequence*)malloc(seqsCapacity * sizeof(ZSTD_Sequence));\n\n        if (seqs == NULL) goto _output_error;\n        if (cctx == NULL) goto _output_error;\n        /* Populate src with random data */\n        RDG_genBuffer(CNBuffer, srcSize, compressibility, 0.5, seed);\n\n        /* Test with block delimiters roundtrip */\n        {\n            size_t const seqsSize = ZSTD_generateSequences(cctx, seqs, seqsCapacity, src, srcSize);\n            if (!ZSTD_isError(seqsSize)) goto _output_error;\n        }\n\n        ZSTD_freeCCtx(cctx);\n        free(seqs);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_getSequences followed by ZSTD_compressSequences : \", testNb++);\n    {\n        const size_t srcSize = 500 KB;\n        const BYTE* const src = (BYTE*)CNBuffer;\n        BYTE* const dst = (BYTE*)compressedBuffer;\n        const size_t dstCapacity = ZSTD_compressBound(srcSize);\n        const size_t decompressSize = srcSize;\n        char* const decompressBuffer = (char*)malloc(decompressSize);\n        size_t compressedSize;\n\n        ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        ZSTD_Sequence* const seqs = (ZSTD_Sequence*)malloc(srcSize * sizeof(ZSTD_Sequence));\n        size_t nbSeqs;\n\n        if (seqs == NULL) goto _output_error;\n        assert(cctx != NULL);\n\n        /* Populate src with compressible random data */\n        RDG_genBuffer(CNBuffer, srcSize, compressibility, 0., seed);\n\n        /* Roundtrip Test with block delimiters generated by ZSTD_generateSequences() */\n        nbSeqs = ZSTD_generateSequences(cctx, seqs, srcSize, src, srcSize);\n        ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n        ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters);\n        compressedSize = ZSTD_compressSequences(cctx, dst, dstCapacity, seqs, nbSeqs, src, srcSize);\n        if (ZSTD_isError(compressedSize)) {\n            DISPLAY(\"Error in sequence compression with block delims\\n\");\n            goto _output_error;\n        }\n        {   size_t const dSize = ZSTD_decompress(decompressBuffer, decompressSize, dst, compressedSize);\n            if (ZSTD_isError(dSize)) {\n                DISPLAY(\"Error in sequence compression roundtrip with block delims\\n\");\n                goto _output_error;\n        }   }\n        assert(!memcmp(decompressBuffer, src, srcSize));\n\n        /* Roundtrip Test with no block delimiters  */\n        {   size_t const nbSeqsAfterMerge = ZSTD_mergeBlockDelimiters(seqs, nbSeqs);\n            ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n            ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, ZSTD_sf_noBlockDelimiters);\n            compressedSize = ZSTD_compressSequences(cctx, dst, dstCapacity, seqs, nbSeqsAfterMerge, src, srcSize);\n        }\n        if (ZSTD_isError(compressedSize)) {\n            DISPLAY(\"Error in sequence compression with no block delims\\n\");\n            goto _output_error;\n        }\n        {   size_t const dSize = ZSTD_decompress(decompressBuffer, decompressSize, dst, compressedSize);\n            if (ZSTD_isError(dSize)) {\n                DISPLAY(\"Error in sequence compression roundtrip with no block delims\\n\");\n                goto _output_error;\n        }   }\n        assert(!memcmp(decompressBuffer, src, srcSize));\n\n        ZSTD_freeCCtx(cctx);\n        free(decompressBuffer);\n        free(seqs);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    testNb = test_convertSequences_noRepcodes(seed, testNb);\n\n    testNb = test_get1BlockSummary(testNb);\n\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_compressSequencesAndLiterals : \", testNb++);\n    {\n        const size_t srcSize = 497000;\n        const BYTE* const src = (BYTE*)CNBuffer;\n        BYTE* const dst = (BYTE*)compressedBuffer;\n        const size_t dstCapacity = ZSTD_compressBound(srcSize);\n        const size_t decompressSize = srcSize;\n        char* const decompressBuffer = (char*)malloc(decompressSize);\n        char* const litBuffer = (char*)malloc(decompressSize);\n        size_t compressedSize;\n\n        ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        ZSTD_Sequence* const seqs = (ZSTD_Sequence*)malloc(srcSize * sizeof(ZSTD_Sequence));\n        size_t nbSeqs;\n\n        if (litBuffer == NULL) goto _output_error;\n        if (decompressBuffer == NULL) goto _output_error;\n        if (seqs == NULL) goto _output_error;\n        assert(cctx != NULL);\n\n        /* Populate src with compressible random data */\n        RDG_genBuffer(CNBuffer, srcSize, compressibility, 0., seed);\n\n        /* Roundtrip Test using the AndLiterals() variant */\n        nbSeqs = ZSTD_generateSequences(cctx, seqs, srcSize, src, srcSize);\n        ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n        ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters);\n        {   size_t const litSize = FUZ_getLitSize(seqs, nbSeqs);\n            FUZ_transferLiterals(litBuffer, decompressSize, CNBuffer, srcSize, seqs, nbSeqs);\n\n            /* not enough literals: must fail */\n            compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, src, litSize-1, decompressSize, srcSize);\n            if (!ZSTD_isError(compressedSize)) {\n                DISPLAY(\"ZSTD_compressSequencesAndLiterals() should have failed: not enough literals provided\\n\");\n                goto _output_error;\n            }\n\n            /* too many literals: must fail */\n            compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, src, litSize+1, decompressSize, srcSize);\n            if (!ZSTD_isError(compressedSize)) {\n                DISPLAY(\"ZSTD_compressSequencesAndLiterals() should have failed: too many literals provided\\n\");\n                goto _output_error;\n            }\n\n            /* srcSize too large: must fail */\n            compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, litBuffer, litSize, decompressSize, srcSize+1);\n            if (!ZSTD_isError(compressedSize)) {\n                DISPLAY(\"ZSTD_compressSequencesAndLiterals() should have failed: srcSize is too large\\n\");\n                goto _output_error;\n            }\n\n            /* srcSize too small: must fail */\n            compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, litBuffer, litSize, decompressSize, srcSize-1);\n            if (!ZSTD_isError(compressedSize)) {\n                DISPLAY(\"ZSTD_compressSequencesAndLiterals() should have failed: srcSize is too small\\n\");\n                goto _output_error;\n            }\n\n            /* correct amount of literals: should compress successfully */\n            compressedSize = ZSTD_compressSequencesAndLiterals(cctx, dst, dstCapacity, seqs, nbSeqs, litBuffer, litSize, decompressSize, srcSize);\n            if (ZSTD_isError(compressedSize)) {\n                DISPLAY(\"Error in ZSTD_compressSequencesAndLiterals()\\n\");\n                goto _output_error;\n            }\n        }\n        {   ZSTD_FrameHeader zfh;\n            size_t const zfhStatus = ZSTD_getFrameHeader(&zfh, dst, compressedSize);\n            if (zfhStatus != 0) {\n                DISPLAY(\"Error reading frame header\\n\");\n                goto _output_error;\n            }\n            if (zfh.frameContentSize != srcSize) {\n                DISPLAY(\"Error: ZSTD_compressSequencesAndLiterals() did not report srcSize in the frame header\\n\");\n                goto _output_error;\n            }\n            if (zfh.windowSize > srcSize) {\n                DISPLAY(\"Error: ZSTD_compressSequencesAndLiterals() did not resized window size to smaller contentSize\\n\");\n                goto _output_error;\n            }\n        }\n        {   size_t const dSize = ZSTD_decompress(decompressBuffer, decompressSize, dst, compressedSize);\n            if (ZSTD_isError(dSize)) {\n                DISPLAY(\"Error during decompression of frame produced by ZSTD_compressSequencesAndLiterals()\\n\");\n                goto _output_error;\n            }\n            if (dSize != srcSize) {\n                DISPLAY(\"Error: decompression of frame produced by ZSTD_compressSequencesAndLiterals() has different size\\n\");\n                goto _output_error;\n            }\n            if (memcmp(decompressBuffer, src, srcSize)) {\n                DISPLAY(\"Error: decompression of frame produced by ZSTD_compressSequencesAndLiterals() produces a different content (of same size)\\n\");\n                goto _output_error;\n            }\n        }\n\n        ZSTD_freeCCtx(cctx);\n        free(litBuffer);\n        free(decompressBuffer);\n        free(seqs);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* Multiple blocks of zeros test */\n    #define LONGZEROSLENGTH 1000000 /* 1MB of zeros */\n    DISPLAYLEVEL(3, \"test%3i : compress %u zeroes : \", testNb++, LONGZEROSLENGTH);\n    memset(CNBuffer, 0, LONGZEROSLENGTH);\n    CHECK_VAR(cSize, ZSTD_compress(compressedBuffer, ZSTD_compressBound(LONGZEROSLENGTH), CNBuffer, LONGZEROSLENGTH, 1) );\n    DISPLAYLEVEL(3, \"OK (%u bytes : %.2f%%)\\n\", (unsigned)cSize, (double)cSize/LONGZEROSLENGTH*100);\n\n    DISPLAYLEVEL(3, \"test%3i : decompress %u zeroes : \", testNb++, LONGZEROSLENGTH);\n    { CHECK_NEWV(r, ZSTD_decompress(decodedBuffer, LONGZEROSLENGTH, compressedBuffer, cSize) );\n      if (r != LONGZEROSLENGTH) goto _output_error; }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* All zeroes test (test bug #137) */\n    #define ZEROESLENGTH 100\n    DISPLAYLEVEL(3, \"test%3i : compress %u zeroes : \", testNb++, ZEROESLENGTH);\n    memset(CNBuffer, 0, ZEROESLENGTH);\n    CHECK_VAR(cSize, ZSTD_compress(compressedBuffer, ZSTD_compressBound(ZEROESLENGTH), CNBuffer, ZEROESLENGTH, 1) );\n    DISPLAYLEVEL(3, \"OK (%u bytes : %.2f%%)\\n\", (unsigned)cSize, (double)cSize/ZEROESLENGTH*100);\n\n    DISPLAYLEVEL(3, \"test%3i : decompress %u zeroes : \", testNb++, ZEROESLENGTH);\n    { CHECK_NEWV(r, ZSTD_decompress(decodedBuffer, ZEROESLENGTH, compressedBuffer, cSize) );\n      if (r != ZEROESLENGTH) goto _output_error; }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* nbSeq limit test */\n    #define _3BYTESTESTLENGTH 131000\n    #define NB3BYTESSEQLOG   9\n    #define NB3BYTESSEQ     (1 << NB3BYTESSEQLOG)\n    #define NB3BYTESSEQMASK (NB3BYTESSEQ-1)\n    /* creates a buffer full of 3-bytes sequences */\n    {   BYTE _3BytesSeqs[NB3BYTESSEQ][3];\n        U32 rSeed = 1;\n\n        /* create batch of 3-bytes sequences */\n        {   int i;\n            for (i=0; i < NB3BYTESSEQ; i++) {\n                _3BytesSeqs[i][0] = (BYTE)(FUZ_rand(&rSeed) & 255);\n                _3BytesSeqs[i][1] = (BYTE)(FUZ_rand(&rSeed) & 255);\n                _3BytesSeqs[i][2] = (BYTE)(FUZ_rand(&rSeed) & 255);\n        }   }\n\n        /* randomly fills CNBuffer with prepared 3-bytes sequences */\n        {   int i;\n            for (i=0; i < _3BYTESTESTLENGTH; i += 3) {   /* note : CNBuffer size > _3BYTESTESTLENGTH+3 */\n                U32 const id = FUZ_rand(&rSeed) & NB3BYTESSEQMASK;\n                ((BYTE*)CNBuffer)[i+0] = _3BytesSeqs[id][0];\n                ((BYTE*)CNBuffer)[i+1] = _3BytesSeqs[id][1];\n                ((BYTE*)CNBuffer)[i+2] = _3BytesSeqs[id][2];\n    }   }   }\n    DISPLAYLEVEL(3, \"test%3i : growing nbSeq : \", testNb++);\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        size_t const maxNbSeq = _3BYTESTESTLENGTH / 3;\n        size_t const bound = ZSTD_compressBound(_3BYTESTESTLENGTH);\n        size_t nbSeq = 1;\n        while (nbSeq <= maxNbSeq) {\n          CHECK_Z(ZSTD_compressCCtx(cctx, compressedBuffer, bound, CNBuffer, nbSeq * 3, 19));\n          /* Check every sequence for the first 100, then skip more rapidly. */\n          if (nbSeq < 100) {\n            ++nbSeq;\n          } else {\n            nbSeq += (nbSeq >> 2);\n          }\n        }\n        ZSTD_freeCCtx(cctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : compress lots 3-bytes sequences : \", testNb++);\n    CHECK_VAR(cSize, ZSTD_compress(compressedBuffer, ZSTD_compressBound(_3BYTESTESTLENGTH),\n                                   CNBuffer, _3BYTESTESTLENGTH, 19) );\n    DISPLAYLEVEL(3, \"OK (%u bytes : %.2f%%)\\n\", (unsigned)cSize, (double)cSize/_3BYTESTESTLENGTH*100);\n\n    DISPLAYLEVEL(3, \"test%3i : decompress lots 3-bytes sequence : \", testNb++);\n    { CHECK_NEWV(r, ZSTD_decompress(decodedBuffer, _3BYTESTESTLENGTH, compressedBuffer, cSize) );\n      if (r != _3BYTESTESTLENGTH) goto _output_error; }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n\n    DISPLAYLEVEL(3, \"test%3i : growing literals buffer : \", testNb++);\n    RDG_genBuffer(CNBuffer, CNBuffSize, 0.0, 0.1, seed);\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        size_t const bound = ZSTD_compressBound(CNBuffSize);\n        size_t size = 1;\n        while (size <= CNBuffSize) {\n          CHECK_Z(ZSTD_compressCCtx(cctx, compressedBuffer, bound, CNBuffer, size, 3));\n          /* Check every size for the first 100, then skip more rapidly. */\n          if (size < 100) {\n            ++size;\n          } else {\n            size += (size >> 2);\n          }\n        }\n        ZSTD_freeCCtx(cctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : incompressible data and ill suited dictionary : \", testNb++);\n    {   /* Train a dictionary on low characters */\n        size_t dictSize = 16 KB;\n        void* const dictBuffer = malloc(dictSize);\n        size_t const totalSampleSize = 1 MB;\n        size_t const sampleUnitSize = 8 KB;\n        U32 const nbSamples = (U32)(totalSampleSize / sampleUnitSize);\n        size_t* const samplesSizes = (size_t*) malloc(nbSamples * sizeof(size_t));\n        if (!dictBuffer || !samplesSizes) goto _output_error;\n        { U32 u; for (u=0; u<nbSamples; u++) samplesSizes[u] = sampleUnitSize; }\n        dictSize = ZDICT_trainFromBuffer(dictBuffer, dictSize, CNBuffer, samplesSizes, nbSamples);\n        if (ZDICT_isError(dictSize)) goto _output_error;\n        /* Reverse the characters to make the dictionary ill suited */\n        {   U32 u;\n            for (u = 0; u < CNBuffSize; ++u) {\n              ((BYTE*)CNBuffer)[u] = 255 - ((BYTE*)CNBuffer)[u];\n        }   }\n        {   /* Compress the data */\n            size_t const inputSize = 500;\n            size_t const outputSize = ZSTD_compressBound(inputSize);\n            void* const outputBuffer = malloc(outputSize);\n            ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n            if (!outputBuffer || !cctx) goto _output_error;\n            CHECK_Z(ZSTD_compress_usingDict(cctx, outputBuffer, outputSize, CNBuffer, inputSize, dictBuffer, dictSize, 1));\n            free(outputBuffer);\n            ZSTD_freeCCtx(cctx);\n        }\n\n        free(dictBuffer);\n        free(samplesSizes);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n\n    /* frame operations on skippable frames */\n    {   const char skippableFrame[] = \"\\x52\\x2a\\x4d\\x18\\x05\\x0\\x0\\0abcde\";\n        size_t const skippableFrameSize = sizeof(skippableFrame) - 1 /* remove the terminating /0 */;\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_findFrameCompressedSize on skippable frame : \", testNb++);\n        CHECK(ZSTD_findFrameCompressedSize(skippableFrame, skippableFrameSize) == skippableFrameSize);\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_getFrameContentSize on skippable frame : \", testNb++);\n        CHECK(ZSTD_getFrameContentSize(skippableFrame, skippableFrameSize) == 0);\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_getFrameHeader on skippable frame : \", testNb++);\n        {   ZSTD_FrameHeader zfh;\n            size_t const s = ZSTD_getFrameHeader(&zfh, skippableFrame, skippableFrameSize);\n            CHECK_Z(s);\n            CHECK(s == 0); /* success */\n            CHECK(zfh.frameType == ZSTD_skippableFrame);\n            CHECK(zfh.headerSize == ZSTD_SKIPPABLEHEADERSIZE);\n            CHECK(zfh.dictID == 2); /* magic variant */\n            assert(skippableFrameSize >= ZSTD_SKIPPABLEHEADERSIZE);\n            CHECK(zfh.frameContentSize == skippableFrameSize - ZSTD_SKIPPABLEHEADERSIZE);\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n    }\n\n    /* error string tests */\n    DISPLAYLEVEL(3, \"test%3i : testing ZSTD error code strings : \", testNb++);\n    if (strcmp(\"No error detected\", ZSTD_getErrorName((ZSTD_ErrorCode)(0-ZSTD_error_no_error))) != 0) goto _output_error;\n    if (strcmp(\"No error detected\", ZSTD_getErrorString(ZSTD_error_no_error)) != 0) goto _output_error;\n    if (strcmp(\"Unspecified error code\", ZSTD_getErrorString((ZSTD_ErrorCode)(0-ZSTD_error_GENERIC))) != 0) goto _output_error;\n    if (strcmp(\"Error (generic)\", ZSTD_getErrorName((size_t)0-ZSTD_error_GENERIC)) != 0) goto _output_error;\n    if (strcmp(\"Error (generic)\", ZSTD_getErrorString(ZSTD_error_GENERIC)) != 0) goto _output_error;\n    if (strcmp(\"No error detected\", ZSTD_getErrorName(ZSTD_error_GENERIC)) != 0) goto _output_error;\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : testing ZSTD dictionary sizes : \", testNb++);\n    RDG_genBuffer(CNBuffer, CNBuffSize, compressibility, 0., seed);\n    {\n        size_t const size = MIN(128 KB, CNBuffSize);\n        ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        ZSTD_CDict* const lgCDict = ZSTD_createCDict(CNBuffer, size, 1);\n        ZSTD_CDict* const smCDict = ZSTD_createCDict(CNBuffer, 1 KB, 1);\n        ZSTD_FrameHeader lgHeader;\n        ZSTD_FrameHeader smHeader;\n\n        CHECK_Z(ZSTD_compress_usingCDict(cctx, compressedBuffer, compressedBufferSize, CNBuffer, size, lgCDict));\n        CHECK_Z(ZSTD_getFrameHeader(&lgHeader, compressedBuffer, compressedBufferSize));\n        CHECK_Z(ZSTD_compress_usingCDict(cctx, compressedBuffer, compressedBufferSize, CNBuffer, size, smCDict));\n        CHECK_Z(ZSTD_getFrameHeader(&smHeader, compressedBuffer, compressedBufferSize));\n\n        if (lgHeader.windowSize != smHeader.windowSize) goto _output_error;\n\n        ZSTD_freeCDict(smCDict);\n        ZSTD_freeCDict(lgCDict);\n        ZSTD_freeCCtx(cctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : testing FSE_normalizeCount() PR#1255: \", testNb++);\n    {\n        short norm[32];\n        unsigned count[32];\n        unsigned const tableLog = 5;\n        size_t const nbSeq = 32;\n        unsigned const maxSymbolValue = 31;\n        size_t i;\n\n        for (i = 0; i < 32; ++i)\n            count[i] = 1;\n        /* Calling FSE_normalizeCount() on a uniform distribution should not\n         * cause a division by zero.\n         */\n        FSE_normalizeCount(norm, tableLog, count, nbSeq, maxSymbolValue, /* useLowProbCount */ 1);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : testing FSE_writeNCount() PR#2779: \", testNb++);\n    {\n        size_t const outBufSize = 9;\n        short const count[11] = {1, 0, 1, 0, 1, 0, 1, 0, 1, 9, 18};\n        unsigned const tableLog = 5;\n        unsigned const maxSymbolValue = 10;\n        BYTE* outBuf = (BYTE*)malloc(outBufSize*sizeof(BYTE));\n\n        /* Ensure that this write doesn't write out of bounds, and that\n         * FSE_writeNCount_generic() is *not* called with writeIsSafe == 1.\n         */\n        FSE_writeNCount(outBuf, outBufSize, count, maxSymbolValue, tableLog);\n        free(outBuf);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : testing bitwise intrinsics PR#3045: \", testNb++);\n    {\n        U32 seed_copy = seed; /* need non-const seed to avoid compiler warning for FUZ_rand(&seed) */\n        U32 rand32 = FUZ_rand(&seed_copy);\n        U64 rand64 = ((U64)FUZ_rand(&seed_copy) << 32) | FUZ_rand(&seed_copy);\n        U32 lowbit_only_32 = 1;\n        U64 lowbit_only_64 = 1;\n        U32 highbit_only_32 = (U32)1 << 31;\n        U64 highbit_only_64 = (U64)1 << 63;\n        U32 i;\n        if (rand32 == 0) rand32 = 1; /* CLZ and CTZ are undefined on 0 */\n        if (rand64 == 0) rand64 = 1; /* CLZ and CTZ are undefined on 0 */\n\n        /* Test ZSTD_countTrailingZeros32 */\n        CHECK_EQ(ZSTD_countTrailingZeros32(lowbit_only_32), 0u);\n        CHECK_EQ(ZSTD_countTrailingZeros32(highbit_only_32), 31u);\n        CHECK_EQ(ZSTD_countTrailingZeros32(rand32), ZSTD_countTrailingZeros32_fallback(rand32));\n\n        /* Test ZSTD_countLeadingZeros32 */\n        CHECK_EQ(ZSTD_countLeadingZeros32(lowbit_only_32), 31u);\n        CHECK_EQ(ZSTD_countLeadingZeros32(highbit_only_32), 0u);\n        CHECK_EQ(ZSTD_countLeadingZeros32(rand32), ZSTD_countLeadingZeros32_fallback(rand32));\n\n        /* Test ZSTD_countTrailingZeros64 */\n        CHECK_EQ(ZSTD_countTrailingZeros64(lowbit_only_64), 0u);\n        CHECK_EQ(ZSTD_countTrailingZeros64(highbit_only_64), 63u);\n\n        /* Test ZSTD_countLeadingZeros64 */\n        CHECK_EQ(ZSTD_countLeadingZeros64(lowbit_only_64), 63u);\n        CHECK_EQ(ZSTD_countLeadingZeros64(highbit_only_64), 0u);\n\n        /* Test ZSTD_highbit32 */\n        CHECK_EQ(ZSTD_highbit32(lowbit_only_32), 0u);\n        CHECK_EQ(ZSTD_highbit32(highbit_only_32), 31u);\n\n        /* Test ZSTD_NbCommonBytes */\n        if (MEM_isLittleEndian()) {\n            if (MEM_64bits()) {\n                CHECK_EQ(ZSTD_NbCommonBytes(lowbit_only_32), 0u);\n                CHECK_EQ(ZSTD_NbCommonBytes(highbit_only_32), 3u);\n            } else {\n                CHECK_EQ(ZSTD_NbCommonBytes(lowbit_only_32), 0u);\n                CHECK_EQ(ZSTD_NbCommonBytes(highbit_only_32), 3u);\n            }\n        } else {\n            if (MEM_64bits()) {\n                CHECK_EQ(ZSTD_NbCommonBytes(lowbit_only_32), 7u);\n                CHECK_EQ(ZSTD_NbCommonBytes(highbit_only_32), 4u);\n            } else {\n                CHECK_EQ(ZSTD_NbCommonBytes(lowbit_only_32), 3u);\n                CHECK_EQ(ZSTD_NbCommonBytes(highbit_only_32), 0u);\n            }\n       }\n\n        /* Test MEM_ intrinsics */\n        CHECK_EQ(MEM_swap32(rand32), MEM_swap32_fallback(rand32));\n        CHECK_EQ(MEM_swap64(rand64), MEM_swap64_fallback(rand64));\n\n        /* Test fallbacks vs intrinsics on a range of small integers */\n        for (i=1; i <= 1000; i++) {\n            CHECK_EQ(MEM_swap32(i), MEM_swap32_fallback(i));\n            CHECK_EQ(MEM_swap64((U64)i), MEM_swap64_fallback((U64)i));\n            CHECK_EQ(ZSTD_countTrailingZeros32(i), ZSTD_countTrailingZeros32_fallback(i));\n            CHECK_EQ(ZSTD_countLeadingZeros32(i), ZSTD_countLeadingZeros32_fallback(i));\n        }\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n#ifdef ZSTD_MULTITHREAD\n    DISPLAYLEVEL(3, \"test%3i : passing wrong full dict should fail on compressStream2 refPrefix \", testNb++);\n    {   ZSTD_CCtx* cctx = ZSTD_createCCtx();\n        size_t const srcSize = 1 MB + 5;   /* A little more than ZSTDMT_JOBSIZE_MIN */\n        size_t const dstSize = ZSTD_compressBound(srcSize);\n        void* const src = CNBuffer;\n        void* const dst = compressedBuffer;\n        void* dict = (void*)malloc(srcSize);\n\n        RDG_genBuffer(src, srcSize, compressibility, 0.5, seed);\n        RDG_genBuffer(dict, srcSize, compressibility, 0., seed);\n\n        /* Make sure there is no ZSTD_MAGIC_NUMBER */\n        memset(dict, 0, sizeof(U32));\n\n        /* something more than 1 */\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 2));\n        /* lie and claim this is a full dict */\n        CHECK_Z(ZSTD_CCtx_refPrefix_advanced(cctx, dict, srcSize, ZSTD_dct_fullDict));\n\n        {   ZSTD_outBuffer out = {dst, dstSize, 0};\n            ZSTD_inBuffer in = {src, srcSize, 0};\n            /* should fail because its not a full dict like we said it was */\n            assert(ZSTD_isError(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush)));\n        }\n\n        ZSTD_freeCCtx(cctx);\n        free(dict);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : small dictionary with multithreading and LDM \", testNb++);\n    {   ZSTD_CCtx* cctx = ZSTD_createCCtx();\n        size_t const srcSize = 1 MB + 5;   /* A little more than ZSTDMT_JOBSIZE_MIN */\n        size_t const dictSize = 10;\n        size_t const dstSize = ZSTD_compressBound(srcSize);\n        void* const src = CNBuffer;\n        void* const dst = compressedBuffer;\n        void* dict = (void*)malloc(dictSize);\n\n        RDG_genBuffer(src, srcSize, compressibility, 0.5, seed);\n        RDG_genBuffer(dict, dictSize, compressibility, 0., seed);\n\n        /* Make sure there is no ZSTD_MAGIC_NUMBER */\n        memset(dict, 0, sizeof(U32));\n\n        /* Enable MT, LDM, and use refPrefix() for a small dict */\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 2));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable));\n        CHECK_Z(ZSTD_CCtx_refPrefix(cctx, dict, dictSize));\n\n        CHECK_Z(ZSTD_compress2(cctx, dst, dstSize, src, srcSize));\n\n        ZSTD_freeCCtx(cctx);\n        free(dict);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_getCParams() + dictionary \", testNb++);\n    {\n        ZSTD_compressionParameters const medium = ZSTD_getCParams(1, 16*1024-1, 0);\n        ZSTD_compressionParameters const large = ZSTD_getCParams(1, 128*1024-1, 0);\n        ZSTD_compressionParameters const smallDict = ZSTD_getCParams(1, 0, 400);\n        ZSTD_compressionParameters const mediumDict = ZSTD_getCParams(1, 0, 10000);\n        ZSTD_compressionParameters const largeDict = ZSTD_getCParams(1, 0, 100000);\n\n        assert(!memcmp(&smallDict, &mediumDict, sizeof(smallDict)));\n        assert(!memcmp(&medium, &mediumDict, sizeof(medium)));\n        assert(!memcmp(&large, &largeDict, sizeof(large)));\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_adjustCParams() + dictionary \", testNb++);\n    {\n        ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, 0, 0);\n        ZSTD_compressionParameters const smallDict = ZSTD_adjustCParams(cParams, 0, 400);\n        ZSTD_compressionParameters const smallSrcAndDict = ZSTD_adjustCParams(cParams, 500, 400);\n\n        assert(smallSrcAndDict.windowLog == 10);\n        assert(!memcmp(&cParams, &smallDict, sizeof(cParams)));\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : check compression mem usage monotonicity over levels for estimateCCtxSize() : \", testNb++);\n    {\n        int level = 1;\n        size_t prevSize = 0;\n        for (; level < ZSTD_maxCLevel(); ++level) {\n            size_t const currSize = ZSTD_estimateCCtxSize(level);\n            if (prevSize > currSize) {\n                DISPLAYLEVEL(3, \"Error! previous cctx size: %u at level: %d is larger than current cctx size: %u at level: %d\",\n                             (unsigned)prevSize, level-1, (unsigned)currSize, level);\n                goto _output_error;\n            }\n            prevSize = currSize;\n        }\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : check estimateCCtxSize() always larger or equal to ZSTD_estimateCCtxSize_usingCParams() : \", testNb++);\n    {\n        size_t const kSizeIncrement = 2 KB;\n        int level = -3;\n\n        for (; level <= ZSTD_maxCLevel(); ++level) {\n            size_t dictSize = 0;\n            for (; dictSize <= 256 KB; dictSize += 8 * kSizeIncrement) {\n                size_t srcSize = 2 KB;\n                for (; srcSize < 300 KB; srcSize += kSizeIncrement) {\n                    ZSTD_compressionParameters const cParams = ZSTD_getCParams(level, srcSize, dictSize);\n                    size_t const cctxSizeUsingCParams = ZSTD_estimateCCtxSize_usingCParams(cParams);\n                    size_t const cctxSizeUsingLevel = ZSTD_estimateCCtxSize(level);\n                    if (cctxSizeUsingLevel < cctxSizeUsingCParams\n                     || ZSTD_isError(cctxSizeUsingCParams)\n                     || ZSTD_isError(cctxSizeUsingLevel)) {\n                        DISPLAYLEVEL(3, \"error! l: %d dict: %u srcSize: %u cctx size cpar: %u, cctx size level: %u\\n\",\n                                     level, (unsigned)dictSize, (unsigned)srcSize, (unsigned)cctxSizeUsingCParams, (unsigned)cctxSizeUsingLevel);\n                        goto _output_error;\n    }   }   }   }   }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : thread pool API tests : \\n\", testNb++)\n    {\n        int const threadPoolTestResult = threadPoolTests();\n        if (threadPoolTestResult) {\n            goto _output_error;\n        }\n    }\n    DISPLAYLEVEL(3, \"thread pool tests OK \\n\");\n\n#endif /* ZSTD_MULTITHREAD */\n\n_end:\n    free(CNBuffer);\n    free(compressedBuffer);\n    free(decodedBuffer);\n    return testResult;\n\n_output_error:\n    testResult = 1;\n    DISPLAY(\"Error detected in Unit tests ! \\n\");\n    goto _end;\n}\n\nstatic int longUnitTests(U32 const seed, double compressibility)\n{\n    size_t const CNBuffSize = 5 MB;\n    void* const CNBuffer = malloc(CNBuffSize);\n    size_t const compressedBufferSize = ZSTD_compressBound(CNBuffSize);\n    void* const compressedBuffer = malloc(compressedBufferSize);\n    void* const decodedBuffer = malloc(CNBuffSize);\n    int testResult = 0;\n    unsigned testNb=0;\n    size_t cSize;\n\n    /* Create compressible noise */\n    if (!CNBuffer || !compressedBuffer || !decodedBuffer) {\n        DISPLAY(\"Not enough memory, aborting\\n\");\n        testResult = 1;\n        goto _end;\n    }\n    RDG_genBuffer(CNBuffer, CNBuffSize, compressibility, 0., seed);\n\n    /* note : this test is rather long, it would be great to find a way to speed up its execution */\n    DISPLAYLEVEL(3, \"longtest%3i : table cleanliness through index reduction : \", testNb++);\n    {   int cLevel;\n        size_t approxIndex = 0;\n        size_t maxIndex = ((3U << 29) + (1U << ZSTD_WINDOWLOG_MAX)); /* ZSTD_CURRENT_MAX from zstd_compress_internal.h */\n\n        /* Provision enough space in a static context so that we can do all\n         * this without ever reallocating, which would reset the indices. */\n        size_t const staticCCtxSize = ZSTD_estimateCStreamSize(22);\n        void* const staticCCtxBuffer = malloc(staticCCtxSize);\n        ZSTD_CCtx* const cctx = ZSTD_initStaticCCtx(staticCCtxBuffer, staticCCtxSize);\n\n        /* bump the indices so the following compressions happen at high\n         * indices. */\n        {   ZSTD_outBuffer out = { compressedBuffer, compressedBufferSize, 0 };\n            ZSTD_inBuffer in = { CNBuffer, CNBuffSize, 0 };\n            ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, -500));\n            while (approxIndex <= (maxIndex / 4) * 3) {\n                CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush));\n                approxIndex += in.pos;\n                CHECK_Z(in.pos == in.size);\n                in.pos = 0;\n                out.pos = 0;\n            }\n            CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));\n        }\n\n        /* spew a bunch of stuff into the table area */\n        for (cLevel = 1; cLevel <= 22; cLevel++) {\n            ZSTD_outBuffer out = { compressedBuffer, compressedBufferSize / (unsigned)cLevel, 0 };\n            ZSTD_inBuffer in = { CNBuffer, CNBuffSize, 0 };\n            ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, cLevel));\n            CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush));\n            CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));\n            approxIndex += in.pos;\n        }\n\n        /* now crank the indices so we overflow */\n        {   ZSTD_outBuffer out = { compressedBuffer, compressedBufferSize, 0 };\n            ZSTD_inBuffer in = { CNBuffer, CNBuffSize, 0 };\n            ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, -500));\n            while (approxIndex <= maxIndex) {\n                CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush));\n                approxIndex += in.pos;\n                CHECK_Z(in.pos == in.size);\n                in.pos = 0;\n                out.pos = 0;\n            }\n            CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));\n        }\n\n        /* do a bunch of compressions again in low indices and ensure we don't\n         * hit untracked invalid indices */\n        for (cLevel = 1; cLevel <= 22; cLevel++) {\n            ZSTD_outBuffer out = { compressedBuffer, compressedBufferSize / (unsigned)cLevel, 0 };\n            ZSTD_inBuffer in = { CNBuffer, CNBuffSize, 0 };\n            ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, cLevel));\n            CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush));\n            CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));\n            approxIndex += in.pos;\n        }\n\n        free(staticCCtxBuffer);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"longtest%3i : testing ldm no regressions in size for opt parser : \", testNb++);\n    {   size_t cSizeLdm;\n        size_t cSizeNoLdm;\n        ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n\n        RDG_genBuffer(CNBuffer, CNBuffSize, 0.5, 0.5, seed);\n\n        /* Enable checksum to verify round trip. */\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 19));\n\n        /* Round trip once with ldm. */\n        cSizeLdm = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);\n        CHECK_Z(cSizeLdm);\n        CHECK_Z(ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSizeLdm));\n\n        ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_disable));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 19));\n\n        /* Round trip once without ldm. */\n        cSizeNoLdm = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);\n        CHECK_Z(cSizeNoLdm);\n        CHECK_Z(ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSizeNoLdm));\n\n        if (cSizeLdm > cSizeNoLdm) {\n            DISPLAY(\"Using long mode should not cause regressions for btopt+\\n\");\n            testResult = 1;\n            goto _end;\n        }\n\n        ZSTD_freeCCtx(cctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"longtest%3i : testing cdict compression with different attachment strategies : \", testNb++);\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n        size_t dictSize = CNBuffSize;\n        void* dict = (void*)malloc(dictSize);\n        ZSTD_CCtx_params* cctx_params = ZSTD_createCCtxParams();\n        ZSTD_dictAttachPref_e const attachPrefs[] = {\n            ZSTD_dictDefaultAttach,\n            ZSTD_dictForceAttach,\n            ZSTD_dictForceCopy,\n            ZSTD_dictForceLoad,\n            ZSTD_dictDefaultAttach,\n            ZSTD_dictForceAttach,\n            ZSTD_dictForceCopy,\n            ZSTD_dictForceLoad\n        };\n        int const enableDedicatedDictSearch[] = {0, 0, 0, 0, 1, 1, 1, 1};\n        int cLevel;\n        int i;\n\n        RDG_genBuffer(dict, dictSize, 0.5, 0.5, seed);\n        RDG_genBuffer(CNBuffer, CNBuffSize, 0.6, 0.6, seed);\n\n        CHECK_Z(cctx_params != NULL);\n\n        for (dictSize = CNBuffSize; dictSize; dictSize = dictSize >> 3) {\n            DISPLAYLEVEL(3, \"\\n    Testing with dictSize %u \", (U32)dictSize);\n            for (cLevel = 4; cLevel < 13; cLevel++) {\n                for (i = 0; i < 8; ++i) {\n                    ZSTD_dictAttachPref_e const attachPref = attachPrefs[i];\n                    int const enableDDS = enableDedicatedDictSearch[i];\n                    ZSTD_CDict* cdict;\n\n                    DISPLAYLEVEL(5, \"\\n      dictSize %u cLevel %d iter %d \", (U32)dictSize, cLevel, i);\n\n                    ZSTD_CCtxParams_init(cctx_params, cLevel);\n                    CHECK_Z(ZSTD_CCtxParams_setParameter(cctx_params, ZSTD_c_enableDedicatedDictSearch, enableDDS));\n\n                    cdict = ZSTD_createCDict_advanced2(dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, cctx_params, ZSTD_defaultCMem);\n                    CHECK(cdict != NULL);\n\n                    CHECK_Z(ZSTD_CCtx_refCDict(cctx, cdict));\n                    CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_forceAttachDict, (int)attachPref));\n\n                    cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);\n                    CHECK_Z(cSize);\n                    CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, dict, dictSize));\n\n                    DISPLAYLEVEL(5, \"compressed to %u bytes \", (U32)cSize);\n\n                    CHECK_Z(ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters));\n                    ZSTD_freeCDict(cdict);\n        }   }   }\n\n        ZSTD_freeCCtx(cctx);\n        ZSTD_freeDCtx(dctx);\n        ZSTD_freeCCtxParams(cctx_params);\n        free(dict);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n_end:\n    free(CNBuffer);\n    free(compressedBuffer);\n    free(decodedBuffer);\n    return testResult;\n}\n\n\nstatic size_t findDiff(const void* buf1, const void* buf2, size_t max)\n{\n    const BYTE* b1 = (const BYTE*)buf1;\n    const BYTE* b2 = (const BYTE*)buf2;\n    size_t u;\n    for (u=0; u<max; u++) {\n        if (b1[u] != b2[u]) break;\n    }\n    return u;\n}\n\n\nstatic ZSTD_parameters FUZ_makeParams(ZSTD_compressionParameters cParams, ZSTD_frameParameters fParams)\n{\n    ZSTD_parameters params;\n    params.cParams = cParams;\n    params.fParams = fParams;\n    return params;\n}\n\nstatic size_t FUZ_rLogLength(U32* seed, U32 logLength)\n{\n    size_t const lengthMask = ((size_t)1 << logLength) - 1;\n    return (lengthMask+1) + (FUZ_rand(seed) & lengthMask);\n}\n\nstatic size_t FUZ_randomLength(U32* seed, U32 maxLog)\n{\n    U32 const logLength = FUZ_rand(seed) % maxLog;\n    return FUZ_rLogLength(seed, logLength);\n}\n\n#undef CHECK\n#define CHECK(cond, ...) {                                    \\\n    if (cond) {                                               \\\n        DISPLAY(\"Error => \");                                 \\\n        DISPLAY(__VA_ARGS__);                                 \\\n        DISPLAY(\" (seed %u, test nb %u)  \\n\", (unsigned)seed, testNb);  \\\n        goto _output_error;                                   \\\n}   }\n\n#undef CHECK_Z\n#define CHECK_Z(f) {                                          \\\n    size_t const err = f;                                     \\\n    if (ZSTD_isError(err)) {                                  \\\n        DISPLAY(\"Error => %s : %s \",                          \\\n                #f, ZSTD_getErrorName(err));                  \\\n        DISPLAY(\" (seed %u, test nb %u)  \\n\", (unsigned)seed, testNb);  \\\n        goto _output_error;                                   \\\n}   }\n\n\nstatic int fuzzerTests(U32 seed, unsigned nbTests, unsigned startTest, U32 const maxDurationS, double compressibility, int bigTests)\n{\n    static const U32 maxSrcLog = 23;\n    static const U32 maxSampleLog = 22;\n    size_t const srcBufferSize = (size_t)1<<maxSrcLog;\n    size_t const dstBufferSize = (size_t)1<<maxSampleLog;\n    size_t const cBufferSize   = ZSTD_compressBound(dstBufferSize);\n    BYTE* cNoiseBuffer[5];\n    BYTE* const cBuffer = (BYTE*) malloc (cBufferSize);\n    BYTE* const dstBuffer = (BYTE*) malloc (dstBufferSize);\n    BYTE* const mirrorBuffer = (BYTE*) malloc (dstBufferSize);\n    ZSTD_CCtx* const refCtx = ZSTD_createCCtx();\n    ZSTD_CCtx* const ctx = ZSTD_createCCtx();\n    ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n    U32 result = 0;\n    unsigned testNb = 0;\n    U32 coreSeed = seed;\n    UTIL_time_t const startClock = UTIL_getTime();\n    U64 const maxClockSpan = maxDurationS * SEC_TO_MICRO;\n    int const cLevelLimiter = bigTests ? 3 : 2;\n\n    /* allocation */\n    cNoiseBuffer[0] = (BYTE*)malloc (srcBufferSize);\n    cNoiseBuffer[1] = (BYTE*)malloc (srcBufferSize);\n    cNoiseBuffer[2] = (BYTE*)malloc (srcBufferSize);\n    cNoiseBuffer[3] = (BYTE*)malloc (srcBufferSize);\n    cNoiseBuffer[4] = (BYTE*)malloc (srcBufferSize);\n    CHECK (!cNoiseBuffer[0] || !cNoiseBuffer[1] || !cNoiseBuffer[2] || !cNoiseBuffer[3] || !cNoiseBuffer[4]\n           || !dstBuffer || !mirrorBuffer || !cBuffer || !refCtx || !ctx || !dctx,\n           \"Not enough memory, fuzzer tests cancelled\");\n\n    /* Create initial samples */\n    RDG_genBuffer(cNoiseBuffer[0], srcBufferSize, 0.00, 0., coreSeed);    /* pure noise */\n    RDG_genBuffer(cNoiseBuffer[1], srcBufferSize, 0.05, 0., coreSeed);    /* barely compressible */\n    RDG_genBuffer(cNoiseBuffer[2], srcBufferSize, compressibility, 0., coreSeed);\n    RDG_genBuffer(cNoiseBuffer[3], srcBufferSize, 0.95, 0., coreSeed);    /* highly compressible */\n    RDG_genBuffer(cNoiseBuffer[4], srcBufferSize, 1.00, 0., coreSeed);    /* sparse content */\n\n    /* catch up testNb */\n    for (testNb=1; testNb < startTest; testNb++) FUZ_rand(&coreSeed);\n\n    /* main test loop */\n    for ( ; (testNb <= nbTests) || (UTIL_clockSpanMicro(startClock) < maxClockSpan); testNb++ ) {\n        BYTE* srcBuffer;   /* jumping pointer */\n        U32 lseed;\n        size_t sampleSize, maxTestSize, totalTestSize;\n        size_t cSize, totalCSize, totalGenSize;\n        U64 crcOrig;\n        BYTE* sampleBuffer;\n        const BYTE* dict;\n        size_t dictSize;\n\n        /* notification */\n        if (nbTests >= testNb) { DISPLAYUPDATE(2, \"\\r%6u/%6u    \", testNb, nbTests); }\n        else { DISPLAYUPDATE(2, \"\\r%6u          \", testNb); }\n\n        FUZ_rand(&coreSeed);\n        { U32 const prime1 = 2654435761U; lseed = coreSeed ^ prime1; }\n\n        /* srcBuffer selection [0-4] */\n        {   U32 buffNb = FUZ_rand(&lseed) & 0x7F;\n            if (buffNb & 7) buffNb=2;   /* most common : compressible (P) */\n            else {\n                buffNb >>= 3;\n                if (buffNb & 7) {\n                    const U32 tnb[2] = { 1, 3 };   /* barely/highly compressible */\n                    buffNb = tnb[buffNb >> 3];\n                } else {\n                    const U32 tnb[2] = { 0, 4 };   /* not compressible / sparse */\n                    buffNb = tnb[buffNb >> 3];\n            }   }\n            srcBuffer = cNoiseBuffer[buffNb];\n        }\n\n        /* select src segment */\n        sampleSize = FUZ_randomLength(&lseed, maxSampleLog);\n\n        /* create sample buffer (to catch read error with valgrind & sanitizers)  */\n        sampleBuffer = (BYTE*)malloc(sampleSize);\n        CHECK(sampleBuffer==NULL, \"not enough memory for sample buffer\");\n        { size_t const sampleStart = FUZ_rand(&lseed) % (srcBufferSize - sampleSize);\n          memcpy(sampleBuffer, srcBuffer + sampleStart, sampleSize); }\n        crcOrig = XXH64(sampleBuffer, sampleSize, 0);\n\n        /* compression tests */\n        {   int const cLevelPositive = (int)\n                    ( FUZ_rand(&lseed) %\n                     ((U32)ZSTD_maxCLevel() - (FUZ_highbit32((U32)sampleSize) / (U32)cLevelLimiter)) )\n                    + 1;\n            int const cLevel = ((FUZ_rand(&lseed) & 15) == 3) ?\n                             - (int)((FUZ_rand(&lseed) & 7) + 1) :   /* test negative cLevel */\n                             cLevelPositive;\n            DISPLAYLEVEL(5, \"fuzzer t%u: Simple compression test (level %i) \\n\", testNb, cLevel);\n            cSize = ZSTD_compressCCtx(ctx, cBuffer, cBufferSize, sampleBuffer, sampleSize, cLevel);\n            CHECK(ZSTD_isError(cSize), \"ZSTD_compressCCtx failed : %s\", ZSTD_getErrorName(cSize));\n\n            /* compression failure test : too small dest buffer */\n            assert(cSize > 3);\n            {   const size_t missing = (FUZ_rand(&lseed) % (cSize-2)) + 1;\n                const size_t tooSmallSize = cSize - missing;\n                const unsigned endMark = 0x4DC2B1A9;\n                memcpy(dstBuffer+tooSmallSize, &endMark, sizeof(endMark));\n                DISPLAYLEVEL(5, \"fuzzer t%u: compress into too small buffer of size %u (missing %u bytes) \\n\",\n                            testNb, (unsigned)tooSmallSize, (unsigned)missing);\n                { size_t const errorCode = ZSTD_compressCCtx(ctx, dstBuffer, tooSmallSize, sampleBuffer, sampleSize, cLevel);\n                  CHECK(ZSTD_getErrorCode(errorCode) != ZSTD_error_dstSize_tooSmall, \"ZSTD_compressCCtx should have failed ! (buffer too small : %u < %u)\", (unsigned)tooSmallSize, (unsigned)cSize); }\n                { unsigned endCheck; memcpy(&endCheck, dstBuffer+tooSmallSize, sizeof(endCheck));\n                  CHECK(endCheck != endMark, \"ZSTD_compressCCtx : dst buffer overflow  (check.%08X != %08X.mark)\", endCheck, endMark); }\n        }   }\n\n        /* frame header decompression test */\n        {   ZSTD_FrameHeader zfh;\n            CHECK_Z( ZSTD_getFrameHeader(&zfh, cBuffer, cSize) );\n            CHECK(zfh.frameContentSize != sampleSize, \"Frame content size incorrect\");\n        }\n\n        /* Decompressed size test */\n        {   unsigned long long const rSize = ZSTD_findDecompressedSize(cBuffer, cSize);\n            CHECK(rSize != sampleSize, \"decompressed size incorrect\");\n        }\n\n        /* successful decompression test */\n        DISPLAYLEVEL(5, \"fuzzer t%u: simple decompression test \\n\", testNb);\n        {   size_t const margin = (FUZ_rand(&lseed) & 1) ? 0 : (FUZ_rand(&lseed) & 31) + 1;\n            size_t const dSize = ZSTD_decompress(dstBuffer, sampleSize + margin, cBuffer, cSize);\n            CHECK(dSize != sampleSize, \"ZSTD_decompress failed (%s) (srcSize : %u ; cSize : %u)\", ZSTD_getErrorName(dSize), (unsigned)sampleSize, (unsigned)cSize);\n            {   U64 const crcDest = XXH64(dstBuffer, sampleSize, 0);\n                CHECK(crcOrig != crcDest, \"decompression result corrupted (pos %u / %u)\", (unsigned)findDiff(sampleBuffer, dstBuffer, sampleSize), (unsigned)sampleSize);\n        }   }\n\n        free(sampleBuffer);   /* no longer useful after this point */\n\n        /* truncated src decompression test */\n        DISPLAYLEVEL(5, \"fuzzer t%u: decompression of truncated source \\n\", testNb);\n        {   size_t const missing = (FUZ_rand(&lseed) % (cSize-2)) + 1;   /* no problem, as cSize > 4 (frameHeaderSizer) */\n            size_t const tooSmallSize = cSize - missing;\n            void* cBufferTooSmall = malloc(tooSmallSize);   /* valgrind will catch read overflows */\n            CHECK(cBufferTooSmall == NULL, \"not enough memory !\");\n            memcpy(cBufferTooSmall, cBuffer, tooSmallSize);\n            { size_t const errorCode = ZSTD_decompress(dstBuffer, dstBufferSize, cBufferTooSmall, tooSmallSize);\n              CHECK(!ZSTD_isError(errorCode), \"ZSTD_decompress should have failed ! (truncated src buffer)\"); }\n            free(cBufferTooSmall);\n        }\n\n        /* too small dst decompression test */\n        DISPLAYLEVEL(5, \"fuzzer t%u: decompress into too small dst buffer \\n\", testNb);\n        if (sampleSize > 3) {\n            size_t const missing = (FUZ_rand(&lseed) % (sampleSize-2)) + 1;   /* no problem, as cSize > 4 (frameHeaderSizer) */\n            size_t const tooSmallSize = sampleSize - missing;\n            static const BYTE token = 0xA9;\n            dstBuffer[tooSmallSize] = token;\n            { size_t const errorCode = ZSTD_decompress(dstBuffer, tooSmallSize, cBuffer, cSize);\n              CHECK(ZSTD_getErrorCode(errorCode) != ZSTD_error_dstSize_tooSmall, \"ZSTD_decompress should have failed : %u > %u (dst buffer too small)\", (unsigned)errorCode, (unsigned)tooSmallSize); }\n            CHECK(dstBuffer[tooSmallSize] != token, \"ZSTD_decompress : dst buffer overflow\");\n        }\n\n        /* noisy src decompression test */\n        if (cSize > 6) {\n            /* insert noise into src */\n            {   U32 const maxNbBits = FUZ_highbit32((U32)(cSize-4));\n                size_t pos = 4;   /* preserve magic number (too easy to detect) */\n                for (;;) {\n                    /* keep some original src */\n                    {   U32 const nbBits = FUZ_rand(&lseed) % maxNbBits;\n                        size_t const mask = (1<<nbBits) - 1;\n                        size_t const skipLength = FUZ_rand(&lseed) & mask;\n                        pos += skipLength;\n                    }\n                    if (pos >= cSize) break;\n                    /* add noise */\n                    {   U32 const nbBitsCodes = FUZ_rand(&lseed) % maxNbBits;\n                        U32 const nbBits = nbBitsCodes ? nbBitsCodes-1 : 0;\n                        size_t const mask = (1<<nbBits) - 1;\n                        size_t const rNoiseLength = (FUZ_rand(&lseed) & mask) + 1;\n                        size_t const noiseLength = MIN(rNoiseLength, cSize-pos);\n                        size_t const noiseStart = FUZ_rand(&lseed) % (srcBufferSize - noiseLength);\n                        memcpy(cBuffer + pos, srcBuffer + noiseStart, noiseLength);\n                        pos += noiseLength;\n            }   }   }\n\n            /* decompress noisy source */\n            DISPLAYLEVEL(5, \"fuzzer t%u: decompress noisy source \\n\", testNb);\n            {   U32 const endMark = 0xA9B1C3D6;\n                memcpy(dstBuffer+sampleSize, &endMark, 4);\n                {   size_t const decompressResult = ZSTD_decompress(dstBuffer, sampleSize, cBuffer, cSize);\n                    /* result *may* be an unlikely success, but even then, it must strictly respect dst buffer boundaries */\n                    CHECK((!ZSTD_isError(decompressResult)) && (decompressResult>sampleSize),\n                          \"ZSTD_decompress on noisy src : result is too large : %u > %u (dst buffer)\", (unsigned)decompressResult, (unsigned)sampleSize);\n                }\n                {   U32 endCheck; memcpy(&endCheck, dstBuffer+sampleSize, 4);\n                    CHECK(endMark!=endCheck, \"ZSTD_decompress on noisy src : dst buffer overflow\");\n        }   }   }   /* noisy src decompression test */\n\n        /*=====   Bufferless streaming compression test, scattered segments and dictionary   =====*/\n        DISPLAYLEVEL(5, \"fuzzer t%u: Bufferless streaming compression test \\n\", testNb);\n        {   U32 const testLog = FUZ_rand(&lseed) % maxSrcLog;\n            U32 const dictLog = FUZ_rand(&lseed) % maxSrcLog;\n            int const cLevel = (int)(FUZ_rand(&lseed) %\n                                ((U32)ZSTD_maxCLevel() -\n                                 (MAX(testLog, dictLog) / (U32)cLevelLimiter))) +\n                               1;\n            maxTestSize = FUZ_rLogLength(&lseed, testLog);\n            if (maxTestSize >= dstBufferSize) maxTestSize = dstBufferSize-1;\n\n            dictSize = FUZ_rLogLength(&lseed, dictLog);   /* needed also for decompression */\n            dict = srcBuffer + (FUZ_rand(&lseed) % (srcBufferSize - dictSize));\n\n            DISPLAYLEVEL(6, \"fuzzer t%u: Compressing up to <=%u bytes at level %i with dictionary size %u \\n\",\n                            testNb, (unsigned)maxTestSize, cLevel, (unsigned)dictSize);\n\n            if (FUZ_rand(&lseed) & 0xF) {\n                CHECK_Z ( ZSTD_compressBegin_usingDict(refCtx, dict, dictSize, cLevel) );\n            } else {\n                ZSTD_compressionParameters const cPar = ZSTD_getCParams(cLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);\n                ZSTD_frameParameters const fPar = { FUZ_rand(&lseed)&1 /* contentSizeFlag */,\n                                                    !(FUZ_rand(&lseed)&3) /* contentChecksumFlag*/,\n                                                    0 /*NodictID*/ };   /* note : since dictionary is fake, dictIDflag has no impact */\n                ZSTD_parameters const p = FUZ_makeParams(cPar, fPar);\n                CHECK_Z ( ZSTD_compressBegin_advanced(refCtx, dict, dictSize, p, 0) );\n            }\n            CHECK_Z( ZSTD_copyCCtx(ctx, refCtx, 0) );\n        }\n\n        {   U32 const nbChunks = (FUZ_rand(&lseed) & 127) + 2;\n            U32 n;\n            XXH64_state_t xxhState;\n            XXH64_reset(&xxhState, 0);\n            for (totalTestSize=0, cSize=0, n=0 ; n<nbChunks ; n++) {\n                size_t const segmentSize = FUZ_randomLength(&lseed, maxSampleLog);\n                size_t const segmentStart = FUZ_rand(&lseed) % (srcBufferSize - segmentSize);\n\n                if (cBufferSize-cSize < ZSTD_compressBound(segmentSize)) break;   /* avoid invalid dstBufferTooSmall */\n                if (totalTestSize+segmentSize > maxTestSize) break;\n\n                {   size_t const compressResult = ZSTD_compressContinue(ctx, cBuffer+cSize, cBufferSize-cSize, srcBuffer+segmentStart, segmentSize);\n                    CHECK (ZSTD_isError(compressResult), \"multi-segments compression error : %s\", ZSTD_getErrorName(compressResult));\n                    cSize += compressResult;\n                }\n                XXH64_update(&xxhState, srcBuffer+segmentStart, segmentSize);\n                memcpy(mirrorBuffer + totalTestSize, srcBuffer+segmentStart, segmentSize);\n                totalTestSize += segmentSize;\n            }\n\n            {   size_t const flushResult = ZSTD_compressEnd(ctx, cBuffer+cSize, cBufferSize-cSize, NULL, 0);\n                CHECK (ZSTD_isError(flushResult), \"multi-segments epilogue error : %s\", ZSTD_getErrorName(flushResult));\n                cSize += flushResult;\n            }\n            crcOrig = XXH64_digest(&xxhState);\n        }\n\n        /* streaming decompression test */\n        DISPLAYLEVEL(5, \"fuzzer t%u: Bufferless streaming decompression test \\n\", testNb);\n        /* ensure memory requirement is good enough (should always be true) */\n        {   ZSTD_FrameHeader zfh;\n            CHECK( ZSTD_getFrameHeader(&zfh, cBuffer, ZSTD_FRAMEHEADERSIZE_MAX),\n                  \"ZSTD_getFrameHeader(): error retrieving frame information\");\n            {   size_t const roundBuffSize = ZSTD_decodingBufferSize_min(zfh.windowSize, zfh.frameContentSize);\n                CHECK_Z(roundBuffSize);\n                CHECK((roundBuffSize > totalTestSize) && (zfh.frameContentSize!=ZSTD_CONTENTSIZE_UNKNOWN),\n                      \"ZSTD_decodingBufferSize_min() requires more memory (%u) than necessary (%u)\",\n                      (unsigned)roundBuffSize, (unsigned)totalTestSize );\n        }   }\n        if (dictSize<8) dictSize=0, dict=NULL;   /* disable dictionary */\n        CHECK_Z( ZSTD_decompressBegin_usingDict(dctx, dict, dictSize) );\n        totalCSize = 0;\n        totalGenSize = 0;\n        while (totalCSize < cSize) {\n            size_t const inSize = ZSTD_nextSrcSizeToDecompress(dctx);\n            size_t const genSize = ZSTD_decompressContinue(dctx, dstBuffer+totalGenSize, dstBufferSize-totalGenSize, cBuffer+totalCSize, inSize);\n            CHECK (ZSTD_isError(genSize), \"ZSTD_decompressContinue error : %s\", ZSTD_getErrorName(genSize));\n            totalGenSize += genSize;\n            totalCSize += inSize;\n        }\n        CHECK (ZSTD_nextSrcSizeToDecompress(dctx) != 0, \"frame not fully decoded\");\n        CHECK (totalGenSize != totalTestSize, \"streaming decompressed data : wrong size\")\n        CHECK (totalCSize != cSize, \"compressed data should be fully read\")\n        {   U64 const crcDest = XXH64(dstBuffer, totalTestSize, 0);\n            CHECK(crcOrig != crcDest, \"streaming decompressed data corrupted (pos %u / %u)\",\n                (unsigned)findDiff(mirrorBuffer, dstBuffer, totalTestSize), (unsigned)totalTestSize);\n        }\n    }   /* for ( ; (testNb <= nbTests) */\n    DISPLAY(\"\\r%u fuzzer tests completed   \\n\", testNb-1);\n\n_cleanup:\n    ZSTD_freeCCtx(refCtx);\n    ZSTD_freeCCtx(ctx);\n    ZSTD_freeDCtx(dctx);\n    free(cNoiseBuffer[0]);\n    free(cNoiseBuffer[1]);\n    free(cNoiseBuffer[2]);\n    free(cNoiseBuffer[3]);\n    free(cNoiseBuffer[4]);\n    free(cBuffer);\n    free(dstBuffer);\n    free(mirrorBuffer);\n    return (int)result;\n\n_output_error:\n    result = 1;\n    goto _cleanup;\n}\n\n\n/*_*******************************************************\n*  Command line\n*********************************************************/\nstatic int FUZ_usage(const char* programName)\n{\n    DISPLAY( \"Usage :\\n\");\n    DISPLAY( \"      %s [args]\\n\", programName);\n    DISPLAY( \"\\n\");\n    DISPLAY( \"Arguments :\\n\");\n    DISPLAY( \" -i#    : Number of tests (default:%i)\\n\", nbTestsDefault);\n    DISPLAY( \" -T#    : Max duration to run for. Overrides number of tests. (e.g. -T1m or -T60s for one minute)\\n\");\n    DISPLAY( \" -s#    : Select seed (default:prompt user)\\n\");\n    DISPLAY( \" -t#    : Select starting test number (default:0)\\n\");\n    DISPLAY( \" -P#    : Select compressibility in %% (default:%i%%)\\n\", FUZ_compressibility_default);\n    DISPLAY( \" -v     : verbose\\n\");\n    DISPLAY( \" -p     : pause at the end\\n\");\n    DISPLAY( \" -h     : display help and exit\\n\");\n    return 0;\n}\n\n/*! readU32FromChar() :\n    @return : unsigned integer value read from input in `char` format\n    allows and interprets K, KB, KiB, M, MB and MiB suffix.\n    Will also modify `*stringPtr`, advancing it to position where it stopped reading.\n    Note : function result can overflow if digit string > MAX_UINT */\nstatic unsigned readU32FromChar(const char** stringPtr)\n{\n    unsigned result = 0;\n    while ((**stringPtr >='0') && (**stringPtr <='9'))\n        result *= 10, result += (unsigned)(**stringPtr - '0'), (*stringPtr)++ ;\n    if ((**stringPtr=='K') || (**stringPtr=='M')) {\n        result <<= 10;\n        if (**stringPtr=='M') result <<= 10;\n        (*stringPtr)++ ;\n        if (**stringPtr=='i') (*stringPtr)++;\n        if (**stringPtr=='B') (*stringPtr)++;\n    }\n    return result;\n}\n\n/** longCommandWArg() :\n *  check if *stringPtr is the same as longCommand.\n *  If yes, @return 1 and advances *stringPtr to the position which immediately follows longCommand.\n *  @return 0 and doesn't modify *stringPtr otherwise.\n */\nstatic int longCommandWArg(const char** stringPtr, const char* longCommand)\n{\n    size_t const comSize = strlen(longCommand);\n    int const result = !strncmp(*stringPtr, longCommand, comSize);\n    if (result) *stringPtr += comSize;\n    return result;\n}\n\nint main(int argc, const char** argv)\n{\n    U32 seed = 0;\n    int seedset = 0;\n    int argNb;\n    int nbTests = nbTestsDefault;\n    int testNb = 0;\n    int proba = FUZ_compressibility_default;\n    double probfloat;\n    int result = 0;\n    U32 mainPause = 0;\n    U32 maxDuration = 0;\n    int bigTests = 1;\n    int longTests = 0;\n    U32 memTestsOnly = 0;\n    const char* const programName = argv[0];\n\n    /* Check command line */\n    for (argNb=1; argNb<argc; argNb++) {\n        const char* argument = argv[argNb];\n        if(!argument) continue;   /* Protection if argument empty */\n\n        /* Handle commands. Aggregated commands are allowed */\n        if (argument[0]=='-') {\n\n            if (longCommandWArg(&argument, \"--memtest=\")) { memTestsOnly = readU32FromChar(&argument); continue; }\n\n            if (!strcmp(argument, \"--memtest\")) { memTestsOnly=1; continue; }\n            if (!strcmp(argument, \"--no-big-tests\")) { bigTests=0; continue; }\n            if (!strcmp(argument, \"--long-tests\")) { longTests=1; continue; }\n            if (!strcmp(argument, \"--no-long-tests\")) { longTests=0; continue; }\n\n            argument++;\n            while (*argument!=0) {\n                switch(*argument)\n                {\n                case 'h':\n                    return FUZ_usage(programName);\n\n                case 'v':\n                    argument++;\n                    g_displayLevel++;\n                    break;\n\n                case 'q':\n                    argument++;\n                    g_displayLevel--;\n                    break;\n\n                case 'p': /* pause at the end */\n                    argument++;\n                    mainPause = 1;\n                    break;\n\n                case 'i':\n                    argument++; maxDuration = 0;\n                    nbTests = (int)readU32FromChar(&argument);\n                    break;\n\n                case 'T':\n                    argument++;\n                    nbTests = 0;\n                    maxDuration = readU32FromChar(&argument);\n                    if (*argument=='s') argument++;   /* seconds */\n                    if (*argument=='m') maxDuration *= 60, argument++;   /* minutes */\n                    if (*argument=='n') argument++;\n                    break;\n\n                case 's':\n                    argument++;\n                    seedset = 1;\n                    seed = readU32FromChar(&argument);\n                    break;\n\n                case 't':\n                    argument++;\n                    testNb = (int)readU32FromChar(&argument);\n                    break;\n\n                case 'P':   /* compressibility % */\n                    argument++;\n                    proba = (int)readU32FromChar(&argument);\n                    if (proba>100) proba = 100;\n                    break;\n\n                default:\n                    return (FUZ_usage(programName), 1);\n    }   }   }   }   /* for (argNb=1; argNb<argc; argNb++) */\n\n    /* Get Seed */\n    DISPLAY(\"Starting zstd tester (%i-bits, %s)\\n\", (int)(sizeof(size_t)*8), ZSTD_VERSION_STRING);\n\n    if (!seedset) {\n        time_t const t = time(NULL);\n        U32 const h = XXH32(&t, sizeof(t), 1);\n        seed = h % 10000;\n    }\n\n    DISPLAY(\"Seed = %u\\n\", (unsigned)seed);\n    if (proba!=FUZ_compressibility_default) DISPLAY(\"Compressibility : %i%%\\n\", proba);\n\n    probfloat = ((double)proba) / 100;\n\n    if (memTestsOnly) {\n        g_displayLevel = MAX(3, g_displayLevel);\n        return FUZ_mallocTests(seed, probfloat, memTestsOnly);\n    }\n\n    if (nbTests < testNb) nbTests = testNb;\n\n    if (testNb==0) {\n        result = basicUnitTests(0, probfloat);  /* constant seed for predictability */\n\n        if (!result && longTests) {\n            result = longUnitTests(0, probfloat);\n        }\n    }\n    if (!result)\n        result = fuzzerTests(seed, (unsigned)nbTests, (unsigned)testNb, maxDuration, ((double)proba) / 100, bigTests);\n    if (mainPause) {\n        int unused;\n        DISPLAY(\"Press Enter \\n\");\n        unused = getchar();\n        (void)unused;\n    }\n    return result;\n}\n"
  },
  {
    "path": "tests/golden-compression/PR-3517-block-splitter-corruption-test",
    "content": "0000000100114101031400000000100114101031400000000100114101031400000000000010011410103010020121000400200110101112112102133020000130103110012004100203000040200001001120000100200220000001202001111101010121201010115010002004010100021001100001002200200200002000021103020301001031103100200120120401601420000022200210000200020030000111004001320100000010210501040020011000022180110010010111010000101210222001101622115033001000000210106101231050027330001200310010000011200000012012000202201020204130040032100010110224022000002410100400411010001021200194014130103103011101000000101121001500021000220220410001000101200000000300010000000000000010041210010040100000000010011410000000000001000140030100000000100114100000001000000002111011000020120070438102121110010120002203300000011210130411001200042000000201000030200200300000201000100301100100044101301020104030004101001110001122013101220000402000120030002011012001001211012200011220310111121101413032002021103001260010000025020001010200100310100120000122010412122601003110231311101000301100400120141310001000301120002002303131232220030004050000400131321003114002021115016000120000000100114101031400000000100114101031400000000100114101031400000000000010011410103010020121000400200110101112112102133020000130103110012004100203000040200001001120000100200220000001202001111101010121201010115010002004010100021001100001002200200200002000021103020301001031103100200120120401601420000022200210000200020030000111004001320100000010210501040020011000022180110010010111010000101210222001101622115033001000000210106101231050027330001200310010000011200000000210214000032604210003100112020063:0011010142114000240002033310001103010020040011200000000001001141000000001001141010314000000001001141010314000000001001141010314000000000000100114101030100201210004002001101011121121021330200001301031100120041002030000402000010011200001002002200000012020011111010101212010101150100020040101000210011000010022002002000020000211030203010010311031002001201204016014200000000000010011410003101210000120200010100000000100114101031000000000001320210122301100200280100210100400001024100110101311114100010410009014003001601001102030420010130213610410400100215211610402301202020100150120020001011022011133040201001032100000001110200303731612000000010322010100313100470000003223060001030000210001401005111211000001000000000131011120154313132001401000000000000100114101000000010010101202401301021000100000000010011410000000010011410103100000001001100000001001000111010130200110040000000100114101031400000000100114101031400000000100114101031400000000000010011410103010020121000400200110101112112102111120031000000111210004100203000222020011011000011200000000100102001134131000000000000001001141010000000100114101030021105000000303001120200000110000021300007112301010060000000010011410103140000000010011410103140000000000010000000010010000000100114101000000010011410000000100114101031016122300501000000000010011410103140000000010011410103140000000010011410103140000000000001001141010301002012100040020011010111211210213302000013010311001200410020300004020000100112000010020022000000120200111110101012120101011501000200401010002100110000100220020020000200002110302030100103110310020012012040160142000002220021000020002003000011100400132010000001021050104002001100002218011001001011101000010121022200110103201000412000000000100114101050000000000100114101201203101001902021200120000210501000000010000000010011410103140000000100114101031400000000100114101031400000000100114101031400000000000010011410103010020121000400200110101112112102100000020201000020431101111340011103000102200020113030110100101001004003000002000000000000630000102010100000111000004210124131010001011044300010000101000124022201110000110000232100000210106010204260103103200000040212310050002002011311100100007002110040010300000000010011410103140000000010011410103140000000010011410103140000000000001001141010301002012100040020011010111211210213302000013010311001200410020300004020000100112000010020022000000120200111110101012120101011501000200401010002100110000100220020020000200002110302030100103110310020012012040160142000002220021000020002003000011100400132010000001021050104002001100002218011001001011101000010121022200110162211503300100000021010610123105002733000120030000000100114100000001001141010314000000001001141010314000000001001141010314000000000000100114101030100201210004000000000000100113000000010011000000000002300253010021210100212102001020002701000111561100104000052101100202332001200110010230200330500130101002510002011010023102213100000010110101010102030020103200171210142111014220300001310010211110113010300000270010211012103062232442202020000001120100022021028021061202111130001120223010010021110011040101111002103010016110000102000011220001014010010422000120101012100020120104030003020005501101100100080103000010100002500200011022311300135100020121100101010103000000001000015100020003000400013011210300100023010210000010100000001001141010030010042001001141010300000001001141010310000000100114310020012012040160000001000000000112000010020022000000120200111110101012120101011501000200401010002100110000000000000001001000000010011000000010000000001001141010312000310002210000213000000000010032120211011000210200220000001202010105001220013102103015015040111100002412100100000001000211011032140001130022370041101101000101211130023001002013112132110022000130004211132000220646110220020012020011000120000030100711100000000100030110041000000010011410103100000000100114101000000010011410103140000000000010011410103140000000010011410103140000000010011410103140000000000001001141010301002012100040020011010111211210213302000013010311001200410020300004020000100112000010020022000000120200111110101012120101011501000000000010011410103210210110420010011410103000000000000101000000000001001141010300000001001100000000063000010000000100000001001141001;3210041010301101010311110000021110110000000000100114101000000010011410101000000000011113110000000001210043110000000010010000000102103020100000000000001001141010100000020010001141010314000000000010011410103152020000000100110000000100112000000010011400000000011000000000000100114103010290530020300000000000000100114100300201013102200000200000001001141010314000000001001141010314000000001001141010314000000000000100114101030100201210004002001101011121121021330200001301031100120041002030000220003011000000000100000000000000001000000000100110002210003000000000010011410103140000000010011410103140000000010011410103140000000002031001106023000001030100100110000202141300210000811300003305320004000222100212123222010020100100281112561001300210015002201000550601010102421110210101102000000011301020001030060210000537122002300000012230020000500030240000102010100102000000100010033000020000001210112101011011101020000300001000101110000022001300010130000011010040210001004020022020250120111000231160100031010106001012010010201040101200100302001000010401000110000002010020131510000003002222310000060020003601010000100000021001020004000451202001000100205052;03100400100120101020011220001200310020331200022101005302071320000112101220200233120002010031101313123011311050000110020212010402300022113011200110112082311310120322010020104100311100313001003000000010011000000010011410103100000001001032100000032000000010011410103140000000010011410103140000000010011410103140000000000001001141010301002012100040020011010111211210213302000013010311001200410020300004020000100112000010020022000000120200111110101012120101011501000200401010002100110000100220020020000200002110302030100103110310020012012040160430210000402100000001001141000000001001141010314000000001001141010314000000001001141010314000000000000100114101030100201210004002001101011121121021330200001301031100120041002030000402000010011200001002002200000012001103110204101214011230200020101000030002302000111100111000001000000003111201100132110000002002105111003001110020000320011010110000002600100010211040022120000132010031021020140000101051001100000200001110004;1000012201221001010111233012004110010020200011201002022402000020301002112101001302140005203401000000040000001111240000321701270321110001202000100330019000000010100010121000120011100000101141000202000110010114110111000301000100000002020030010000000100000133000120031011110003010001000000020200300100000001000001330001200310111100030100010000000202003001000000010000013300012003101111000301000100000002020030010000000100000133000120031011110003010001000000020200300100000001000001330001200310111100030100010000000202003001000000010000013300012003101111000301000100000002020030010000000100000133000120031011110003010001000000020200300100000000000000100114101031400000000100114101031400000000100114101031400000000000010011410103010020121000400200110101112112102133020000130103110012004100203000040022020000000100114101410103140000000010011410103140000000010011410103140000000000001001141010301002012100040020011010111211210213302000013010311001200410020300004020000100112000010020022000000120200111110101012120101011501000200401010002100110000100220020020000200002110302030100103110310020012012040160142000002220021000020002003000011100400132010000001021050104002001100002218011001001011101000010100001105001000000202002331200020120041300023050130200010000000010011410102100111100011301020103102120002002303100101200220030001010000513100203020000100110013001313020010400001010002000001201413100010003011200020023031312322200300040500004001313210031140020211150160001200000001001141010314000000001001141010314000000001001141010314000000000000100114101030100201210004002001101011121121021330200001301031100120041002030000402000010011200001002002200000012000000010011410103100010000001010115032201010010110230200160100001002111320140201225161200101111011010000012010051101204440111001310234110400120120000024:13000020110400023300301000100101111410111220014302001113003205000201006031012100102010001220020020210011000110300001020161002010000011300302230100300000000203104043100000000100403211110161000200105121012200031100111000102101022001101212130101501003201222222105102101000001010010111201343000102101321120010220110000020000211140000011240000000120001100304122032001101322101004204300000000113100202213011000024021110000020604001002110040300001001140010000000100114101000000001001141010310203040031151110100340001021000000000101000024011000020101010000000100114101031400000000100114101031400000000100114101031400000000000010011410103010020121000400200110101112112102133020000130103110012004100203000040200001001120000100200220000001202001111101010121201010115010002004010100021001100001002200200200002000021103020301001031103100200120022081101015104130012000020582021000010014100002301201300100012040003000000402010400110701020000031200203100010141420100120100116110411100000413110140230143010310041130180500420040201003201000100000060111004100311010022000001003100200003100100220010020101100003200000121111210520200001200002600100022102012601100120103020010000010110230012100000040120030001100210023013019001005001002410001141120001010302515203010201005000210001103100101174004000731021000122322201220100230000112200005000003201304100000121021000000202010000204311011113010000150100000001001141010314000000001005501000000000000100114101031400010120010012000101600201000000010011400000001001000000010011412405101034000030004100202102000000010011402110012100000001001114000000000000000010011410103140000000000001001021011042000101122110100110100000010000100000200250410003010000000000010011410103140000000010011410103140000000010011410103140000000000001001141010301002012100040020011010111211210213302000013010311001200410020300004020000100112000010020022000000120200000000100114101031400000000100114101031400000000100114101031400000000000010011410103010020121000400200110101112112102133020000130103110012004100203000040200001001120000100200220000001202001111101010121201010115010002004010100021001100001002200200200002000021103020301001031103100200120120401601420000022200210000200020030000111004001320100000010210501040020011000022180110010010111010000101210222001101622115033001000000210106101231050027330001200310010000011200415100000030022120312001121100001141212001026191000003000000000010112510011250000000000000001001141010314000000001001141010314000000001001141010314000000000000100114101030100201210004002001101011121121021330200001301031100120041002030000402000010011200001002002200000012020011111010101212010101150100020040101000210011000010022002002000020000211030203010010311031002001201204016014200000222002100002000200000012000100000001001141021100521002000000010011410100002000000000100000000010011410103102210100530207132000201001022100011301423000000012200:30010111201343000000000100114103030141321010000040101211011100000000100000000100114101031200:21013020011000022180101300000001003005001200500013111100042010105320300040100002012112002101010200020111001100313000310001300351210100351002000002001100010000200040122121040121111200100300012010103101301002004200000010000120100401021101110000100610201010010110014331001302121110422000105001700720000011011000000111421010000000001010011210020000000001012003301000110001020100030310000100002112010111030010000401110112200200010000500022102002101031200102010002112002000043001003000450014030100100044103410011010210011000100232010011401102000003321031130400010320001021001100002113620110023610104000100010001100001030111001021002001133002100210023300102410100330010200000010300100010001400010010030241020010000102104000410101000016511110065012200100000022010001121121052020000000000010011410103011110010102001200300010100011021004013000061101020001311002310107121002000120211120411202002010100110620050031001010000001210351111100011312000810300111510030100000303020200010;10001010211035071000102001402011010101524000021111002000100500300300610230000030030000013001000301123210123102032402003300301061660030200220004032300303001000311010001300010010511000000100000112201020022200200210210400013030210020000120310000004000001014101210030130003000111020220130002102410110202000000602001000011001110000400060100020110000000100100090140030016010011020304200101302136104104001002152116104023012020061100101001612012102000011220000021112200200110120;0171210002012010403003011200100012000020140010031000010001501000000010000000000000001001143030010021000713000000001001141010314000000001001141010314000000001001141010314000000000000100114101030100201210004002001101011121121021330200001301031100120041002030000402000010011200001002002200000012020100161201210200000000000100114100000001001141000133250334011000000010000001113010012100000000001001141010223113021010416020000300010000000000010110202010123011000003021042001004000000030020100003000114001220015000120072110010000001000031001311031302000001120010010001031002210140111000030300000012010400000000010020102010100100000010011401000040020011011000030001000300100000203010010200010011410101000000010011410103140120100000600000000100111000000000111111310021011100110001100031002110000002010020131510000003002222310000060020003601010000100000021001020004000451202001000100205052;03100400100120101020011220001200310020331200022101005302071320000112101220200233120002010031101313123011311050000110020212010402300022113011200110112082311310120322010020104100311100313001003000000010011000000010011410103100000001001032100000032000000010011410103140000000010011410103140000000010012402111032103205000201006031012100102010001220020020210011000110300001020161002010000011300302230100300000000203104043100000000100403211110161000200105121012200031100111000102101022001101212130101501003201222222105102101000001010010111201343000102101321120010220110000020000211140000011240000000120001100304122032001101322101004204300000000113100202213011000024021110000020604001002110040300001001140010000000100114101000000001001141010310400000000010021212112020001210010011410103140000000010011410103140000000000001001141010301002012100040020011010111211210213302000013010311001200410020300004020000100112000010020022000000120200111110101012120101011501000200401010002100110000100220020020000200002110302030100103110310020012012040160142000002220021000020002003000011102010132010000001021050104002001100002218011001001011101000010121022200110162211503300100000021010610123105002733000120031001000001120000001201200020220102020413004003210001011022402200000241010040041101000102120019401413010310301110100000010112100150002100022022041000100010120000000030001000000000000001004121001004010000000001001141000000000000100014003010000000010011410110000001130000000011201410103012110000000100114103110001022000000124202000101010110000101000010100000000001650100000001120120022320110010012011310053000100100000001000103941340114000000000000100114101030100201210004002001101011121121021330200001301031100120041002030000220003011000000000100000000000000001000000000100110002210003000000000010011410103140000000010011410103140000000010011410103140000000002031001106023000001030100100110000202141300210000811300003305320004000222100212123222010020100100281112561001300210015002201000550601010102421110210101102000000011301020001030060210000537122002300002000141400203000050101501010111010201122011020336030212010060010201110102112221001007240010103010000000000032033300023131002000102531022101010204001001110011002001000000043001200112110:1130120000110011301003000039000022200012000320000110042030100030130314202110303120001041011;1040101150210001014002120010011020000001341181012610120502120021011332110300300603131010011200012030201310012002000001502020010010021010200010020521010100251022021010032030100004342001330201611000310000520002100000502011000113501201250400000020102011013000000001001141013330003211106114000033131001221230013110201413100010003203010000430110102121301224214101121101001010003002201101101000032011101013020011000000000100114101031400000000100114101031400000000100114101031400000000000010011410103010020121000400200110101112112102133020000130103110012004100203000040200001001120000100200220000001202001111101010121201010115010002004010100021001100001002200200200002000021103020301001031103100200120120401601420000022200210000200020030000111004001320100000010210501040020011000022180110010010111010000101210222001101622115033001000000210106101231050027330001200310010000011200000012012000202201020204130041001010100000001001141111110002001010002110200110060020001100000100100110500140034010001212521001015020111010000052020110413010020520011001000100110011110003212431200122020000110002002021110012220020024000010541201221200102111240001220000216002212140000016150011021000013501200002000314601000001210300210320331200100000000000100202001000100205020000700141400000000100102004201110110000000000030004100203002020403000010011102101000000000100114101031021000102012101013021361041040012101210025020040201000001102035013220121000019402052218010102000700221000002011013000212000000001001141010314000000001001141010314000000001001141010314000000000000100114101030100201210004002001101011121121021330200001301031100120041002030000402000010011200001002002200000012020011111010101212010101150200001142201010103001000210150052111113100120002100330247051200520001010320200110000702031103001120000001010110027000023031010002000120322000101101010400231111026100010200010020252450212120002001002:501211011001100001102201101404030000031020010210000:8320008000020000010110202150042110121423131100020062512102113051002000310220001305313002121020011000350401020010033311111402310030041503305001057002116021002012121102001002001100210301000001102101141113009001110102301040210000000100112231010213000300202040300001001110210100000000010011410103102100010201210101302136104104001210121002502004020100000110203501322012100001940205221801010200070022100000201101300021200000000100114101031400000000100114101031400000000100114101031400000000000010011410103010020121000400200110101112112102133020000130103110012004100203000040200001001120000100200220000001202001111101010121201010115020000114220101010300100021015005211111311210214000010060011000220100000110203501323031311410101102003102103311120134300010210100201102004000000010010001102520100420002210010020100000000100110210100020011210000010100600200000000203000040200001001101000200000010011410103001200011000100011300012201201100000100000113200121010000000031000049300000130101111503202231133000031201021202110010004110030010011202010210221000420511000010001042081000031102010000030000002110610301030400133010621010005110112130002200000101100430100312000003310231003111001000010001251311001120021311101000400402020030200220310100131000023000003101111000301000100000002020030010000000100000133000120031011110003010001000000020200300100000001000001330001200310111100030100010000000202003001000000010000013300012003101111000301000100000002020030010000000100000133000120031011110003010001000000020200300100000000000000100114101031400000000100114101031400000000100114101031000010020110201040101200100010010323000010000231000000550022102221201002001130200120010010010400210115114200001100200000000104040220004100002002202100231150203210001102002800002010201010012004100203002030100100000000100114101000000001010100020001311002310107121002000120211120411202002010100110620050031001010000001210351111100011312000810300111510030100000303020200010;1000101021103507100010200140201101010152400002111100200010050030030061023000003003000001300100030112321012310203240200330030106166003020022000403230030300100031101000130001001051100000010000104000165010000004001000000010011410310301218102121111100120031010123201000012021011000313103001000070034101601000000210001200201000000016002112000110274173112000200002000012010100200002011211511101200013033021000010700301100010320210131130200100124213105010004200112010020001120010021000001200310111120113100530003215000000101010000000001000100000101110002000000021000000010011410103041002001030011300010220002001501200100000000113001075110120010100010101104102020003512300003200000050004022210010311001200410020300004020000100112000010020022000000120200111110101012120101011501000200401010002100110000100220020020000200002110302030100103110310020012012040160142000002220021000020002301110030040040201010004410121001120001000190010121110011000520001000000010011410000000010013021033001130005030000400000000100111111100000000100114100114101031021000000010400000000000100114160330020204700020210200000001003533005202031002003103001111304110000000301034221002000005332000010000010010120200030300212100000010121101200215410203112001402081410010200000062020101211003200460101001202021013000020101006210330100025210151014001300020042204201210200112101000131320602100203100101032002210021003101000010120221121412001004011401002200001001101612322122032100100000102020130002001710112010110031001110210040000111021143111002137000201000001310612131410004030301000010221001020010104111311403010010140100301000100000000000010011410100000000100114101031122200013001001000000010011410104013241100114101031400000000100114101030412102004100203000021103020300000000001100600200011001031100120040000000011000100115151210101000121000120000100050060420101010001051000012100001100001000000200002001100001110132211011000000110000101100310131520010110000012000120141130201105102010020100311111301011010011000304100101100401110001105201000012301011110012010110101001011214302100010021010000215001230300112242100001131100510210012010513003100310010000201101230000033410200100021000020220001001060000000001000000150011201210000001104030036001000100220021001213122002200030153200920021010310000100001041001031410000000001010011210020000000001012003301000110001020100030310000100002112010111030010000401110112200200010000500022102002101031200102010002112002000043001003000450014030100100044103410011010210011000100232010011401102000003321031130400010320001021001100002113620110023610104000100010001100000021130011020000002015003200302011330002010030050000015100000000100141000011111111100200010500000100000020001100010011201100000021012371014200000100000012411101030110001018010014010000204210103301201502512111401141231412201000200300101101201901000312000123420020621000300001333020070111140100720100501011211100010420000034000021210001113130302070215300203031020130003001110100111010210400000001001510413001200001030000003130010020200001101400121051010213100020010012313003101270018000000000010401101001111100031140001212102100002300120210030230400000011401011010200020000000400110101020030101210200200000001120001001111203230000000100114101031400000000100114101031400000000100114101031400000000000010011410103010020121000400200110101112110000001110001101111001310002310101310720212101110003065100020131100101532010221250012000110701011030020133400020010000003702210300012120000100000023010300030102010000000000051710217010011010001103102000102100100203300011100601001102001310001110100312142101010120001000111210102020403400600001010110000010050001011015061100001000312400401030002111100010000000010000400050000002210310004000010213100441000310010302110100200102001002100101320010032002223170011121413102101011001010231020521:101131101110301001001011000100103110100401210020211033100000040200001001120000100200220000001202001111101010121201010115010002004010100021001100001002200200200002000021103020301001031103100200120120401601420000022200210000200020030000111004001320100000100000002020030003100000001021000102012101013021361041040012101210025020040201000001102035013220121000019402052218010102000700221000002011013000212000000001001141010314000000001001141010314000000001001141010314000000000000100114101030100201210004002001101011121121021330200001301031100120041002030000402000010011200001002002200000012020011111010101212010101150200001142201010103001000210150052111113112102140000100600033700120100114230201110120030000111004001320100000100000002020030003100000001021000102012101013021361041040012101210025020040201000001102035013220121000019402052218010102000700221000002011013000212000000001001141010314000000001001141010314000000001001141010314000000000000100114101030100201210004002001101011121121021330200001301031100120041002030000402000010011200001002002200000012020011111010101212010101150200001142201010103001000210150052111113112102140000100600033700120100114230201110120030000111004001320100000100000002020030003100110020100010222151011001200401030010002101601029111322230132001112102000021010050100101005000212010002433101600231010114000005001010100100020022100106143141100001002211011010111211020021000400010003522011000102201232101030061506231020411422100000201101010111010201100000101040020011000022180110010010111010000101210222001101622115033001000000210106101231050027330001200310010000011200000000210214000032604210003100112020063:001101014211400024000203331000110301002004001120000000000100114100000000100114101031400000000100114101031400000000100114101031400000000000010011410103010020121000400200110101112112102133020000130103110012004100203000040200001001120000100200000001001141000000020302413010102524204220261120011010112000021411100000021100010100203111210000000020010301000000000324003402301002100410021010000104016000220106011003002100010002320140020311200000000121200210100032010310011440300100601030000300311101001101002303000140010000021100001341001000010270000002108400305003000052200230001203120002200010333000102042204012000100100103010010000112001301401002100114001000000001300100100200003001000001101212101105112013001021400100201104000214001002011040002140010020110400021400100201104000214001002011040002140010020110400021400100201104000214001002011040002140010020110400021400100201104000214001002011040002140010020110400021400100201104000214001002011040002140010020110400021400100201104000214001002011040002140010020110400021400100201104000214001002011040002140010020110400021400100201104000214001002011040002140010020110400021400100201104000214001002011040002140010020110400021400100201104000214001004010001100000000010011410070034101204101214011230200020101000030002302000111100111000001000000003111201100132110000002002105111003001110020000320011010110000002600100010211040022120000132010031021020140000101051001100000200001110004;100001220122100101011123301200411001002020001120100202240200002030100211210100130214000520340100000004000000111124000032170127032111000120200010033001900000001010001012000001001000000010011000000010000000001001141010312000310002210000213000000000010032120211011000210200220000001202010105001220013102103015015040111100002412100100000001000211011032140001130022370041101101000101211130023001002013112132110022000130004211132000220646110220020012020011000120000030100711100000000100030110041000000010011410103100000000100114101000015621021010610031103004000214001002011040002140010020110400021400100201104000214001002011040002140010020110400021400100201104000214001002011040002140010020100000100111021302010010100120311010311002201001001101110022026010010005110001410200000122002002021031025203401000000040000001111240000321701270321110001202000100330019000000010100010120000010010000000100110000000100000000010011410103120003100022100002130000000000100321202110110002102002200000012020101050012200131021030150150401111000024121001000000010002110110321400011300223700411011010001012111300200004300100000620201012110032004601010012020300004020002010402102023130010003140003212030001000302100010430031002011300120120012021310001110011000020100100020001000005010010050000211000300620101020000000020230:013151001004020023000100000123102110213201012000040110001000120010210020222004900400200000000000120021010500030022102412010300000010000201101000000310021101121104000201201000201010030200055011011002001310210001003020010000002140000100110001014001000710111000001000000421101112401100301010103222100300003000010000001001141010310102402262100001004020102001030000004030100100044103410011010210011030106166003020110042030142010000227003200120044011130020211030203010010311031002001201204016014200000222002100002000200000012000100000001001141021100521002000000010011410100002000000000100000000010011410103102210100530207132000201001022100011301423000000012200:30010111201343000000000100114103030141321010000040101211011100000000100000000100114101031200:2101302001100002218010130000000100300500120050001311110004201010532030004010000201211200210101020002011100110031300031000130035121010035100200000203010300000000012020011111010120100010011410115010002004010100021001100001002200200200002000021103020301001031103100200120120401601420000022200210000200020030000111004001320100000010210501040020011000022180110010010111010000101000011050010000002020023312000201200413000230501302000100000000100114101021001111000113010201031021200020023031001012002200300010100005131002030200001001100130013130200104000010100020000012014131000122200110160000001130004041022003201100020300151010000000131000020041020001030000620001001100110420210000000100100000005033000100141000020420400101212001102121220310002010011103021211114010301102112100012010100302011311000110001251100004120012010001000150211004220000110013000240121021023300010200000010313011800100000013:0100620032100210002010315200001101105101110031001013016000011000600008310002121200200100002023123001101102200003002700041611000002210111202000200020031010011011015000002001200020021210320001311100171310020131010020231211101200100020100000110110211040001121301201020120000132000111021206020221011105000030121002000000100122000010201010141001100020002101121010011410200100314110010011110211010004020000000000001102010114303321300020341131200231132000150101000010012000140100021000111227012210040016100004102030002200040111011220103100011410141010314000000001001141010314000000001001141010314000000000000100114101030100201210004002001101011121121021330200001301031100120041002030000402000010011200001002030200110000000001025400103700020000001020050102012102300000001001003101200110110100010011410222001612200020000215000110010000200201031050000246000001220401012000020000320011010110721200030000000500103400014022120010030002122020213000100710030010021105620022001000100114113000201000100411125000000000100200311101100000020030010001031400000000100011013300012003300011100040000000230011010010300010000000202003001000011020028000020211000031001000100310001101100001020210004700020210200000001003533005202031002003103001111304110000000301034221002000005332000010000010010120200030300212100000010121101200215410203112001402081410010200000062020101211003200460101001202021013000020101006210330100025210151014001300020042204201210200112101000131320602100203100101032002210021003101000010120221121412001004011401002200001001101612322122032100100000102020130002001710112010110031000110520102032004123141220100020030010110120190100031200012342002062100030000133302007011114010072010050101121110001042000003400002121000113000100710030000410020300004020030110305401004011001201311021yY1>SCA5kXAA,ool1G(6U3r85JUWlId`))7\\7;9R_h>C^Cp0MFzjBL[ILH|5PtxduF@(mGQcbYI/QB=*Ka]be8Iru6d;P|GJO;yCI3lcDa>BURrJC@<Bc-Lk=s2qoB?OKO6^ywQDTX8U::3>7`o\\QY7Dn\\3T9Cib5-zyyN1}?haH=5Uw`jZ9^3l)kgC.nm5DV=uWlD;H1vHo`oyRZs>:doAg-Rf((Y3N)lBLn_}704C50V?+04O@c3[4MMH39R5gttDBBS4rg0,zbZo|5[>ELApA5PyzXK<LhsMX[C>):kfs>+O.kHO:DK_-haBQYUvEM17;GW9LAYqTT;2okyB8N@mz}ww)j]<bX:cW5RdE7hU9[QwG/8W</K:l\\R{U{OX[|BA;NBOazzK3Ik4D-@7zu_8]Ykqs@U7A:^:3eEtK6,x][SKZP89D0?^qDDnl87D=29j-`,-4Zh?DY37(JKL?\\pIgJSZL|+uL/sYazH)-e14uUf:rU8=He_0<o9QLmaVG3:T.ep6g.X+r|)CWv9f7{XU`RR\\B7L3F`N}-CIljBR1G5IqmoUqM3.22JUaxmr[X{S?X8MaBU+CYaXxc2T/4kHnZdw@O7yF{W`@=PrWkBtNIi}PVrBeuYEc3Y2ny2P1r|*\\;w;c`?E<OT:mX_?PYl_{CxD[,YxaASsGDz:er(4:vZP)^HT[dxYXI8NVz\\{B\\pJ*D=RQuOlcCA6>?f]@*Qb7hOGmz`|0K^.Gtgk4;*2wd`==SA5mc7A40Q`2H9*NLO*6<JcJ])7>iF31b>z:E3:m?<.E;Hi8]vr8?B]jxTxN:1z`:@Ajk6uH_p\\|(uhS)M;hXh4>X2]1Re{htAyDQIO_9}j21e^u@@C7p8\\:0BBnb2z>qA}XTi}oT0OvasVAe:H<@_wkA}-AF=rzoUj?>Wtbf4jRIXG[/WkVX8Ens[(C\\G/e:AYT^<u/+6J;5pWbFL|Dz/6Xo@GWY<rCEk;Nzoq=IpaUF4E<IA<Xi39V9/Y>Yl=8yVU\\QuNkpOhY5..d=>L9t}-_\\ns??.xvQF>/+:=x0o?aYZxvNHJ@M7jaZ02,;I|*?S<JbKG_qw.]ReojYerCc,FS+VOmHYzBji3`=)04UI;];W3Qc32A0<}E{6H3^D>K_K`xmH1e@xWl:?;K9+4)Xt@<7a=2DQm)C]2QG3n=JnY>N1Po-Va0V?<8ElNK>zpz]QSL^=\\h|+8^u<=F)}ZwQDH1]R=p65D4AD<;UGa_ak?G]DuRW=T6R(=*QOkP{ReFH4KiGU*FWTm@:mM<zP|`m?yOgEm6XakuN*[>w+WzEA41NEUe`<?zoKQ)<Y4XfJ|5UB;xb9mCQ8sRKWe?7V_aXzy<t3ne?W1SchZs<2mw6Gbp1_7>:F@LXxL(1,h?:g-a]ZDfbcG33[1{<aU`w_7M8cw5?^FfA4Yis-,Ph->htU_AF=[DP5U=^<G]-q]Ha^U6X>\\:0S_y]e10tivgX=)8Y3tb,D-6=7eQ\\O4e=h,IHaC{S@XmXxJEGG86}cMa:P`[Y=u6aIPRhUX[APlOQ>@M_G0VZ2tJUnIyGUobu6aoqX0H?lFJ3xX8g|[9ZD)De1hlx5:/KYMFRGZ8=GYpK^rm.gno7IJOPH-<Ip02?hLB7]Q_\\sV\\0a=UDYeoK7V@{fqmTQX@Vl\\[cF,W}-@7;9EGai1{ERPNE>>/9kUrkHg=s`<3+?O5,b^=^*LF7uSA71T95FZ7F[17p3tFPO5gZ}I:P3[IQlqEWmbZ=feV@u4M=@^Z0u?KRj=Yk^6_1A5dE\\6gHNs6q*6vx(gb:Ma*j*>jf00A\\v-Xu3x9k}aBqgEYr+M<Oo?2L1Ze7n>QGYU8wFte*WBS*GQ9LJ6lIU@s;RR)7>hsZd:P,3CFk>KL4aSR(<I<mhawuS_YR/]DK=aC9>0q8CjYwJ7|:0b,(+sx2gHOAM|K{;9gIZMd/[3;896\\lF-N_+L7;k[l3`Bq,@caPbEL7Tm<<Ki2eS59d|N4PokKh`,VnmxaqiIC35kgb)d8:79haiiwKZ{XMV{sUW/mAW\\5k5LK1+abdXE@YGjI|>flW1Z\\D7;HX>mB-|KG,6B3UOj}DG?,M`9a`)C-d+cY}7Y[]?96vlkI;53oYjuE_rt3L=RkEK33|:@oGrjxU6Go2<W8acA|gi9G5*ijJr:=;M3A=4_8:l]4,_B]}[785AT6899R99AyU>O|AU/kVDn746tr512t;PGf+[31c.Isa;9RGT9m`P6ptT]|2T>h?d0r*?D<?l6JT0JX6;udyBM(VX\\\\?C)*J(V]3X2h`chMg2:39^Vql3`CG+[DB1L@dpS0<9[Mg:uJe7r{}rizK;VWRdM>P<sn]:K4Rs;-S0WD<U,kFh:9o>FE(N7X3GU:5U}b9DA3aId:H+`GgR*^DhZ<Dq+LFp^z/gm:wV}i/)+gcyz30KWb+BSR*x2wJWWe-8cD;y,B\\=;DY`5?nF8ttg=PN`=KK{jgGOj7f8:DhLABq+vL6hn@w\\AHk2A4uN@n|[g]cDoW=+X+2Gx4<o_rW`ve[Lz>27\\*BoFBxFmu1YDzoilS6uTq0((RGDX;PD/n-1:JnSn[6L7Z)AJ3ADYC/0-49lttAXIwmiCRD,DkF[AG9J_G0z42>m;6@phtaL@.3Jh{YTFQ-Ev2?N8Gi\\QjmFN>p?27.0nc8|6U8<J_04Mgq_SCAn]a|BP>P3D7=:V:)=8PlHK/XFobBT7*h559N@THE>0ET;z8b2Ja.<:@Sd>3ATfQ*GDVu0vW;q(otiAF\\1PSMHmZ3JD<-ZcJW?TD<3B3i`/<<8_qUQ1,=ISY5U?Yn*5}uH9(P{b-0;Vu3YCgS?]2VFE,qvG-QNZ?VEA2Z_)tSrKX[F-U;O<otyOmOE|@>MVW}J[dmTovU3m}>nUG?N{PB)eTW1.[7|b\\<D>pvkSQ-><WWpM0Rl{CLrh,7Zk|J.HgMe28m+u<fVvfC/<|+3Ov[U1Us<ZzQ8oqoROf=D:Qp?BHDKfb3Re:(tz,YI>3;vk^al1YYP{q+*zMbB`9nr_@^ULU1=g8wLsfJ[uK=5s24MM4lWG17iPqfA>19ytDnFPgNi3?/X=3m5?=@^t},+W}8)}+7<ui>xKevl3+]>d;n3RK[m9*h_NIsmIC`D7c-,V{hM7q;TQ9I|:QY`rc.J0a?@u.\\Py47gcbxN1{uE^x]a/Q^Eq^s\\9:fI7G/N_M5\\a{(a|2My-XB\\e;@7B5,5[I?9ijUQD9uDuIKOd1tJkZA>aeNsc:n>Y3/,]QR[`KS@=?TFUfyuk>YJXVQ[Kw4_g7<F*=1[Y2vz2?\\qJMs@0*11:+19KAE33LJugiVGI8<IndP8r<[fkgf|K>Loi|YoK3mPsKV<}?^{??0SUWwWXZNHT5Z^[L0>p2bb,EKb6Ck8Ym{vd9N/7:62;l0CMRC=nICczNh7G._+s[Z`L8D]nH]69K87{<_Kbza-}I6/_p.ikSX1EOH^l7dd_>BOeEEobLmY@>S0qe;F|7sH95>b:07bZeYlevkK[T8Y7C)fk35=\\q;GRJJlV=.97sP\\I3_sJg>5|3g.W+C9n;`xStCs8^_X`w7L:V:qxh99R;IMC;8jHh7]c[A@JWj2/LKG`3BT86zJ=[7YB?UX0=JCUKo>?3>hgWKhT_E91o`{Jmr(^4rqDuBHZ9<19^-hB5wsjS\\]7pwIB11[UU=<@_;hCo7JNNgvHhAs)u_B+_->O87G)quydNrmB+(Q;vv:{go_W;DFTc2nHMk1x5,aE?-8<4,a1v^Q4i?sG_87Ut*=oreaF^8F@NL93P|{TsT4E}:oD)zW>XJCw)k65H09O;o491ETfG69q]il3O0fP\\-xxzQizD6W2>1,UxdtCohNO2G3Q>LC761H-w@WO+Gw9t6AL0/3)4;hJ;N.a.TE|;JlL|-10|AiqI466Qur53dnm^S2v]63fE2k<|_U3G@<-:;>Y3:5(J_ii?XLh0<=hjnXDL8/8BgNPnTgH<j7L;^wzayrP3XZQy}v+m2*V48dTcZ>7iF\\aKNg(PGba7tn9D-LQ)d5KS0LyOK)9:lONjPy^;[3HC-]{||}3Vd\\IARD2/F^Zx.[H(MUKGTsFr@ZNv0?.4;BzhSn5}044u[32X.c:_<u6CSCFRmVL|:Q9o6R*W>Hj|V3P5Ic+Dh5,0|Gp8S90K0;=U<@X,ozSnNJ^F6W7-@\\zAoxXp^p6=47e}N1:1:OMzcs9k}KnJ1@9VqZsbJP?N{ZJAT,oCc8RSP*AtL^9v3ItG>B8CH>0j`|8cz+cy6?4K[9v/n3X6+*sL*dqlBa)AiGQ:9<5PwU(6me\\QGc{v{f@@|4<wM|jC3b0j48:K7Ou(+7L3X=TCMrBaPC|j3tQ4?@6u573M`6uO<rT10rDDtuD.FGTu56H9rL<<LsJ8BJ<GK9WtQ_PaKxA`NNkF=Wr|TFSfS}3=t}3w7/5\\qs<el/rCmkCJgE]l@(4jkjqYRV3W-gug7_<2oM.F1i;,P@hI\\TQ>{Cek=AEhy/wn}fKzSV3>WG}=IH+0>3ST<*1C0YV2B6,4aIPTMndDZX0DTzr_<Y\\x(TiUZHw8.+-_{8zi4(;<Y`2>NkP-[NKP[rqB28?xZkm9UUy;\\1IdGNZ_}vfU^\\0Xarpa=Kq[xUd):8p]hIUENpKM]h4B@A6+cr<?D:5iik)V2K3HhG6:>BK[IPs?jH;=E(qZcmlR5ZGqnpW600e@EM}ysw8B.DFc9IymNa<|vwt3`nL>hjLp1,`O9OtT)jnfYgjux_umqAJ_E2XEC|V33:gu@85M8KJ69+G6Qr:<2nwy@qrI-?DZ?IRimW@BmXk)7^R6SfAfjz]W>{7|vl8w2xGQ54zL9\\M\\1m09H5dYs[BVwREM*895J8@5O;`trE+@4l370AC<26s?^Vna:D@)LHf?Ci{aaoat`YKuiO]xU6_N(<R3ZS)EG.X(mh:W9JlXRv3|qM1<0Pf9{[A^JT?<o6:(82NFBDn65=LH?I4Z\\J0dvT>gV8l1h;K,nmTG13sg]cj^jY7\\+5*iLJ30usO1vea8}1kU;]eSAjj8(I,s9;O7G[q|X9Z74HrXxBR>R5@wLTmIo*@AzV5lK2L9P)N12,PgaEWq-8K6-k9MB>JjDP38q991IicrK[j;4wq)OJO<pjKIdTG}{|59u-OBI0`mQ[h}qRhQ4zd|HH@D(W^ZIC<7<S*/[CJC,SNf(6sQOl@F955]Y0NVg9i-PlrO?e_lF)oL\\S439@FG==*_CuYu>}vWy.<],BnH2q[L[xLyG\\@<:^?e\\@5Msii<2zst6][ql0J`OAm8b;uH<B?:Z1=S\\Axos=gH/6^WMIvP2tzp>N01wy@3Yip8XtXOQjED{vb?F8:_5=Mn7gTW;g2m4\\Ef>oLSbJT\\9L)+Z{Vb[m[yv)tYo:MHjyF<U}EJqGoDiC9],rZ:6<4KqM|BZR@il^7+YPN3?ndsB8m_YyQJEWCz2fD@.Gi7h<|OQB<I{DS958Rk|m;G3pE=^2`23u]Yb60oCKoJ`F2E-<H)U=5NTyKB@e0dn8.lce:y9;0ONC_KVyTYSOiAAO[B7:J=/s=:`Nq0z;|`?s@6,Bp+_-<sQMTI(ir]+v7KGv{QG4RYoBMR={F|g<Rfsl]IkGIRF-.GJuF@Y1]0/fPIR3af`t-nfQsU87Zu(kHPG9u@M;YTr=WUpvM(NtD2GJ|^ki=e/]+S_:2`YgP2uS^1|;hDEw0[xKI@KKWQ\\P3=;Hn^OPOdG7j<jV:0NY^;N8CQG>Y2<NE0f8N>qTwWR3-,5Q75/|_5g,EB>l.Jnk{b9=o4v=^?By?NPNz80@8szWp>R)2E3>2Ut=aN`c9eJW54W7?Egg5YL+5}76*67LX@VC;IX(6ONH3Ot9yz9|Ka5`:gv))C80-<:@a[/jlvqDB4VvEf4Nbr?/3;84genwzAXwT^BJ7^_LCW@SvPX(|io(>As+>9mfR{67NQS3qq|)UK-D04P3mQP)FhM]PU3yN2et78cvmtC[RtN]d@nQ9deJMeQ3LxSKdH6;fGmY-X`gygWQ\\GTnJH3_6X>B`6Z,Jd7KGPX0Fyw>0OI:3YM4FyK0@1UXI-0)7OzbJ+osF/E2A>;el@:DW@pX9h\\5DI2`T3EW3>(8]fn[HH/2D[mRt=}5_BZ{>h3q)]l>15^aW.14\\S9Ej*dGTK=m@G/0=>|<FIPpSd1<yG7:Qn^z=9uIA<XMHQbZ00F2?08cR=PaNPCZjuZCQ<DFAQCk9_O8]*1Kc=*8]6nj14DN7:0-;J}:@hb?WW4)P0e{wlzQev1SEgkW]*Q(TWzcFd4liO?r}}u:=H,5j.8IH4bVo.vs3bh(J0iU?EC_.(|-8aHr@;zRmy1+[JC028a1i|sm5Sb.k(eNWT0yENOaNsU=E22pCw:_DGNS;T2ih*cKtPt4?l89UNMn8=S:R9P6N_Z5}kIYG2i9A`ZmtB0VQ5o]UK{h)4>2VVG2P5?dunIK@9bS6Fk9*DWd8J2W[0;4R\\T1UuD`MDn48cY^4ATubGszv9W\\<zocc9JT4D,*;ATTEc::/<+`]8FWKLDt7lZgZ4|BzjOd>FW\\,(OyDyA12t6w;b]:yqjvA=7=`s;(v-_Khjd5Vf}y.Y`XpHBHbs)bf6LiRbKN<D{(gpG3[7f.A=g{>J3=M:@B6mubq-wme3VXR;ynwwNK7V;Hw*KUI1vsO^ag038:@?*uh7OqEY>*b.EctjF9cDMC*AD;k^D1fFrc]Fh<ed@4txXf3g:.:`@/BU7Gg3iJXYKvZ:7VW*Hx<d3E5\\MfdKB9(VY=m)OUI1v6zJKo@mU.H8pO*i:FQ1mF3G)T=dNfKx]GIx?YU`{OI;=da8YZPE*PQP1)>?kb?w\\:Euz8v8i/t5<`GV?TY(ZkmWQaqFZ@8CTFECwd@tY[GvVidN8M?veDJ_\\gP<tfIYL*@sjnvHv+{M>d5`<{S4oNnm==TvA5342P*P5BBYv\\ux3l4CKN;Y-J9d8^OAIOg6@T8B0Ejqv{Yk3OS.GAvbb2,9j.4WxzYMJI\\D@P/xSk-82hsQ6l?9|IxUGiPPZ8U?t@U}mbU>}T2CIKbsRi0eJ4sq837<(5EFk=09fJ`}E:c@McGgE0B]s|aEpBm3uD/uE@{4T2g8TL7w-51>Z^8hVjvn?Q,qx@8ApecIjj|Ux>GM/^dac:,\\lPGTR*SWE8=i>f4u>T2\\].t4GJ}C8ZqbH]OmbFAM9ZpcF3:*O;LWjA6RrB{prDvWvaUPk\\pk5S)^P0e[y[LJ(JE66ek0h[2Ydh5VH:EH;]J<@4.cu1MJ6Aq74o]GEUW;9ef[HZyxioI>T5lJ_\\Xx])]k2c<(Af,7Em70M]*TdB*V9<rB;e;N.}73-T-^uT.m,VomZ/HKD-Qrh|AU3r58{NnuH7`/d3/O-f@:BG08,+yLDoNh*Z)1wX7f9Rf4(NvC0d<Se:Zi0}Q1?9<D/AUG@WYb{AsFXmOg6i1jbIZ(BT/*q-YG)Dj5a5db6IbA4{1ku>?N^hy-JWU56f*]hq0OX8Hu[;7X55b3=4sI)>FeS?M5Clc63FvzqI_1s@@-SJ@zY7\\3)iUAVWQstaro2xKbT=kb(/Pn}V]CLIac07um+]@Z0kIP0>LOwXnwdJ1AxMOTM6yrQ|VfojR2LP@mkD*m_ua9VtS>o`=(38_QE2Vz9NA-m2Z/-7c];1{oX^:K\\)zv38ZcV]R8-4H4ZmQOIdyN/gDIudx{4R`6C?:|D6)G<NxkDK:u:(L3udC5=2kC2ZT1p^ikq:VeY9{7]T`(eHE`Tb]B`H[9O0u}/4=6dBoQp>[OlJo.pb9I=ED6z/LVK:`Z|D_AmyC[.l|:49D1Lx7Y[2p^_aK^Hr0xaTZ|N]ju3JY6*|]2@BK90stUqo]16I;r_x7QbY<I8^9=VO.1\\k<ZH(;mW5Zt1nVGwBL19ek|\\jR^r|EU<@=IpR{4eC7]l@d3-;b/UY[1}G^/^^W*X0g?[{?YNJ4P)C+:]]:\\fK[PV3XPEB8_|Q?Q0:j^VroMr\\zsRx;8L960SF9=oUCyEJRV=>DbXe5D731Dk8*mD0Lg\\u5KHGfU`MQcu=\\3;5-BP`i};KX+]@HL_UysX2]J,7|G4-TxTG[P.O|i)x,r.,9++70LLk5[|4xS[FxNPn2k1OtKV\\tP(nC^w>vUyr>9Vr7IWKG87{DmBVC?x}cBqF=5nrq_H(R4D3cRS3oRu|YhTSI>L:T>0*]gJ;P*=ab+-t:[jKo_e[TqY+eF?^F0A/GBSWDGBhfxm]`l9t>(cEC?8`0x8<jZRJFkEu6Bg7n;kR0k,Y}Y_\\68XdB42rNzQnOL,B{SBowTC;EJu:lURG7>fIZ>fJF9+qyGv2PC;=LWU@1/+ysSA={wDUb}=A8827-YTPBF+Pl<a[DV2D0/_GwIi64B3gJ?UB4d(u^@J{Sw}]5RsD4[G*@drB>X?lSZ6PUN/7l-4W=]`c]VVNI\\G9Hl]|)A4KwJXv]BW/B7T<k]L>8hn@hbhJd=8;`3[WC=GXXwomM=GuW1_Qqh:v<Am2Lw>2v[1jB|NEj2SQCN(neGX[1?]BINy69ZIJEsFjj1NRxb]4DT+p5b07uN*u,@y=)@lofC_0Kr@LoTG>?SsBDWXbsFS5+.{Fv7vGs?K>C=v`ITTGH)Epv83Yc(kR_Ia2,OFJV>92yz>DQXgjaZNFL|<bL\\Z=62Jr14pF-g46L7MC@DUW];eQ9@<\\5:^P_FH)U\\c+sgP@,GRfX19oyE64GYO4F2F?[Q<4GTzd89ZQ66wYCLx`IoG6>Uv=744|3K9qE|{3UPUHFHkDC|Iz?fB|H_wss-85HUhJq_DQI>8^eQn1GrFb9<q)oRh3KVI-`1w-Z*rQ@Tc`p;1Tw_eZ,*cWQ=S-8(UWZU;zb.C6S(\\]=I@gO2_kWmt}p8W_SjK9opz_Ql553HRAANMN>y}t2?VX_DLQNpkP8KEa-[CAUU|AgO3Ex.OV@\\41d3I9+TaHL^mtbyKBJ3t*=uM\\DS\\@<E[iID6=\\0Oy|2TB3tf+e<M;VNT?>LI@}l5Z>NH14;kNJ54NuIoS4N1C?uFRRr[o98bB8zRK3ueClJa,:4?OCrghBq1AyWcn8?<z;dqe1zdHi<yu9C=P\\?^]oK{M{B04|N]c_}r^H]C/36eG[Jt0]J3_,;NSaO9moc[EBm42/N2v0;Ha@yL,Q18lqQGBqUcJU>XGOoo?s_7P8_IGE04lbn1)xHk[pJ8S<hw4B,Lx^)^Q^RZioGUmd60P)bQ)6GiG8I<:7|Qg[`.9p`s?6Ml217-|vBdR;W2bo_TRc?NbB2B2Q;rh3>ZwD_2F>mJ5=6rx`\\FDnEV}el64y77-=9dY5^r;i-q`Oi7-L5x=ZG:*Cpx]/f0NQh[l5BSrVQ.v|@^M9psf0,V?byy_:j61pDkYyLX*OrI>HxdA84d>*]4_3HNBwSGEM_-bA:EMt)qB=ePOZV.bbGmCesNEN\\uVwX/InnrXI-beaF]e25SJF7l+5BBYYG?AW>kg7;h)zKZf1V9?SJ-_]3V(>=gdZA2411D)UATA2;yKM/c<VC-RH\\DFaTVs-K<XNo]3]Rp[KOiEw?7ZyL;ZCvS(2SA`J=@L0930_a|X5=b;m76@GtuH-aP9MXN07I3_6r5>:W^KJ88;|N{(6(G_G}A.NGOaSUcT\\o8E}PPuXR_/ApZ|Wez57ZB?W{W9Q*@/5hX<UqNV1[JZLzH*^l1O(eFEi<bT(I1J_Rr+R4LK>ZHA;,857<.=u}S+kCNPj\\t75-:Q}JPPlA4hG>{lqvFUbT=lYa)2:2\\<Q4irqG283r7M;fSof{{n51V:_Z::iggO;:1h{JI?9V2|H]CSRMY3h\\DWUN\\^OK?TArQFUK?es-=4V](iWfGm\\kc6JKPZ|Ls*e@PrhOONwfcr8VZo]Ex\\6i5D{peyv7B+q)kY<O`CW=z>i+;A=UR>FyHdHI7ibM1M<99\\A5iD;/@rqvw0)<[0Z;4-6O}A}K8GyU0>106eRAW1ulNYRH,e;Yxy3TE1io;Zi0(Z43G.-1?ZW{)*[PX3:?QBD4;jYy7r7<IXJRl=4@F<vT7S12jj=8ejy0QL+F?p:-\\6U>>gRBID`;[LqWl[Fc7s7XJa>1GDg_])+.U-EPaC`qm@ArYX|97C;,3Lhi[CN44*JV{)mBJuU51,:ScOt:3ryPT+@gg8+Ln[70(>;*aY:4S;UvcT1Tz3dKhPh[PUQ[z8J]R{Qjg5kH{534a]{7/coslNSoVqW]3:J5^GEZRjlD:@QW)NOB5iWr1CAS6et9M2-4sgNW0J+4T;j+Zw8)Y/5]IQTV(q7>];8bp`C=)51B?ORLV>;R3YW_3x9Og}5FlCyYOrha?i=2,iB\\2((<DISmiR_3LBWMZ;A?@h8lNN.XK8;b5eZL.|s6Y@A?4J/RxlRdnN[ICp1ElJrnyh_)T;-gqJGY,1YjMhPIAk.t|zn/`D:fOhREQOagFifIH4`p]3RJ736+9ki`]IE,ier^_J5q.0\\H}A)`q1PJej<A*.6WD6?;f77G{bBtD3:3Ner7XJ6j/X|7Z\\F<bUlm4SaNu8Z\\\\=@24HYSId]?VdTLK4k(N>hBC4`BV1INM@b61bCrNuuIbC\\G=`rXG5dAtQDC]*3>l<;(vBu{+*M]JCZCP,24cEN;]_a|{H(]3uOnhwIi@ZqdK8_-bj:)7N9lRb;y<]q*}tZ@D<UtM49t8B4X`xFW|8IP_FL@j.fiI+*e`N)R<*2F@}?.{K1Ov+E>`wJ\\={9{.CU5D9<Z_DuK0V=y|4wOFlepmM3;>-6pa_oE<5oZ,*\\m1KT;s>P;QV1iGn1PXU0U5iWO-K<iYQoL0[@eifX_U^]F7bWzvqGv3+Z+/U0gf_<M(EL9EF9uI5?;D;WIPi1[MHMP;V\\5>lNa{sSFdeBC2F;`Rf9Dw_:jk?;KT-<ewX5K)QN2aXEq-TF9q7Kh^BGNJZ@U+UanzR(3c`tmekm[Ypo(e|XL@Ftf5nY>93V418[I-7LENi3B<8-YP=^p,1z^?nek5o;m(F9qcbhA(h9:fh__);,W)=D1Ee{1>L9@]kzcHNJSjRY5IH/tD48xy]?ILGPgwmOEJF:{{^4VEP4rGZ]eE8?qkR\\?5fki?E)|ZG6}Gh]FmS:e@o8z7.pJ4^N|H9NkPJpy^B==HBOW270\\C9w}`H5UHpJ7A;Qsk^\\2VEn|fD@P94FG7P>N15oLr-*O_a};x[YJ3\\Q-hR=_TVQIxBmSr}+5JT8qsMx@81IH0Q0WA>Ag1*Z}6My@C5<3S-O7mFV61Wg4LNHZcw:i^:0KR]TF8:nLE\\w0D5I7u2}R<N,U{qPT2Xef9Y;LDI*DL:;^HVK3u5HKR1:44nzEvU.+B7OS(ymjRqre\\LkRt1^Xz>=+2d>>f2aa?hF<7PCb@uTMy1S-z?4JI=T4.OTH9`Hd\\0@2aX-ToAhs1P}PI}vtj.G;1F>MPqBrHQPU1/\\gr\\9XAH4K@i1MLX]u=dU\\Zvh4k125A52ZvmHnFZD-kUc@aWaS:8ug??@t`,-<Pm5)eD;}CDz]tpa7D[1rW)xZfh1^rp^owY5lP0WGC7C*HWgO<SQBi]aCfyobU_>=:(j7C-uV\\3KL{_{D-9Gqs0eFK428fvP^S6_=Ou^lIu_RF?OfU+ml>@90?_4xFCG0WwYtDw):E;\\K*CG2ErwF1d`OJNB.1Zg?POfrnl8wgJ3J6(3w@H=D7Jb30Q1quxUxF`b_39v:fOa6hF66K(wFnUp:Xg><LaFm;SCGX50pulDXEAHp[J28oKrXQ6Z39FHR_@tbqvTZYyp8Ej2_0IF)jaivqH\\pR`iIFCG,8QI9_Z:T41=c<={MA0dT\\S|CyP[EpMz9WdC4L\\SBj0j.0WQ9AICNQoRY?C869?G;njODwZ?dABJ`:ZH/U2(7f2MQt<u5,mc|:@r?B6UjY`92teK[?GI<LB8^F2@9)0dwnOmqGHTXh}@N89:+RGxVNbL[P+xX6QS4=IVR8^E>G*_I5=cDKhT.M;SJVrCULD=4PCp+m<Vet=P:1Dlq4CT^GLDN1D:oedbh\\urOT\\kZ:[A3;h`Jaf3msa)UBpg<XSC|]ZaHhk)4R*[6d}>{3yqFgICeE6yQO{zXn_Nx:GH/.SlS`],:Hu:ax>R9kSK>|8OFjA0NQ<W)CA;SEc5i40BUSJ|=P?5>c3yq_2e.18(EjUCSTt4\\:P\\RJU}wGa>l{f=Oc{BG0BhstCkQIotSPG6s-oEOHflLL9EsUwL\\4]IU2HEhBz[f@+ITMK1kwcdP)V6\\_@:9/CW6V4n5z;OpI4M-/cO-.5VeNqE.dd4l^l[3Xc9Ei6\\nt0Df6uV(JBNU5I{hGIJhf@:V-H=[OwtrSQ:h77=J.[(7W?MqcPboHPdzbXU=Im*f_bY?ZR`K`Q\\ofEK=KcZD^28lT7e6lFYJ>*TBWSiJ}4gL_H-0E:xZkBG3957vec_wxr\\Pk]c8U@2yb5b}QwG127KY,9k<Jh:U^?KVMY91[ghcU{C5UXZy^t6w}825ae@Ge?V`YdqE:kQq3Jk?wM\\Myo:y=afPzi0Mc,VA19T1Gu:<H+WJ:hRI0{m6dB[25U:B1Mp`jEVcn3^7ngYn|eTI-2`b1^]Ja*WQ2t-.q;et=KwD0EJ@aPX@C9ZJwDEc\\QXrEo\\)c@2SM]K9]ECNW7kIHaDB.KkLA[xT`RIEpJKKJBBvA>WH6CNp/-WE7CsGA/4<wGPJ3=96k-JEGeYlAQb-hs61@8xOG:uNO*jVOe?QQL4:qP0c_G|J.3ruL:A\\EPJ?c>r){J(E:@o>>:sJ}.k@6v.3c\\GUu\\zmq4:G>\\<pZQ7a1PJ({UU4S?MUHG4l<.id15i@gI.UejfBI5hm;0a81;1oIyhusdj;XR:tPT`ceXsHF]dg2@KO8Yt1a<J]Ap]S-K:UkEKU\\HVHsAmw/GsDL7;U}ea_1>S8ZlD.BT4v(R>m`4Q[Q6/=Q;UDbsGf:=fQH}9YHDOO.E|Hoi^VHJfZ9sPJ;RAWLhXW^\\`iUw0:yDv<rxcX^DuC4a:7jlm=vLMvhitlL^1Hhr2\\d\\h\\@-EzsmIAuJ?8jOC7(I|^Xbhqk0H42`t],8A9q6tyhhq2\\ddGBDPzE\\.|0iJ^<\\\\Lz;NqHi93)Nsa*i4tW]7?K/<Xt88SKeizYQxi]@@>hCVa8?VX|<<w\\?`FS6/48xo^RBjXTr5rZ-*d{?+7dw>ykPM7\\oadyKd4UY9{NVo3NPvJ)ZVEA7N|2JFQ[hQ/g/2p(z\\iv\\rS<Ynf|9(>gootq1<Z9K2:0:m<.3D19@[C7eF7m?-R2}TzI,3FQH}CDPC.1U)SH/{JQEQG2v\\I-|?]cGVI4GE^=0;OHMjIK3?oiXlR>K__zB36(J?@4(@rKIkHY>QCsf_f3v`OXP{q)oLl>.MYHAzsKp1^p>52mWMwYw-.6:g5I39bvWZBjA5D>>P+<-BzJ(LI_^<A8WB]^wy:Iv`q9xZo8_P[fK7G=bFS+R^WH\\zb\\[py;2H63PoPVyn[qWC(>0@UzotQmD7y5;bpiXkOST[9hqVNXy<3};7pG*?oLHn*YIu5Da0s\\tz?GH*;I^)Jf8tcbo_tyMc/+}@MMN;9zZ2=EUT;Mb=0K7[gqaDH^*aa5S8R;)FyBDC+>+)G|cZPB2NC[>\\N6g^;6U4W0u`eo;`;|<M3c6S`IHF]_2:_)IH@LV?n*}_.W5texl<(w7kEydb<:H:_nB]9MI7W:b/dN@O<0GPm<G>s4(M^y^?XisGcczPYc<``o2Me{a,10U<Lv>Lmf29hK|mSJ+afHF:K{SR4X))@bgZD|XtKxgtCi:LJ+2>K<5P49oa28V>05Z0?OeQ]HqL:HBAN6>{hJy@X92Z.LSyAI0,Y4R:UT)}}/{`P;[l4rcP5tz[eNaARVM|</QLPF4lC3E{R,AkO-CU)yZ@P91(eZWgL:IwIcznBvU[6:R7yp^|3qgUHp0yRVCOU}TDm,[iSOT>9,w*}k,i:581MrQJq\\@ipoQi@C2RVcu;\\S[hB\\76Z@X5Y:4Cv)3hZta533|H8V`n)EH3`0,0/9{]XPF6f4I|;xh]?BbpeF(?{E}+pu7F==xMn|SS\\]T6o7NwYNB^3Q964dfULa^VX2WKA->43E6[z@F}UKhWKSjF?WDp7zRf9-4q}6e1fHKNIRH?bX6^Ga.PWFg@XB9sZ_*jVH;BA^=@GTMK:=8cUxh0`H9V>T|DiJH3_4Hj.Dn)>SLF11VH}=b^u}^]e6c[A<XELNo^`GRo2MFM>3W4h}d6QTKf=Ul8NO>+-Z.59c2UQ7<GXABV<J,mwt`1w,l^KUABJm6=iJCtL6>^aD0NVo8+]c/GhM9+8}{\\ciJ@C-wu}ryg7u=k(5D<A00X^M.f|m?6B10JBa_Z1vD7}zB\\gd2a@]KgqZI1,61O*w7ZU{`]v]c:r+NR1;+6/e5;=+M5B?<J<2iP9Y404I0=OgdZ2,Bl2@gV+0QVc=Bv2t8g[xAL30?<A`5e*3q=B=5t}Tjx_sQYaCJ3D@EmC;Kd:afeAFF<x<;IuWL3]ISx0`j}DUkOu/h3@mFIes7LIQ`b.QKcVx?qn;gM`Y<.H0K/2=z=T6@g3LTq-d93ge3GOQA.2U>`_a9fNFC/x8X6+(ZAO<v|bu6;>i_{dOh:XT|M.a|qpgUo<L4Ec=Z={e}{.s`aZ6F}l5kLR45-8ooE*\\?fWkEYyKgXw^@WBE8=e-bPi*D7cM-kVV<uRu@H@bjI\\GB^}h^n{u:B880JdYp7.uA<qWhNbrVuQbjlT::7pbp[7j=zKCM,_}Al5UA9j;n^o?VBF\\itCH1\\BF3jLCnkNAeUToILph2vt78OpjFtf5-R2qkWtII9N<b;p;`?>i<q]BO?Ze3tpwTJ>PZz}0UBcUV<w<bIE70<S4bfr@c3josM5cN-nAC>GhX^dy:<G>dG6sx4urnys{DvgSuM*Fkf6(xg*?w,*Vg5:P1sxi6d8_L|<t;QH7eS33OOKmjpY@S:xYB0+:uY7N8pD.AE=BIyuOV3@4Ur}Hqa],Ze2bg60\\M):H6@C@e`_;zDLz(D_HPbIFoYX,Unn<S4e7.Ntx6|+BlgHb0qB@^J{3pQHEguW:RM:8R4Qziv3KQv08^H([*mx_(i;V9I@-aFlHH:G906[=>Pc4>g;u>l,YWw2Ue=84nbe3V>ok|ce:QmW;mMD;XdE[5*>WjXbOEM<@3FT0pK:\\zIi,?]8JYZ=R]}e}6D7;9/5=SqqlxI32BJ-pa-Hcb9m=]mNdMFvv{2Nyh7t[}R,>^]9s9S8\\kW5K+cZI`,XT;aHn*c2,6P}aN;IxZdW\\YV+D=G^qJ*Zw17QHFNvN.e1i5yX;emNaQ02)EXU;`o6_,cENXM3u@ZFDH]PkN7_T<FzJTb9tAgZ@6{_J4AlXXg`cv?DY0>DgF\\fk9@96T:CHe=5BS3ZmaK@=AZ@Cd1z,@o@]6w95YR@}AEB:OQr|S5jh*.M=YL;}mHJo,c{8O{8?>V9d[:SvHT5WgkaA1`zcn6^:*N,:5Z3=F1G/8tC61:Dc==cl/S`xC;M@58[lKhnDH>Wv<_4]/*t>psED8oP2R=_z})XVi]mrYet,P/YIUXIa7O25?3dd[?XiTG4R`>a_5Gt9_HL<j;rIz]|l=LbE//08ORDL^(9OApVoPNVUrgpFiAjn+hFMCdX[O_IV1U>9rp6dKyaA)Sm?_K;74dN5g9Ky>REy`>IeI}bTP,jHJ>9;bDamHr-g{vFK>tp1Z)x)?BU+\\MXJQHAfi3(Z|UHUoEG]9EkBu4UYrS`FBqwpP0X,2cX25@uehL7xWUR,.0P_=?RM{tg@rW5`\\D+|*m7N02iH1SiX4NJV5DNDM(]ulbeO=l-ABQGOD74N(79Y.>l`J`gL^Tx6Ihc^>HOf=03P2S|_[=E)7/hLk>h3@AvZ09br|E6UtF=nUlAZ*H@>1i}s_Tf@pF2f6XsYalI22H6Kiz8Tm_|FQ)<X_4a?q{[u|\\Em7r?:U83.CYVGOEmEm\\<?qNTdEL^O0UGz:s+54cXd\\CMtde`W=LPT*SdxR^82JBSocKrfuEQ;ZlpL9PnK`uEP`i9C:vYx^B9F450F-0Lj*L6}4Y3mS=A-|}a80w=w>Jj7B-C5P?k42k[}[|M6Gxw@GM.5fZW0FXJ?3(8YmIm*oD|eTz=:24)(RfqnNc?HmhV?@mM]4rX=1FZzJT>3;^UBU=Zl|^5Gx+l04^y0H?sdOI4cxH>;a0tz=c7ylE_9{>tsXTRe\\V|X6@a_r=3_x,@HH\\P?La0CG;Tc*@ED1|Srv@NT3?8GGmJ]L5RAbdTk)*k,qHn^P9n06gA;G]|CywW*FPb|hbv3rOMEr;MLO?0fgr3NF6a7M=l^22WNZLA-_66rR(s3fY[?bt44_H[jkjp:O.7>SAh\\bQ8HVhz=jNCU=5ZuH_\\r6qfrepd>auT:FTIL9mI[/0C5jiZsbD=@q*l0zBd[/xK@A=d?[>5\\U9;f3]cL|<8aGmKz9aoVN8FP);3oCM?Fj5dj18:mr@q<7iqxSQ9.*kwGTRen9kwZ>w<Dz@M_]i-9a|Oa^?4X;MG?K9Vp9q60AKsmXIGHV<O\\[Y;mA6PvmFi>XtLQYmI65(BIyl0pjBk:o[k1f?\\BsF.0W9=ky_rys<7d)@.IJ1ZLlR1iPSQAAR?6jGF?Dz?b0iscU8CO?_X@3CH7JWr8UEuLS.ZxONYp5Wo25d4?]U8R]^i:y5)\\sOPA=4(93>]|@V>:OWa[Qv?X0QxMh(377.Z@S|h[G0IB<)FFb]jy7/|2gN9(Cyz9Sv46uUVV|5hP{WYYHarUkH[n?Dg-c*(}AjG5{_WL?m1|E55{m;cAv19}6.O5a|DmPG>BBsG=AIvms+g`I.Yp6p2eI5N91*(m7CU2P\\{<<:3sNWTkw5z*CVGV|pAU01B<}-6)3PRy?p?Xlc+j1KD,2c/brWF(Q9<;PiP4T?xkBd@8g_KcF3RQTPEOZV@Azl@Gy7;RvN`7bZ1G{TFBU;>O5EiaV7{ZGJmF7m:Y[i5BjJ1_TnuKEb4dhRSQdpg_]F0B:J5AH,qtC,9U9JtlSe791,C?4W8feH6)FktB6uF:o3IX]3Fs0As5JIeyDH9glB-7YUM98/4rvOr4<mEYU>SoHhpB2HDV;04FQnz3BmlEHAAv3Q)G,7nFpHU:>,P^eB+D\\9H08]7U^>6z>yp1yp4+H/AW@?Fr(Syx([L)ExOP\\Uo7uP0Jpc?<)5;2j`U9`OAGDMw9(9^9d4cSago0*1AxPX^a(>E8wHHoZ]VCSOH>2|O|Ihbg6[]8{7x[6;/5_j4HqY\\XaaU;.QZ:*_kbk3*X7PEMRe[>_v;|DEshyE7{jF5T189>Go]1fOB9=[qF<620na1l`=Pa<+:6g_gF^}`[@bqWC3Ij51Qi66R}Tsna}0>P}8jS03VEcc4\\H}oaZ3Pb}2B`fUKaK]Sq>[Fp>|jOeMpATlgd{WI+I=T6>,dL]*adHjj}Qb3mmS2{hWo0krPFmHND>Pt_yIaVP:^HtLb94GrYbk2;Lb)W_)_>)9*+CIFQ=G;<T)E`Huee8,A<>)5SQVLN_1fogX*PR8VOL9y_Ck>`lhy1tY[AI@Rk4R:dF.Rp|0]Y<zBd0v]MJs;*-4@[<7U{=*Es7S}Ks:^:dMEGOrhb[QBq4Cf/[WCu0J{F>4dXyk+ggK/NN-<Zc=0[hN7xJT]?FW>l8^6[|w0zPS|s7)AP9767r@|40Z3Jq7fgZ_Du5mUbN:@x1uZ6m7^lk2mvXW,9MT1b>Y4?4G-U2O1;:z8jp@WV`zOONeBbgjh\\c6R^1Ql21(OUNdSD)FGp}NfC:Z0/|9yKQE\\Y3OQ.sL?v-SDwTjUyL3g=d,7|O]?p8]eX@lng:BEjP8iZsiVbCJkYqf{a^U}vBVo^RFjLBXCyA0dphP`{;IjCeh1@Lm*zaU;foFRZGo>Y0RE,I4V4S5kM2mn9B9GMxKRgkf4/[5h*PPm3PF3EPv5],pVt`RmDS7-X5i?z04=Qu80@Xk`\\Y4l9ca;`<Xr6L1I80V2YFYaLjRj@?).\\5xh}>42]lS`2C:FYR6m.3_[@k}9epwgS<*7m2ia<LOdUZlBqLX4\\TKuiL?Vj:3R*:0uK*x7-Ic<B0o_>Zcor)ON}2oqONY)=W[aTHk|U5(M8HMV1dTIFa5S:672H?iW26GnJ16QNU95\\?RQ0{;r5^pAVSke5:0b<[(2fu7zJk?[b:>GW=BG9:awmW]L/A;h:OY8}KtmY;rFAa`=`iCXtf}dv[?F)3jVK|nR;prVC+K1{O^JCO|c)cCdZU1Ed<hM,F6QXbgbbM.aL-h.k(FQIo;))RH<_LYO)J]J+OFH8PqE]uPHO1}ibNCLF6vI*(DQYJr3S;hj(r^SG{?rIT|cC[fG=cV?{x{9{9)+FOr{>PL14s^]1d>Z;bZLTD;1qy,+ak:8|,\\UKCC1;hqi?qCZ@IBmT3}vQbT1VBozGZU_(:_zc|Vo1AhpMck.2Dxt2:/`vJD<7Gz2EEBhlj-7,qUPJ0sU8mWNEc9H8C:OIYF:<]2W(\\^@3G[Ej_;S]sIDCC[Y4i(sV4Zc_6BOym/rT?oi+=k5>G7{F@`3A.BtO@Uf{AnpU4@-;UJ?4k1<H90AtTg6;a|6PFG0H;+X5Gh8wDzr85.n(1<d}GVYj{e<6{6rc`Aj7Mc@GQAjB*7]<iKcb*4PL82hk4t3H3bVAf9]=*AA-Gc/tU?cUW2;W/w9lhnmj3?q@EehU)GhJ?BxzlQ0gAFl6Bl5\\8ai,I3<<Y+>^TA68)CDBS.hgv5;1^)iv,0_TAH,Rm3h1S]Pf?cFKyFA5i4J;:qBh->.;D`N`3UJQ8N0@oP@bOj<;(y|.oc}rD9wCG4auM-Y__2Kj}_x44>LA7hLTEm;N^heC5]qz0H2vkc3@9Sa282.>1f]F.IH`sq*twl[y3)(;;:WnhH8^{OdX})FH4E2>t^jC]kU32QXYS_L?n_3q5O\\*FnhiRn}7Q3VVWK\\,.K.4zNMIi;A5?Y<<ERo)HLzkW1.sYKnk)aiGL/C{SR44|9>_m6J=T)RXN}hI|g(WR6dSfIp<i1R4G5_L>s/ztxvYM*,XAe4[veGQM-kV88Cz>5qGs_{`6C|ZqrAf>=Ax`.]hK}wjR7l:0mY[>E[|\\F^u_M7jy4.YI*EQ0Q1@OKm7I`KEBiPP>6:hj@4_6}W^iA93`*@)YJ@W;sdb3JHb.ry/F?PrJM:*KH@f){R7Q0BqGV2nwW7QdL/1i2MtpR5G:4rWY6NQNCU^Mz;d{}SQ\\ho[)B<0<})3`8i:k^3F/5:3FVa?Hjud9H}k=r9`dot3:/1@R1/dqcP;@9p<]4AgWy`5^6j]Na8dPygUMc8.N7H\\{5X>rkl8M}PnibQF0mchB5]2jb4_4UbCJPLakq3en?r,K4t9Z{|/=s[Du:Ayj+k^UET,aI2i1QbX*c?u\\:5/5KIeFVTTz41)Sw9+iopxk}?@PVW:`HQg0nnqyb>WP<A1InwZW>>Bbz2U6?cbr7FY20x|H3^,7}8At[H6Q\\KK3iHtc0IhlW1w.xZ3oro]t.-RAo`j/Da91jUw5;l_KH8@m?2eqv2_5-GS7Nud}zdGp>9xC7NT3IJLR>>EYjc`maz<?tR:[;_/myL9/Mg]:k5:F,1?G_gl99I>}Q7Leny/i;jeX][II?9qmKU8_OYi?1*gVk:lB?PwlcH;d)?I9,K]]8e@xDi>P8K?*^?IK:7Dj8D]yEs/(Ji6=3R/15i>6OBRBv]IzC_I^sJ<tAD9|/GypO2Oh6F4?=`S@iL>1>W3YJL*uO9^@d3;18N{el1;23>(yO*d2N5(J2?4klOEO<)7htC8:|*?\\Ua@K8|e\\Bd2K>I)703hB]dGBTKw:L;fUwrT1.;V^>;@nHH90LJ/G\\ZE(@S39Ut}Ia.(/8()bj/G[H5dAVAr2qo{j]>/H0]7hLPDN|\\3[_{Jik@P}GE|Je[G_E9H9^-r6?Gu;>GT5+aIVeG;lb_x,/ng|x@LDC=rRJl0]+l4ijrae`7`q]}EO`fIxT}9O?j?=M@20oRI,U986,WEo>:RS3A|`iLzK=881I88xLXFC]=X75KuoA]1C`f)CJNZtN/e4\\1qDzME7KQ^>=76/Zdy4Lu4XOwBo3RDI\\O@a2eeFjLT0p?7g*VE8-2Re{?ewUCg6luxI2dEA[e_>:f_y<f@6g6<^f]X:P`-/u6.dkRAU>;5pP[obcrB]p>emswNk7gVNF[MB8a\\GyNPzht28mPeK*8@1DJOULD6b=Bg=r7sFvcd@3`o/SFkO6l@}p[Q;5c?Rl,ni4?58bK2vhU9\\Pr)b8hKu^07-9(Xf1rLuT@oF/m2Vy8|[8p_OS.Awh5yX6uA>TxWl8|6UjHc>n]\\;bT3/afm1O{=7+4IBOrcpWSWb:5x)(FoWdxiNk+9EY)b?=+3^@6T(2LEbPE:LZe*d{LBItlT=5x3Z]=b<R6IRIZhM=3E868X+2110rSS;8mI5:_Eq1DmVLK\\P8QG;[=E0-x/zE98/8R\\uI3(FK)7/=^2:aE`?bqNO:?053eRCv1k[{7AEsXq.RHdk,uyq9FpQI;AhTR;sWu0E=RH7Za*18G9b]KcbhjLXjX^4@kl|o9tm77)^s7:DVTw9@PM_M260P6>WiB?3@9OsB]v_(N<^0?GEd5QgBe{g2sh@1a+eJ2,f<R;/5bPY\\VP:>J,N;I}ciJ0[`Y9/h>VgT1\\P=N38>]2cUK;q)HHzMQV{8eN4+Cc@@w*E(e_}ZY[axS5JT19jCaAkLFltPIeoerCb;<)d:);^L?mK2OxPDGH[Laf1z;,M?AL8T-}9d9hJuoH[L*6H|_ZwY:BQIL1C|q^D3uzFIY7HhY7jBR6TvHJuAO(WM]u39dGCFG47@[*32-G+YJ>yR6^X`u2zH}kjVLfh0k=tLL=@\\0QFX@I0t`JL2IL70JW{u*>J{.[WL41TaUH2Fs}JC}\\|^<1avav<QLjU]C==X_eLZx]fnAJ1h.5Sy9j*ksAJQU9k6YR(P+97j7523r-QFU(8B7rSXqa/T>}@plbd;Se<MC[<;L)2a:Ct?:7kVG|Kjvi0AHtV|TLooyG6P4)1WYC0{AcL-oqiUe_bNGpfH_dAg|Nxxr6Te,LA9Gx`X;*;D\\I41B8CnLRN6IE}58N=C_XJS.ZVzc1;V0QPh`f5aBW`*`flbSU`Sy_|xQU:h0p6-3u)uEbjH`*WG9k8aL<H_tI>]6I+R(t2,A:R?=HsVsYy,N>K:<Jc49b]0S<a6xd=wT6UBZ>35[vb=I38.B?TNs4fT{[|@cK,y*8<1JA2`LIN`P7_77Q1nK_Q1d?GuYI)0KX7IhUfE[8GKY`RCK<mEJYDh[6Rk1B8+pBz|,TD3K}VI46;1j>,t;-29=E3s4w)BM)5;RZc4zJl/X{^S?77OXG[7q*-zZ]_>9IIeJrD0e=IC6y)FpVGD3lD5?,CvN}YailZM8Bwu\\J<(:evF9AwhJ9?4Rz;3=4\\V}qML1EFLJDO=Vr|M[qCs@M1(*VT@;csFhxLN<tNJ[zZ](43.,6q=:c7IRyfhgrI592N`jJ04y+|k5JU\\A`+1dRMvM5dU)R=iUAq|2H14b5\\j;_TP^p^v991CSDp3b<H=mae=A-sP>`p4fC1N8<VX9S70.z6*Yf2d3(:>WqM8s/A9Cg34>EKif][5mQ?D{+M[bQ5E,8Lh;HV]QYwBTH>BLSMe`tGI}wsm,Z{XvQjzA(0BR3I*GXQcR8=:kf1TJiT,:)lh@+dnGpt5Nn_uMKAX)bsuxTEG23l*]cSZ6]Wflwh5\\J8|obb-y9@<Y(o8_()sJE|/<EE+?zXfNtt9;;NwbR[R0l0=H5TA4WC6,=|f{^-{0[3,\\Jkyng7.S))>6/Vpbf+kz2E=nF{iQr1S8m?Gw`f0pTA:w7I2-pQ1Sk<V3(EKG8Xe)W<iZnCd21R>v-3WNe]rlZT[HZAAj-68_Yko@w^D;]6;9FwiL1M,1SUUY]6-H^/T=Fmg9{YI1_9vrOGfQ/37l`[2Q9;1v^sHR/:.Z1L/gjc*n@grf761chK?zslB_T6RWF3rn1x36<7wq70y9k9|vbh.Hh?N3uCzx*ud^KIkp9>:/bIlQHX]L>*V4`18,dN4]6S_bHs474C,-5<O*4z/7>]TU9T{<otG8;O2p`_8md0l1]m]m9R<@ww{mTLn;3BepR0rA6U^of8v=1U/ZXC8Ceny?@;;hv?8tOg30^]+k;3LD}CR>Q5fU\\wXMoiD<\\RAAl=IfbyCa7T|(BcAvEgL=QuPq?DF>@-h5jK_ZDDN/}43Bia2HLV6]0555IsQpbk9R79([h@]5d4cnOh>S)5m9}cV3[N|0[h1C5X2wbmM29F?9?z>*NuAG*:aoB\\x28Orkc9h4FSPK?:N9Rm\\K=oPD/>==+8:h^K1E+cXA^:|ej/{HU+l>C=5QMmE-Jl}?J-<N2i5?2rg=Yq;>7Idk:_1I}?8@S=yfHHZjF6NAA4b-|o[z\\eIf:TjI5kY]YR`mtc_Zb:hKZ:P1p6DNQpy==t@7Su9L>{6]639lKja:gH-Qw95]uv_u?^7AW/ZdH?:.H6hZtl2S==M2EYM21L`)qUJI/>XE5H0^EiI2n5BYti+*@uf`kOD6y-u[xPYUkAocz\\?,?43o:bjOT8xDlF{}Gw7tXCMlY>q<HTey>DVC6.mb<s8@GXQBKH=;J:hT[Q[77{ceEtidk|FB}kCa)`rak_ezEM0(e.sQ2C\\t=GwCF(sK=*\\YL4_=C\\VjG7>0@G[mYJbE4u@y6>2*5OAF\\@t,HtO(gN\\45Z1R@1|rWG4TmM8+h;2G:hVAdEs?NEFhmM;GKvlC49L7[jQL<UwFe/@XL/5;G.I18F7h>i(7vIz/eRM0Elz1u=<9NjXj<d}ZVHk(}ksCoC8jx(]_{SVaCWIG[xt;ICm+w^`66Z:-`Q\\rUWMCCL{-<`Wm>-2D,ghST+^bD636ulI=69U0k;P<.r=ZnSinUDFwVZ3Y3:Tgph1i+>fn7ERl_F0/:9F.`rxO}Aa;bTt@8LEao\\/PKqb_xqm[:k0[VkCty;.n-6x;;P-`8PuTwTeKZ1|AA-B7Q@7(Z3IBOp8=+2qiO,4:qMpegU8K;YTAi@?2n2[NmXVZK2EMTm@(r<Hx_A:QE625^=3WcN/x_fA1Z5{m71s+@6/MTWEH2D3/_1j3M@33L6vUXdI*CL7X1[7K(f,Sal-?qRgQTE*>N?LMG?sR-XuI(6:)<F=E=PbH/Z|([HI7v`5n^5?g=QBO@6>XY|RRg:@Fn2{^BD0X@f6Y:31@+)DGS-v9U=|/}8g;6mOKcwpOmaCg9h6XT(==EGr8D^82y4{8k1VaiArJVE4e:i{RX607v^aRG^ux{DmdfIlJ7I4JxE1Ew>LLyC}kOCBJn?:u6,GRduSKJbPqJXDjjn(.AC?bsFgAK4N8xVI\\;=tAtDW\\h^4YPs5RLt|l;vv2S,<Qf=tAV<Fk)WNc(=Y5OY0ITaDqnD6_g^Pt)OxhP[0r`[n0Rl@uSRf?A/piMFe9D8|*.,qO{rAB5.L*J=_5h*EtYt\\gX@O{:vwr^w_7)vn^9i1:_FtfKYrxFECa+l)y<WX`f-p/SS<6cm0k9V3E0n6=LZ9H,fxlg]g=WS|7(OyOHM;*P14?o[N\\HqQ=>0[Hf*H{iBK\\=()6R:Xs[sclw[,-8r=t<WpkCzR;pbUi13t5(?h`DU`=8XH;diD8QBM{F^Vwh1b6ypbpqMYGsKG|+vr8Kr1ebSN+{4<b.>:vih2Fmv1G4>0yF|RAt2>640td{zmO]SDZHgj1Bu2j57Ot1b[F{0m9hV`6h54JpZ9x5k;H:7P\\fCX4uM@:I,S8(l:u)9;[{?\\7e3:[D@IXrHtWtNGW?mS6pjg_`m=Tff]5whxL{v-ID>\\J7:0c0w<X)f9Q2@AITKIYPO^C+9zLt@^8D@H4a8Bp[qYI3P1(;`ma\\ghZw<`DQRCT=??-;r0=u?4w@gSuh0epE}JSxxb<Oh<`wkB;V-ULq0Pv|M>R8UQ*NC4UH@cEGPSm7b_67b|Xts6w0eUL`cf5`FCWSN7AWCY<Q7qSZTqlAm9*4OQcA:[<`QRa(zR2{+[xB4po>=+C4v:GZq@UyTCKmqm0eyS}_JzyKo[}pIYZHa)uI=yG^[?eH/`;m>S0HUs4<]@cJER(6D[1;/j59Ji7\\14B<=^`ZP+k0Si8cT\\I(E`^-Wpl<kKKi2Wdn3tgM3Oy@FA3iSRR5+n1=[C{EY+/ISSuyDQ[zd*W=VB/Oe>Vo5^RA9gjW8;=t4ZKFN{?]]@b@:>bj|vDVzzW=;O)hL6=]bDG;,*LTW[-PvP6M=0@<LV@WM8LH<yx<`AMa{@>)UCDG,Cr-oB`M4x_>;8-0h2PJ4a3FV*-gE?T`VC/t)uqL`8YV9A?aOO8?O@|{p[h7H_/I930[Kp?Sz193Kaf^+X,2ewHz\\d,s7(/C<sS?A\\71rhbYw{dTdL,K;4Gk\\HFBnh-2Az?c=/=\\=U5efXtrXvl[V6=SB_?{mZZ@T\\Wo|ic:*4XdGpVAWNMDH8[ZS64@4alP]D@n,i5xtZY977:;)}q8P@.N2dH<C(Y3=k)G49HoN,7lkIE77uOD6aCvY>6Ie4Sp>[]-ZeyjGSPwhk|^}X)gPT\\<@R0<+g59T_QLmJI9`1F@VDR:1b?q}6|^8^YL>h6x(sF9HMC<i.CV}kJhuF75Ra]^DcA0s4/Se/|7Mi5?ZT66:9c>,dBAT6RFt23AWnu|19Bbj]kNR0jmJt2;p99LRvI0)jHE=gTS04QjMBY9P3}6^.=>Q:@^=_aeqK]|j-BHKDAtoUIb/@,<QmPV7Vc)DRiYpn9>U97PP7XH4RD]qp^6foU{cuI87^B;4VvcPD?rUnO@v]X1a[A^[oeevY|AqTLVADA2AT`mKonwCEf9)JM/|oEUO[{YsmltKx5E}SEA_HJ+x3D>Q/7]n.@w\\v8CS9(Dr*`XFl+EtL=1snH<FvMOs{Z3yN9HS1mkXPF7ZDsN</SBMtF3zP98T=(B01KZBSPY]JeZ0>xs|5f(oaXT0cFdBq]Qfn9KBV(s[2GZ13Blws00G=KU7WVjQX5U_bp6srgcgGq3+RNK,94X3ODZK4\\;B8MI+w:CM*m=8.RJ23S|lGR?C4XQdIveb3WDhhj=Cdvs{x75*J,lO_MD@24;svGD.w)m+_XFUx`cjJq(<x*`UM1BjQGLoQ+EDWfrHnE1dR\\H7K*mM7-sO*6Oy_0E+`03hBBsZ2R3G>2z.GD.fjb4WF8o(NG<AYi6a5Eq@]I@0]k<>{jg>CV8nTn{Y+g51o/`SU+9d9C=>F@[O@YB;<(85L<u2Mi}_Y,f;|anXVJBWOhxT_0o|6HBk99D;SKs8sB{)Z|Gh27z5->ra}Q9mS})Zsl6<XxOdW@wWf3+8_[<Iu2Ap<3VRvxCH?G\\VzdL?8+vHyfke\\Z8iKp{,MX<7z1Nt/0s*?m=qmD:eHZ7NLISQ+g3?ByL:-a6>hMR,;LP?W>nme-H7Mhm:4):=*s<s9,E([>T;A<xTz6qyQ64e;3S`V\\mQV4L:T4iLE58]93y=Nd5{8.{YtI8]GF{86[ze\\g0`;OMFV[ga1FA,EI0Gm8V)BkIG\\C,278<|ROJX_JGsD`g1O=OLB<>J{?={7rOiZ6OT`3nU1}9A>=UjPMkQVF?5eB9FF7Z5qY*;M:MD6FMPS\\gsS2f*7.4al2SrD;gYzk?|mO=P6T<AI@D[ff0m@]|*p,K-ff;\\XP|bTQvLjGDkh;Ckpb[)7uPXKnpFbX,=(dz=AEK73NDb8.\\:;aW:LVs=5Un=2BSDid3uN@`LZT=@I5A_B(+kma[OYo0ORnTAYyRzcdelHC@1S-Bx:i(?N@9*Z??5>i;nHEaoc6iR0iB5f1}aD|@?3]QpboZaIS0{]T(E.8Q+5?EUdh54A=x1/7O9NiOX_WzQ@yjuN@)4RwTA<72yzQ{9+W^{A;+8@OkJgpudRmg4zK|n2R)PHWBYDv\\R_m8>DYUCiLP]U5sIik^,Ltj+6p_LZ57l<Bem.JtXw>4Yf98mB^Yz+WrPYre4qLR]kSul\\WMiP54\\ZE1sBbS]J3RdIH.3bs1afinmP*_G<L=O6,BcEsI5QNtOfSkH?5hy6G:LR;\\IUhXyAV4z,Ve)-^K:CI@1u5YG|j.4U._Me[gzZrxckJo0PW=T_Wtq5]>ld=.pGRlD.RR2O+ei0;7>hK5P=MH2Z9*)?]oN8,>/xtMM6C[aFyPg81KNP8TkCZ](D6pY)3z+3QW=>PcV3DCk4>d(s2:^JDZ4:rB1WH70X?8uUZ:O*3RP=B|NSAutdIEJoIz0`GD3xrdqKh]d+7H/3zC/H>MrE1Z@d8KTra0Zen28wM2}l3Ha0-F-|/Gpr`P7I0bRB\\5LRX1)6gRm-M1v4py`?Gai6=Cp[1L|Ip;r:K9LjQ7,NPPJ:+M43E<*MQ9iKdv30\\ducMnU(WC44h|mxYJQSV=1Ev<LT/Q=ABQuzc(DSDi4g<*1s8</?;oc0HNWD9KY0Vv@F:C<I>:o^;Tcn*Uq.[fv:AB[0D^S*8o1W0HV``poR*dAC^SC[F01dZd@X5Cjt1kSRGmR4JFCh09rTKa84Tuwp`1F-Ch[tI7xa1rvi}/p*0@[M<;6>X`G@Q4*d<JNc@k2H4ZL:9e-F:7L?pEZeDx2:X1j}yQl3rwFN2YS\\?UThaPSy|[,e];4,]0VA6;s2*r{x1*Y[T?hTfd>JMf*GD=OBCD?0hQ5H|oz;9^1eUa9UWK2i8;7cICA@dEnr`KLSW]{6H:<[;iOyLa`mywCG7fp*Q?,sJ;tep3B6;>e3?9EFPeN\\76^>6poVL_I17E6m:|H0b|Ag<eH(4HO.YZ2j0FFP+a{4bJ6\\0pltdwSAwc2m64J=)||8-y,pIGL0}gz_0VefGB47kC_VWYa6su;>x,Fb7(7JL307d}/P8_a<fO5ExNsJs5CLAbBDFh,:285Teai\\u<5<O_wV2A]7=5c{Dy8{lICNP4lQu>[U..M|kFisy;brh@69dDFKI@RtGb[B=ziG0*f;(|@{m1\\`]9ij/=NnY5rxS8ZqJeoM7JT4EqkDsrw_[SVM\\GSnMAnF__Bjf--0fJ3E1{u09FC;:sYD6J?3nN/Pb^_|[+BhwP}zq9IZ;vsDM8;w[Y@F[5EEdHTZ-}GfGk6iTp*A<Zj}`|>7FF-k?,Y4lAaG4i><{RyO1G+E8Mf@U2G2=8Bmtt<0:=BLN7|\\J]25*TOa.^?ha]5=|jO)\\x466M_9OxN3El@<c6CkIY\\qGC;p9Xi*3Tj?_5YTxUa??I/MC^62Sz4g/1=*Z;[Svf97@j3s\\i=fIkk8=R7ZxCknndfg`DF7z./]T31iX<DS,wC^@/kb2Ul6Yy@HPH)IjH:t7)y(1fEA[0+{3TTE+lgur<Wd?PUUl6gN61Q;:4QX6>,6L;(d9]j`pQC4u]B7qc6nCDhxO^FR/:VNCC)A?-S^HzcAwhzbBC3?s?PWbW@|JJ=hmF5L=6A/{dsgguThuf>98[M5s}p]2SK|<D@/(C6_DBWEt.X2i[i8t;(n}KA,sXt`pg))CJ4Ueh>2?kAN1*]0y-g78PqE+@mfo,2I1^3|?g2lU-S<NH3B?aN>cH/O\\kW4`688^MB_M@|-=9P6pqK[K7?@fCvPn>Fg5r4DjQi>leSyes69NeZru7^G5_0=XT0?\\7[CNQSmkZRweBM>dVEv?;qZNTVB:;`<R{HOaMl?2AQR:=S;5cfb\\<=5gDR>|<K>_xw1h1j@E4sq29Jf11.^25nI>R\\@RG99X>GH4?].j9fb(RQ`BK|ZUO[`]?0)4YLFFrA=g*mPd.>;POabnZgPFSr+,Q9AWsG;D2.fS/(ISCLDS(?4aFApDI<Ff8}sXYk6H>Fo26ENs<YZlH<AXS5Wd4Jk7RV6hol{lxxhJf:X(Ad-,-YMoRUzslB+A+pKp2Tx|KmombkSTF0IbD[jZX6i95BKTB4_sXwUq2>BWE=f:{2<4C7_]k*+<=YgF1,a0jQc^`ADTE?A4uSdKQe8.|Ii|AZB,Y>3R-6gqFD5r_}zBc@dv_^MswRwn;rUZy<CzemTa7pS)IXMJI-P+aVi?LvMyg3D=vqnHV.={pnaR/GiWqnvf[47_6?yt^0DemG[peqm|BneeDlscd)9@1p6[+d__fZBu?ym_4>iO}T3j[<(1V>||oW7iv0{4QSKPC|>fi`<PoDB*:pG2jIbh2[s-?>9Sn30r98Nl0ZCOn-J68SK{C_e]EpB16(3t_PF2i-GV2RQUQV_vr([jsGht63=4?EFXfM=_AP0LZf3.z=jyAslSEv;BIgm`>39Z0nj5V@pwW1QS15^^f;HZ@*_o:slB?bk:BeoqJSE4Wd[[W3X6JTXQ5flJ8PWWNI9v}p2u7*E2bf=Ns6aI67Fc5mbE/x4MaF@OJurWYK|D>lGq2k<2J]H[l@b2kBEz90mAU1N0BwJ:]<k2X)7rIjJh3>P<`752`a[*I]w73VSv,jNWJEG3mYHL6WG{x;vL^vlvr)8OX91BMyHXhb?<iQk](Q3OelTa*sTS8eFnb1_485atODF*YrgOmUUkAFvm9KVqWan)x8Zr-?BxDVuUMZQqec1H.u;HRPY*7M,*28]j[`Cy=@{7/gYaDe6l?C<U@Fq4ZRPC_7._.wo3s@sQYMYDe@1mNmaAumNI@GRs?:5BH8_DQ<Y=L_vt|jyC\\HRd8V]h4oDd8wIxXY39_E0Yy.P`]f@n^SzTtE>a0:+4trhVSk[b0C=<3rigx)3Lo80^f5GE<C:eoV7:gMkgSDcYL*qKq51MAZtL);C(eD_VpP`?1wV;1AtA3syp{l,9)3ucJwVeY5[t\\^>YWcoCniKZqMfNGpQWf9vUd3Ez0q=;+D+g5cf87FEcct5zPWrHBEZf^?5VO9<z1|_QPt`s1+xJ2bDr=;3lP.S.8IX{XJkPQz7xRwcVXG0-WBS<)asZ:7F[fM@4m@WGG_3@5Hr7Z3/>=xf4TN<?I?p-1+@`m(.|N0R9<M[N[uT6gtlo0Q}/4/SOBIfOd8>Z/9OQ9IZ6OT5V3lE.y<v08<lNA<E\\:O8B@cq8O5B10c\\uHRSHXNo2P@v1e:QAySYg,qv[(HH7rqFYXbm_HEz`k*lb\\{4=q:d6k*oXKF3mF7uZG{bc<}Xit;pE?T^}=82u9m2NB91pa0\\XGMa72l)+8Lke`Lr?G=S;x^}pOtF\\rt9\\AuG2BW`N-B`CM|IZ{_Jf?tbI}]P613r[6H74RK;]>Rc[^:G4X1SvaOa2OxbeaM4T>OFrO7Xo)+T^3)8:1Y])*u(MCIb4YZoQjI6D/c}e[ZA|d2V^0^BhL{bLb8P>2be>v::_TE1b24b55Ds+??7Rk04IQxdE0I]LcjF;zvYAJQ}_CZj)8K*mX,e;Vrk1Lk@I:cOnjf6x=:D5FEpb<4a*i9\\zz{qXnffTrKR]C;F\\v(qL^(.[6=C;UwFfsGLH^*Fb9Z4J@Z3j(CEab_KW?E30-c-}qY3(s1V-4]{`(3`qvXB>3K\\.._Z_7c8ftZ@;xdFL<q6RcpJORadNZi9ZB;J93;Nwt0w0la+SNe3u3.58^{IIX@jBvCaq)/]F=gsC1L<O4p:II7r49|-}g>0lvuBCZ2rGJ[j;ez/:L?EA]Fj<qLL|9MGJenk]D4^iJZ<5;ie?h)-AHq+VlJQ;;=}y3X}YH6hcq74hZByB350?F3J>?n\\JC(g.4^)|;1yUbd-NAx=;pnGjQ50I6DdYN7VYvmAyOW7FClD9eO2_XX71D<oQqS\\2}dH1|\\9U50?rJerxfcKvvgX;*w`J?{5peW>DsC45GQ(_{Ukg2gLN1>mdgT44iU`*d-Nhn(jw^ny.]C4Nkz4U()Cby4+2rq>;C+lo2tRMP6?TN67AwVLA<2D+Kmd>F>zWRaw3}.9e.tBzC*9Ub>zHQJCAFn*n8jUM.Kd<r]mDs.(=3s2JKK;<.iL7Ex3t<Zo0RqK}GKJlb1O;Gn)6>S8sAR[`nf54QL_77,n^B9F-QU7Jc5Z-2uYkDqdSIC8UbcEgzC(:^@d2U<X<<0:+2sFWcW>WGD8Tp;?exdP;fQd5W=kNKLIoksTk+r`:t5W[*wWY,WA`UZsSWe1<Q7\\|`6o:zY-o7d@A|3BWCN1GhS6RWCM7}fFmZ)sMx0DhnIG{?hCC0+S`Toa>Ld:3`Sr?=F2kHixK7E}vgcnKV^Wk/G1hN,OU8UFdd@i7ZdYi2NQ5O8=3@z+@?_O-:6b6^Jibt>bA<9VPA>55`YxLIQd0;=9?0[`i@A6V<jAIy]m?RCDGI+E)X{:ldYLasiX}EYo2\\W[=J[zg:2AQS:0UyNcIm\\TK);vI1+OBo-eVNpEqEHI<1w=H:6P-OZKkmGX7Nh1)eB[@j{PQA@7y0H22pRS[M`YxpvLiPj*VdL-\\^SgrF4YMPl(KjiEw]0T87hLelCLHo3vB<D^XZC@20sSjs5R8Y93R@a<*2_C<A6^23qKB`lDM]Z|yVFW1`_@szCSIj4Ejy_FR\\y_?gNmA;j>+Kn32GmA`ObN7,AV2UD4fE`fF-@s<YLe7<|lv(?mm9j9A@1zyHT?KfV9@3abfS^Da<HMcG,[Mv^mJ|GiV\\;F/Ssz`/9kA[Nv(GcqXHA/sRftTA9+5:nF/-AguIJKii?44TTOXuZL8vem|jm5`<ja:?d2l<UEyyHp/:SHN8}(M]l}sJd|G152hZB<;Elm9o/Q\\*/Pwl,w8,PuZv4SO3bTUSfKz){ikswwp`bwR`Cpe8^DJ<Ud(UrR0yQ5u4SP-]OXM);L9aFw5._WKIiymQ{H@4L(cu(F*1U^LX_Mulx;^L)6i9:FVK:BK1Nf1CMRK:9Q:l|VpKAS0eY}Q/;JFDR{424a4]P0Z6rRTB1YyRW5XRRHfV[CNMiU>j]9W1kkf8>J9O;f2Se@{;{.K/Dci?7O0WskCw[d0ZxMI[+_w7O.kVM.7:4g8\\Oh2GXF35a:4AzVdTC5+(W?C<AfYIZlSHd)|xZhxe;*ZPw^g80J-}m1VADWL6Mx?TG0p-?ovPFJ4Gj|3uR@LHD}lxNw=AEY`t39grScL?{P4F)6_0UpnBc@@7To4k6cH2\\fz.a:eO/G5rqWj/NrV@,{KH<R=YKj6>:eM8^l67:B(WBg*;F>}5=p|0Utw;{,/@<r\\evn=u1aY+;)WGJEZ*(9FiU7-uL{_B+F1ez@hZ@wl`;ta9Z8Ye:OtS>7\\1;AiT3Ium77@nR<]KrHr=ONhU1O`@+M]_In)/.wmh==BA:b}ixcIa03l-.D<iFu}IkM,zU@_7<`e_S=I(LAzNsnI,0zl^4|p21Z]OD2J6qUU:iW;2)Fkbd?gl\\>9NEFLt1IM6}XI:AIGv4zH1WShV?e`2DIsR9R^dD1V8dAZ|PVKPtM9H5qNaLr9)BR*s{2r_T}/h\\2=UKQZC5K4tUFd<dBS^eGzON|:w?r,xU>7}?;i0u6.9)Y@Qn6|h]D|l>Z+>>o2OQFk>_b`C>I,.u?@laIG2G9++VP[B1;^yL^O<Vs7xNs71J`{)a(EGYP+R\\k]{qNS=UkT=_CnBl4,A3rHoM4=c@D[,/_|QuGW5v8d{D`nc@q.i>JEg__5g2fZGYMK0E48-DI9Lq{?FKOEhH03rC3u2Pd>8|nW^[?HOJL5V*BnM:t?mv1DKh}K0sf6Z13qtC0]6lQ7wgIQ>:7BXjK@B`_I4dL[Xirj@IK<VvI1Bkj1Z-*E6\\]osoo1;1|1E<?-72\\GG`{<_[FOGjQ;5E`7f_Z+bU,lCuUH12v0A2RmN*K86-]-:Ng:}yYQv,lA[{;C`7*no+`u6np=?:fz46`Af2Z>Y7nA1hU2FTI<V`@Ym\\2BPqrO3CMHBf5Vt6OTT::K.wQik+?Ze^hBOMfG2<7(`W`l>(qMWu69,00=KM4cH<x8<b1M[DQ:Z}9<(<BMr>V[igVrF?d:qNf[u-;s4]K/j\\=hH0U4ni_5=2|PhQKsEaKcTg(LJ3/5V;m)m[Va*?JKH7V*Eopf3lUi{8t82N=x7mZN\\7t0xS?<Es*[=@lY)r02FpjFM<7ksV`Qu=e=9y,C<<H.\\mB<V8Ly)=^S}:>i0r;:cZ1upd{XCJV3{L8L*:VVZ=S/WFhHcSITeRD>(B*y^GZwD,lc0^[HkZk`jw0B:AT1dD02q=s2[ZB9nClrz4\\rEp*0/l9Aud/e5M*UA?tk)Re242h\\Z|6I=aDq?>=I?A}7Eu0+u13`;7/Kt=tHOg0=BqMr3zhNDQ0LC:H3kDnA5-S>K)@UsKwf1Y?p1O>dr(<WtFawRGW[ff5TXj=(QZ7oiNhGXp7+/@vjPDBHM3Xr2.?n:|._:ai0T.gLAQN13CRhE7MnQ8s6QbuM.GYJVmCph83dT?lHh8Q4JnnRNrwNw;7Dot}Pr\\EI/G@1epTsp6IFkSDz2xLEO011[N[5-?67X8xFYQ6bw{=IdW4jT>TFN+il4;{T22K5f1rW<MN5o8D]A12,g^4Xkm98qjyVC9ri;;etKZ.oudvehW4EW\\se)H5W;4}3F5s[45=dXc:`|^b)M:+uHObuRQ@D@w\\?P(}mudX.JT?)jad.y4I5qS6j5:TVcb<1JO/+,^WnH5F-@MlBhva7obP*]<gPNHHH?,lu/2S0w*5HU_MM7@UQTOk3A;cr7m}>;H}^w5<VcZGyH4:k=0C@E]i-7T^j@3Aw7.+lW8Tp<*ZG0tfE\\M/9yd<w,bDCE+Ma@x5`5C6uc:;@(vJ:fy-<x`,YGQr,_=j\\DyH4o2.k2U,A9S6>Z+Kz=Ha8inK`LE1cD^rmTP97I3<RY*Et\\7ZAlNCHaF(D3hmrnT2JtJ]d[Bz\\|Y2mk>`F<Bpi2GhHBTh8iQl3rV=GkQ{3FPz?2KAd|XHy3rjtZgy;ewcG56BuHAj1`*ijDPH?AHDg}9AS3+8GK_}RDMj^bJr3nKSO`BMVid0eQWw13Ca7,m6n\\lD2y]=L/c?8F9]1\\d9[I5jln9zz_Q9`d,:*RqQ7y,s<u0x0.kcDgYa_bBQ}{>Zc4cZJDgf8FZF)*`f:xly)<AS\\1L[A9l]<(5/4LvKp`h6uQR^(Go=L6FRznMS6z3l6:n4JPJq<mmViua^MWU\\Dxehh5ar;^e5kJS?J^7M3K4b<;be<B`pLfj2rAghqAm>q5HmFTifGXt6F+KhH5x*WB0fT;(t1o2jO2Xl].iq+>9z9/f>kdl@KUZ;y`R=}R2*e7(.qvz?vIMn+]x(a2+<5PGt*{jlclK(GG92584OzBol@X5AIIp5FBK9=g?8g05p26W3of5+7Ex;[aL.Ao\\xt:9X1P)P:<6oSuJG9p)HO4[I=9CkW}345k3yjG31F<qU,@35oim37g35FT]h)?J,36;;1`0;1^303@\\124J0xfKxwi3/H5l_;jlP*X9I69}insQtI<u|M7Iyi`jmOS;`[=Y*eJZ>d:Ei=)mJU3ttq/Y=8db}Tv8}2t<k\\v=U;HMyfN3cY1qk]eBHA1I2kO*\\.*1>d@@--5p3j/uO9F5{m]]}N;-_H@KSu]T5cj95Sf/BypJ{jsS2(?{7{G]7=9*Y3XVFABlZf?2uWLqUZ(1<3L6}H86oh>C8ksoC0nbGu80-4WhkGmwLW7m9P?D[4II0cw<a:`.Q*uf|lQ={3^9)aWyVD05Av<TKS`/Y?07_6G2Gj/r\\lA/JdZ,sw)(?jXF9CXuaZ<m*+yLSz[WD2Vn:+iC<n<<{HGB{Fkz;q/QI7PPwAGg+1U\\}RuueDO@{/88W.cv2IA8VxofcIH^X?aV^cvaD}hM0*0YUNOO`77}1jI*xO>>C:^R>l:LgY7.0I(.2^0302gfw:LVH}9P15\\;h?Vpj1nl:4LI5Z=j:RHHwd\\M/_7q3EMw=YvD4ls79DOLUT[izOL<4nDW?*:vMSl<4A1Fs>DC-H7`WY6yGxZJKw]}AOM3\\C6-K/H.\\1I?9iAtLepB12i@\\o9@FzV^udet0t?@3rL?1x?^^(Y@2;ep3U>;G7-t/]yI\\XQz,E@]mSq@t;A<[+G\\DlTW4>JBDGws`oOid1+KW67*U6QE79<-=2xKR<LAhTmUaSFc<JCz<2(Q@^b;^4{a:^-xT^zMbF+7\\_}<M)W7\\o:pC;yD9bH;Aj0C^j_hB4GaZWPCLG93c7G67)^m)h6s@)oWipwBP@)lbQ2fjhAOJKoK>/hgoA|LDj.0cgA;wILQtT3WkM:r=<>=2=(1xzAg<sb9B:0]4f{q(Vk93(,k69kVl<5O)ep:2k8EK[w{liw+N(@1<8EEA<Abr@7O:C]R2?UjFKeEOFv{EIXO]1g>p[LrKaN@m-;xr:D8|O|}7ond|}BBabMF-PhpP6;1b3Mp;tdY^3TO<l=MYKsHWu5N=[Y,vhfPolRQG78>kyG@dhySu?uGbOP^l<7CJM2S8mI@\\oU2u=y1{xt=M,q8/?VE^A\\;4@OVT6IW89]LXS7W4t-Ah?Jk1pCMNQ^B>_xzfH9:Nx/|Q1vH;oJC*GQ9Z42M?KM^l6i,q@Y<kum2NOc9<pFA3^dQ1@5c)4dEgcXvET<Pn5\\gb[oUD49t;8gT7FnpDbikT/qgm[|>b-x/ac4I\\^g}\\EEoh6WF8Q;h6VKQNbf+yr[gobzmA*El[Da:qd9sRfs5GB.\\GV]={68*1R8=6T+3].Sne@2m9QF|F7y-H.J?KEh0n>|i51qrxUOeEZM/f:YIH3RCXZ[BQHR|X/q7q\\|8Yk|Bd7La76d1D(u\\2W;ff[x:T5n3S}<9;YQ8o\\M7vWIuabOsnA?rjT.OK65[_H>9+leY.}dT_*cV4M3o4KK:,gghn0SFQ6i:TK]dK8`pNHAe;Hdq=41D8Z)6R\\]O7.Fc[rAj+H>r{[<fBF3mGEd_Ll<,^;D;T?GCHM\\7EFw>PvO.bfRXJn-JQABVe`jwUxEbHTS=6Aj`34P3bKe:c:t\\gMQLHM{1Q=v:,bFGX]F`gN3dESS0>DJL[VG@H5NKopCVTUcP3_)Z^3.^4t{oLC9:b0-KTSeu=@FtzkR_vim49Q>`A=1F9<IIp{3erWY5eEA8|:@N[39aGMZ;DKA,?:K9kzM=M6yIB}NYIHl?|GdVG<7*OZBZ]W4t0,Bj=XDyM;wXf\\9b5o}B8-_l|PacxZD_h*5Nk?)d8:lF1T;OW@+IX:x\\@s55\\790h}L>4|0v[^fR:|EvaVK}nWL@AI6:kedn)fQwH<y5D<N-qA{mrZ1An4=b\\EM[56ZkD);]G?QFHone<,^PqCZOLHtZ6I[d83`E7wuS@Q2Z,>*1O6?KoSA`=2vtq5`B)@=58EM@MM_:8?-5*]F`:[]WtA|iC6jQ3KnFka0]@qPfin?35v?9@U9K^1rEw4wb@I1>>K0Pp^+r`5NK2MdSj?[nstZoUFnW^Oi7zc`EYrxOlm\\ViGB@7g?}^]F{a0TeL/]rSQ.O4SPA386VlCrq9?38<9}.5yvIQ\\2`1U\\]4R@Uf;JPKP18y7_RRJFL`tN(NPum5?O4Wqc,ZXqY?z:\\w<IHTmiWW@>VSNd0BNm6Ru/0+@P42}<9t16R(yR=83s8=KUW-kFwZg@(X=Z9NJ=L7A/;u:Uk;\\-(BaL_ZM:AU^K5;2Bv[G<uCxZ<=ne4p2A2>F34VjMt=sE*/DO136pzw4PS2W;hZf8YlU|F(6PC<T1?g0:f=WEuF@D[R7tE<S{QGmaEA;V1F5:I3Lyx7}p5.,*KP7;w4[5\\JlTy<DK-JO+uD2HO>I0ZX3V7WUVqaKIa27iWTVp>l0:C*)]@C6:1258c@AvIL5p]:},zDv:f;`d3sj?;BHQpAVibC]Aqt7,F^QYt1<jD778`>q`B?e](=W]Z+ry(Q-;2<1F{4qOE|C5980lJPRZ1`aBhG3MFx{:d4v5)7kGkmfC`EnN@VRUX15@U+<[XS_0c=QK2mR6oaC[WUGsETCka3j;A*h4}G{S5QQmM^vrKm<1s<f:SZ_D6Y7=LF@DhwucVblHV{8}xuLX^d0a3Aq`Hl^YE_J`?OpD\\|@ttg>9b0:fq>;6kf8[eQ@mHRq8*<WSPZ`FJx-@aXl<^=7O0S}Nu8M_}dK^Yqg{?n3<@z?b>gJi-I`a>q^RjsT]NH97jR<JSyM4v9^lA46.@XmG`r\\uRP1f5\\<6:QnX:f+}Jp5@[kcy9RO8rJ/z1fzFII4i88cP6[nl-T--6OKn`6UWF:i@-,ct6{p{YZEU5K{eVfFy/WUBep5r@of3m5vCX=eKr<MJm|m2xo6TQ1E`RJ8DG-rR1hmB2ZbN_bJ_F/iRD@yn(1yB^BP5czSOluBd_b4M,7Gb7sN_X9oV9Al+Whx|1[rI38qOpPh_[7R9>MrCG9Yhdj:X@X}VhW3P;UStsD:ryan7,,:U2KBcJdB:GG|EWT\\hi=djI650oY/)U(c=1-kc:utJ1u\\uLFA?x^sevK0rF?6n=C5_?F4MqiKIVt8O-4G:q4qy>8j;crce7xm@][a=bTOxeoS<z2zCcYfntG[ec^-o3CNZ[S=e@fBO?-0^EP0@y<SFB<lBEA82nqBTa0A;UTDXzCRXApq{]IFL{xqo;P?G*U?vko3qa{Jd?WU=@P9BH0mQ]hNh=@C(D4110;4uR/LnUxZij8Bgm{=9[)\\fQNc+(:`zq:K6fC*K>/y0/9+1\\vsVP(:I8ROgxU:|jNIQ|_[Im80t9eGe*bzi>?1qG:{];`k:z;^3fT1-@58gKJ.ps;/M<50Qfa@?>pv1/I/4J6vDw>;Dba_ag7v8fS97i\\cC@0;xY8VSROS[[1?dE40F1O_7C_twjG/]aKg*4xy,g{@C0.C;:<A;t>cwoD>tLc;xHkU,EfNz?mIw*e4>I9|70w.Lm?N?4ryNs}7zo;33W<W]o9b^5M>XdM\\:_seC*{[G@gZu4;A;UO9^W><P/u|=QIg45XDF[X3[@I`mnB3qRLmVvIdHA9IU7ha=B:@XU7Ms+c>5c4t9FN]jI.Ae04d,dEb|x4h>e/ZeKfB1,U{]b(<Tz:48]JAqAWLpSF}.\\I7aCbtPQF[VSOfXq2T^EfqV\\5o{^REU1E^sABf<8@;?hQ/iVf`.n@H[T81fFj0K61eZ^BsHffckQ3FFNz2g_y>cE@9SoEZ(Dbp3D;]ia|JGAl25?`p=>Vbh4cRAsm/3Lx9)KbsNLcDl92FUM*CdIlhe>0(7_+7+:G>}[J9bjh>Q{SGzGIL4a>KZ7vfrF0]D?HC?VJP>q=2EX=zEt16T36*nY6gvX{1\\O@d1\\KE>F:9OMp|/RZc^lZVXMq\\bB*.9Q4inAF5z(e7xh88EijphrcWQqT,n_/bU3_+>{M=p/P}|k6={UBtGldgnr`raX>`0Kn;hj=(2i@l7c+A;>6.y:m|th`qUl+j:;Zjg3J=L8SEPWl]:v?(D5SUy*zGtPKV^ieS0h92|LSX,+3DRl,KR0GfhX?7{]/c9fQnmv8}sC;oL@)s1t;+X51.H5](Yv|BCa.ram@E.r\\08LZ9yESMU\\NTVvS:TuWAkX>S5<?Wf[/;KlO1jsCI-\\j_?<7(EJ4R[jZ?r47h,_rL^}za>9[h^PsHKQ{zsO6C}f3^eL=P-lA?|5HDuq@aL(x<D4p[}PNbdA`m723<@g\\e=[Z0Z_1KqRBp>oWcPVwXd\\=4)uW9wqUhS-ZK+VaYJ;Vs{GaPphKupA8DDX9pNa[5:gq}FS<5D<Y5LhUqG5au6:>2;p1ilg>c`Z^0Zk`mt?9cWO>l_4Ct_@s=JlL|H0@{L55}30nX`a*sGjc-jTN5*fsHvJ8Zs]XQY1K<3@6AAA=4(3FHVDXtastrbtf6U:f(prcQqOkWRe[cboZoR3c>l1I-5HCt|0jW=.hOiKZLwLM@k2)HLF/\\/k<8XQZo|2zAZ4VA`9IL]TlH-^U0tzekm?oP7mlf+2DU[(gOB1Fb`h?LbQ@_e90QJ8[X40D,tQp?fIl*h<IVyL_Z280fLkXxG@7tGS93934G>G3NXS@G3Z7/lME^Faz(i6FZ?4i>Z-Ml>;caJHERo>u*S8gJ4=kCT3h0]^WB_7N90^B0cU]GGp_zM0wH;(_G78@ctD+sjO2C}<s[[E6gAlt0DMal`Fu-0prn3XLnR1.mZ7dv`l^s97n\\0Q?_KvxJGN.3nUcOV{_LEOQEs8w3bih0m6}>R{p.R?Tz;k]_^NHRti(JQ3=WsTe@vPcAL4IH3`.^7N0fnN,{Is2[Rx?]41]1Ya3ZYfB0ZYTe1(_4F+1C>eVGQZ0i<Am,@H]ZUy6;=[0wvW41?\\WMo]ki?u(-01;lmKG@5cgyGcLRC9SFd6dtx-9*^PY1>X6+CwA-2r`dCoSSP<Dz9(I<)oS_VskNL:<93:Y/s8Tpg,=bA7:?LtuL0(y}i.k<8NADmcACD;0]tP_MB{-THWGpyX1AgIcb22IJH{t]LzL?1G:Pu*eywaOIrwv@|7tOO2?3bqWhNpn8GcG.Nf0lfRmTT@?4a0|=}^9lWjW8`[*b5sg6Ui_zA\\2yE?`DaZ}C|uI[@2]y>QaD|^eBlvY(+={bLVJtqv<En8w3-={CfC6mJG9xRCYS2Q0_9oiA]:7fCGermRxyz=G^4]:2K0U40a(a3.L[5_SS\\6?ItcwD;,nA|DhS`hsF@8OzXH)X,r7]i^:rk>sEnNrL0k0H}NPu(8Pe.`2?2k(vC@cLbG8=dDkJlE6W4u\\O_v/[CcCk453WI33F0X7<9w][V[>w1h7ANxUov/(NWwQ8A.lZK0EbS+8iUQ*@C^0[(YM1zWEm-48;e|m9|K)[eRh5k+iI3>h1_y@J`6yM_>:a>?NX}Ol+)A9E]|\\-V=P=WAtlA3u>)t0,U00CYt5DBR/jkAnU`nZ9AO?g,C^1`p<w;351kiISd40;P*Gn5,f0S<>u7tZr|=]3Wns]?A17z88[OTV?6T^Nku_aa9e0ky1eRmtVqY6=nK5M@o<-2|;;4SA]`]3;[TgY-OTWgJDTC?MX?/H54r/_UFpG6T>b0QG.Jh{t6l2`QB{,X+W6)c^hT:zB:M3YC^XKYBFE3nHxVo-*|1;WmMr3GU{SV-U;AB9;/R61^PYb\\\\as`j95E?nNH6R0+XeeVN}JKIZ^GI9FYU2uI4}z0p901160bNax:qt_HmW2eJ{0e@\\*ON?z0toD3/ZS5`HImlsis8-*CtP3mND3NC2Sy18p(_7gTk9}BzUkL*B+e:^]ACf:r{3U=5OLp60p7@P4867[cOfA_;VV]a(6lxZ`;8R-?P.(8J0<c_h^UT,<,<x5,69tn8o|yrCvPSOH\\G@JA@<xoWA4}>-r_n^*aE`E.;]uS3X0S10[)E)F|]YC9i8wEj6D\\ZzG*6J?>*oJw6@pjZf?LkZmUSMvCi0;YZn}tI(n:N[-pLgK8En=Y0ajEOp*m7=?^5K5we8d_6h]w1ojTKtw`aQM<ZCzE;k{\\**9V8;ODE\\FG[cGUD,Io@}y]OF.=(_tB^yZS;X:\\MCl0Myg`GAcESP(.Lu0eS1?TU-6G7O+o>saOtDA1gwscKDQZ]v@DBUp:OH=a=]gU(o@tR\\<GY?WH6vW)S=/3|<tnu>DYR(Rs35taM?gKr)BlePcscP6t=X4Y;OwA<IR/4=\\j\\z4jf4b;s53/=[t?gba{IKe5B`IYO=Va=V:VLR17M>o}4d:AFJn0k5kEJE3Zz}iA>;3K7H:b]*=r`YXws4X_JZ::7{QUG::3*-9bWHOPi]KKU>i(lf(qxGv)XC;UJapn;11:7,oTNeoMe?U;hBt9sFT;X}YF}UZG[Ez\\Gf\\b>X`aHG8R,_5t9[h[Ln|Z<:aoN6c_xy5r`dXD]MMhW@_2q[>q)irJCPBSB?D40w5P0hTkBk4GMBLf0EuA=<qE6AkKb,DiVn>1R4}79V8u4=?P)TwgTWCABFh7k:+P;^4l:BA3OOqZouyd8JGV>e}[BrG+(>DY]I2DtExPeqYwAhycQ7POM:4M@KA{O1rp;=H1b;sy.UXU[=l9*i)pUJz[/.3jmMpV6wVA-2{4c?7}32DVS;T1CQCB93sGzD:h5WY9CZ[Q>);Gx^N\\.MM3xutk0GV(:MxB|JZl4z7)9@s;q7fNK]^@B^(Z1cSzO6n+gZQ[-kO1>Ef;o6Q*ipr[6PviXkZUf}*e>Pc}SeFE\\R}KWs50<q.:5(ZQN@F?Kh.j}0DC@,y??U9^Dg0mh`<f[UV13S6N3Z^@QG+ECXn`-Oi)Y>\\8Q9mNwjDF|l?rVF4vF=WM@N]Yl:D)Z=37<h\\XI9Nf(YYTG7_6Odm.DAtOcXW\\EdHvI,kT1ZgZSkQ9R0m[4Qb0i?nHTNKxNSZMGuFPGFjLG)}Y*pgd-?i:MQQTCLO{0u5nM<E;;3b9c.0w9[Ei28<{JO\\X-q2mKgbF/4*OiJ.9Ixf\\a0H:0Vi]ylOI^LX/?l6ddBlBH/_5W\\*C(.,aGoZwL1x<`2;30|ccLB/K/o?dzZ0VpV?WmW:N546(SK29DxM5(79*l)(x:A`==DZB3RLlnJJ*?OEk{0k9@*9EF@@[GQB=k}:V?Yv1gS?1>-?a^Z^U?z2US6E]MIakZI)ErY9C1+m_t/NAxLEbICF40\\F@a<TZu?9Gs|F2:v`XrTGuHShOqzv5MSR?OR7?R\\eES0B@*Qu^/*>RxQO`LzUD?(S?|BVR9Ssxe:+:]4>8?=A5E6nIBIh28z.WqC3iS6A}eel6?1vcbd0t9q?:,55`72:1bBGZbH1Cy1u\\|q=>5DIQ2qX@BZ<Tn<v3{E5[(YbiK(03zoKUF4TYTJb35?Rjt1:8N<XL}=_T8O`Ld1:D0Ka1R50tc?T3+:QI4N08@gV7e89j0e1;O?<@TJ}X5}3KzIf^EiT5gO^jEEH}5:`5H`69{.k\\=aM0FnSfBNR/lX9W5:32B`mxh8qk1Y]enDT92F2j8SNG|[ST-7+iDSM^B{K8;L-3:H?__VF:J99;d9=oU1ffpswrxM@n*o2Hbh5eTD2R?Q0n5}Om5@c;:1+kQR.3[whky4=T*\\Yo4F?16wl+xC;lcbA;VCP]N)Dk:DV=Lu>lj39;}wC-:B@<Mj0_7DWp[l<05)Zi15Qsk837K?QOWAyGlViIYi7g0aIvEi-DBsFHp*?J_e[,w5SN^@O7^4\\sn2Z^H^KO`<0V1UC@JA){23060_:}43WnNn8Xt5a]sXIk_Fb9G21wo0yU=HG-|tJYu=FFhFC6vwAZhuSC3Hv.4M[+ULcQ:Z0/Hg7S6kPq84i?xVRcI3}uqLBXr2/qwHdv7|(5kK>G^EYF=9SP.2_pJ24S``AZAXCt6q(JF[k6Pv7)4AAW9?E<o4Pc\\6;HtZZp_|)KW20Xs9{@`aa:vT`)YMA}]JN3<L}(4bIGdB|8K,b2`u?/tUOo:CKvbJ*Jx*3H2><ZMJ<=0kA+S]kPK{cK>4EL94<Qe9@bOP@y6sE`7e<ZJqO_pKTEuQhaafrinti3ND?e@aHx2DqIXWgAB=E2s,f:3zB4d=HAzGROaC5u1u)5=Bzdq`zv]r}([DD-6\\bu255J31EI`?1v6)3YHj\\g*2muwkV]Nj{0L\\bK7<BQe3=3h6\\`ByBw1)+in?V<IRJzk1aD[hTXefrCNZ:p2}=3.Uw4P8<-a6d=clng@T<75s3)@7;?F=oF<^mNXN/(bV?/E3A|_:SMMygZzrOEA)Ttf@3E`i-nEw6_L8R9`F<@J;5i17?B4=RJ/6P76WR8^Ar`4Rnwe[D<ZQP4sQJ2@(XoVy=MV4,I8PhRS])uWOCk]gsr=qw^fXBN,.gVva26YW7^LW|Z`@4Cf1|JyRmY1=QbYLL5E:4e1Pqyv(xBS^Bdl[=c2)Im=X;HsIDNIA?Fk@o[1U+lpz`H<u=dPUEf1Y@T(@2<E=Vx.2z87@UT:1iR4O5?4>o16jjkP[RE+:VUC+t43TO2by^r0On`X^8_bc_380KoHI3r5k1R(fow(B6t4L31{J}7qIxO(fJ-kG:<wrded-CIEWRekH2wG_w0YgJpfR(H0jDFFy6*=t643dV<-|Kax5|5q-q12sOKfNryDy{M{M-UB}:MwvSB@725[S47d`Vs@IMVDWx{i(bMX}qSC@k>+8JLpF7MwW7_yOb<V}@Mh`ncH_LH)7w7R<+3@PQ@TX0CUm_HUi6aco;mR@x.KyU<EDg:.\\]CUWCN9\\|Aj=8e:ro8:j5NR>1djD>=/nnILMe>Jnpy7QC6R<lCkhxbq5`4E0{1E9W7Ny?1>}*A)n]1(:-QX-7p|A)a_*nmcEPB8BJ.v2FD`M(3A+I?)5JElxfA0|yLgGV(DH@r{5KN1ra[C1SMF>25Zg*I>?58O9\\<ror]r*AOX={X4GukaALG^}UHrSbG>(bO6<EsWZuNn?s>Pb*hDf2\\,-<A7jrbuAA5/N<I>p=m|XPgaXB@O[yGcGzq)T5izU<QX0Zct:k0g?vW;N4YNf\\@MvgP+4{B7;Zl]HN]amzCNU0|aj>0M*75^tTH6QyDO?qBxyG9G>umy8`uEYPTP17:>pDyhTsG@f|1XW^HB]i2`aIV)q56Y*JM3?utn9oR7@2WT184u6kmoV>8fBA59:UZLu>Rg4-JwM?<5q,H@DKpnEH]tR|uyuVI0R8y8*7m/]*T_rCv>?@<G^W3Fey1Cp5,<m4rk)F0J`mGNHc5525BVmC6GSAqi`):OBB3{5}20(f+3Obnz>KI)NenS(HuD-8*7a\\{2>[-i2{3/8^\\-xU?xz]Iaff/c:XS>]1zD<G?4_4bP:P|6K+vAGTz9=Vjsu^f;ph1XNy[mjY)1o^v?FT.r3J5L*7gs>i0a9_vGpyQjd;XnxObmHQ*lg}0iqKWhEWM5@3D;{h7S(8f13>BJj\\TT:|.w:o5;0R3lXE]@[U3[NlQ{VGC1dCKYuBSg3gK2w3hJTA@}2TX,\\Hn<Omb)VOS0Ybr^VNh?D)_3Z=)K)PBK8Fd,D:Dwfg)CJNyNG8;9-k><67JU`z}sd\\)skxR>5^U5?z<RVujJpb7Ut3wTtn6/jtc;m.}zQCRIU4(qxe39w1]\\^V/keZ^@>cvdokT`|DnT[`Vea^9:<79}PYW}\\h,|,ZV:H_6{eRJ}eb=*,J=Ll@y6:-Lt_t^C1sAGqHc`?c7;n7V2n;_A:goaeGdg;WJpX[X(<0/;C/6+HLLvPOGOFAmt)5X1cIWq_1{lQY?d80gjQ4Ce4YxVFHU;TS06=:N\\<Z12qmFE]>M=5i9}rNVolyh|APtFV[j;bGWI@Ak?(44SCW=z@cUL`5^E:V>OzM?<,Vb+Jq(a:76I4kL]1_KDd9MMcsKe>nAx7eu8Sh2H)3=>X|KDJ<AG[wm:oW>)uK_,6w;X63vN]Kz`XJ@[4ppX1}f;97pk`bAcwK]1\\IBqX0d[,2CC0x;EQw>Na:3h62=Kn3nExp;`G<.GL9JIYNBoKdA6hC7)-OKk`9y4c^C*;nC}N=Mshj158Y5n<Rf680x?W39YjqAH|p=3X007j8Tl0v8W169Va[_oVC`GN3GWc}EK14*QwBm;9^:hp/=.Y+RCi=(TD(>dN`BzBmSEjUgi34hF}K9@N_aKIeIYwBIdz/]=TU]z)hwgYEi|]W>r0cvEZ:U)l^KS(>>f8C4BB\\4[1AQnQ.@8e+V=IoqXd/dgM<D7jQKAaAn_Oj\\BIEUI@tLloEDe4\\6vG=bT(B2yIlp[La9CQF==tV1NBQ6fE1,l7=`O?5KUySD=)Li*6mY52R2Uv9Q_?x0H0kznJX4kuLoAsB@4GFsED6xYTxQ)H-1EiNV`t30h_evHkG@c><4HgnL[Sec7Fh-HT;ay{s`=;;lKhSQ8E3>z/zqI9ceR]1.sAXK@8Jm6,X:BJ09+yBXAt,NJ2YE0@W;g6:@oaF47\\Q:M8,*Ep@r@e|T7HqU\\s2B,9k>CktuUMcPTG\\x4OVRxaUn_*TVuePJ_]BpbRl-^5Dz[`lWME?6f.S+-z9oX\\?VF,]Zd:4=weJq8EM7-Qx3iS|Rk_U\\Lm02DICNjU`]y4C-C1+esVZ5{4hTH1BS-zS;K1N1Y4Lnc?I}2HT]4m`5uDvvVuB*BjY1dSAPAOfcL88zB=Jre?`USE0RC{)S9<_?AxUYjGyqS{;WdM.xI=]chbx8aspXD-/DB){B:_B}GmHF/q{kiYTS(w@>SFIf_o]UVXG2^8L5}]M<n>B]3[;D=(6{yPPB@J-bFh}cHDcFo;O4*lzE)XK1Txd6bp9WT7|zqo3C(spn<D3o,ADt8vH;]_x]8zNMY)0CrBGQu+xL3:HHAIW1MsQL<3Z,f{nTj792]?{GlrIA55bv*5krgPX3<_Xp/UsGm6?c1Z,P{^0}(^A0pG9\\K`MN=,0ccAI;JEb>kDaLdirH7>,>vQ7H+HOMCl2ZChC`+|@2Na>CI[twQkCQhCya*H:`+.?@Gl\\V5QQ2(74)[:\\A@r63[@KNH5N0v44c@bP9/I0r+U?L.EUBE_\\W>-fp3K7.?\\gL,|LsQ:-0+F@:L6}7tuh\\/jE0729k8Eswb+@|N_W2r:6A4Hr,j4|56cLxiAc8E6dRc^jVhPm9WezJNlG=Mq/Uk7Q^6y(z+Ri?|wS5nDyi{rwJ|F:W97Y4Ot\\Tf*,@6MB\\Uz>Eu<@?O,LUm_3GJl,WjMLQVqXW(sfIE`(m12E<@?56A){Ts-I]ncU,lUjb*ogIA5`twB]tDWSO|^f3,I:^5|H{+(Bw,?qK=F3l77_IQGkBykV^U{o:V4K`qL(q8/aFI9e`;GGUhqbT+z>ENg;>Pq@TJv=.;1J]]y63QCSOYML6YEZC}TEtdFTE=KD{ckA+Qy]{9-{+.Es99H?WUoJ@Z^3WRhgQI0]As-_w/nDRZ]v;yym\\>U)m0\\IUvjFJt8m{UQ?;@>n_Zf<R6@lv(4E5pL<TZPE2;wPdFEI2wbL1niZPmk;Uv=SF)9S@0zBs4c@?VQ(?Sfkgys=8aDR_+PB3];6jH.;,`eiU6\\cT4FAZ[[MY7Jy_ez_Z.6+-bt909yp2>u:E4Ro;BUA9UdOQaM+i}\\RO4FJqzD)m88W\\haCNV6Y{4O;\\V0_)A1GafVJ;+aX^.wQ\\]2iN<BxyEvBMMPoJu5d^_5gBYFQXFCq]r\\*]eE2qf;EA<w<^WYy5?EWMqU40TVGHK3z3gZR`hAG`P{cDYIku2JWxtTn|Y^TVB{8Y1]E\\le<bz^_0gp2Wv]}D?oKHgfbCc2S1<<_(R>z|B+3uS`bQ@uKSzmH95-BrL0)i)M[j,4m}6Y`Jy9CVBSYYQ=+d\\qFGUN3Ne]xt4iriVbr\\ubO0Rr?{B_q5r|{@g{+4Z.W0;OyAwR.B;?H4=r?KKN>r;;A4uj4GH=(oa]0\\_j3b?eGiLZPc+PJjw@Nm8ZZ5m6[ne08R=EshqpYhW=0C^FdN?P.9DZ*zE:BDwF]?=4PDKQ2kC?.KRq4-a;og\\Or1M1SyMN+LHYS7JS:X))_*F3DQ:,PSUAz-j*JckIK=JilUb5hq88AX[fq<PpiwNVsPnHw0MPhP0d+Z4HdZTwz)R4wO_c?e^;U<18`(MYi1HWI0SLc1Qn7+I_^[)kDm:)<45*jXLQ@8:iI=?nR5B:_[Vb09GTsStB{7S-L,4ed@eU+}/`Bp5|OxWt-nXDqbcraq-Hm<LBPe:iTHa<mMr`;[iV[iW@4FOIw7BBRJW8,t>xWSLM;7O9a9Rl@y@CWDD0AmF9S6>+:GiOhA\\ClDV0*D6TV+@xWKgl7.qkYg^.8Ef5))lZ<x<g=NY_xi5\\(K2icC.c.1h_@+[cqCPTpnY=1igExFG7NW:WrXDArM*uM+HOKVRDfxjb3CYe5/2(IH?|[6ptz:v_Q9}AZ]nl/|-2;F^:j11EK1sxD;\\qG4d}P^3|>@j+PrV|:Mgovc>Va@P|.wD?5A-YNSgZ/GGKa*RI7DjF9i6I\\;yDPm\\}@}Bo{@J_M4(xziMmh>.65OJL?nb;ddoESSG`hEfLB>cV[S)EuJ7|lzif7\\IN*J3d.X9FVLEVZC?Q*Lp4H=Y.3F,1<U,N5e`-e{oGkCAQ2PvUAT;Y}BCxX+?vx;0ny|:4/=Y_VDZKC7[^YxV[d_n\\trC2[*=_,L9j`I1Rnw1FEXTB_l7H^>YI+M1cxZ2H>y+@fJPnh@OP|5;E|Jd2ji8GD:_D03P3>Ye6QyK\\ts^HCMH+gt-^]Lr2z4uBHhuj5WV|4[W2>8V4ZG23GDRcv7ZH]b,2F7wLnb9G2T)7VjOEjzLEtgP}<.nIr^0fuCW{CPMVeP*\\{[491F<v}XQ;9^ZXF`</2LXfl@h\\u@d0I4pr]F)9`CKBKA:tj)_,?kPV:tQ2dB@?w1s2BHfd6dR9vW6=eA@C+)([\\?BK7)Q)@PDTNf`2<LRPGXz<tVY8T\\\\BJ{oBl{V4js:9aUxUi))RK(u3ZG^q0`6T0zQ*n(@rjA<hH0CbG6@SLLLFqQ1=rH}I90A7=3;}NYoi]S`qpD0Fk3fP\\+6qoX)gAof*U1M|P\\iivOr`XU:\\eJ)rS<<+4+.c`<dl=d]dtt5M=LEgBqV<S6R15i)T^\\is5A34?da>u50;`97B4Uy|OK3?2uH2z]DU+KK`*a:u\\D*Ra,PX/N|=S7k`Q@8xQ@|Y?kT4w@z=l=.:Ny_q3bXIcLF9:=0RQPKg,OVV4zWQfSKpIV7|EmbA@J-8B^n`lsW}HYesG+AvYeMiE\\*<F|\\6bUzd(;8?5|6GVxFDD_6r@M;xi+\\k4uZGGp<*]4Y6iVp6fuy{::]G[L_e(rCK\\O6UpLF3jg\\CXP*fc=P05ey>Vap3n0bDO,k=9b{aJQ\\\\?J0oxS88V_V:V)qyh4AOnJS6]_,s2d@(Z{3Zz3a4+\\QQlLeL2]XQ?fbV5kF2+RKD4@(j[+{mt,T6*_jRCiJqzV|fUp.A8tWP,h4k1gE`gL4it3zl>uojFyPD,q[nzrX`bU>E|l2?=)p,huP*LOk@_Hm83pabR>d]P2SPh9n6a^0[1]>/T=ChndN,af<T*j<Np<nn}CO74pt>F}qQbH*/c:P=iEFa4Ak^9Va<68M@qs?CjzZhl*gtvlb.)q4SfHEnP;^Gs8WCIXNl0Ob=qBYEOQ9s3+r\\Y_bVc=yX:K@>[`z<4oQY(x02G2[_D^DXONg580Gr486v64Kw}<cm<+)03Z;J7|Z5g[90e6fF+;O.(>+Tn;?tO.lg,:N(>79R`,yJX<}ihR\\@oPD`yAks^5-dS=|75D/`3\\9\\UBPZ+X]GZ`9x5T|vF6?;<PuoyMl=un17uTaQ;?0>=}|fv>pZb4l,jd4OFs45<8g8o4Qdk9+Evo4i?WY0ASXZ(PeYcgJuwo),GT@r-qZvCnV{VYMH85_s1n_KNzWjR37k?7J8B5Q/7K<IHxoAHimnZX43`NsQ3S.A>><3;2Cv)SjqN]|xr|=kZP{=}<VR8Y4Ajz6NqC?MJ5,`a1Ic:MPt80V7x9Sb+fG*nB9QYjSM:o}:8d]vWelI1@_O8>AN^H@;c6@).2b7s0kRJ-thB^EA\\2:w=.jeLL;b@[(6L3i9TiMUp77YV5/5e0.lL0Um9.;zC9)E^@Zn<\\F14|1;3G1p}JA3\\<\\=L4kP8vmwjGh`/o:4*:mXSv5<.EJDaqbII:]54-pAL:+ih/+U`hMpXcAjS`GXh{W@tC`2X`TItu*CbO7sCk6Fw:u,JK8@aQ(0YA|F?Hns/HZ)E5D0Ot{nS*<4c^1K0])z)|kR?UU0)x=A@VsY+U=M1ujL]mQE^P5^N6cTnPG?8];T,Z3oV4pzkL)<A>qgQ5L0qSJh*A:(E:Wgv4lp61aJ=(@76lw^r6[hd}A}Q1N4@IKc3jK4pUgr15`EuhNHoZ0qyF\\E_lv1hihf*M<V31TFv>Xc8*NmXREb2nTrlOyK9fAZ8sC<uc/`7:B0(/ylsib,5|>Ofd5c-Xvbie-p+kZ)euJ:1-iYE7pZ<=Jjr=B5Uh1DpZ9WdAoJT?weNe9Lp{7DQyZO5EOn?G4j)>lvuoF0G|avV8waf5i48WNA?CT4jM39h.D=-c:CrBu]jk{bFjiPRcgKRj:,9dvA,ga\\2<0(]7C|uJmDB4vpDn=MLE88-FoEgBj6Vryk5Yr_HwRD}fWE:O{X779aL01@|\\uF2|2aqPa5.<PFYcJH=B:OK=dF_9->cfo9]b:}-MTEl^p\\ImU2K12Fmqh_S3uc;[=iw[rh-5Rt^qJ2H(P>AgQlOXP-Yp8(o5<9]\\)rsMQ^Ul+mlnM_dW<n>XO;9>:{@RboagLO6*\\?n2s;pGKZ<7cLQ0[>\\vz2<Fq654GbB8o+RG6t.<93nv79pR{,jsBdENW?V6`>7H3sq-]B}Y1ND.m4To<n1y;5VZ7_hUwT5@cT)r9ts}HK^)33zP)8H^I1:}M}pgG1+=:D<;v+27FWIgq:Z|XF06_UH<QB@0r/r`L{F:pABH_4shJS<u4f3ce^FIlLx;zw>^[oxEk8*JMC=PV{a8[x^XBmNE=CCHODQiOC;IWZ05z_=<NOr6V^j9Xm[8J120EMdpbPj/IGz,FVMXW2ON;(i9uYmeNy=Ij/O}Y11]J@e+QETlO[yc=Wf@I?c)D_]Ck5N;tj0\\+;UN]}(m}7{iM*Gb{No=]\\W_`@/IF[??Vd:AW;CwEY<S\\iLdg}EE\\fI35[^YlUs|,2{z/??0TQgFk<2Di\\<hDJ9b8=xFXW1{S(hWj-r:\\QJJq4AtpJXy_os.Y*DU@D[mtdyhM8CRFR7AHoKv@[F-00KvF1BXpXiXB-fGZ5{947Q^TtztN98e>`\\t1TcO9=g4K)n@9_tCCg@F^+QgC1w:W1(zb1VNdNJh3_sTH>e^a>vOE;DJ>3|5D7eOIE2;=ARyMVG[;5S5YUM,4DHd_DVYNSUL9ih{ILDTAN2(1LF3Zn8aTXA39Vc5WIjWvIQ5)5vXN]4xWOX\\miMB]O:4j_(GW_).K8q=H3pd6GFSRPiOb>kr?o2MR=0UnfdmM.YoS>J>D9WB7co5AgVH_yEdrHatFIsK-(aW>`TtrAt2Fm]ebb`67iBPs]7y1<CxD8>*<^1|HkmOINfY1zD:5:^nk-/5M2WJclA,@rDy<70F{|`6>mS56^`dJa2P8?3Dm[j7<>:Y<2s3HOtNg0Py_?164x|uAnUPxSAz_F54>BeVv65U-l>X1C+0U2cSzyPt/qsOaMOIBOF2-CCMO_xlFJMg]wc9?9`}=>\\NN?C?+-Ope*;uXG6?gr>kYNo]Ru?q,^KIs.{LD[,>Tes8ET>D{8<\\agd>z{1C0?/a`9Mw]1^kMK@fP,J*9m6nmAsEGsLd:G`XRD9nJQTDpESO]UtEm|>,oF:O<lP>7veAvfg3=0lyO<(]VCZ6L96TYd9X;*e)K?@_PKFY1uuIGpPF4*MUNE}P9PFIe1YW\\F+SP=14Z-JdypgyV(O[_/(SR1t@GgrInLN7MY;uy3z4`^@+v?3|L\\,?{4<lbnN<LC71zov_yShF(EFA`u54bMc(V}wF)x>y8s@?nO?qJIuus1L.0=kYlNliB?iHcu=MWe}F?tGU\\4>^C\\3Y0<pn=.u>DjWYGk=ZUG8(.Y.<-89kIN[Q0N4FhOA:i)7tJb24j=vh3QHCKhHC_2r}Z8YmoKH[[4D>EdGPZ4IZJ5=c]qNmKEr4<C^v9Ab{rti{/E=G25[Ta/rM-<Mrn8GS.\\Pp7deQ|V7]GjXo8GXygn-=994Ek}s3fc75DIQ6]rCv;6xefI;[XvsvF1]:96Kv@H9[eQ)MeY=DJQd|488e-(n*;4?S]5ye>D4[EU*F*\\TB;nxQ6SeL;KyvUx.4|6AJF^_G.wH|vK|YLvv6@}q86uCISyd5p{g>0V8KU9M)ADTPOac(85C@?As34M;PfdFH.2+_HuCLo1T:vHIB|tPn0;}]UZvtZuZEcUgOPl=PtL79]AUiV_mKFNk-<UsDTC_G@HI)sTJ]NE{PK9_[OhK7h+8oX]w`)cFOajjBBa[A::[?=9Sos^o\\<fS6GAF\\fq66@?m25HaTw0o7)b=n5N<N57IU4Bcr]wF63.x52>eXnZnHBb7xljz{TO.X(UmBw50Y<9P`ZL@GH`1>I^((5Ie/3A,t28*fno3ico|A<gz9HTz76AK7jaI4LI3)id+_jG:)i;1CYwqb.z.t{E[Oj}2<cgb=3}xmAP|DFf,3Fk\\bx_]MMnLj0G5qlL|6n=?dJK@TNFa;_*f0NG;@<_ZI|=n@M2qvwV-`PpGM;ap.qp;E2bzkS]5.YB]MwtU7xUHSF)yvm@cJ_f=7?\\CEd9Ost3qVq(o56HmM_diroEb39u`kzzoyryRDu*.h];QdN<hPjL]O>scYxG@i-0>d}8W?d{jH/7322cWaILw;*9d5}{3nn)oyM:zR4pcIQ;12EGZ=kL3L\\j:tbqHV`V^7u<a(*cK8@E@68gFV`3Ky<[_X3{S,5ki9,ObyI^;C@^8/]r]swudb`t6iYZlByPlSX)WFWb+l,^0q:04G|z8ACuQ:kf9|>?xs]SohA`d@6{C9T@k)[fd3f<9yQ;1O82zbjs;oq}3*P24nw5beb79ZeHwP1@tD_sDEt;|vDZAXKnnr+jvf*7]fsO>r]hz:g1+(x*0qu_W>DRyge9HZk[OFg:1U2D_.HE`@>0BcdJWmt)4b7bNd>;N0TP?+VIYY5ZGNL.AL|\\r,@4.76dVq7/3XBw0-OF-A*@H6N7bJfn1o[3SLE\\Ii0wV}Aten<B|5bggfHD>I_O3pR`q-(L(OFb48h)HS]6:m:P?AAZCGl_:@6NczSbX:-ycDUq0q+LiyO<{hNdb57K8Dn2485WhBjz5EC?YG(xlmAHi9ANo4_RM6h3C?}m7f9pPyv6I7p>Yk8pdS:-R\\6w6QG9z-(5*u,NOE+vC(=uGCZC>Zb8TNjA??^D0;D?I9azN1?LhADJ@X9xz>G6}g50I1[ENTKJb@J<MJ;|2?[XwTi(T_ApBV-S?vM4exOG32LlYHVhN3[X]=(B|22hE8/qOI_/xr(O7xYc70ns1tFyF-A|28NUYa+EI*8ntkFG9A{`7@|C>ERK/6PZNX)E.6AA9iuQr_7>*=4t[3;hV3Cp6DR8)67Ab{/=s5@DO{[R\\}P3Lq<p(iYAc]5FxPF_QO,^e1Z?=7-FLxPEMY>1c`^1O6IpgBIdr<5C36BZ1iIsZ=1Vh``(ngXjFXoV4T:A1yKfj7[3R(HyhxI\\N>vD`3}I7c,Z44S5p5Lops.MblaDJ3j+F(kPA,}qZ-zJ3efbM^TqNW-L@-F@BI``iUy=LL.em3m1omt@w?Jrn;r[GE3=cw9=<JHU7;(+OCrp8MnW]DBQp2@v|0tTFn`ugEqa=0F\\/BSG-,RA1VO6gf]8Ac}K[MxSfb^\\g1M2?HDWIbR>)S96/tLT>D_F=JC]\\TVp_<q5:80F81s2M_0K6j}G|ZRAiSV1aPDx3,*z@xQ,l?HnOr;a^p4A\\Q|mW?[cq>`0:re_03brvJ\\3A{318nBHxDiIm{;X0)[bb;X[O2:S54;6ZjGMi`9I1Lgq2JzqSjl)lD`i7gu6:^x0N>58[}Bm(t3|1B4O6]U3gNhJC[H5f[+Wj4+0lTFN5k*D><:UP1:N4PMI:(RFtW`H:h_3lHIGANRG|6<_LJ>EZua2g(D4Z0s972}jKXFC9ZK@HR|oGhLbN*vYr34LMT3_D@L25jC2Iu`VE5R}g0reS36fQgk2}Er?2ks=X=NJDcJk_3BqC*W(2Dmar>{(iW;m`iIoq]hQ|c_^yF_H:/^wnPq=AA^1]LsV,W\\y6|]Q6iBeP9DfRQJx\\1RK5I7l=bipM+@S}9rhY@?VDP{oR{BF0L[YEH={{>z7=4FJg/=cB;=A=gsxq9IOjM=,]nUXJ<C0Nn2waJRQ:fh5<MyI@])J132,>4ThDH=]90ET=oc<pF?ln6=kD0`hvdKT1wZOL}<(b7sk6.H/4>X+(9uX;R9`wrIw0YP@vxxn?uZ)Je-fuIlIT+Ri-^:T\\wYN:JLq`wbJf1BAqo<FyYG:[T6?W[{u1Qm-A^=;sYF\\I_HCBZJBj0EsK2BID)-]LoOd7Q,a<-rrI-gIPT[71:G=EP;HYx1ytSsI\\Fr{rxR:OR<Wta,<k6uhB4[LxFRcYN4xge>2f?4oQ6S,*-/4:Q9[6C</.kdtK9{XDDJEH1YzgUN>/K{j]]:Sk1YK_xND9@6V*Gv{4jR.D8CUwCKWv*rwAs)9z`<c`-?^zjU]BOPRd7:iCeQphk4y{@,dl7gzNyiMGWT`W/ZDTDqJeHL+k)qG[S=V`g8Z]C.(<XUpTGA\\x:xuTH,vO4TaX]eVt*<<u3uVI*;zzs56xl:Yr,AYF<J<5u9zNUk]1iAwd3<CACLq=_:f+/UTj9Oh9:K2XI0|BC8[}Ulm6dM09S0qMIOsj4LG8Je3lD?=Wxa@JXEdvn3Et?h6QBnS=Gq}]?0*f<*`<@<@)r@@ONJ1SS;gr2VS]11XooJGmR=ABQ-73^gKvk^;lmLn_[GBK4R^7yw,|w8k6C8Cxi>-0d0bsT(?{E/l(|LKSBq/ASUr2|[*\\*>2^TorL^ywpvru7-Vs)l-v|N9k>A+J7E[ISF*0]=:18N}7H45g4?V0YbW0m-/(Gu=t9lbzaVF{fGOO6x@FiW88OO]@zZH65FM:{wOyjcgYBYz@8a5]4]ywxc,@Eu;P*js<4,>ELj`lmZ>`J1j3<KQrFH1G8OTZ=eB.;U5EJ;bn?JaVD?-8HW)8a1dc3C)_;I?.aj+ZZfjl]X1[VeG1,8vi,K2T;.b/P(kqndU0t9D\\>Yo*IVmS8v^7HR[-`/oGW6.bo>.DwF/TAbQp+sk2,6?9ZE;(oLUS1vq*/j1;a:]WO_+9PC_.b?NDdi6kd<5?;|g@BmGiA1qlL6],mfy*ep8c@BYnynV?7K53*7<w8PaNo=XX^5zI1dMBl`,E=Q(p2S>N478H48NMUGfd*KsC(?C5f8LKX*Nf`\\xoB{}MR5SF7MU9V05Ku>lR9r[SJIpZBKXIi^bgY6ykP8e5IL=>x1VN=u{m|T0w8g16?C9i{O510IxcyVB0bI2ZP)EI_vqK3vcN_X+9UfWY6KMtTJ>]<mGBr79A2|kUSIDDp.?0xv`lr{bC6>c.>FgxF)mtUyHI;D*1d*hQ+29sw;XO{:c058G_5WpgytD8}\\:WY)SUZaEG{UT?{ZM5;<HuZCd(6gyj9;p;V{4\\X|bn4jmby:t4O^E81E:u^h;ZeT>Qu|iPzL}\\7T5O{,w<JKjZ>2\\+X9=N9Tsk;31tUSRN;<`B88@1U;ID1<REt{XCpT91Xlw[vM5iVQ|NM@AO_-h\\BG02fUtHC2Yy:3=lOLUGII{M,>kPr9dEL`:.dd*6a:lf<3JPwNF96;HZWL-Pj?Z>]z?NJenaPkCH{)AVLf16:K7oPV=CQeyLgNV(IbCL@t12mUvNMAgbjBW^S^OIfS<QK0wD);EN@*NI|zvUePBCs]^,B7p{3-fa23*EK@vH[[dX1KxC|yXTYMzXrF,Lef58@tf,QW4QJX}slK*WK*b6-)2/m[7S.fPvZ]7t-G^C@d_hp3O?z8eH]h+GrJHDBz`>`jxI*Yt1,hvzk4f5Pd2\\dHI8H{7:t=BiZMa7Y2D_)8U5<L6tu;?KF>DeRm2z7Od4PP3yBZDY[ebPMv7JgpWdUsaD+mr>/5vkj0K9W])RAnRL`G[d0w-kSGbR`pwQlx\\{9jUI:msf1AmS`|Ja:6\\evZKX5{p4)SkVK`_CoNgY5RYDa;0^}[AtPfT{N5Dq=\\CK6_NQTX:PcNXnCm8bfJQ\\EWOS;76S14lXQ8EZ7[QQH4wc>SGMqCHmlHl8,T=`,?oAGJBDIdDU;MdD<3B=pf9F)_,9tQ6*Wt?LQNGkhE4=6M@1HB12tG*0TKq;RQu:hoM;M|I(GN24cGe_J\\DE_*,rvu};a,Tg7jd2o6CFhF7F9W|5zVPfFQLHck9hdaLMeKHg2L_a78}6]8XJDY=b4E5L4T.R[eL/=<rHDwF8d[pM)]0UH}bSf>p|EBL`m*ZnCa**Xt570?4.V/82?kf]o_HxsFXGxwv:6@LJSY52fXchmQ[Oy<wi?[nhuc2r56l0H1A*_@=Yy60zx9Fnl@@+GQE6ft5,Vp}Y`KOTV[iHF9C^^i9og04cl,wiF-WT*/WKkIa(@Ok;yZG[v))8QiB)Jr,5Fxpn;e^^{S=1:DwPDDduk<BcJQ]9lj?yz3)4]pi9;kJ`cP{hOnqM9yYihS61\\v=)*W0}KS?E_c4bCH;dK1o(B55UklD*yN_.c>\\Y)1/Ce^HH4AZ\\`qFNe4PY:}5`5T*xznQ\\t9ZGKz1m676=?XGHMK;08*\\ilCOK21xms<(1h5@ug?aB28Tz|J;^\\V10FHbD;+,jm\\[Q4q8G|(9KBLhaYsrH48Bm[43`RRV=wOINDIsBcLCBcHH4S.Fgcx,8v8j1N`yN`I\\.Yk[o;DVBISl0W\\hByjab;qN5Bpl>78UcwL>q_*6L2VV,8u]vtXdS3Kow3fhr*5)cK5Hm0J5AuF>?GlaFF-}C@d]g83TVUXPV0e57r5SVb0kF>gG[>65[n/+d]d[@5r3JdS{JhW`sYvMe\\Y-QEZRCDj93;@3SepyfDGQ5;TGaNs/>D5S_)n`Z2>B(<rkwF*Pb@;Q(J{9]C(_U}Xk:[{Ep5kU[YCIq=H,us<|o1N_,E(@htf<HFD0>tjfkyOonjOlxnqH25qAqELFJw6,51}C>N?_J[=V2?BO[LsJS|lyFd|1T(YJO0dl45+T]*=4]8Pz3<Aj?3R9XHjDO}XmhX4f6QD^;(Y?+R4jo<W:j>8R;.|irlMbTmV+<fh=2aK6q]0VjOn><g@NzL?d@}7qZ]94^k4/I>op-6kjx@?6v(3@@GRG)l?m7+ki;4@CL1IHn3N<y91FP7*gs*K-i_:a/5[AB[>9r:PHCQ<PLioR)lr7g;`4w@Y[wg(zW/C;X9geJ|6XWe*pXE8_G>`+;|JQHqF266Lo.ZhTqel\\GM*=rIV1::Y9BA`:A_`\\1=x0@aG3K>Ss.JzTDnu,Z5=aYKTKV@u*;d;Dc?CeU4\\<e?0V4xZ0f`Wi(cDifGSIQCYV9]@=XuZN4kCNL@C\\rz4a6AcUL>zVZc([Nle`9KdOC?m{C)5WmYvEW>2FDMz1o:x)<O36.\\2ulH4YY8mXxPiC>t|AH\\+)<M(Dn>b9pmnJ77NSsC\\[B1XyOUoh:o\\NI\\ddGs>z<zGLT7Zu;3_X?o_EO5/KkI`;^nmw<7Ct:[8N=rqTHjy}RD]@(oB}_a7?y/(@l?..:Xo.wyg)7\\*o|[i`:HV6Qkag6xLXUVEfn+;@INFH7L:nO\\i=,;U4K=6>BJ5\\Rzp8=eEO5D}ttXF\\9c9S2i55BLDsHJuYGSNIv92+DhOYJPkSB.f/L*h2fu^YUV@7`JLHR@?x>1Bf1mda(We=(;_3-F?kgdcqrM]+U^t33NGv:D5h8^H\\JO6ECoR=Jp9]X6DSpCnm9t<m}pe_;0aAd{cL*b[{HvX7mQ0gNVQ\\CXh,zwywK80;vh]FIF3x4zF==eUSU5(B{HuOP.o;vsB8Gks0;B6}nt;34UhLi@pGf-6<2@f+pY2T>+F<o`tFS@MJ-q3i{[{(E3Z@EKMkS\\7@wW30;[DY.@)\\Z>:012c8nS.J3Kw]H}8P2RBI(<}W_N9(?Z)Pwm+1M=X@Nd9qdKTRLsX0F5VLZ.=ZSpaViyVwjg`?tKE^)XoJ3Nc9AZ;d28/ZCQ6Gb1QP<ZY8CG_9<;tzd^V[oCZA)512Q1MW1+\\p\\pI5pk9Qi_Rz{Qf]ZfqGC3Vi]H:\\=q*Y@F_c3)GWEgCxxxL5:3>d8E3+fI01jGIgtappu[:CboeHGIW-L5^7V6J6/FLoG1dRVGL80OAUdMh4RSU]O8M8E8WD3bbjKa`_eKA1qJRQNS*fN:yZ@T2<bn0cZ+Hd?R[b@bf0phxITP4wUZ{gJWq0UP8,{O0i`CKQknMsk5AnWk1pcD>KJ*M?AOhO14xv5*UsKHZu1_o_:IkD-M3fk+lpvB\\fzQiGRUpY;ZPo?F:vvx@pJ4[pr1Pik:<V<O@75etBH-o:0cHKk2HPtV<.\\I<Jqo`sv?xxHQQBsqYQD<e7_4jQhNSHdp5ntW(5JC7W_73QPL?nc.aTOH\\2C0s0gV9kECr@dDm@K:NkebiiCcRfU*gFPR?pOyG7T.d2{tr?YidFu@w`,KTW|/Of_(Q1-W3H})wB`4O0gLocd58CNW\\l}h>:eZi=S/P+7I?A]r51u78Z0SGgMt-\\>XFe/`Avv^6psR/jD9(j7SXG8(=;PhHLl`ac4w@h1msbqyUv?PBN@8P:)T[l4|^1RCUf1:p;9[?9TBM3JY6ATPL+HyV-@4k28Q8*`4p,Vzc91Db[9):Ov<Bq]wnCnI:*kR*fRIJI.lV2Y\\D3(Anb9,RG;\\LqfEs-Y=T0Srl6P3jK)L7\\.`)[j)14{wD?Prm3e}3R@PNX:DmX*u+K|@}.JV;NXdXfEuG4H7DQD27Nso<3S[DO<A(VQfenC4XAR<5BhqO8XFS7;LrhKaWOVg4tk7aN9-aj:u,/XV.i.CH_XPu\\l_+Sf\\6Am_{W8pqewFn:^8GE`G>BH|5>DeK;gZ<2QHZ:ZE*][>;;fY1/YbwJXJVO4BfAmmfCInQOlC+Sqktn9OhRQ^sv:@mxX9<6.C50h@2AUr@(nEDRz0hekYjr3U:<LC4=YZ@e<ug.qq:70c3HkU,a82pb2hEEcXU;\\|z2)Gg<a1b\\DY<`PStO*/33EBs(DcPu6[AJZC^YU=S9^?U0Dm,?\\1Vi^`\\IV4AD:>JDY5g_]qS|d1/:Z_{j3^D>uMA,Sp:EV.e=5QHSc8@V@G.(pL}7^ZUUhVfIG]yvi/h)TE?34?0[@MbR,B>:M>q5LkxCjKjBNS1^C@>*JLahv@F{lPm35FJP)F[}({5>/NHf\\rBhBmIVAo?tHDz^Hb[:tl`pEH(L1:iJevg=[TSI7=\\f}KT=3z6yk*GTIQ:-KpBKRH9H_6?^^NW8P?@Ty+9UIOCKD2S\\;:OkdDR)WK>9CZE_ckJ=QyHKt\\pB0?||f|/o:<8*Fn3BU.Q@`PwXSnZgr<;P36O4bEBgevrG*Aj?jM9`C6==wZHN8;sHOBhXCDl:ukl1z0NoKJ/UQI6SK`j=;HY,3OiK;TjX}LoX{[0n*BTx0WP{1B::OIQvhfh:f<CpHs|Md<oa3IjPmAK1nwR58K5F?7uId(EX;4F9qAHQ*[2Ep-`Zf3bqPfw:KFX|P_i8klv4tn142BX_(E,:ImU(E=H21/Zn8<9x8;5Y0Gv9HJmTg0:aMy7>OJPG(y7i\\:z}DJHHEKIh]o(b/neZ56=se`Y0G2@wr>=:;P<HKMw4R>ADT@:sZT]+(5v`*VB:bIeJ36LQF7+f>n4H7<Z,=bRf42`67D,ab9u3kJhcjic<81};EY(\\Zol`3i>99)RI?:fec0Ej.}/\\gCyFry,*4`;gN:N8EtM(_{SOC2zW0PJ:C(kZFvzTT2N;TQbDjx:.r;8ekO)wMgtuvxg;2}2QF7`8bg6G\\bjR56KP4{QB64Tu5smpA{B\\N4-`;-{<Y6Pn>xg3,<yEnD+vs/}PWUKMOpE:81vDgkh<w7A6Pok05i2`RFG6)NF\\1Ncn\\F`uE?|BnI0zOW,^V*?=SRUha`gQ(?`i^{R9IWDYjKT)N1bysH6BsZu\\=<2dHnWF4c>K,KJDv-y_`DOPVX_\\QVI;`R5`i\\@=_x,kxbUE^@097FQ^NPgkGGRL3I:QlJAQ@bEY:58go=5I-=W@lh@j?wqZ;Njq3ch{:crFbc6:Gc5:va32(IVDoKkOD*PuNQ;*VC`e{o`Qakzt`c}m5GZ}\\*2G[M9xH*Vg3o3fUbCgj[R3U<v`ZKYVfcC_goP18R_5A5/\\BxNbVyy`;pB}mE[GUB]`A9Y<ySq:p=Gxdmc|ZZV7h8O\\7p-e>Yb@\\>t<aQI4=ywwv^1^nmw2fPnv]}?mnmvvpREka-x@;7^63U}uH51EeoY|T7J*DDv7pMAr>8JiR0qC82YA4gZ/@@SE_(q,B6o8@JTPdL:05V(T\\)4<n`8O}bhW[EaUsJ/8[0Nb2A7qOX4Ap+juXSAJjDLG^Bg<Vl[\\RScrby8AYE72;@30t+1\\KuAP<N8]M9Fb>G;UB38Nu8P8KjxWD:Om6EJleBuH`gC:G/-n@d1`Leml4>MNtw3om5uB_C6x1Oz5hTAa{r5[4CMG=kecfbUKbnHGHI6A8V9D0)?A;4q<{5Zo1WM]YK6_b4?R3kEgy_atUKr^3=?av>)`,NSi9ezA@g76H@R\\(Hv_ACn4Ry:itRQL35qfyS^Y(01>SLrM;:vsekN>lw[Yy_z_a/>}[1rSZ4*EvC,TNWKA4OJliJQ0_2a=K\\C3E}Ym8@hClE5pB+>:7k{uzLMSig<<OCX\\@fzF^0WWPE]>Acmclj>YmhWbi+eA=G2b.m1FB_\\RJ>GZy:BTQ^WS+^,S/gFS>h5iReWaVQ=GE7S_@)[m.3\\V4:Ju)Jf5;lsl0>g\\WAEr71/|H6GmKQ1D:0S().l;52W]DH[2eZ2?O_1O{5Nv`gx9^zznPyxkZ}d;Y@vN2Ts>Juf<\\9VIvEQ_1uYz<x87:Zpb[DKn7)2r54Qh3Awt>s^W\\^9:F=b^R?2mCCUWV<61MU(h@>wxYnii,D:1;y2qof^ABGvj0]LG9BWc>o[[aPtLn+QCVae|?wD?XgW=9V|H<E8TlP1_RF2,:nLz-=um9WjnwIXf_RE==16[ONy]Zaly|Xl;I10W0enn@F<P][@N@,bsb0{B=5vZ93V8}O.4LM9GPsz0qQw-4}CF<bL11q9{wM,7>JGL[<ZE,BiMgHi1Y]P.15@S5Tq|1ap0W\\\\3x4Lxm1E{{AmfQwD1u_9=,W==wq{a}0Y8rn\\0E+/a59\\qtU:6r21v>Sx=`?D8o>nWD:y8i?:<X\\S/\\/=WMhH@+/TT*Y`L4HKIa>WMQDrN\\Xzvk2^nAC1MpU\\/VR5n_i{z:o,y@|Risj?(220yDHieLBU[C>Az43-[\\e69BG][hg5?V;avAZpNXDqpF;x;<q25_ID`2s=cxfXg]XvLHUr>R0>Yx2w5t5SiLxP]{dS;{ITA7nD47,tZ[`<BBYb=:NXRk}^NA2q7}AVr_5_xt>|K>M4HPOE|6]@x4;[BO.9(e5hzTh[E=Oh}EgZT[RX19N{d9V\\LBYwIX0gUs[mOS:JZ+=yO\\BdNy/YU*6ErJAfAT?BI1(LJ20Ua\\Dkldw?BYHTqg[H=M;=]M;Hg7AP:_@a7+R1zkJ8V8B38wB^B==OKVQ^4|506z=][OWQ;e.bM\\;ad8NN>RFM`XBZ6e2;s9ejJKx8dA{Z>d@ZV4N;uEZTRI3;>-II0dG*>(MoM=]D6QD_C2G9}99?T]JPb>Y<iHgNWt_6YdLlT^rxjv{O[s4=Td^GWpUv1tk4I\\6b.\\=9\\QefX@1UJtst_wE}V2[W5^c7@+nUK?2\\1Os11/:Tj:`JG`m_?6V<V=[edG_mjT_PGM29jho:18,[-0`R?R89d=szHF2Fpr:hU>lOUQ^1CLLhDoODV`:XY;^}JUVkB`+>[X`wW`(rBYm6Q5u[UuM\\DvQVfW@5H7qe0E=(1v5KFR[]cAUgK@5T1WtjVLoYP<Nc?7b`nZr<]])Gd[5UaYENJ4hP8]8j52Dp,EHU+21Mx:yAD>WdTUD*a?SaDWx8Mmmgfpk?R*s>BKYB2OX<pxN:xjA/<F)dU92vFmt=ftc3C0bH50kK=n1700f5^`@[T7x0Ax??PB.@7UL+8JKWMgj\\R=6L1<URlx*WMc34seME)7;J/0x9}6pTwHb??f7RyPK1x8OxpFLxJSxVAF?u1m2gL9+77AFpq{1O1JWKPOQ?eFk)^1721@2s(2-x`God{mbp};jZBNlw<}I79Cgl3Xo/2*@FVKJZgaJVG25{9XLQ{EwM]=C5A6G7q/xJBp<MxLM\\Qg<C01<m=C{qO)v6f>BuJ/NQRG1(fAq4M?:`oq`PA0^eVRmI_]^|DR3[p3>H,OvhJ9L5Y;aa4/yS_c@=O=ddd5B4^x5dK]yjH)aQvqcv6_CKwVw1|g,_151T0ez{j|=z3_c\\52\\mKLsPV^VS*tVQchx}A^>aRpdalnACe\\F^X10pv+q^z@A=6f1\\Cpb+t>Ut{xZA-\\702><`W1K3GJhWn}gdg[KR]oBsRgmBt>prTWffH@ys5[I2|5*5ap<P)K]v*QtkNi1f^X)NBD<HMlEAr0Ni?-u+Bsmu:8EiB6Qm=CH2K<OO4u6cjKhZuR<Bp6=oT[l:V}Z9M*A(dBH-=pu:4;J,.5OA?)zJ0;A]bB5.,>3@WQTBVDdZ=+Gw6>JQEwGXZ:TbX5c4jp`6GA13k\\<=:XBSons?o|:t[B6btg<Phm\\.|]jyHFrlJ\\H?@Ewv_MyX^Z,p9OE7_:Ihvq9N<}Bk8Huz9QPxFP2tYmS:_QiJAPxy<}Xxge,(=kpt-c?Y{cc}8KnlxG6MMYd`Y8F^3cEg[3WF6S.O7<tY9sUBAj\\aZObOwrsc2V6Wo:UMk7LK96sBLu*gYA(RS=}PpI,-CR;VYf?[uV(Ft-O)Cw87>l>e0oRb<<3IKqSAP^6Y_dl^LuNGZq0\\dh|[-7|YK3)6dR<74=B:amf/@E2h9s`\\:pz[>9mw>ae0)b\\8O_Eo|3305`*P8kR>NMv^CHfe4|K}G2y1}_Jk>4cjWQ38uF|y*|zB68;@Wnzs=@:96CF@eg5D=l1S\\BZ7E6v8B}5G8U</T<]}+6BGb48QdU?B{lPQ9sg}FAs)?:[D>@6XXps7Nau7cr<[i)Ju?H2ns<<?(WZnVNkuvY3Hki7|[R0VPKVJ|?{M-a`ubJUmmdPSn)o`u+^XmRi?:6]*kO1(57ur/]SK5]TL}BGwpX+U=>X\\XFG\\1OR8<NxHR1uGc;5uK26eWz<6ek4FG=H/JTfE]E.E)836tRHRYBVGuvP,^AvXl6Ru:APn]H@Yp9EhfOe>`2TbGpmq?Kh2sH0yRd9G1ac`[1?9BqQYFEVQP\\h-i)GN:0uUMAQ\\<I)dX6UqcEA;f0+K5]3rt9=}3kHdFFC2UkguoK:KRzJ=M8wc=;?8/eGu::1fF(SrT]Kl32=b9<|b.^2+GVIV?`eB@][H6ECVK0ih|,yeWN6;IJ8:/,NfGQA;7*tYQcBubcg?]`ixuSjF*\\^q1`9Oxa)??8Benc2N67OtPj]LHU2iQY+zm|sPUKTG2]jQa>305EC/5tXn93r0;F<*<j;lDN;vzH[<b0FCX3^{s(V{195[g@A@SF=U,^P0e??8W\\)>L.cNpLj3(;LB?(M;..\\Jn8aZTILh:H<a[PRvnxKr40HXlqY/nP}M.Z<W)@hV;]t0<ZIho_FMIeS=2.vW>,>([gwlA\\`4Lq00|VaSW7X7T.n1T9LK\\0c_Ji18*wAPEWIlV71cUk<A1b_zv=tQLPv8dyH:e0zh2mt*ZW8;f>o1NpEXvHlq}U7ikDGAe[VRI|(@)@B6o=Dm9<JBZ:b<]nJ\\_y>(OVna6-J32b/t\\-YMoX.f\\sR1*h+M6AiePGF?(P(P^FT[?sn:9IAB3;]L0Z||d]VdwcXV:0D2Xs3/OUv|qFwuWu?nS/A-fOu)AYjm^*o|9FcY<RjH]04C0+P_LQaj3zSO>TTqR;7C2F3=?oKG>pKD*IQkc,Q5r,`Wu+CxK<g?{4JvrzL}V.UeMJ;i\\pDL0`eN^X/;0b8D9OXgrHAtZ<SWR5b7}1v]4)am*2\\:5gd:TLtOw@,i_NamvpW4@iP_IY\\U;DlbjGTlVY1D(H(Rv6++4qkfUm|*:hoc94O52OWC:1QR`_>,5iDM32C4|Sq8?FJJk?8^5W=u0_Gg@H;/Hp}74^58Ujw/,?\\`D<2q]2W_1q[`7TdL`MPu-d{S.G?9;w0>-sDUs83`=`t[X,h9cu}0U)sIzBJ1(6]XG^ML)e)PH0SW50=vVoDxt*gxESGt;EE,p+L\\C,2*1F@ONY0L`usMWDQ/WM0XrFCNQ\\7QMUSHNQ-,?yh/q[5`bMeoaC7l{4X96g6gGt{=R7H_e`[g_Fmp0wKNsB\\Lup]hHHcd=2+opb6q<_U3T,<F^OuMAk4`:dz@`9xU0XcQDu[s0uw?*^_H;QnUajg:8RE<LeL|@iT6T_GHPPJmV>vJE>Q`DzMQ^b1oTbbG;7FlXPwcC>?aq)_T8MMLTBt6`7D/>/:?J5[DXHiy?f1nPhY}RLDxs,L`0DN1lk|j:1;:@3vh0yU/b4/]>Oc4giT}Zg`fPxCa:>Epjk:RBTo\\[5[+3]5.p0po?V3(sb0KCrl05DL?i;jbL>/<TKe4q]AabFK_T_{Oy*=2=GP@:[2DuT6PGla:qBT1>gcADNS5(Qk\\sc?_O5lfJSiwLAHa<AaxuU}dM6hDbvp89^W4b>MPZTZ90i6_;H5H4;KW4fVge-L*O[<DExnHo.AW4ksM;9WT34@4|9N4as1P5>Q5HBVHrZ{.Gb_W4YuP37H</<=}E)<.=dXMil{uCD9m?UE7F)r4j_V}6?FT@RZF(W8cS>?aXbsapXwV@xnV4[MmE*v=Q0>6<9aG=VUda}*c/A?Z[Bu;:IUie*avGHn{1GyG[Ar8TLV75>I[<G?IR;(AJAKJ<tEHW^|nq-KnAp<9DvXC7fZW_7L4v`y*ogRH6-A@.kES3OEHYJ]Yw^]E>83L}o<TgzGpC<lThFYBx1J31K7ateRa{>2ml91EBo/>prEd?w(dDi=LO\\=99UK0C/EsgR/H`RA1=X)Lx/TVqauQq9D1m2Q2a3C;[f->3A88GK@?vmYm.TFgUcc]vr[>}C2GTQWcC]upSLc3+?bFzhXf`*A:|ZPMpJD2p^a})>H7nvNWU^KP{@pxejXd;RR6>e5>l@ySWc3GF?JG9AON5`+uYNRO{g}7`a-t^/;GKtzD93ZG4xK77?,jX2aZHvNy=0bW7uA_J}_AxU<H8(v_oDhm2jNfv/;{.6O;Ah71y>WNF5GN[y_VH{`SvH;Bq7Qzwz2HxlsDh|=EU`;2rwJua4o=n|=^RGqy^rC:P86<DXVe>.T*>GY>lZ4Y+9PZm>NzcC4+O@lz8A\\QC8/1Kdh1]^/yR7a=TqDI3K0v3G`@]34:]AfP1ABXHnI7qJ64w0CwA>SoT9G]tiyBI/^,1KADc3rU]>\\XA1t9U5:@v}?j=ynQ5WNV1dZ0DfjR:\\33{M1rT_lHA3lT;Rc:>Y[-V11]JaR_@+qiupZ?bq[DhquRa;E`gLt^]A0GDFdkW31?1V*4fdz=Ud+1h<V?_AnByjDO}H[{4oxUZYBg3_Pj2U6b4OS{BLABCrnLE6=?a:63_NmB@Fgv\\lcc{8=QD+=2F6RkD=3v.qnDvl:k>JC2UJ0:3J=:.So7A]nw.3<yUFWDfJ:0XZ7?dA3>Qk{nFOD-0EU;lA(xGIzBD@/saB}<L5I1^N2U56T?LI)DWD<X+G3hV7pJMTBe8ic5LT6C4xqO20Sk|YOId\\UlxY<f77haOdo[[v0Fc-b/xG4VbU;owY]a=uu/O8;81-ej+inZIDxS@3E;379S([r?.Uo|H7)zU<ii-^7K\\RPE3M25I3sI+`hKI;=I[COdKHC*49<xF2(5q_C4e1Sd2\\y8+scvu{L\\Z2Yz1.iEpW14Dl>;8cJ(NF?oXoMd=bxZ_3W-7UvT_UFY?x4fCnliPkV[qXi>Kb[}[LldF*AY?BBkV3mv2_sYhMgD?CO20N1>eOkOG80Ik3mlm4X5R5T5YorVLMDq=SdyMKi.BWDI@jN^dM-^e=[Jt[+B2/tRfdX9`gM>nevRCByv9AcWi;^1y0z4oH_*8Y1v^d7M_.hJBr/+3a6KKGXS5FH[44H:Y?L>;OdbuQ.|S`l4Mh1JTU.NO2Sk}4(mepUi[8f]MQPQn[xG.L1?aH15q@Ej/7Yn<tE9g}oIRN];0]/SoGM<QK0`;.1H9++cZMA4N;@NJFw[96F4[IazYb<0y0::X8BYkXIxpK`X+yR,ABKp=G(:Z-5EA]rj[<DdL56F^utQ_GU7*IOK@grFOR2reOJ6Lr=BJI?7<JL]=OTA^.87iIdNh5gJ1i2ExH1o3Xm[yd4.PJUgP<uA/ByewPo*54jUV/)nAYb}*JoMmQ3;d.g_@b426ulRex76t.Us=^1IbgmIsGaFR.>QrC1DNI?N\\1K32g6_D{=<{PB=S^,5{sYce=am@lp9(rPg`B1[-<NW3/g]Vo*>P+q9R>uI;?sJ9B17>>>g>GS4GjDL1\\>,(9:8Pxy?1<h:w`{>A.@N;Q[v7k>qTDW..E=IEJe|9ycNRj\\Oj:0SP=qbS3O(CXFWEc:53`:D9MY}k44IzXR3sck7.Vd-10dU5a^U[eCuGQ5UU}DkL9-0V)2JcUj>9[e<1Xf\\hpp/ITz59`LGi<bB+;b}O88wB8rr4[47O\\@s:qz(hRR5aOP}92=;70NiBhWp1t9UI71`i.RQbq88FR`2>E\\O2LhXKD:[,HM@=ohz(WYCSW5`3_,b0\\;og}p6<}}W-^e5BpM``:34at_,wF6QFHpT)Z2][=e88{>3wyj?V)wVh@-9wVJ\\v?h/X-]GNhRbQ+:<Fs@)G8mSD}H4{q(e0|HPA9(P52b3`IdGE>(xmP1ANLt@)1A4vt9Ki`TRUK);YqUFpL-[1Y3*=_WQ62d5?B73E[kK@Y>gY1<VWdMe52JsoZ6F|vP]<RlL:5k+=TV,V|=bc5}awh@2,B>[RfJ0]hxr>8guN?Z}>hqDF8UTq(n9`YoBJMmiy=fn,{3h6,:PL8wvSU9FW5+]CWGBr5M`Z4=PpMzB>O]PKM[8Equ3>=,E\\iAT13`gI*}10aaZH5r9lYpZfFAEe}b@S}oNjQni-K?B;MHi;?r}6DugC57C-Pt/f;OZ2H]8(w,o2svz3610.kmPOh+8x6k_yu5ddq|+i5Z082RTmm6`YgZLE+0Ed?U*MSUbj2w/+iQ)Sthfh79X2mjc@VPlh0@5[hn?6w_boRjJ=P/,LtGa0.stLK>LYg6gYJ}K}\\:Ir{j{.hGn6T9@>H`pp8bBZVmFHm100naju-LAd@[k]fHD3Z\\hQ-,hRP9I9CDT@>8>o]Fh59m56i+u>7`ORAg(9<yMyriHAIHVB)ivH`PlIeJBY]oaXF:6t\\0:3NxlDI\\REK-6E;MDoCIKbX@_yYjC9jT_wSjGf3p?/4*^|tPg/fEr\\>HDLL]5O0n@7YhKB:2cTX=G@qa`ws@FbL/4Bnu{hc{7|P37,p[=EpZ_C\\_bB?mE_?kFfc*LT}_E>eAqfFbGMg^;0YAYy_j;1JAL=1@J8gLw[Y>{mj87pLJnY2p/0IM9G0/q6ns_{@r0FwSg=6L<XK9BkT=?h4azHeP@Ea+e01qESl7Y88RE9T3xY0N`p-nm^[LxsiP_4RY[k^hDi))9AA+=?qRw;E_,[hdAA0/15mU\\:A+|BMq:SRsJd_J:i{*vY\\DyT?kUxpM>N`FoVhr89V^@;\\eo3@XT_*l7PIE^+v<rAMq05bbJnEj8=Yx07_Hxy>.6qK;>gO]1MvLpzDCeHNTHoN=<ztvPAr3IPf^A2nIBp9QvX+S,VBa9=7REll87E5+0J>r\\?>JcxNBm3jgy>pkdA^BV.>4GGM2q3tH[j5aG1Zp1u<@@wjed6wD;M(b>oBx0780e?NqSw;\\EpD+Dx6K0-@8MRzLI6<RmHla\\wq_CPD@+NFBMc6|IN6YS]p|QE(EAxK?O7CUY2sc{c[KRo/8):WUYlr-\\87G:b@}77xe,[*MBC?9OQfXQa79Qqra>CCq(Rp?M3ron02+y>|uR<499?bV:p,4Sh>5,lPDN/@*luDxkHO`[W1+h=gw,9fWy(<7NAdDT`,2Vsr}GI=53F\\q]H;?=fp=k-9W,+Np4_rQ\\Kx4y2`2=[yIRBy093jZ9USOT^ao?@3vc|\\iX;B;54N<F.H8dQH5>^Ry61GcF:PF6^32X(Q5+fza`KdxbXZ7H:JlxTfwrXsgT>T8\\L^`k0]T((Q8FdG0F0IKj{Q?0_RLoSI[CA]cxuz;}MRAs<[-o_En:_ghJK3UXzO72A`Aa\\^L74P9{;8RLc/CK*@>Cf@yB=o@a65uu{X,JA]vrWyE+:J54-nnOxu-YU[vKOL@\\[r1D7,-[)@SL3a<ibFF_R/V9D:2b]=PLt*M9kOE0tp;@/7:9{JUe6=BR|v}r,u6\\nF=ln9;^JqQ/yy1TvgEdk3J,3EHNN2WA[Op3,gIl2f8Z1F,U{_Z<=F:3MB5^_23qcuQ{SEoFwb:sQgr;:6Qy(@lR,AW*rla}B<oxNjQ0[a.M*qDaKDBX*g2},Tc0|r}Be+l=[]?hs_)N6xGDgWd*9[s]CN>OV@f\\07]JKQK7`,S,.DP:Az01T|_xlcRYT02^IoEB`;Z26qx,kOKbGQpQ]zm+_/KxSHlKLIfc}gOnKjSST/1OW[DUg?(Ii7*1R^W07>Z;?h]\\^:bG9{Z5MD5NG2F*,NF2Sr2W]N6321g]{TFghG?FU{(c.-_?7qY6}eEv>=)pnIGDl1^vBpC2FnVJ;L2=P1u1gTt0`6xr3eA{at28PTu<_95Krv<41J:6M,:Q*C/:\\5\\2rQ;7,N0{K3GAXGTKp.g5C_kDTythi8>RFzY2hV7hKwpoBU9QoSfqWo`KJfu.rZ]FAD0_x^,;j5P<8Ta]A8hCCBO6MDTN?m0D<xVL?skXD\\<6E<DP\\cFzw[z>Ygo59Gojjf;DtzOrQN`MpK>yoIR<JT9J2RVgRBP|ZiY|)GvdM3d5R;TH]=u2u[UFm7HRR]`51;k\\x_78awvt>ID@|Sub1>U)-5t]aO>ocsTN`hkP/j.>L(nCfXD)bFyI=8U]D72lCJora03k3ueYGU0N@PZ3sRYjGV1hCb{?STSMN0ZU,XnPI:LYt2WY?KKAw?2duFECPu[U0oy?ZJ1P3Lt67;I7.R*7WN3Qd`w[;-GXc8Met28tq+ZD6c4Cv,.TJ46A<B{CL)l*9@3<4vDl1J<0GO+3b9Rsr7?QJ@i1Nn2t.W-oy65HC^H8AfC}PPANYL>P78fb?PChJ0C`AMUFR]e7F=p03AjP{fU0u{-4>kVM;92>g<>\\^\\4Ve./Vm\\=/GHTywFl>qmq0y{0H;35*+B4\\SrJc)0u:IryZ:{6i6I?up/xY1*(lW>]yIvGBnZh89B8e?P2uV6w;4<tG^92Lbniefuqx,Ao5Z41e+3d@S}]pF87QgN):P=4B`{gNooym5OYH:aI/VH1`S:^QL|l,J6W2<-09@nFB:64G24\\K2U5Cd>J+aC]s_:_h-zZH[^Z46[4)[}7?j(G5g4yF)s:a|\\;z=S2@rrV;>VD|3c<JL*[g8Zaf2.jRUKXfXdjz,P5(@tPg?<_Npas_]V^;b0UmcWsUC]X:=T?a\\T.JNqtHW0jGOP17pW(+AZadKD4UFI/}6sg9Xq:PcsGP<N\\VO2Yu<)^lP7t;U[U5KFf80:FE8cCa\\SeuEW1CqE}=kt;xN<`6[jdTG>VPc=CLM>Aw1n8kh>h38kMK1ihk}HHAQfBlA_S,R5QEQ}.CoGL3<8pZyv*4Ap(^2.E7;NveRDE\\8:bFH_Muo?Yy2e5):6U<yFObjj\\qkx1:BCic4S(hPE:]\\?|3AV?qYkBQo0_]wQXU5>n`OUnFDv>LFBZBMKM-dOyTh?u[n-I-V9g^7^zcuN]te9hPeI?@8KP^\\E0?eC/4eOH_.;0MVciVo:4j30jZvLz0WW@WK0x7<]xkG;0>pTmhXURjNYwy[]2V7LiV/[eY[`X]bL<VS;/eC:up-Q`ax2o}7uW1d+(xl2sDL,R)<`YIC|^;/XwXD50q](}LT*Z^w0<?TPRHJx):-aGA8T?Tx)XnXW,Oq-IC6EG].J:K;vPwE7LABD:?lVKfuEo0388.90gE=(vDrgJ[pGJJ/TLbPr/7sC4qH2eWckj6A;:gXHP,3Kbs,:D9-,8*AYMfU>VgIa5ERtU:^9l814iMAG1=6<D3.Bbc@@vlP8jZFv]m8hH7KQz0Bx|(TI(h]xEK_3TD{pj5>O]Fs.TNTR@Rq17q7l0CTmJ170O:WDJ3Tg,ds[aPa31|63kdVfqIRIN23js;`}_[*U148k[c3H<@Sp[jnx2hBYFEJYlE0Vk^[Ig@ronm>.AE7]9<4O*e[<}jJ[T5w\\p{RmQMKXr`HU\\+)?WUmv2,2)HVkR1vBMCt0l=mi]6FzE>AuK51S1f1.T8H2cC7h7S2p:2Z0U^WfKMS.PZ<;w[<BFL;q4?h)@_[xr*`;Y2`9K1:;hZP0oKz[b2N>J<n1|D3CCw:|TP6EdlH_]03I6P.<W1:xCsEg/1r{,ow0W6L3=S62F_AkLnA>FV=N(xtQsLKxw7g^\\mmK1;19A>Jm=YZO96[/)337k<3?y;g@i]?5cCo)H*87*HjZei[w{<>yGo\\iIgRwd7Ao^iP*lC;7IC5<j=eU287D1/Z6Ce@d6t9y8H5Z|9,wpkz4optK03HCX.i3^I^XcTu6td[4x1MY]PWIoicMQR6\\zvuUfGJB5rjK|sEfl:FNnQ7UDe`jBs7A`_>T6nOQW?9\\P|Q0L>J9We`)wtCJ(W^O0nBD5;Xc8@tpoiJWfS1JSv=Vh>wW=1N<Zd.:h_JLgpi:*eW7YRBU?`0m5t1tOB`75JUH78N[1Pd\\5<bdYKm^0@>n3SZu:,|q@6-h;A7,)?iPd2i7Oid?9M_bOX5?=\\wHed9RC9n4J8K*=ROgH-<nZP\\2D9P`=9w`I3|\\xTkW[BVf]OivZ=I@q-3tAZa=1ROqR6Iz|,2w;-H]=osf?oe[HZr`FT<M@vk8bcCUedpi\\LEE9\\(wE;PXrZOZ>YiD8wl.+626<5n4MOb.D]Dg320XrQ3E/|NBXbH7Lv2pi@N7C;^hj^*}?HIIFlaLFKKak@4=C0xUpP5pERMIM,jugJk:SJ9S;MPweghD:(T^y9p*@NjGV-2G?\\1VvB->^|*QQSzH4@Bw8t;s3}>x|M4pS4ECs]iI3RDhc7tI)sF7mFWeE<CLH^fOC?m)3^6WxkpWzen\\7e?7}@y6H@@O6sC,>2]1u6<]dQD,?=Cs5/GF5omWD4)YiV=54D7sds6?na4eLqr7C;+B,2?GQHouHTcoJ-<Z(\\XRW8|CRz7;6;5W@4cbyVHx_,wp<6lMfEqU/3BnhfEj]FM5A?98Z1KG4,QHzMe=W7G7:-yY@eZno;OH1f6m?ROc^gTAQWU=2P36DV6oS<(2-DO80j*eC44EG:88G,\\_G[M9f\\_=Fj<1UP1VB7X1P5a0<H0lTcqWp_5bpbT`AH|lcvyWC4q\\H|21>`6sE?8asYK5I6hgU|zAZum(gzY8Cec=7R3TL`SZBX+?2.*B7g6+USx1CDZZ<)1Lpr3D1|;K4:>W\\Ut/X=7H_83;u0N2QHgcL:?zT6GLnOjxKYGd\\k<`o=5v.l]=Bc}Tq14M^*jVyoJnX|r6>7q4k36oeLIo739,9bL<<KDXV/V>d9:<pP9e:)]?QH2WHD{/f(oTjhr:/F8X:ssA6mI>xX+*}teN2ziOP7RIO4NjRw5-yp\\uVJq0AMJX^n||OIFl9F9p5Lw44N1=CjtPGp@+9\\J3vSP1|gVkxNKx@fB^K6]9?Mx,T7i33t.7T<fj1\\k0*N6BTI>iz9d(NUYYsZ0^<45<4FfO<>Dhuem<bb{B[Wrz<hdLTXih)AJ<p3KBb;O`}o-*:Y`;TE`@KqOg3=iCt(0U2B0q,LXT9rHxCwy0DQoSehYVcGGVG4b(lOWG8]}XLc7B|XRe,AAd/>AK^ID3y5*FGEF.S|x-<7`R@g/0-_j3@(-^AF:*9MXi9M.}NUOivl;6AjEO`3GHFuEw+Kf:s7JXzO4ux@D)OHD>k68n(W9Ud]2j(UR@4ld-B@[FHgGTi,CMZ0<3.:_KvK@1vTv6<omUFy7zb)<<il2?M{bwakDCfn5V@<;52L@Jg`/.4<BQq:fTOd4w:P=zQ3Y63:\\L5e8,C^baNfD+M_sw/{waRzLe<0Z\\VBMUE]]uOd?Jm8EfL<-_E<^73f2CuY^B`lIi?hU7[o{}\\U\\1uX7>ryQA>*8d;tMC<Fn=+V(EO^L7SB,4AQ3OhZiWuKwHFTp]@8.4la|c=}EN{E5)HHMF3CEa::HK+})lfp`D(@MI[QUKN^bpQmWX\\bRqtP\\rJ1K76g^i;[a\\ED5PcIw7K;U11=Zy\\0.l[=4hNN}4O]H;bh.Lqn0GGh]5A}CZ?hFzIUkg^xESN)6XAI4JihZm{<30CK;(3I`.Yo3S3y9^PY-Ulhy>*\\m{g3|]7j1=MEAPhri;^EQ.8)bsJ8-APE8>S*_-tTD0{o099FBQ>4EI>cCJs5bSEr{CM_QDG];Nwtl6LdTaa3/X+.|/l2hfbMc2RG=_7iH+OAEK*.)q5/m7iSu5|`PrVjte4wF+HLVShYy/sIMa)3B[,uW]wWHVZxRiCd2WraBbYU3*{mMot{EX\\{+9uBMLu;q8u=b6IDWt=\\)=7V;I35Gtj1f_[2q3B3TOzlUstONm^FFhw|j*04D8Q:8?y>K;SY=tD@F-k;]/Mk33oMYj5I(4(y@zI{L3KPG1y-[u<f:IG{d7QMZd>@zo.}(c+7@js[0u:z?9l518lGOS0pL77;XG:PwI>FU}?wEWX}V7<R{^\\S=YTj9bUgzE+7i0uj=8HB4v^lM4>}D1888?x7BD^l}8^Qr[oY+(\\c+Bba{04-.(LN]5-5+-R<a;`@iB<AZ5N[l7J2Ji\\_IfWsbY@X*g0Cgmih-S,:Yg@Se1flwp->JE[wwiw0d@V;4yT|xWFFH@)WX{6FZM4kD0:W1|XqS4>DQNtS(\\DBz;6UlO4j2qOQh90p+G:2}QDk{w;>M)IdtpT;UMh*>>VKxjw0+CwwDI-*o=2uko]JSXW^LfOkG3NA2^521u,?xPqIWia>5:Bp7J9Rpi_C|6PnXsmJ|e*BS]VMG?6T<0G+^{ZtQLyDMTIm-@@ZU^uEy4CEPj5J^V<axPuS9Q\\z9rFbo^JFggoNMm[tMRMZaBw=f>1?6_A^*B@/|AI>9d66GY@gp8X5HmA:.0Ql{M6Asq-DB?wUH[\\5(P1O`:_/SjcGEe:3xWu1?IZC.Pbo]MP>7z*j\\Yf9rmTCf?X;6u9^q1yr*QTX}XJ/r;+NG9Xjz0{6>-4nh3N.7EZCflFCXz[0I7C?1/Gx[yIy7g^V*eM:Q4l;VJAj3X4q>TGI{J<4?HJ2*NQE9)Q,54n;L5bEuJ?6K6:-w1LLsf45mRR7gqCrr/[;l603Xg1?z2f?va^4V7rs/dqwF74>K4W6EunK0?i*9EFI)jabw_Y[.[|1B*J}md<rFrOs@|9VHFqnN/PLrW*RR{u2EU3V^*?08ONypG)9rxTtO[Eh+]0VM0[;9Od=`/8UD|S.^1=8G1}PH3XBT(ONu,<3HI`_2Yq`rMJ;6<e?3M/:1=BCPK`X5>y*1Jf6@rcPzD`[aWRzfhRZJSle41e9ZpZyNI:^gl6Ek,5<GaC3xr@XBQngdhrRSjxs>WBHgQlPXK3E3=8ZbUI0IT^I@:HgMP+wDyuhAzJvc,jsIv>icsAxg4:*wh2`_;Y,8i@A^VXf3b`E[Fr-xnb:Sw4Jt^kYzuJ/xU4EiPg1`1yF2T:G(7TGMkY8b3gEg9PL@3U+|4_w`CHwhSdVePDx;PlW@E\\hs=j[?mzoYJeksfD-K[(Y3@)Us2e7cuAw<6nKZC]Y:JV8<Dr\\ZzwpL-HEUwQ^/n0>PXEEIV7<g?yG59zbNfjv)dSG,yN(i7oNtl9px-+H6M1dBT_yT;(Wq{DB]oI:I]m85yMQ8?k(c5/73-9Ef/N=^{W_Yii(E3AlRh:)inS=qjLfox43i2v6>nNEJ6x)nPUibQQ4Dx(5P@)KGYg7f@K*c(^Cb8g9GU\\+^Wg5Y<HX96Mx9<vA84EM8QU5@KXzX>@D<h(A,s7AK8ZIDlMuZ:HPLfG>s5`=]7l2I\\<i:G,)yT}V|+mVk+KOU>>eO^G^Z,|y{UBWcV,o*DqHW;Xi9OF84:Ya_x-J*|VLI*IxX3I`M}?05;xF;>35aYZt3@d24_APoc0ulMhTJp[):D7]oE5fjK]Pr<GcE<RKCN36usbFG:67KAZTigs|9]xBSQMKVFmDg5?X4yT_yB5\\TNljL.\\a[b}<B=VO7_C9=7ceD5p|HD+_F`TrbJv^A?E\\4J?Bs:85uBjvlv=G(cLu38C25.`b][Du:X8|f9CYDcH]N5uj:e<:?b1>l^8/[:L92wxVW)q;58[57yuIcPVtQTCd0lEVf}cQ{AD:aIs.u,Az)P@hYJa>.KL8>.YO_t7{i?o31kCdguIBIBKc+-9N>4^=`ohVOn-6FT=@55*Q[@OvJ6Zcb6Ey*9UCagBf8`9Ukdh0^7-=-M3XKGO7VOs>II_AQR84@N-X|T9:Jm}F,WvWM.M1AqMf@n\\cPK/0ShAG}71aiKV,qUGAeP9;PYn;M,7qsU4G{PT;0}\\2IRu@FC@o8Qg8a(_7O\\k,PLHV@2YS`:9aM3zSU}W{QFWgQ[/?vt(54G.ZLLNC?Q{^cg>osB5t;8DCACc9R_Qp]}XEBfDnDiOuy=dL<5V[K2@`uO0[:30A^W9MC.Y4Qu?VM^\\io2BZFW_=jP6gGhJmVFpakBgA6:8mUgVF6ro^VdY@4:3v;-[fsgCP]eTe`2F3KF>[=^0|6F1[Ki@8v.9rNR@g>2Gt6?_J0uFoDM}G]g0P1IW,z0`QuT[DU;I5YFQ.U834Le1Fy?=AU6)u@@)c:5fT4D]LYeVgiv^x+yL{yWT<z2FRHt<1=BH:0\\PrAajNkXVBO8fL`t?k`yvq`Ai1Zy7RlO{BKiJcl^]s[*=ap1_vM36<4I72-l6GP3rGHxbwI.yPkS6kwkN[G9M(3czBo>83Rf)vjv8LYfY/qrpP\\r9BE(Fh4:xfxbFCeYGyc8PaG\\\\fABEIX_uDcV8-pro:Mf97BDXnTgk:FsG3\\m>l:C4?5Y_OLGjzQ/K<l=SOu8m9m|mR=Y|uQMSbwoNHIPt:.B,V)1_H{f3RRYO3kC[dZW:7OJA9yj{9ay|p[US\\au0?,h,bRFK)h>Bc9s2G\\\\6XjCuAU81<}Qa43^Ig@1xR\\@1T73B7;GHE|?m/`\\n:4bbXaFEf5z4/e:fWg1*YCQ-J|NH@SA+vSH:u6>u?7O27oEUAM-?;`.6A-1sc+B.v:b9=m0Z=x,jEavmWY5P*Ydq5(JUe[SPbWo2x??dNx\\L]J@d*`2eWTNUe)35W\\CoOHY0FZ>6BINl@mo9G@,BUeL(I92p[LS/nZ(Jr<G8WakX(EBWKG1PZYT^0pK9<Y:7]exuo9^,[LmhL]S2cNlT9:4L>qMgVkOAHv7:dUJ9SFX8Yaq*wS2?.t4oEy76Hqvn?m\\wf@7u1Cq5}BA0Jq1ZI.|2o}vQQ/g;B<Le\\TYLXzJ>;IHoMAdV,=65R/IC}m1@mV<d;C7Wq18o.<RO8uZEV?Ey=q?m}n-`W/JE1Qh.t^>C10,ZqZbGfTFTG<pl(BWtuIM1Q>mESTt\\1Jd`Us2Ae3gXRZ@K}@bk6we-K]f@8dvV49|58D;n6E14Mi?w92Z75J4T}IK_7EZN<cp4;2UCs@0>?S?>:gXWW@QG\\XlGN{KBCi/[v{[L?rjULGrNS@M7Sz3fP6_bu<I9DJ8NAUUl]6;^LV:3]NW4p_lQZ>4Qp/?=dMWc0?KoO].Ue@Fmv)U^GpwJ\\zbmO?}5Y:;L47s9LiFI.l+^9d,:;.OF_wHM4H4Wu|(co=)V;NId52+6}Ig]:]gQLuW]KuRszt6[Y+8SQ>GL`RoYu^=.QgEGQ<fJ99fvSP?:5?ycL[Ef15nLoU,AQ=Mw4WYq;lNPKr/A|{jV<>WVl*M,-e:Pcv=b^-:_oD*8etT0+YV[{<rd[6nG2]K5Rz<RW@PHI\\sRxu]TJqCWJB3Bi;4<Q7z3m`q{@c;K<|.:WNWPzMMN]wae5y+ar4@P4oVk?qsqY]+d4<@o8\\(C=P7;ANRVK;V*S9NF@(2yhcKp;@R_mShH31wc/z>68FG`pd=-Jgp4{3`fHjoT`KUn}TAeo_MbPjMBZr9N^Vl`_XI9=1>[*UE-@C0h(QqW{5:D8_e;ZC_ccs>4WNL\\lj_9xsKlg/`)I,(]ws)7=BObN`c4gz<P=Bb2@+*q}_b8KWsDIJdTtqY1,b9C0@F0Ux)wK<pNAd:f5EWBi9fk|r2l8ok[crQVWCyxA[Jr|3F-NH_l+B:Z}KDI4n^Q[FxBBvW:]KY[S,[7LWD7l9p]NuoHL\\7OG?g]V3iR<fg>C`HqpBQEbTwWhQi6CX<H7DC_U(]dzpd2dd3j<F{A|>feO_xD)+DAxKYpaEu>5*aE2=bQ3c3,62ZU1VY=i7GENO^?jq00\\3JLE9<QK3zjGb)|7.oYb\\\\1,6=iJj,Na:L`:raYr2=hdXGaeWjDGPsJ:lKVOxT547c]U2.7dR2:ZB/X:@}->otaS`Gl\\QI?B/s;*2n1>?1^B604Y*Q?7laz,L7@2o?:;fF:M3N52\\}pay`cIi6*)=wiFydb<DvhAC:>4?q2\\v.LB0WiLC`V3r^}vbVb=s:U=UO4QfY3z_V.?h7?qU]Fb6V;D/oa\\eBo.hXcF8B;e,2+M=oY`fbOd49M-GZS/nx6l2`S_[1GM,\\L)=^/OE;Ae5Up=[kOhhKbW(iZT8k{V;h>3M?;UC:Nr+Xefqq)xNF:lUN_zGW=46wT;d:=7REYZpG=K:1/wUW\\BA}qHd5yi5+/LM<m1Wm63No9Ke|)L`\\\\@ZD>?Kxn<Fm|P(d<EOj5:xXrm:,zPBHZn2Hs1w4NS{Bv],[a:61(>2@^?TJc@i{MJDzgDsUt3sy-L^lKXy<+uRLl0Sd,MR6XNdD}dZiFzP_GH[?TD@>Hx8t|Tf+ljg?{_W=bY96A<,\\>j<n6ZL2N0}B=Ltc]8?g4vi7Wqg^lK*)o@s<pV8zIGa59U6[IYz;vtgVF|3We.,NY21tDBK9v8gxBR;^N?pwjRmj_E=6*\\xEh>yH`pgg09aGRFV?L3VRyLtVz5,}l*7G+l]91iy\\Y51IQZ0z[v\\?q357fk2EA;@<83)y-G{TWPH0[C@F/m8n3Be[2At3PN[[47m5jms71;}b@1`Z5lj[J/2_fxAq5(O5`GxiBtD>mloUy]VX>Axy=.Pbb6sLLD54v-\\/VG\\EGNr:D\\W=0Xzucis5t?vA`IUVrJEN`]bl1{j6<:7AW;o@<paaP`j-}JY2\\H8*SP9?Aloe/mjY}F;j58H\\1]Hda5\\\\z[]Q<BYg24Sz+bbF?`8al\\WGkpOn5_>>Vex}WUOxF9eO+D5=mDOf>[BsC0?K;n425{HsP]3[U|x6@*}Mk[Y\\RjYtzI,Hcs\\UD6BHMB.}l^[}_i5hPJzFcRtf(;QwJkQ.i`o8/3F)>kqH:1*jun\\O9kx>SzS7.4}2:UC<Ye8uwmK=`1UdC:Ma2*?Z5\\7EK0o8;BcEa4X91IN8g1\\)ee>{6)E@KCG:7@@tbBTCl:Z2EzGsbDfHXLA4I4+Kk*eN4RJLW8m}`{6(|Ao2o2Q0Sx|\\?=Nl/I/FZ<ZRSR`hP60AtypL.11-dL:4Lz,A<M+Kp4oTs\\BAPF6r6O9/OCUFap<5144}VO6\\pJp>][L1D[BIr?uWr<Q(n}Y17-D|.eMJ2O>DoDjB6)MD05\\4KIF9/=edurJhbv4zIOFE{H7xB1exqQxdB?R,M4X\\^zkJvt4CAvRsyeYNp[gT1ZNQJ{_(CP^O=mbCyVZCuqiBDTh9H}A/DHzcBWQ_kL2RX;>FE]yQX3_?HNe20M9IU8<4)<LPFiIX3>>RXAm8qrfD>wX<Rxj8*pj{9QXl0@vB;<PH6{@`jC;EVAvKM17Ut=}2^Gc>EcYf?YW*WD<|04fRWI`QLk^34ngyQZSf=eE*5bco\\ow=Aui7TFd*^DD0J^nhS{d6F/)99Hq<AWjV=sDDn=+DBLRVv03Y@3SsR5/c};*IFcb9EA^pq\\t)?4TB;\\69haw[].ZUP]iu(`F5}Lpjp]:@]1(w\\V@:odXW[hM39Y,,MrlH]**M>U|9@07T|4F@V;@+KFclh`cbsM?lFz^5W]bafJLOdT_VRZ>:)O5fY7[/T_Zm8TRB?)WY^6v9/DO}A?d]JP9L?J|Q2z4^G\\D{`4`Gkv1Ulg/R0Zj*3HeXDBDkJ`*sI;cS)RV2UJDMhcEJc6<<?s)Lh2KpZ.vTt>jRbx3xo].@Ah{AHX,bU{ED1,^Z=Ugx]B:FFQMJ0kQH^=Q(B1_8\\NK>\\=)5B<gmy1TdltOE[?Oib<L6[(={DVgF,L_TVA/X@lr:uSJ]u7=}<@B5XTGznl@gGO+m>0divSAG)AS0W3;mi{,aMe1)P0\\=Ua8?Z1.7@a]afkaZVZ8qZD-e?LKU_L?RD;Y7?XSzkd9FO0h\\>8<QkFMq(N2l)9]<KK_f),[9f/_LPyOEEplD<DZj@4kR9IF;8aaoR5vFl4n?s^S6O^lIKGs}<2X;^dx3?LlD4XJdjyO?<emLgtU(I^pg1@re}a3O>1-vzEYy]A`;dxA=z/.?m2`64THef2J<ZqH-?Z\\v<AsCA`^02MN_Y9\\`Z<wBeNkpJ)0VW?j2=b0)BZ5wu0X2}4zTCmbW7Lv@`Qf8?tS?P14cx|mr=eYJSb}pRA@OLm`/AC7.j7SQ43@]zUIQQG3SEEFd;ZzVIPN6|s=xFGs8A/:HsQx3H3C.|e)],CU0[Q_{\\c=l7i527d7poRR\\B1Z8O4/(n?9rxelX1/v2ZDh*L0NqXnWHv8tk8A^NDn9`WfNEIwF+KFjiXWfl3W2`=qYNTkd4;^R@?X=@-w99SAGJ@82/>CXQL8EoKXICj49D3,48K59mz1\\/(|,L(pm|8?<ZT|>7KMQm>O=;T.p}_iI5N2hVe]VKURw-^V8O[2N{8;[Z1DYf0YtS<B7]nivHaux]iy<R16TmfNmD6-VA5HY{0rRds_w-5bz^HQB0a|(U0rzesDZECM]([CZ:>gNfM5x-9vWToP@;<:_Nw5aPU77\\RM7xQ1|Cde;T?13W\\3?8+3/gV3PgX(LD@?Dr}Yy@Eeh1ZBXWLG`7{(Fr{9XKu6E<Z05E(67bVml3J}8\\@S?oc2oqEFsF70VXwNu?R`kM(`>VByuXQU.6c@/[D3V>I;bL:<]>zW6DAZjR`N3`Z;\\P;bGdAs4.XFm8(fO97P{91i(PLl:J_vBK5f*|oYm*ioZ7L/g`Iw44AnJhEZR648CI=3n1/29(QY(oZC`/<INxNY=y1Y1tf7xUy8VU2W|IO6Kx@?}OxDH5C8487L5C>2z{2:d\\gbt02_86tC+BIGkL_5OH=LC_kBS[b0BD;1*NFiWjn@eGM>:_ey;Hyr8oo0h=+H5GGL*KB]0`X:N:UB6boz_RbY*L@FoONHHe*?s`He6zDTv1c9=*HutgU=kYT6.h5Yj;5;paG3>[n-<FK``+w?S?.eb+bHKKFglqOfKY\\B}m2RO:Cgn70E[j@0:x8WV*aJXf`U;FIa6lLfY`5NH4{@GYxB=m31Mw3\\8O0JiON@<Khr}`8ObVUp2=><FvvEfgX}\\`dy/MSN5Hz7A({I?LZ]R^)8hucM5X0wx9^OMTjnSV3y;3i<*jK}W[p-nTY{W-=llA/Vv;WX8RhIOL;g`ekMLdvI9Y(9`02oMp_H<zF6zVh@TDR,:<=S?LRNpIAb7bABOk=085qSHWw3Dn>Nnb/D=.Uk\\}=G,70D2y@37<|p*XYD2gJ9C?KFIbt=q2jLP0T_=KGlXtHUeS{G@B9\\-o-5V^zZ\\R1>^^NC:H4`nA,IP8WZ`R87tAK_m;spj?S(:K;`oLB6kE55]mB6i}NwTZ:eAC[d*6@-;K[2ia>.z4jmI4gcpK.PmsaM^`4D8Y`e9e(>C6CuR?Fo2_YBi|zQem8Z1c;Fci*_rNfgKp7]l{h{0ZR|aZgB7MVzNAXUD)2RZlN5`E;3[H5lXUB{VCNt):(D@VoX0|3}hjJxhXutoL*>[1F)?<9I8HV/>Y.2A)B=^-wU4^f-qjhZ7<l_c<dNel*ItMiFDP8AGY_U0NLy2pDPOfqIJ:mebw6]Sq80;1n:oj)(w`G2sm6OT*Ge=1L=]KD4wx>(nlBjX3IDPL1KgGej\\dDRQVP@R0D>MPzU44HA]9rD@x*dTU:+ZU806I8mu5HEaj]T(Z?I7K2r]I<{sdkK46D;8r-CB;33|>x_F6hP-^2y>zI/w-)^dJ@,zN9{_J.gAdck+_ZtbP0FzVMz?\\Y8m<A;HdPM57B__t+vE7|=kWQfJN^Oh*qPPZpo::>{FHMXSrxYnKoK@BV7eAHXwg2pB\\<bkUt*_Wkc*IbjTOP4F>MBWQ1IWb4zC5/F_u()@^KH_h(9^42\\@IfJ26OV]f::,O1T4Lc>g>H\\eZoJ_r1EEKOFaHAL{K(|[O3xbrV-xkv)OSV<5AF<:U99>_JK7e;\\.F0CFP020G38[2a@>kq`E9fBrYM4,D^Pm9Mq6y(cJ8O6X3FlZzCL\\Fw;b6rLi=zX+U?9*p2kF)2=b,i9f)63FEHssu\\HpxxjeU7Swtm3Bm[hs:EI;cw;O;p=-8]zWV9UgiD@<;b?RTsVk<]rDG5/JBZxQ`8^`ADi.x:FdTGu_f9j8^Ec`E1AGFZU7W`>39XZ>3_;8jH`\\W=`T,8.FPVe@Of(CF<^B52RW{{UA3g=-9yL7{*g_lGILQ;e14U;mxb}J2NSeN@),ZWLPWN0IgUk65CIkHbR7KEU{k4d>._M8zT0|gDMX{EvAc?;y*N;L8Lm<*wbMEo+HEW5QU70<:q)1q{w`U:2XbTAga(AD.OPx*u=<IncFou>FaFh}@xf{_QT[OB=jI6U^zD||U2ePES.u`Ur=GG?1h{6<NNb=][K=*rrP4<0wRPR<7.VhR\\>8]GWBkDbM5Vq@5IU4/a-1Y9C8J5,G27j135pJ6@o?rwO:`]kS@PAukuOT8s8<Ykb2cET@-RuTNWSqLZRKEw>KFEtFLBdI>E`/Sf[A2h;>E4Ll]:S3>1;qfSoDF=?S6e}[HXYl^+2mV;03RjFgN>jh^*a^D5GEI>TppLgPQAFPS<XqGxZwSsC:1V/3n.m|]80s6RyG2;1Cj5unK5Z\\_0t.o<>utA;3yD.4.EMMuf-k7CCp=rGE8>`QYtmm`8coMXMCbWmB_TVG/SN[3EZG:2ys`}tJOfePS<)xPLuF\\L.=vR58`^{g0|nLcuh6zJuh7b2dn0BJVK@zLO3=3@f[j+]L);UmE{8@ta,)O6-m[:<63S49VA,VT@4{d;}uiAE\\_99MP@/B\\+gw;L\\I]bWq5:*9J@ZM{-LP4H>dk4MIv?<oiG55@A>tBh5@J_K\\icMJFD@BP3iCGT]F^I]VX4<5`Nv[p5;6ld4Z,OIMdf3`k2+2B*bF\\j@;ogkE<>[ExKN`OfvXAIyVJv@:\\P07D-*?Pw76MU1gJ45u0ZFzwD?*Bd?mtaqcN[mwfnb5>AI8^j)CQj@klyM33VF8?qVB;[dSCx:k3>2*n>PSKOZJC:VC1^Nb7Nd;Q9Cw9.fz<?D}_8H7JxJhCjU=p=^<]dQ9i26Uu]??zq,vKI1Au5^34-=M-_ze3CplU0?YvM`9;1;W]Z2B`P4r1]bs.2IL@|;3E;1L]`k74Y}cZ>?ZUxheMWAbAulsro_OIA:v@a}gZDlEI}McZ5_DpA6|WcOPq0:ywfm3Y;0FAr0qH:Ce:z_IE`.Y+UK^:TbH2QIcF;2ns9e9HWN1S>rtjjZ>|6da=i\\F1h<J09}GwbLFfE\\HsJC3V01Xb1`LNvTMApetc9N[W4B8Ii4gInO`7(.-?W7cqL`E\\1-T>dWeD]7BgRf>v0>F8Z2pj27(1(itUY?uJ\\t*<L81iD8B+mr/o(VWOcU`{Nyujr=ulEm8[)RCFhvNZVatou@`xAy\\.dAc;<QeD>htfB@v]h3\\dJp/;2=>@B4;3yx\\oB[HZ9>-C5pv31R*6PJ70x1dNv2<5g0SGRONBDGtjz*`NSW^EOZGKxZ.:3Yi2C6IK1:>UJbSWa72kl08q,V\\>DdQe4[B[I2s>`9pF6YX;>KNdeKcn,cOSM5p8.[ZJVjVU7]dA4Tyk7[830j8z8;`oKqDH7ZdnoF>{T7@=0?=ds<;EjmYCzS<0}2,uJXsc1CxKxR7PR.Ef1D3q2FtPoE?t>.5eW/|F.3V+v|v0I:{,6{_j^{LU@Wy}RQ63W.sJd5^V>t*_(;z=\\la4D6FPJpz9WEZ;=^C(p\\xxtXnKJxJ)+t;jPqO?pkaQnm)(NKS);nZV`3nI\\6|L>0JMPv=_tYfcp?roOT[dY-bw2:06R9Z>gbhWN>j[Gd]j}?aZ<1DeNeM41I;SrB>w/fvY:Ld1746fVE>_b/+9OEO6_bNd2/56fqRtJ};<TPFA+\\W7Ca81+N3DwGCJjD]x({kI,E<>QON{f32J:S?Q`U4@8QAj?E4Y=L?K53DfByt}9Fibu2[NFArba(wAl{B_O1iOGy^{6|xU0p??_]KT@Wv8j?nKJp/.1+IB7}:5_[HmzYN):1b9*TFUGgY?x2pe7.Ds)5n8]HDB7?M*LuDH}U-puYkGg?{ZjL3AZ>1Q+d87^?P4-6-5kQ9d]s0bT93R>RG\\I\\NnXO+Lp//Ldfvd_8s+ExmU6Q6y/yi}=`SFs`+CFgH]B2QL=RQ_v_daadr6R176p.21c16{=Rik>]`qR*t3dVHJ\\rL^H0W{d-Z2IoA?k=n00qL20;{[ZzAq5oT3A7@RMUi\\d=D`p1z;7hg1B{2S]9S?Pe|E6d{76`o;(9Qh}0_qS6TZ:<J^zCdY\\H2L<8yDRl:=1Q-qH?O*YDp:lKg@LB5RCQ(<[B34KbHgRTEGp45r1[wJETjP50/[=Eu787TI5,hbU?k}LJTYV\\05j::B[b)OvZmOfwP_>jBfH9dM_i7)Oxb{@lA5*Kh6_/sYOoVAV,vR6sj[3gf-hE;AVf_n6)927TF.FKIi|=Sd`r-bm)]+.Kv\\i(c=bV02446Q9[olY;CP7gBXw]V`=_Hyy5U]j<g)9s0)7XJJnb5;Jbzbqe]<r0oQv`|LHya77?VN`k|f]LJ?_Q@;>CzLqETH(iRA5Nf2tu;^BNO\\EepEF-V5Zm=W,F5lsF2o6HLam9FdJ6L1Vh(3wGM^*IgC,Wd^(2b7_+3(i]vv6*oLMZdLlWY^WPNki7DaSRD;b*Gz^cUDGBEQ@9az=H66sQtctEei_gCv3bKC:5r.5UYK<GXgFJ]?YP.ed7}QyaQKoBL|26X51?3K4rrWHZ{<]FDgT^g[q6?C8{=o9y]TIVb^hjr=1okH<?5S4C0w|bVO3ruUr-g`to(u[5KAL5McKNlrZBG6k\\OK@(<Hdc}hN7j8sl:OJ5+kE:;WK:o<=Z6J|;0syRk1PoCU|W2M[>T;pRU,`9NuAT>-.)+W:C8G/e,>](2cv^1VNV+UKvB8@L=\\qqe@05uONokW:BGtE5_yn]BNDT;];^1gJ{K7X^39650nT<:Jq/E\\QCvO{ImLCt5H(8>ul0i(38s,_XnH^oph(*Q;/=JVQ:>j*kVKJs-kuj668(4-9-81{+-dof\\J,JOa]]cH`kwuZtW.Oz+==JfL?@qXDi323C>`G:6<=pXjSR9*(k/y]9[\\vuFK81oB8G?V}vDMkKC}<2=`GZl5PA:Z1hQNzEi9eDr>8ryBY>K0_M7}AC)*YMvUff3uq5xZK\\LLbKN<mJ?g}QH{I\\kI)}:6(P5AtYqG-07]IdbBx`D`0h0p;>3Uv\\PA-mKNcy*yRJIC^Dx43s|uQx^`?5AW0OTE^}@YUJEGk]tRpfdbF}fnG9.)sVu<@T8Jg:o:AeMah\\fdJ/RvJa;):*YvkJ=`rP4*M)u+`X<ROY;ND7x?(c[o<(H3\\\\s*mY;^w=n67Q_I,`(p|vA\\)Vyxx}2F2h.A|*55^J[,V2];ST-2lpWB6Y]Vj1yUgu@0R7WUQ,X.UE)GdrZ8zT=DKU1:037bA`9(*g=|(gdhs^>g0^F6w6>i3A9(qn+FX8y[cc.fGCmqO55qu8mrA2.qZ:DB[xrMTdgQq\\q@Z_w27Y;s<<*O1Of5E}Tg4P0WHWG}7Hn?\\L4Y0=(PTv0Jta9um5BfGtD89/S[QJ{=+sOFTY7sYs_GX_eOxu6Aa2Z(.`;:zjM^|r]RVppsu1\\2Ara9ME?^{HETq46(;:RZU<TXOC`}Zx.LmFgc}:|*(-J{_Z6a^Z*E`<9p(ztkZXv}C9WO[:>Z1|-GI>;4IU2?GBcpj57R?_|-[>hl2X^D9T2oTq]\\h@1mekA9Xr1XW>;n3*RC4<IvW`y<:*NMcLs]V[hMhF)CIDtIo?J5K(IFL|85LJ/4=:ahw>G3tEeRk*cq0:[bgyr{Ks61RNgED5NRF>AQUFQ\\B4Lca`D*q(y:Y6CF:U,/`8?\\s=AhnU*`pgFF5@D6qEaiLm5mCajA2ON[4f3}3G7>3KD^>spzn+|`Rmm`;/z36uNO7*7W|QPw:[u5=ms+^GN(ea3<C6z9tZ;=FCA;h2{cPA5[>Q|c0`cj\\CRBDNF0uS:q:[THo2@=15DAaU^H+=;etH@lC3WfD,y>\\c`r6bFa;kHYV7mTFe_|9y<.2pN{j-1AX[cPO,}a)_=^6xk9`Mm1_sPDP29`0;(^|<q9VHN^WYgsSd7Pli1);nAvU})`A-kj(Z?.cR.,pJ1<Z3hv3j_|O>y9Blu@M_|__,8]+wWCN;|+C,2qcifQCf]1X+\\U|CY[h0VE4jcFX9t@q\\h<6eFL_<6w6K3J-Z(Bsw?[b;X.[o@(s7qE\\s-mhTCc}Oi2>0_JuVa@iiZ2O,Ie8C@HzD1SD}GtY3Aj.2]P15^xU>7j\\@J4KUo@of3i6zKNV{ItvNJ;GM1MomUC8|}J1Pp}0Z8;1-*6*fWPnq).cC4CGG2}ul3WfAR8=WJtdgj8dU^b8TQ=|C^_0Yy/]K_HpZ2>5}7SRKH^=mL8hmk2qYcixH_@qx|s}@iV|Hrgnd37)0Gw5W3[.jsnab:oC>d<Xkkwzd6P=97CAcH_9hjf]nfDqM]50KhLh5.D3t`{F{,kly,e64rqPVxd)lr`?QtFQmW}vZK:DVg.dVFQZ>R=T_0s>I>W7.aA2K)^8.16E:CJAT0rl}EPFnK3oThWTLg:-d6RSYuo+y?/,K9DrbvZjS;FvDk?2YTS44R29`TB8GbtZ<XKMsR>=nCgG[@dy81<^9_-0cU3zYDwUA]IMAwc-<:b1=<83/qsn/YX)[vKm4C10oE.x1\\Gh5{uhF*UF9pO<0;]0@(dWjk=?cUs8N@V:]`95-s)0@F*e:dor_Hmbin+@2Nf41S8[yG2?7d^9f0etGS44lZ1tF\\3lMV*4Bv5q[d(26)[p1c?Kwc@+k[[d5?AXm7DU@LRb3i>R7d`BS3OEn2/ikpz}u3g<?TQ6W769qA]ZndfYVIvR6xi4qrHL)<cl>5Fo8I1u6rHE7=Zl>BO:I4>U?fPgaaiC0NSf4JjlOSShADWf[mv2M,D:18jJCY6j2JGkc@nBDu(|=}<?-I><lDijX2cTKQCA4[uyho3YvR{vq+nqVpcug,MOWv2FZ/4]ejMe>=`3C:KyYU9}JkB_L0YQ,sy`+HJSIgXPGOJ6T@G(`3;Cog327K?a1JdnQo4rX-:V3qLh8MSZ}SmvO_0SR=IiFBji*UE1t0\\@BTGt6lFS\\j2}[3`1Af1Ns5@WO^3L;=1Kw:0Es)\\BIt?=M9RIbZt:4O.3_z]UY6.j4wFjt[G8m6}H6?R[m:_@p;<N5I>AMCR:2hEoR]vsgBU1bSDIVdFUUkj]dlnQq`{`EB6+O1/5s;1_9`YPE3p\\BbEh5d>ga]hNyAI9VreEd.,;=:l>Jk91Z7\\P<wGqLZ0WT,:oPO<Cf>MEOhgbPrpe:QJ|]4d:K@S9)OV_a_tx@vdsUU4}9e@2U(MivX}1tlAk:t^6oDh|sRlnOC4,W6YO}1Fue+WhQM4jygQ>7>:n3252+W0oS.58MsR3b>=;w+sDuqECq4n7J6A]fAXTyQX,V_BMKcL7]1m8`\\8N\\3rqiWl-|5EVX]l|lq]Lf8FDO`cnIr1l<`n@W]Td}<^0LbLj?C2?dyKz6T/iJRQWbcAI<ZwB@RxH1D)U.U>a+35EHvD4`@5IaX=?pBdz+^IvVkLV@ICEe44uA;nu;)9OAR2w8I@c)4|Ja-PBfK=VYQ/FsetlnE=E?+<7q=Jlo1bRzEnhPt]EGGL_C8MSjPcC8BI@h<66gG:O0p9B*2C0{KGGFT98Wm.CK4V7`)PG6N)m^t81EyF2HTE0XbyZkY6r{u?NOs`1@hV}Z5Ih;h,p0PBMd;>Cs5poU:fq>?|AMge{?_Eq?HPP`BJc31e{.3wEWG\\xrO_qbbK,il?U,>ydbN)IirHr^f2<S],9CF3>jA;1.mMzgC-4dN(cH{n4A^6=.C,ConOhnjG^SvntIjqAb4I<{{wm25imZX<(1AC:u<>hO2do9<3XNGfH[S}2R?`[2h08g:YKPP`bCr0;tY6E:u;HgwE:qjyvC]]<`7Y,6\\gd4r:]@aJ>d2(|3V>udRzSkdu7kVOSu)iN(|>AdvjFe`@Qi)^ii<Pd`OQ;tFQa6B:m^tJ4:2OZ-K9m+bzaTHzWcC+8iCZMH]BQinb:.pGLw@90E}AIqnVj6GR:@dl:3[k)V<}I)D>bS0FIL)O3<jBbOSi,U*{5v5O)I4<E==]24r12fRpe>kiA:{i3ZHYH>deJ;ViybWi.mITe)7T*SM3+hSjg0?TK<1`nt3SN`7OQ0(<7>GV4gzwQAWTM1{ZQ`YuJ(mEE6+964qt*)``=BCl?{R3I:Q:Lt=<.4L2}hw`.j3SPJR_0^LQl3_OQ^x</aQ8-N9x)28aqD=rWP`X2W4l0uQJ-99pxSx9980wUHAl1`a=Fu<9BSp<M>d9do`S9RiTb[a]y2`FJ4>;:u/64<TeJf]7[U9YmccULMa`Dou1dtG+V4oibaK+MOQ7;BjV)EcQMzIV?0h.G7f>[\\oU,-2Go?hZ?@oIm1)25=`]@S?Z;qaQEJeBWEM<JWFK5U<)bM8d4cVA-ym*kr__0]old;SJ;I3>2>X}C}iXTP+gMQ)dW;gz[fCjc:Cw/Hg[@*Kr<IW6R}5RXMN8}3IhPf7R19t.F?y8pFAtS4xh8Lc?QqG]o4IRlixzV8*byC=6w+9^[{S*-KRoCCbMB23bK)RW:aRI\\8:[In9GyfH488Q\\9d?1DI5TI(RmPU1e?>3t|S}C<xB4*8uMhDoA{7Fy[,K>5C|bvr72{kwzF7@i@V99bWk|[)TY>ER}cCox`jq871Xvk9w7:b-8X^`}QI;HXXkfO]gNYQ3M2Z(mX:zmLa;e}weK;/G5v4I=sj[<H`(;ak\\q2I7@?7Y9VeJwG<;Fm|XZS^d`daFc\\f\\??-PC[ZN89`;>C8<2,w@28?@Fb6n+-}5cmTXM9Z:n0CN/4\\4N^4M|fL9KpUJ26D92m`E4U{lpjlvtxN.tadz5o0BG[:G4A*GS__j4W915um<,;=LB6BF=|m6wWY6P7}6[RdV*IZVX[W}mt4qOPyg]CuU7NXR.id6F@<T?k(oq?Y)=6W6uiL5spc53Y@hmkfbox:sq6UW7.vBusy.8oT8|5GdYf\\ty[RPFc2WHK7BlLbvlqM>UHFsDEvz7(u+f65AsF1@PEV}_DG3>B>U7}4]?G5E|?aJ{z59d7d5gk\\r51()G9j{EB@;e-}3*^ei9OGX2)zDJUA:S:Bhy{Jt;jqcs_vV<q1i0vF;canCZRuAp(qqckxYv:c2GFM[QbN<GvPz+:X3[,_h5AGBtZfn=G0>N>yhB^P21GdXBEVB^Ig|mG6qGM^7yVYwIq-Z],J]}8>cq^m2)Pev=SfPXWem4+M}ab[w)I{C|s*K^jGTuJCF4rm?Q7T;9^5?9qc,@o>Rlb?<Mc[R=AeSBM5/GPs8MgmI*vWDjc:1wo)Nt]y2mD/I7_A9EERPBfPdXoj@>m_u\\z^x4y20@P8h>QD?V\\1U<hVN4,4Ut:Y+BxH5l|Gk[l}4GPg3cPF<U=M/0;`@NCQ7.<N]4VERFZZ\\FQ>G|WQJAH2TcP,DE4{*;LGi3x@H2JdW0CycwDP7/l\\j:{=AD3B>N:zq3nt<;ENMk1MN*=rPDB|I7LYK7oueM]S+<n?VAJKs1XB^5XkfZxJ((R7SyIPHzL8B/>Uxz=pqPSnIo^ZzFQ8,RHNF?jJlX+VLULAQeMjpsr[7/fg1s5k[`BB6h/Z;4CKV5Aj@fGlsaK4m<ENe<MU?w=,Bfh}X<wsYU8EJX<gZov]_[,uXiss=2Q=G4Iqqte*@3:ENlKY8s=g-S)NDg<j1VNv=GvaD`[gJ?F))Uc59>[uGTxR>Gp?o[@O0D63L[.ID@eQDGLW<-j>CP7iw]1op\\-)r,GE\\cEk|vD}rd:OqLsXM:*Gy4},JqOfouG+xt*_(C?/m5AP:13QY|^m;>E6l83Nx6Joz8@LO4J<c7N89rzK@IitWQ0;x6{L8P}[K96MP9`Brf14PCIRjA+1Nq5UR48F|QO@{@/I5_RY3[Ucb`:H;|0dOZ>7M}bud<@<Obu2<L5sV|c)8FM8Sn70rTsG)_?V<N;Y9ab]>naE1@zVdn[C=e<<IQLIxXdIepY\\:ad85K.`DD?::BA_)e[2G`]W{63l1YS8S{cp^(Z2U`ugqclYer:<\\J*n]G*wde6o(H8X,C>\\S|1M7F.o;>{<W2e=Y;Gn@5ulAc}cp<LBZJ>7Th7c:{9}SWNLSb)OcTv@vCia58X@_ZPK(g_y<FOxC:f;fAO_?8G,@rA?GIMJ0:0Z)X?VY2Y2\\qGq_j`g.RD\\3B5_+S13*wo*UhMq9SC2YI-RZ:7H=HP4`wI5Gj<?h<<c{uHVCzG;sB=R6tnIoa)<]e@dRQ{5z6,;8GEr@G;-mY9E\\6<lRv0Ca9J:FgAYEV\\\\3e8=7]DW8hY*v_.UD9=?Hio@;^4FQ1T@rP6G4`5?]rMdtJ4\\<JbZ[(S<tVddJBPxS?G5V76d-9D|iifZJ?`:0e3a.:Y5eL9AeX2<hw;_Lw7kUi:DERw`B:XUzmeOelU>x6{?e9mVC^4f7f.o6uP;=mPk1`V;=H08eOYCL@C?+EeIz6LhNa4My^0iKA***=9j]GC3-kL{n:g8@D8;acSZ[5W\\bB7AMyTcpQWL7n?GmeY49o5Bk6K<l}^C?r3p4K1O9[y8^JOe<9@V>[nL:OIm3TG6g;9*bXPua\\BZ@P0_+5|z=JkW6DDpkw{yUvu?/riK<5KFe@??+MX5=Z;<i0O:c9j^R6ID.6MIc_PD8bha428PLkCDn;8Xf:dP>)853bA1gwe?:DMtC8.}*ZVvR/t3k5QlB/0y4n3o1hQixrF.[YgX0Z8?`VGMF9BG?D^J-e|^D:EmvXZC6;rCu\\I9C:1zvBMZ5u3@4T7rP,9@BpS?=NG01=:L5)][62CHqCTpIYNTdj}(Rg15AD^k86`iBml3GlCBCj1uhT;w9^?`Rm6eCSxr*[YOS}V\\<Jsf+=]2(f9`<@?Yk9N0G5u)\\IZ(5j:f]5CYv3mqREm:F7Ek?v@LFJ*PpW?*eBC5K1_fqT]0h):LI@(=UQCi,nH*f;UDrLX8:e?0L5]AC,P5q711+nTtmOKJ^*,XUZzV\\(Jg/Ii7lj=H>pT;8uL03QTM?w{eLa_G)puK\\Y^81AwrFuR[kg4>:hpl`nBpWmE}H?uBIMR/(L0i*Ht{U\\|J9R8;txk_<Fd2p?fH3JDf56_h-hR@>wLPO}3tLYE(,ibe8Dms4o\\cl0ZN}KQ3<CVls6`U?Wsvy5BWUSRnaRpH.D<{;0{=30WS0n\\4Tl\\;m;BTg6Zcv<UvksD99R;U073-/bMr9Ea9l6PCx,\\yMYgB;H`e}fN8-{y\\[IS^;U62WNCP4,JGGoI9+Sg?N>MepU)lGZ9V9sw^M*P;\\c}b0+m,5eBhZo.0H+xD)4JKdw(ER[0F-v@EZ<>UHZI<IpP)L4+e,n<B>BKd3d=5Bv>iD+,n]>]S6^H<8d3{J6TriCEd;Ev?2GWP{RVl(XQrQMq.bhK?.CjKtO`Q_kaW>G*BU|m\\u6:B\\H}X7W=H\\8A9}<<?4WJY*VSD|=usitV:=K7{fD*GSczIL8x=<Ppk6-j`f\\YQIsE3GdXE?rs:5-H)jA{}t21-GY<K9Mkl*[=C-JpW6i?3zXL(P;20e>S3=GGugyN:if.A}r`_5o7[eTa096`0.3):Lj(Gn[1WvuSCuBiiy[jg>rdNVU9mQB;WJR[/F^1.vRfUGDq7d`EX?4yUBI.wt)[,++A{JSz:2?w4nUy8mZW44_-QV<N8L7=H(Xd^i@/C27<R=ZMsv.R?7pN2Q.+Fr/m(A@-\\y6EF3W;s{WMh\\_R`M`n8hkE<W>9<Q25h[)=_V9I)LeHERzO9mc:spCNMb(T4B[U7`d43BcKKa7wHGrac=zeu.a+Hbg1;4|{3:848vuO3(,L+KI=eM45L=HgHr9/I4,^E]}|A(5,O[r4lN@|}fU.\\B@Yu:cJ6,oM9;y`[SflL|9,:ru>0R`Zi2F7qVwlhR[N4(Oy/)fMUYna/IQ4_:PTO{:(3VG4<(Qeb4YD:cJP3[CIBzm9NN]N^N<Sjf0C9\\+Y1k5YBQEgpfd9`T1Y9SFNLREy^|j4antNLK0Vu{4^HW-eHX-4{7A.;vK4Pr-{8{8F(MCvoOuZs^7>0DL[[b;-3t1]}|I-j]\\C_M`=jM1s=V{/lb\\sSoDH:p59L*74H?).X>WpR:s7aD2BdMS;9y0;B2zLtPkv>ez0|4B`5^1=M6XAco2](_FCk=[wJYRep@bj^bBAJ(B5B.8jo(eC_pQ6Vo=U]n\\pY]Ur[tO*s4sEzI*bREVFxGBby7E4gIps`*bJijlI*Li^EXI_8uUO5HgZ^F[Znn;1:\\7Y=N6}6g>}G4\\9Q;X25HVFFB^Y2Wf}4m3QS-3TH9/A-WZNz4,?KLF4Uj;9KQqGEv5^H=Z@R.h2cM@i.2mPX>2F@_xBp*iF?y^W=XQYv@:Pri-3P6>IICL<w;7L6IA(4}<VM3SR:q}UCVYF04=Tt<;W.AyOCGo[dllJjrW7|{JdG*Q0[=}0k^z.nUSN7cEw>/^8?a.1H\\@P9e9P<J?FgYp<04;odqP7W/7GX7aL0m6ecQ6G4\\z0knopRFXDbaOBGOHiDR>oo60NJ8/92;\\-FI(N)]8q\\>`[;MTk;97kB7;:Xh_[z=J\\dV,6||0=IHmbZ:u85AamgWG0(CsFxMwZ5m4`P:AKMwX`NTBYK8sA_GB<Zo^<^RItF{|9wo*MbU=3;MG0fR2;08gW/VzAKa(Ct)/9S0cH8x*_Ff*-DBXY:`iPC[j9LZB*jc?G\\(a?BaLKk8}e9h@dTI1bAE1\\ZQ/wZ;XRh<f.PRrUeEYiV5h0@=GGc0?0X9CL\\h1O56WGY0{=cU4}^xy3LJF^p`AQ7L[->WQ(UfB*=NF^j8FRW6GN\\04Q[WUD+,kk?C6?yNa9W1==k7=za(st3x{V@v/58n|sG02U>zS-8?[Nwj8Ah2{YZ*Co?8}T|ON8_w6nEY>*ly5y<4@|gQ0c.}zEJ=WEMpk:7fvY32,8iBM0U6<?f2r85)N7cFp/>a?59xcifO1H6fOo72OE2x485yS8p{2CHJ*g2cRR{WYyO;Vr;Yhhx.L=-J`^W(WSZQO5wp`Q:W^Bg\\A):hs@=ApreTLM=+;o|0MPJ88aC5D5\\/>C}OZ[U]ea<3DHd.Z4?{5U7Hj9Sn=_CJ3ESbH),c3uS-CXRA@908j[o,[gyC2C\\OX\\Ggx6BC@ZdL)9/?-S3QwL84:k|eS+J7(H02}Ty8j1378f*{5>Z84(-KPPe8\\9IhfVyY}Zr`@]A;(VJW^:FCTN8l=c6PhY18EVnA7b/aMi8@n7@fM-98zn\\]?_Bvq+h}}blOtc\\z4cr9th6Q^WG\\rXs32_9DCC]ZVou0eV;MsI);\\]uh0H3t0VtLZBXN@J;lEK^Z=^SlTT6ram[yGGT?PsG.0Cny3_CBxTEYj2865W7R6MN(]<QN=M]_,B;XOhJc0cH0ON4_ULP?H^K).+7;eC.2wGJm6/G)N/2;D2@P8L0Isj:(;;A7cs4DDvoU/E-DB0pFJy+;MC]4a{=6Y8Q]N?3^z8yDMWH>o7{6}Hn8<UJ\\0F\\>f3EAucJL3f2(38JMdWwEX9]/>*25mkkhFI[fy2GUQcO,y=v)>q2)oQb1Pf(QyNa:J}EZnT^jerrMx1x^jrV?LoX;?JuXr)W92M/i*dr*Nv4:/\\0HBO@B\\LrH55]M9cz7J07tt^Kdz15R`LDXo[s*O8]}n-/FAo[6Du/wQHY+7tFpV4EOg0HnlN,+t:;Pe?6WDWQ8RV/_lCvUBiST[8|FgTM-qia9I^lD+5scixxpZ9cty1`cAXR{_BBCZR0QPfnHIQA8.rF05f)tl/l3/q_mRPWCpFi5<:FSxVd.zG;G@>8JB2IeR<IOiPAL-[[a6*Y7W`2|7n}=n^T{}d9NFvjy>4c<@gV4AlYHt>Ee5<lK_)73Y9[(7B1a>CwRR`>p_LB8{5m(T<s48\\I`sHBzwt,p.S9m7j>i7*;AA@zNDt*VERj}kSCoE3)P7>ji@=EHJ_T`IZaCU97(}yh@9KtfK/{2<lgU3oc`Y,r5w|Id=b7Ak7yE?eS=r[ZT2\\YWT00NZx?XnOSFx>>kEO}R_>T5gSdR?NK=B]ds4>VzuNn-kT=8Zur;lE?ar]TH)KpLJ<jjDS^U8Aw1TL[b9DG54Ihl3^{a6?21R_Q+/_.nJ4s\\M;6L`S:S_^TM5ZOn=QemY<</XRR0bUKz?n\\J,\\B19jR:-J5EnGdtG<<6}3w|2=G1SpwHN=j;0HFhSl5-\\RI}5FfLXsAu9LYQ,>PWp\\.EShlE]EHUlp<N+Sed`O8]ATEU02@A{K)m0K>;zPx+qK`G5S0Y;0=4q64[wbie9ZbWU}3*-89}85W55*fd[Svr+o;+B1A\\<:E=gA/jeUwLEk7o>7]7oWZ^KjwM7CiO1ewP.^AeKq9k4`6O[f@[I_Q_k3JXH31A7JlU^:Lp=O8Etz;LE;FG1V4A:Ynm0r`0pcq5CfDh-4BPj6ro1ajJg>56E]3iTt,GV>reZ6Kr9H.G*<ymiy7088e;lWd4<E5J[P;+9PQq`YjB5(-:q8y06OteYmp6ezJGo4SiDLIT7fnSFJ+<uCR99x}VWinHnQQG?Fe12lGz0767Zu)*9{_G*1+W6XC?Z`H7WY4yHL+g0}lU\\{T5GMyeC6Klgznm1V+JfA;5sC}AHpsw3`Yzc4PbAtb<lphwjgPp3AKQlD_\\Q=43SFK:543^d=AfpY)`Lxd0)NRLz(Jm2Xc2anrTPsIf,k3nEkf0IVq;[N:StuPBm<gkP]<SNNtgMgJ39j0PO1Q(feu5>EklI?KiLTV_yW|fWd:i2+180:Dgi6yFCJ3ZDC369m@:N3XudAO9=FXc[bN?b+7Q-l:|JxtAaT68+n/=[EM_Q4tqMcX13@mjt8r3a`,UQu5+i.)@<=J1H[:7n?;ehrQ.y0C_6:OCsN3t`G-p8H3vH}U>D6}15XQ;^62hHNefUgeje9ef_h6X_iWGB=u@JIo7DRRkaQ^ZVaK/S:)T4rvI4Xgee;@RJwvWLd9\\(|m-@:b\\qR0EH]\\e:L;(tI2z3O=F9k0\\9Rn6iD}7e`weD`97i=4-];q@ZwbHkgB7Fl)8gJ41|dlxPCN1u*u3k=T)XRV7O>lC*Oj95]EB<DBf{KIX@wVF7Y*Aus0Zp?5;P8-=(mS1FkUFcMl]]=MV>HhNZncqjWVUR6/CFqGnE2BBQG5TWpPO2RyT;DTL|=sY,85M:)EW<S8R3F5u>F^0;0RG:4je2?\\J5\\/RI@CNG)hDzfR}bv.(tXFH>:m=-^uBd[qn;0U6?A<0u7Tr}u<IZ\\1l4{IC.AN:]p.gMo+;@(A*5V4`_b(k@|x=ukCy9A7{kaU7h|14YT5Sn-i_N|4@wx4]2FPc)1Qig3NZdFQ@O\\L_}3:S*KhT9A?`MB7gS5m4o5e>S-eDPz:F,vy,J9TGFp).K[>Qq@NYr08JPUBwZIKYS^9mnUGTblxP;Vctv4/PpXdF|PLOM5q?:sX{DGPoeDEtu35p)q?|OIL.wtEC?kPGjpBZwtDG.-sJ:@Jr?4=,>`h4Ae9/BT,{7),9IbQ;Na\\bvSMB,/BG9ymv=YJ@,AlvflsD}`GNfi^Z^{XU4O+0SXymt=\\;GH,toX/4T8-;kx4m8hT\\C[<1Q`3E;rQ@0She3DvfW84P9{Uo_<bUn4txU\\B{DKCG2eLB0qR2j7RcT=t({CT:U5Sx7.StN@I.LK;=Z@vQ==Sra_Q>}\\`(J2cGUW}M-3eVRL><RNCUP{3KtV<p/;WVJl17Rd`C2T<JrdQw=QLj4H=0Nb{m35_A_vWbYlxS;DK+Jd(ZV57(X}?du\\t>C(C7MlQLUYsQ693loyVMlUK(v;;adf8Lmb3RDlP-)c,P*ylC]3+T]2y8LO4y7v2bg=T\\jw]**RT5C1i@pi}[1@;byAKH{BH>c4O.p9q4F|Xm0p^OBAjji8059wF7MCZ4m7N49dID\\(A6al:iQq`H0l\\Kb9<xeJ^96;x.g=Ys8Riyz1847Khb<i2<sS(4pRzwT<F>J`h*LAM7IvYal=`l,\\8EMN;:i\\8c3{`>L=E(Bz5P;K<3A*g.C)T[:jJjL\\o9Hg{o<p:`IAJ_V5*y\\6_s0eqA2S52i-[:nAE89:H3HjN;b1jDg4B>uIrA;1+2WGD}TCVxS@S81sdn_d9nx/BS3BLT8RQ047RI/VHW*okRiO0HorL^;z`rK>hO_)J;.X)`z(b_h8i@PRnn)q,F4PM>w*OpAd[+Z?>w836_d_zTEGK(liIszyP]9xD<U;U^1?FXK|8AhqS)AD6Xfo=6d9.lG>B6S,eAZ3Wm/\\sRBNC[K1o0Jk=AmJ8KgH\\R*4F>R;*vP;o^GFx(IM``87J|E]XV3FIAhEDD[}F5@qPH>`<:TZTC>H/5av2AMM=;6FtIpNDraldbu@nie@MYZtrPzn?:?2?U2/O7b6?.0zVTg7Eqyw4kgI3HNzT1c|2TfWOG@^NCL49v<M\\LA{/{:2?uDl5uK_En;m:vcKX:8+86AUeQe1}8W5eVb88pc^`F:Dhtk\\>y26sn|E_mRwFou<ZYH2UddHYgF9+t2pg5LzSc5mYl}gCk{SP{{6Hfwj\\1RcA@W]R9hE0zYwC9aOstDF<qC\\P>:TWKbU54Su@tay4[cv8y4YSJvg3-_>1<yTF{/aVA^d3}swS|KzAQe\\H:jv[BBwl\\GEs1;D:j2(:H.PZCJU(LAE/|@]R`TAx2b(pu\\wLH\\QFzAi@|2rEQ20[8_<`dX[CW4PYCARr\\V7D>Sr;gbkq53Oi`>H\\r95a8?OO-]8Y6idwhCG0GX9r\\5.r7P5*7N;Ne0?;<48hF[ye,D?wVHXjKrMH;}4uQn\\k6EfA8R6vw>uExWuGBDLCR;?U,jaW<_bNO5ruBor8a0;`5sJ+|rSPHlwO?a8i:-g7@guIm84>VR>fv-Iq/qLO0N<7Ss?a;[)fm)JKZ(pG54<pBI+3XP=d;5jp0:@?+PIx6l[7aJWTB0CA;`<0+/h@NYM9-QVX@XW:k>41xP7l/<OR6HnpWs_gg2[1p@J3Fe8345HIIqg13oDT=vBWN}(B=8b8IJ-@0r00Bma1.Vm(S9<{`O\\G|bOW4SbB/LU2)lms]:UeCK).x9n@AvJ12B@lo7zT<054y5c.;*5+?u;6oSf18^IFCEYfMUk,<DN[i(j^8e7YiqfbQxG0ZAmPGi|2Mf8hQ)ik6E6G0DBnyM5*6:[xS734T;O>Xb_+>;}NX]9R:6\\oO9nZ71`UZu^01^Ax::7xWD@z3sfJcPpUNl+=G3N6(k>FQNXdorsHil,zGXXtBZ<A54DN5uVO1fhDT:eAF5n4VIV3B=INUZ:Xv]rY;6.)arnUf?jrTIJX`FI>b+7JQ^[kw7PJ,x]hoUCd76P`:fuv6:=sUMOiB_jtwu0<-?]4CUXGFXgb/rXId?L<_@DXYJkhf2MOK4wx2LDj;N6:b3D0c>bn2o\\`6EAM9JS2zCWB7DCx9=G8@7d8|X2s;yr6A)s}8GL:?E6rY;v8Dj|}]\\t=tRE<H{d9]69nTbg(0[D8;|oTCHtd`I}Qs2uXZR_fo20.uAPuvpPwDAXNs?qrBw57Re39:yUy:.o7E4`_kai@f;C/|\\Iy>GNJhF;}]*/px*RtGRs=SdJ=-H>Sb;}dCD7:{VEZ[@pW73?PlS>6.HnQ.A9:7P63A[Tz_injBCp]KE|z-9FSkgW,h1F=@Dnc>4V5=P6PA?8^0?kF|S`12{68S/4_78TpRIa4N*CZLrM3SgE7Y(JB5rrcn06>SuC0Q=DEx\\=47tm:gQ@>-4IHp.,WZJu?rLBy]*0oRYQ6PWd}MY8x]]r1oSOF)jDhBJQ<IGN6/[9slxbB4yK`Z=pDC9n1aTcDzw5v,TrE7wxSfmM8.4]RJ?D76@dj_Kh8cROW(@sTdjdd>MoMgCd55H8pp8(GWot95`/EbMeKVi\\W[Buf\\g;fPHsJR3JROK4.KIux2Q{SaZ)HsDk}E?=XRH;GX+;7Ut6tIl6u@mE]iNUE6|EVAq`VS6f3Fl2:NpHnQbgdgO]CA=6d;?)uPyuVkGXaH{7V1M4_+^KpVFQ0JjbLNstwl-tG/;BOr9OiW4LO@I3<F>uwfVkw3kF6.])}44}?Jdo*aWd@=Ul+qtQ6>DP1:mHA?_1QqC@fk+^.]2JNgYJB/bhs37`fkbHM2[PU\\/B6LL9o0vCCU[CDUf(64QCF]-zsI8i@FCQ76/0EP{,XW)P)yA]2@0GjX_tQ|)4b?I+Z^c@YG55p}CZ99v^N5`74K8hoZNKJ@RqSIEHV{4bYPEUf,UjKCW4D;pJeq@9v,L`RlLwX==2f:^FtbkcYSO/mPYbd}2@RLy/d0pJ.c2o0V9v88A,i8o<\\;\\C|`}X?om`GkyIR6yp8}FwE<R|h(_2XRtg^\\UX<F;m>C}?0qO2,=?9u,cGGC5^b^j]f?pEVF[@lGL8B7`i4R8o>7:EnGcyQ{O7GFB\\C:t=lCNB00\\K78PAqXaJEJE-9F8_1XK;})A4wYjLAgzxeqTyzTQ-N[[1;T2=e>h*ls3K=MA)yZ:0jH@XKapdliD:qM:b>@R3PGEA^,Cd\\=`0(QD8vK[7`C}3]AUUh>]OFPYa_:qevq14]EJ0rEG4jVd8r=u;/>k:sQ):joI0L1K+;Dr|F6Ml?ls;M3fU0_tDYfF:yPgEC0i:gPq+{QQbGpc1jR)lH:/1Ut?TpN;Z[sQa0I{hS(>vlqV*Ly<C1a]42t]=cVP@8++20JR*=M+rH@C<[xPjX=6y-eZ@IPP1pTkE;n|5)2h5<5a4Tw8uSKCiVGVNlZsFH:o6N9@EY4?Kk4Cf?M=?1X|1W?O__QRKYK:0R.E>2quYndkXO9o?E}A;e**58AfIU201UN8HblI5qP-uk6OPKngz<f90P7*807SXvBwiGWl}c7+lN76Cp`b_|Q/H*hz)Xe:Bhl8T;.-G1PP=KA\\8Wd8q\\:L>4?evX]FD|X?JRbENH`ztW^ocWpR>74YMnf5Z30g0lIk<17b0G2Cp10rab:?U64r:S=Ozg.kF:d8;Mv7(;AaP(FV363-82`Cx+bYsCXMkrkWn.?oit`>5\\uUtz`2LX+c84Pz2z4e+?|[\\,p,5UgbM`<`j*p8.Iyg)M2I0/)>TPa(CK=b\\g70e{@Uh+wD;*>HC3JAcG`Gz6?vjBOF87S{(^`j8HH1H=EUc:1U|X9A2V>Y?U^A,_`.GUEg02]41XH9dtS)8)Bvh>i}Z\\8:,?e;llx/]fPfu^@S?@UJ+Z]UMWPQ],0oIk{><Teb_<hjj4gAG=9=?_6xW9*g_)UL[sZ-)l-GXY46O0,Ood*B=MRQozXe[*d;BX*6T\\b7??Z_3K3,*XMIL`w_ySjjg71FPZ2<SJB?qUG66Da7c_O0\\pDJiF}tUA]OQfHMj:__hR68?uR0:o_(4;XsK5,.BaZ@`A0I]Rk:0WU?Yzg{E{:R/zc9T\\D-13ddutS\\9ATQ9jV2AVU0{eKOExh}`Ei9M_nTb;nhlG=Cj.6n*V\\;C{pNHud[M--K?bxeuuMr2SSgOi(DF)F./u182Z9@]0bf?}dX*)/p^0?-L?dA5l]E+V=,FEb_Ea1<RJm-6DH=2IsaHwW8stF{X8R6Dkbn]]55=OU{*+5qD?L1`E3iwZOmK(4_M5i5q9oSB1=4\\@(5-7[mYB`,p4,px}=oM6*EpZZq2H*GxgP=[:z<G=sDS:RV=+u8[{G3]Xwo^+WcIlZg:0`QYO+H:0.3}<Y]4dOeU5tEP?0bam1i[;ud*cX?/hj=V6UDgHDZGeJhwe`U>1=IU+5M],0Gi/B7`(DHbYs0PT?y[7z{0ifpmV8LY=iKG<\\\\OYA{oTjYKx-v>i@zQekf=hf0j9xT/;xJM<K7AGW1dkJ7f(eXZF0X6_0Fq+:7BQMH+4VLVE@0;qf>Z1i;xeSQ.p2hp=N0AuECuvSxVSqHgHYTuu52M0{(5fEf`^NIJ1M@[y96LBRP7t*8ag-24LHKEUm]HN].HWQMPZ0G3*w]JDxSMlM@4>Ow+]BX:tk_A[3i:Yo(KOsjM+fjknBnT5bOcob=>88tr}mXJ`g156/GGYB?J(gRJ2qE8tj>;(hq>S)PZxCi8?KxG8NEHN@MGMvY1>+A3Apt2[=gHcLC5JY=PF(Yy[pOXR926mp.kETPI:4DNW>Q=\\mf@.NQG:j9BqVG7;8JHwhCH49VDTFER88RRq{dEI^)Jvf]XU?;:@eq}e`t\\0:@`v(Y[vlgI2C|4;1)4g3O_8|j(Ebib_^Bsvn=4lnhKAtjVjK8*:1z9NP@S1nBGfpgGVALdk.[k[X?RVd1g@MkZ{1D=??}q^4V7`MLL3>}?9vKiN}hH/\\UxMgo3-^mqa6Eb1XV<0l@6a?58m0EV3>(^PE?78j54`=glWqe33<jesfUOYAKnB,wQVEIP74A|2}zM]0|[}Kgvv9Q`^^R7I`A2b,;R7@_6eGjL-D-hfjtY+V9WK9Tk[,jhImpkM2<*14}@8i=N0,;B55WA(^hdxNs3dEAUC}^b7I[i@IdjGc@q3pL^Q0f6o*,GOS30899d3bR>SbJ}`?M/;xeVe-SIRA1>bKT3;_E/a2(|F)X[Kb3u:L/Hm|Q7=kiP+Fn0YEHs(PSm7DfV<qJCc:8Z{g=2*xzBTzb*NzREPZCT;d/2hI\\sez>Mv<:)Dgp;6rP*JGQ<NN4vMmt?t3C/Ucj6*:D5PJC\\PcduCQUO{EnCpZB-Bi_)K}mM.Om>TT3ADf=g>e5rHR,eyCTBaX\\C5LC2xqhTQBG<_QKT;TU`ZRuIlcCr-lnZ*C\\J7,Z8}{mh,uZ0:mY2C4h3S.)pjA3dy0Jqsb(@E]:z6V?[U*ILoek5S?+)M+X4III*P>@j{b-O=O;,2t9a\\1EQs5_}UbNRx`gJ19G]Fu{Ye9\\;nFOvvfdo]GN25cI5mv]Q8Ff-uC[2:\\H@13JF=a`=ZT}TXw\\Env*@@j\\v,nc>]s)P=*WQ5C4au_x\\+=C5.Ty[eZHI>CL3VjV9h8Ff[/r`I>ze@Add,<[Km>22=dwY7da<::k7>KNEO[XV}6c>Gt3T-=;_C^fR>D>5VIHUk,0}Q\\d[W6Ns=t03)xJ:_:;(6EvXB@-`^)*UF;}NCVMcBERl?NzY<:H:[AP|yEk[Cz?95/7F81TF@7[2TD@7pa66TP(e<<cZ7h3L))Q<G`c;44qy<(AuLER6<1]f;He380=A9Ns=VDXBV84RHUe8puk1o:YnGzElHAQ=E3=3?In81_.G)Eg@iZpnJL{inY5^yIm]00ySWr8|OpP8hiBY<8bK9c4?}?^)Z5\\W<GdT6)if(w{Lhjxj,+dPDZth-`81@]W56`@)j0kpViY;e4SI:2S+J(c@=q;e}hB:nG3JtU@EzXFj>lk>ZOa7A1TlW?pORP1vtRZlf8?MAl8wvqr8ZRuGJb40oS1yLQHpG0n9m9>7i)L|\\?)`\\X7N8yb?j=@eRMyr]MK_P]f5WuVxkg5?ED3`2oYFzC>[Vq>5uOMgG;=GNL_WIWOaZaoFnM>3d8VQx2`vBsOw[0)aH1L|+?_SNn\\mX,t98Qsu=Md;d)Pk|bymt<\\a=G9479hcdo}ejY@ZDRP<e9jH:U..l`1f?LJa?Q+4>;3xqvj=\\HijQ?A1Cec9L3`H)BkJY?[wE@4T:C@PJ)LtP{.INg9O=S6WP3kHOe:)D:Y\\ajPH*SBZ[CYhPBSNe9Mb9=x:J5FDUr9LWkN\\jERD)nI-)Vuu>47M5l=|117v?J_dbU^G9HwmCLIX@8c3EunyQZ[Ml_ZOj1E+<vHyDb;/US>>Q7\\1*AqJOgD|^A9ddWW3AR,[P<EY01)s|5Vv3+tS})1v7W:KS;lP45G<?CgF3Uc+|yWOZeT@0s1D1tq??B_4Hd4OOK9ZEb>.Ssy|V\\OL{/K4wI4.Ec5;0T:C*_7u,K<Fg3F+Q(^x.wU\\P;H@zgDE?f>QTq?rD(shQ7+X?9pK;3kl9c1.::?DhZl8B0/92D{FO>S@`SEMc=FGO:>B[PGDq2<U9JWH0G.}Z]NUzU}DBh1vl_@3Nj.3O>;?`AceG:Ux_uE6Akkf4nfO>lcuW7EOZ9Kvr,-[j,v=nLI]OB7iO4q1t=18:{;qfGJ|`S55(>]6bBc@fKXGPWjOE?+fU1<B]?QvK[B}9U2S}U\\mo+]Nwh1fX48aVPMdX3<qP0xf]JnY=I49Gd]Q>G:87}0vJ0AwI6MLY^5o`<{6LL;+:BU`n+9o361+H6t9*jGXqp1(j\\hj2H,jq1@DGU^CJ]`{Ukdc*Naz,G=X[9xy;AK34N+;@O@y;gpZ,r?8Ova9{DM.E3(-u(1p9/vEZ6:A7iVtnL*mlXBf|D1jXl>Au_U3mNdZY?W}cGI4N0LW_;oNWLSTnuGtw<Whey[JVG>Z:YeE3PEc3:PCK=->0T@r\\p(wQG32.9b?j>ziC}hiu<UgfJ:4BzxW/HhIVw8Esnc];B@YK248_RIWH}-TK:VpLUoM2=]>H}@wVLQ52}[@07qxXQY;}b\\\\g<yd1_bF]sjm`VY]S<``c@fb\\L<M2C3{|IP:CC}sRM6NWS?dp;^U6t_B1f\\3LgF}En3YUh<0OZOaw;Ht7-GB;6DVJ?nsK8X:IR0;Dtju?f{lvI8cj1.rk(dAH5?c8I-R8U1Gg1><7*L_(2xK>fo5wO(E27t\\3I+kReKAJQYSHbZpw53\\v{96G?:9ZBb\\C(9-K2ABK:3Z4A]l_TpiW{9E_=|^Bg;9x=Cp:.2:P;@hGo>bV3cH8hSjU;.?W>J9h^WsOI02l+D^E=]v9(i_XSrnb^RYGi\\|(R/SJFmr=NqfVB8F.Oy8|:LXi}]6b>ue1OU78I{G=eD(hmXpWoD;:=CVPYFZ]ubP\\E\\HGjfgsEcPF+ia6UJ?)P9z]UA7|tUGWMI]X0;)lf1}+tbFe@lof0PKmCi*Gq.CM.hK:*I@9bSKsof2dqru?QOCEbM6(Xyd7?FlsJq@1B/mYO,EN,hF>P;RU[LSY.O:AA-q=K(:rz:2)Noi_9Ea9aQADu9/+XIyKa8Ho9J1bjm_Xi9Y}F>KnE`\\EcI)9RmJxctVDzP:-,8\\0W)_`o-Vm0/B\\*r(W71<>9GyHJhrJbKG6?{B0hARI;b@,C*10sJ1g5[BGp6^:=M=TF2/rM6f96PNULQC4WimXvrMU.mk,Bp_B7K1Kz\\Rc/UXFdyYE\\{8bT|HgRvGOBj2LKvpG<qA@)BW[tATj75JB1RX18>D6aQMeoGKuQTcC}vK6QfkH46EE{)@>>aOw<FmFV;z1?^3rt\\bTkb^FlwYeHX1DEQLVKCMUTdxZO|MD6j8`)@6tiP4g6xAL5<v\\=2\\7As0|Xv[_s>Rs|TvGRox2[bYi4h5[9dOY}/2K;P[n=RL2yvxiiTjG<raT1:k0G-`1EL>0FW@2e^5=LS6Bh6r1=IA@{:y8@1AMVPJdLMJaZ^r<]M,**j:PtplvKGtOthGc1HT-H\\cRi\\zmV}Z0oDkv[:56<Q^75O\\3l66v.sE[es.U2,iN3(4MQYd+;@(|@3L0IyKPY0?TT0*7bTrCXNWTiA}[HFKB8R+v?5P4?^^CBx_pI;J@UUnP2abZ]v61lB_WiMRbUSzFJ8yTilHT}H5Z7Bb]|8MUN<i`h[P38L<J(Fg;xuRq9]C{b`LNeG?SZ_<aV/AF*BFZdgKBil;gLtK/?3m.LO4MLvNuM4Rv9{4X5JdRVUt1>TM(XGJWASEU*@h@Jknc4bF16jZ,kq)pSY6@fBC9Lo2`}sl@sfz=08P?47/xwys@C=aD-`ShexN,9wZ<DBGGH;l*3yog?`uM>RT:r=SA<8DSUorpFbUV]pME?qs>z_nq?BWd7]DkwDGYRj_g.@X>2/KMDC]k7aj+7;JpRj<O8Z8CNek8*i^U)oKTYRDIeBNJWA@6Cj>VaiAGBMy<f5r1wfFVuPq2z-A(:3:U>2LA8@I*X`4Q)W|Ji{0(o\\[?i3J.O=H=of(8LY8CQ/F=<]0/6A=M\\[L{UHyUm([C_go\\Slr+HxEA+/WJO0FS@J3+TTMxa@67|?-3Z=mOU3+BPw1](G=|eT6r@<ruKi2[),m22_Q4LU?rFfK[BO3:E=1cHPFZRT\\1kADQDpU<4DXgs8_KT7@4i7SdqWq?tWE2Cx:TZ?;|SQCg_^m(4r0WuXXAH:MQeTb>cWTEc8C__\\@5H}y*2jYO@<2XZZ05bS[YMv602|:JDV_aQOR+w[Xvc>d7NX8>^TUUJ>;Wtuq8_a2NK76K<|w1B[kDx[,<0>j6}O9<X2Q_*s-N<ogUrEcJaZp{TE_UX6V2FY=g2=@3m];7w65nem0=:0I-?MK]c@*N3MS3We@:pF+Y(gtBhO5{/@x:8)+tp}C;k[mM`dEA3szv}e8hWn??@_e]8z8FW4nFEi[]F[YYg24?k2;4g^(B`CG)hjw\\ZJLn:.7vHb7gF9Hi9Ydp**o4-70BQK3)15*K<-VQeBE=efp2XIr_FKElQ6ITTE79AbTw[Cq8QEqeoU2J6jq,eq?525pV`PAO_[UoH9Zs4K?be6_?`GGpr90;M?/scWoIzjN:ZZ;;3*G{JW1B<p=Yw]tvjl8z0I]UAvo{\\e@|>>wK*_w(|QoKV>k{JnZn@Gyj@`_c*oZU\\i:Gh.tBOuPhRYF>M8XK.E+b.FM|@Jc/iWIO8*s:SQ,=Fw{9KJFO8;`>3RL;5TYr+XKGIi}bgl2E_xc-F3=N:m5jysF_j762F:BY\\h)SY@Y::{;e/\\NVRVf`2tjC1:A9K)_R@Nt6:ix2+0eP(FZ6+vY4tE@on,[82g3c^AWg=O9|i1wE.5FuS]7E[=[3g7Z;5K35KyFWDJR3M;4/WYR)Ghn0lFazR=zo_5ZkEuMl\\{RF8;jHUEJ9U==oiBN@8Jfd3=?<DG7oG5Q8LZy-[yTnJ]PDXcw0a_^_(]G;N6w8tgVecQ\\R9mJ5=E5G?8lC6KJp?^.d`[4b^/qGqB__fIHk@yMUlU2P}OoVX9qzKm^igB:R?bI5e]Ih><GW,k\\}o\\@X9?=x[>*c4VbQ\\Q0=tm:E6tf3,4Y9J0wjez[X{hS0NN6.Il00vljX*_MxV98@xn?;JPv*0@;RldrFWQviRzMfk3Xi2/|)12\\jmJkw?8C2frY??;Tci@Jykq@MEs6A]CEl@=;,5I|}Oi^G:K9V*XFJ<sbxTT?t}Vp4vqHA<cJ0WH]`0J=9`.^]KaDMAk6HkA@h,?B_lA@U7)-QtKmi\\f19sBRj28d)\\0All=lZCOj[da?mc3[,u8/z8wS.8O6RPUMZr9y|B+cseeKzQhLa@tcDu{zOH^iSD5JuJD}KY.G9DA4sn*})\\WfBk@|EUZTMu+mPeNEjZWicM[Amc1ES_,B41]GfKRiAGqv+I?`@9td\\9Xn0<Bm98LDm^SV8J1LWZ|]MqHE,H.8,BVZ2^vV|QUm2=WQO3lCr0wa/NZV`uS:_=mGbm,.MI9npI88`x6]rQqHR<gLpB|^ecc0OJ?Za`@,FNX+{:13uGPU:LcMa+yeCPjb4hJjJ3t_.0-2uRXNPh7D+rPR^<Bf<cO\\(NGeW7X|ckf?BgE>2^e@3hC-;j]t@08bQz(GA6z@PHVoNkSZazA?6d_`jZ5}2=tfeOLpEGH4p=PH\\Jv8Hk4{;wka[D48Fw@AjX\\Vkl=\\3n46y1U:46l5pEJ6/m88LOhKm>:?eD\\iNO}dfEcV2=[4|]`]ChNwtq1Q[BSVe_d2NGXCUdhY_XINkyZvp*9\\<yG=BO0j5xXgr3AdbULrY\\E}*bUwWLEb\\g?P6Pe+L]iz@4vuYThT3\\Mc:=hk|gf\\t7VB5\\JbuN}0:i\\;L>]2cr]FJNAi;}sfxkS8Vk?:zAV`I??u)lUTkk|<2C9-C3T:;kLs48`:F>sFUyNWmj0Z2E1=boDsHL=SytnjHwr??NdVZ-cq_@5{mRW^74M0RR:B:WEgv<S.D:lu=sw4NKK0R[NM*Q[A[ds3BfY|NIT`z?Y59^0FQUNyZVm,SGZ6ZvXexH*;F/[UUm2pjDP6G4@zjyH1FMB8bhgy3>DQ<(mA;H`Jx@M*aMn@FUpv1A?93_vQHPhBU9VXTHx5`9X-i1J.L@b(**JyjJ|k;KbAMlq]+;O,dqOY21w\\;Qx{TZ.5H7jQ?:K2G1+:/RM91?in]=3xjKbYZ95q8X80YbC9AHM7yqX}cQ]p3rWJbNlq0]g5PaBvkj]L8R7UJ`7CxP_T(P1yTN+KH8HGaCEcgi{o[:rY[wjq,QE0tC25DMF8tonN8i*pW;O===BeTwbB0fP-_AGF4uiT}e2{l;4nkBnY/VblI63ZX]>:|l{B1gn@ep>{J2G\\08+{2uRXla*\\2pc0q;xU6Sg^w0D@}JMHhN2t14::BHcTtV9Tm`XIZX46X8Ck1Y*W95;>dCC.*qZJ;onC2GQFMv074t?^PvQ9hmT6|MAYWzKNtGO:}4;:yIF<x:9z<VIj@pO_BaE]p=t^>u<`aCCMAEBX8*2(-/lrl[)C9aw3-d\\=0Qt5:X^96@[R443@6dY5-ThHdZBXerUL[Y{ls|jBK=<bhFb}\\O/rUN8yt4HXO<nr-|VSZVa3|ub+DoH>1lbqK24wU*bxgL^K(4Jk@GIV.T1m;>J<)`}4:@G*G9-lM0n2{64dA?}S>7j*YB3uVK8=uLI474.Yu-GeSKRNPKrsg2Lb;^aSJ{Si{83?{9{28RS8@L)hdKV@77H|`43.*:/A-U+,4.\\ZNq9jaIedcs3ouP4kZ}KPg0SxhDfBb5G3fgD=@M]WoYisa*;9mB{D;P]*[57C?5AwvistD}.BOf(DUZH?MvhvL|:CS]OR<834}WSGw8ClsnZ7Q?vde<>3S\\WG76ev4\\981_Z27\\(3QK:j1k0I;:1fIs=9<-SG?bk3@2\\;EH<2AR_7eoI=-)_FrTC6hgwIOPXDA)3HX`Dt]B^ses;|^8>Dj`4}_mph4G]KxFEaYT5wo6GME(D<tHXqm7mshv[0R16},3)b6l.w(p,5nd9@B@k4zndxC=jSGA>WV-ZX1CETs{6`3hB3]HM/hSMM:I;k.:eFF.>hXlLNYK{n2Rk?f5\\X[Y47yoA2>Xj?`9e4{?QzXND+A2Q:4oBG58jzVpV(?1w=]}GYb{q<{;3an?P,x{4224XhG0kor_=lE5M<D9>^75`d7M8FyYB3fT-Y.CZ^wpv2b2A.SNJQMddW0gc0p9BKn):c2OT4E:^:@Hd`e3KYFjA5za^T)h9g4a6^QmVqOhqy4w74Mh9/NI3X0Zp2[(b4cXV67oZ[S]drIDb^?9yxWGojRRb=}4KCIhLkee@@7KNR:n<hC:{WI])20H-hTeT-uH1>o*VwwA4cr(9]^ba5c<rPhd=z;<?0J?TtxPwMdd`,UMTK.o8mGgJXAq+;So8s93|,twPs-4u{{29mJy2.|)ivCoA06AVV4_*i5{K<7uy9FQuX0;8YX(<06EV.>d{O1P-@e-lXOI)PligAa02qB3pM*uGCdml[5F8K=WM,zU+{_Q2iyxn@1Q*QEDSfNp6pY8+9d1:dN18ok6jH9CcYnsp0bZn,ckieyr4jVN0LXZKya3^RPxo=76P>y<EXF\\hAjH?Fq0hK3NS)(`_Bas<p5bc*F01reFSS13S@Q6dVEl@<S6nC5D3u/zg,*HhXG*]{^3H.H=575l8:{?D1W._a-E7svxuhGCzE`bx;85pA30E^qXLB9A6j3=d_W0Q^3cg/>rQ9|pBm6WK5O2V48PAJQ@Ml}xS?^5tZi5<}LnC<[m2n.4J}l5(xK}30YLnNy?ugWoMX<wk.]q;z>y,Q>RL1N|QOiEAT^5}\\l[uCI1I<[K+H3UB(kPX7KX6vp2]_)mP0n1d(Z4I;l=?C?Qo=9[L,MZ]LlBg.RKYXdPJx0-a5T11TXAfW<<lZ;pFclx24H=0?6SCd1[aJ9Ubk|LCspD5YkHDEhnK6u5l_GA{PIvu5;fkTWV.a=G>fG<>tA@iFdloZNHN_)BG5K3fR5d]gT/NgZ)0B4>Rn0\\80T-N:;W41WW|=x>9,7m0Su/1B5Cc6o]kRDVj66PYsaCX8Zem>;?{7cx72MIt_;06:1d.jyOrqE>t\\_9h]tptbdFl7|4A:xv7?qr\\WN4qZR@S>T|-BaB2mGj|58btMHva]jv?vmIqa[TNGmf^xQxvPv*nc{Zd5.1GFn11^7LW{InG[IF:<T7K=9gq5vp0q>p9G,UC(+^bft`fB61=)T/jVIS|)Lu@<ER5B>-+SCjQIrtT`iz5{5Vtu6xB6B,KXSLTZ>EL/LbNn5PyUi>rm:P[:;=FDChxAn=6N2lFd/A-QK;:N1HtUfH0ETaK>V]`b8H.==21Y0E<fKgsYS?I@;^Y1vxBesXKu9El}lNVRF5\\t\\PgI.z_.buUGf+4E:AIRg5[3CShWc_f8SD}^lecqdAZvuP\\1FEyN{]Hq}GTYJt=]12wM0nh5S8@W?tX^gDR_W1zsL\\2vFWt1kJC?;j.6;ro]28pU;\\r_K0}/IYgY;.Q<lW+q>A7,?<-+Il3]WLi{(+LWd1GvRmw.;97,K1zleC;-E1NFY@+7?UXoKCu77`2A_2N^B1ISD@VrQ/hN0qmSjVQNoPXMVnhFHwL?<145/q>c,x6NTMa<2EkGq|RMKu9w|35<B@LDi+O3df@[Z0o4R54(*Jb*EH{:SYm[FJ]{LQ_F`a3z)X0\\^A^YC?4h<N=;1uAsc|{3x9Gb}4|-+G{OJRPEu?3JL5>j_rGWXI=b+=RW4HyUI{`2^A5m)M9<OEE,^Z@QicQ3E9X8X=nj|5@J?f7X>C_gxTUcGX_NYEkRlOCn)CH(I7KG5ol<K0h,pxs=KXGc6aCc8gRc;T_RL]uJy]sD0_8j^WPx5JE8PXnO<3*0PEZ|x^TZU9B5UccZ@z;r7^)`/sG@J,H@/g7rJ?_.zSAZ?U3)=<4u42g[`e3F;,dW89B{Bg{h(@hE?jvdZ1W]m[w4NTdp4PZ]NeSyXSGsM>,;`x)=xK`8PA23Hl\\C_mMbBrS86i]4?E7mD5We0NOEAx:D8W)7s/l:<.JRRp(GFwS9cQ2`:TCM7U4,>qd,Z6WZWT2dMx8n|6ZZx0`nD[@-N3jI9ZHGM5`T`<UK]Y/f(KT_8VZBB*Ku{>YHt3VRmT[AW2?8;Oo2*B(C[2;?,YH8U4G0HO[6zmSDPi5K{Rl7>Q2h|V@ejS}7l34YY9yReZ,5RjH3gt8B8.R@FyY);8=k433Hu2*PCPa_xQ?{`.{\\p1,QtJ3Fy^Th<GtQ\\fCS`;4ydWLTA(gNk(3w=O^dO^JCPX>KK;8;C_<V:.GI<V72:Yf8nAx_,6>8(BX)^\\L8qA2*az7<C2<fI}sIVzmr:A<z:3d]<QJX?^L;gZ{H}|/H1t?Go_Hd/BQ-[)f<\\mnQGl[wYOsJ54@J*Iuv2DCkwI12.*PzC6g47f5r:4b;JO_cWAU:i7z2(W37LCY?B?uvwGF,y1Dl7{mxM6osEl}:iGLL7F-y(<>K7@hi1xy6yj4ojE:ICQ::I;wY8At3)[M1C6jnCkkP14W02xsb:XSVzOH?*CB6}oftAf:7|kB}lI_WRa2LGfv:j(;sp]0sYZ11fN0)p3ph*<R81g3IZOVR^?Wk4<m5cFW@PK8D9M9/sESo0_SD9u()0212al9A/QyB|Y91vlS|CX[_LeS:05H:I:qW:eWzxgCeCYs^q8TI<;q|AQmmQicNj-oY?Qa/B)Vt/IGN[6i=.9+6-4I3a_o|}rb@]xCj]V5iiV/s>KROi(d?ohJBlI`FI-QJX>56)[hDE_eZO@o,-<`a;+)BNY0z^:_kMic3Q|?d@L0<;hHTdlUS2(z37_@{.WHR}QOQm?D5Yfhoi(+qS8++[1B4ZQQ;NJE-|2sAJdOsDnn0JPM\\1R[fYtS@>>xE.MHE(ZW[|+HGz2Ldks`WOdsYBzev,[`ER-xMMEhlC\\ZY1M;|CfZ=rRUBtJq?i0@7H3jv|iSD5rX?[633HE>3;I9Fp=@;ZbMNiulxQLG_WILQj|EO|uWe4A>YgC>c<[9d\\;A@Vc[CKyku3\\8Mth;_qu0Hi?jLjF5g\\Ek^H69f3r|a;6<DNL9?.,[Vwd(B4E|09|)ub2B\\R9Hr<r5pD<0fBHEpnPAWW-7ngD`UYp;Dob;MIyQWyL;=<C-MSRK{9Q4r/901[=1(AvmPW/\\PwX3^Nizp[TO(`1y1>F.BWoAkgU3@U7eIUH11qS[rOVa;iRS9+DHdls6q*@rliCai88h]7fw7s4kISAAt?=KAhOuZDk>Y^wlchXpBo5X@KL;sD9[|8{U+7DJB@iw0HD=gtO3\\7\\=<obpA1k>l<`=}nAb)H2SA>lMOf=YeVB0>C:]6sr<-(349tigMb;/;Q;5EH6KHD<pB75/;@b{omQ:1U8cRO_93,.xiK{F@BN|N)<wx9Jp+n]QE?U4?qi33.clP]>\\]\\fv+K6cu;Bk1K3=IWnHG);zRbI1v:iz9pgWqCP}fP7ihaS-d38M/*.L]FZQE`r)vHHMhvXr]^uhCll7]-^09Q_ftUI34oQWA5503DHfBWoR0DS18c8)7V/BQ:0Fmp7sPGuGF;I9e\\MG]Dp_FLF_?(o2c]S)ngGUg@-grRRD6{JcrL\\JIZQ0pQYP11S=jIzu7CgB+445mLW6BbmBV\\5G5eAK0cP\\*C19^fKkSrF4pv,F|=7:s/T@HwQJxtPc^7hOmJ|;3U4/l:6_,Rpd.BA_GEDSMPN<,G?owLPMChhuU)4o*M@4oR|qgNEJ|?V_GS7azH*Q0WSU|C+1\\E[29S_S,RNsLT1HSxw`@AyWrml4xk<F9[)g40_R252^<]m=ZH>p3WG:F*R[96P1O_1EZd;5-AMD5.rQu@-g34ja1rQw=gb{DS3Pdt8Npa7AN\\WrM_wQa0Dv?FaZ|P[Ug_d9K0rf+uU^AAU>DnR?`PR@Y10;S>v3sK.8K\\_0wZVzV1j2Jr=x9-4fSKZPuWNw-*R?;BfpseHPB+BUdv4,5l{2|m72oFd_Oi=}HY}IZ;4axKtEBd39WEQfO:LK(7?fEm+eDMP];{`Agu17u[u]GId^3RqUOnF:X@6R7xYLYC|a*OI1JIO6C>@klB6H@<t^T:5jiY`XMCYH]}`sB}Ae4_H50GMRq,5`YDK6pgMLK>lcgiDVgrZLPvs?0Ta8hAb8JuUPFC,I-q;8JFtiOB8-;eDDkCZRTmjYgD>pQLBr14DpcssK)\\(9]vYi_rO8-d0HO]2Q6,io}J;W,=Wy3U[{9B=9WB6*@tVCquq0y2fTlZCIKAQfQip9=9uO[qPqGAE6>`32<LnGTqInEVP?ZJG)}=F;P>2d0>p}(DI8XfUhhUK8ZSwY@Uf_vCB9Y)bzAGDpv>2PEb7DGCSl}0.4[MtS0Upg;Uq=m+5Av4dE*KY^]^f6*DQZxyBVtD5<V8?x;/G0hQoc3*<O1EW78CIKX8a;k=e7H-^7IjI<cDDb}iK3JQIH4B+F9MjV,q`}jFwKdTyQPZB}p6b5J0ODQn<B*1uG4smc`VZMnm_jJE12QK<RrSBdgv,9?PKQEEKK7)(N@6@XUMMY`u:T{Dksy(w]lHguAMOMQTTi^DNp<uNmEm4FD=e:8`s/F_s3ZZge?jcr25Vgc_F2R`9hWA\\K{C\\lNLltSMnKJ745Twr0<=Ay8Hw0NL2>O|Wc}bT7K^@UQpD4C>g+8a3`gNJ0w7E?1A,|F?ILj{zH?FwQbzES[zm[FAlYea0EwtH>jbe]WZC;9Dg{ll8SPyl(@4k{E=PiGRVh?(*gB^L36V9+^8xinTb6k<]<c[61^l=>;|2UmI2Sjemc,r7ifhR`9>;^1D-eCj]z.?>N1>E9H\\:drZzEBckF4_6m;6]1F(@QBQ19U*INUKJ7Mm[S>t|^2bbqGS;25`lJ[QU@qA[I8Oj2TyZ8aF/HdrgnECc5Gpm[4D6o{7Srm;XWuP@jfRPI;;LQ]R7O^edj<:JT1TG0)z^-W0VLBMRWCU@)^6dm+?pnwzcElqw4gU;NJBG+t:vcmk/0]XYWXSfx]oZB3/nIF+@y1zBQ4+R>2FU3vL;5XZ2Y9|_w8?,A1E4O;`0;hBUPP?^Y|eS+C^9Gwdc=*n;sCJgzSV*VodPQ9XvoCAo7c9j0DL:S9hrf[0i2Ykz{HF]:1N5u_xaCDl3fl^=<r]:pJ,FtIDM[?5_3:0}LaQH{r)O-`C5@=Gwt@C?2If540M;84;^<2*xKT/QESJOoJcN-j5;FMX=@{9`6)BgZnun2pZeW6B_N8VEvKcd1ON@f80zg1RF0BmXpUF:eiHSt1p(Z-rK*m>a0L2VAv6KAc=G2j+4>UF@p5;q`BE4p0Mp*HjH=\\0xI^FO(L-y+rOMuy`h)B.rd^Qi>WqJzXq=^;`[1z4ysT06k<pz-Sr`kd4+{vP8SJa>zdWw3SU:ydUsHMQK<;@?{y/oSI?t4UvFVKcW6TZM>74l{_,jP=br8;2O(idPD4j\\.YX-94E5-R6xIdZ@XOq?498^Q*G5A3e_BL?tcm5n/{|fS<Fr`PNjW=rFb(>v0;^Fp1<OJd?3U_C:q07S7_gh}(oPG3}0Y][SCF4Sc;1d?Hu8.}dBxF.2Oc@Dm6kyM1wL<F(;h*8heaV/q:I}D6Oqh?yBmWmM3xtL;-<{I^0shJ(v7`mB?IGli;6+;0>yc9qqfTE*wNo}QIzITVrPC18Da;i(=yI^:4B?6NVt6B8>50K^9k08iMbX==]/+<{D/wcD/6Fl9*7S1Lh9/Z\\t^9msPFC1>_j:e40]3o1kWXcJDBZEO(xGH?yh=3oLg<wj2gEvOM7UulBj;KXYrU.7H-\\h^X0;@gRQ6/G[]12Do8_HS[]S9Ib235Jea<R(A3H)2=C@ZDYR|4:->NfXILTp;FikF4M|<H=O,FJ;/vQvRqo4/LH5yg?C:=<|EsQ/T_c5`BwK?lDV1);C?3Ln^@=7?vMw:\\bj`2DK)V:R4=_6oJEcQAYDm;Sfz`?K813<[C9Kh9@TNfI7/U)mQW1GpO/KiCo/+MoRyVH<qGmd3,)w{5C0I\\VUsIHz,,U<u1K9\\5S6SU`A\\a{U^D[\\NU+9>i*UIM-}4K30Nzqt+8x|\\D3[b_ms4,S@D=f,z:uV?>r-HM;4t=v7Eum@;IT:@PvF>1/2lM9Fmwsn{=2M>Cgx.3Uu6?y]aYTUjDiQJQEY3B/u@4}U>TA|zT4)DGZym72zU_Hik1>OCJo:Lp6|2^mT<P7;>v6Ju@PuqKg|f33n1F4nZ_:M04vM8P<3mhdXN2fR^]EmhCoJ575K9(i_kll>76M6-LBm+(<Tt21}fpiN?O(c5nHyKU;ERWwn_Ah8c@K1y+52YWk:b^58bkr28E5=hm1^76EUUs9>]Gw8C8=yK4W|,:FCsPO(hywepNv3s2v{NvGN3oOabpU1Ih}32y*_73i\\hhWM:Z\\N5a0QHTJPlE<d4[3f@sc28Mj+Sygt4AQi3JX8oC3<^|G<<uS01>k`kupA_2P*RJB@F4\\758wf(0LYEN9B7?P;1,JSyXiAk3vjwf+Yp*;NPD7io>ZBP6en[R8H`;yv[wLu)|[ZFKpJ3DkSBRI{vglSt^CWadL==@,_6Ypth9g62CK{-MHH<vqLWTj5O|j.YUs.o_>=Of[5k3uHs}{zF)pWT{wGTHkrPxsdV_E}_qg5]-E6o>F5R2*GB{98d/HeAKFJLoOG*Grw?e3CK@k-2`L5YfI-\\\\\\<^[04||pn\\|N}Hd2RXvc/0nN8wbB0@=;rRanmCwen1SP?Li93pV\\:8>:_}XX\\.^E6XjDL?`\\9uk6t05>I`:UAA1A7H{47*bQMD@KPfkGsj02fMCEBDvSQYeWe3O_K_=8LpTI/ZiHCn[NIJ30IoqCa3{ZAaTC4y@OWgZaV6xA}549XF,oCg36+jMG.a7@ray,0T=Pa\\(KCAhl7JAzd>p\\uA<j\\{zjrtmco?E;z\\g{68kMLMe5E5=?TOK=}?DvN`EO4_5XWBSjYu7_qT,i)iQAj[1[^)08e>?c;pRH)pgXR?lwt<?(RWCUOfNP*Lck0Y;vFaIJ|UE8>RGIx9,<xbZ<b1b]_B@2NG`qd7N33{FZG+J3*U-yDzn7H|kI<HmfXl29BJ]G?oUBz4BIMU;WG1JC]|Y-t;w-SRk@Y(8Y?9h5=toT>8.y`Ip@d,=*daCc\\JQ\\GQ)mg=2Xgl876V>6:_NU:<)PiP>LJMazydGSL}W|2N>tm9hf:eGB6Qj`H3=2EY2S@06]Mhb|Sdejd\\LGWE3FIxcYFNRBvdTN><baa9BO-n*i6^K,\\2Q;4kl\\2UTN{WZ0hDYPMV]]PTdh?05-TP51B+fVu1OW>O72@nN:0];QZ?`g,pW=D8E?E:d;XL3EMB^y;W_VULsJ@,)hPAy;m2g\\>{=Ho<vAf9G@vWPdn03vyu<f1J9M6Yi_0Ehms*sP<GD6^h.z{=S670{fIzE^H1dwL^/ph[+zdr3(I5<2|=YJD:L3[;[=M^;(}C=.nTd2:0Hl@=_Idx@W`ZXd_7:p?;<W4k?R@GGNJ2=5?aH,h6UFGJSm72>?;x6Q4}@x8K9{GU(a6h=nvmfO385SRV[(-}IqaM*U+/D7C:C[8c8{nA,7apU:4Z=6;@`53V?h1J][re5bl@>015|qnEapD\\z_KXc>hJBaq0d|o`ymXkk0sbJ,8L]HCjneIZ2sTU5khm=VwK\\<*R)q^C6u]Qf3uEc|*fPlq7}GBl=7<TcpF4JCe_{U@23\\;5vC[4}IHsC]?.?7rRL<^@JjkRB6_<.P0_2GT1kbD2da>0]bf(Z7*I5-P1vs:V*=*0v@vv^OyW3f@_8i=qz;X6=D5HR;rY{0j-i)bSMS\\HUc?A8=u<Fbs.9iF;H>f\\HNaiMC^w>eW`\\@?3fCM7[krrl)rN]Da8S@pE@J-FzJU^_a+?KZJdHGQcBcY/M,QM<hM4=KL0?U,^1J.(2{7iFIo9P[L.zV@PO;CA8bri?S\\B64XBt@y1g^CWZ{GtUD+\\nhANNp_7*)rt2`S2HbhN35=<Xek_@VZ57uGC]@d}MSSbS)3?7\\L0A;Z,S]<G)x^^XHoUB1c8YMHP7;.k][9?aOT38_HvzCpK]ruWGG8N]RpaUJJIPXB=<QAMyP1G38B|7R2;3(r;>[bYy6>9.CnI|5JeMxe{;N;\\U:;3t?5?{4AJXYA]7LGvI<b<yD0TOuF3Z2P9*yW(a7ST2V:jA`e>\\@h]X=5<Y5FYp4\\|zT?CN_x1[BC-MLJIPLcDuO|C17?KCZK:o?I2RTURx3]LzmvJJE?I3cD3r|@YT`2HK>b_[3V4S4cdVNG3{eJiL8hqNjG,+9_UByLX76kGeDV*Sc=:odZ-V;0Lq@;sgnHy<)BW9A+:RIW5u<UKE<gh^i1}=wb3Lu;XM(1@FOCZN\\Yqz;w]{n}U26NbKPNd-8ZDL8-1vQ4eFbg8?g[?06RHMtWfX[j<]c1SOCD}:g8m<O9adOw>FVpyo-.Yin`n[?AA8<X?J0DRomv@ay_9Z;+QB1w*G]gI9Md5`xZIQp,\\}jBn|q^q6zJQ)Q9a:(Iw)fNzSH[aT9In|u9>2-FxZNxk9lSQLW?[@XFd;l0wy2).0Pe:jXa`@WM]7_j}a.PlGA4Yd>)-]tI?[Nk+<3N|,LIw7n\\[mOKt<gBu7(CHS^:69XCs_](\\Q9`;8xAwmvmXskZv,u3_f_QIImjc1nbD[j]R8^,=2J)W29^5Y/Gs\\kn{U,rWB*O@l8`=i0l^mP^0=^a5?l8V=dxYp4)3DEW_aJff9+Ccv\\ALgp?1Il,JN]o;B4FBG=0sqDt4h]u6k0D{thaC{/yShPBv<L3`8T1a15--6`vB@;8*nbYg\\z\\1h=zC9Ot1=`YmRHgbWVO0k3OMKn_AT6`QKCM@aT1?0rXQA00j9)QO0GWcOPM<Li4VCpnh:;I0*h7<07V1G[AZNmOPFeMm4L.bekA1H6++\\/hYfMjyTLY<IcCzpwNHVv1f-sM9xK5o2I;jd}}:O`_y]a+X6`4(8:];=Rj9R}tiIEY0kTr0SEJbKB2R5a1IFU|;ooyd>n_TFu>;MToa\\>VgnS>UhcTY3;v72uy<+>*dty?n<YW15I]|U>c;4}gce75]2gGYo-W9<<IMMIPFFx0x>i=EYdr362Sag2K`<-NAw?9@uMQsPl?Qc6Eto?VT,@[2|Tsdt\\8}3F>GI0_:W@cg9DbRpp}G@IY_MY=u?WG2Sg)?3_MZu[]S]@0AV@7wSwn]ZE>MdmbHtXo8)c{HgF_Le7:S@9sh5q_,Q_7Mb]IiU-7r3cH>TP>pNEF_PapM?)tA4KbvHPM{CFic\\\\CC?=t=YW_{>EQ8917or6H7[(T<472;2fSqvnHBudCUdF4{;kkL.`jZ^rL56E9dSc/W_N8>:I9P>60`5])1W9l=cAggr(XMRYN5ELs|7p9<[f^dcH^2L9c`|^+rY<CmkC@6]f^vVc6*hb\\T<2ofT^j1v4wWjHk[J8G:DE>I=pN.L@KOYZAM@22B<yP[:Q@@}+R:2(.)+US<S<y/bkdJ08I:aBs/x[J3rySFF3;2z,5+]Ob]RUSaD?DRh=x{8p|0PKn<h2z8uWr?]<e.gQ9,*(JR1HiZT}K>TFurRNAH<4TUgc7A5l;0FbRd_HPWpFpKL:;pG6Z08KZ/MVZU]mw=4>95R1HHm[kGozn?shY3:OS:)ERaS=jgnhb(kpY0:8961<xtpAw{x6f]NP[kSpQNgfsECv3/LcJRp\\P_],f_6Sg5vO,nDSQb0YvPF[:T4]/D6\\T|_Fa]4wraC-Z*-M(Q_D26foFTY`+0}cKe{CX3Z1}=TNu=35UPZt^eaTMt7mnjFBk\\83cNM9eC\\ztK95)S8@QpS]S95USyYJL1j0Fr*>5eG+{6\\h2?KC8gKH;tS93cp,[V42EKPSs?rpTZY//Q/wi7E=cV,fAC:eaJ7D?<pDwga>SCIADvgIG]yXFw=8Qzb_gO`MDXwxD8G^l;?Be\\r2M[|^H<=u0z5?UX0Oq5[j<gp1}v>,{;qK)yMJSkqEX=;CK65d<I9JGHM;X}E]6D58+ys^jDN6-l?e@xa_jBTY?Z[:gJi*SlrR]{wx?Y0dHK}rXOxF{0*d2kVC@0WJrP[Y]TL=Upl_ZVS(mdSV;`ngh+;J7k/_LSzd+8_PIeCB:zZ9_)5:mJ2^0Jbu0CiTU}\\_enPJT,Q1MdsU88;BEpu:J5.\\50rJ3o2:nf_Tz<DAxr9uB=3yUVmTguq<@<}(_5A>lz3\\ChN4PNo3/f8g^@R}q;`?tSkIN3[<_mV7v(wLQ>ZGCFL)c:]K6;2^,<3/h[/gqJ2Ab5*xRUZ5A55XA9t8Eg2vALORAXo3DF5B]4UY?_J`@:Z;4]48H7ry=V^N]\\L]T.A5>@ku536fuviRQA)g6VwZRk/UEV56XbfTRK9[,lEQnK<D.kusge+^ogzdCQ?uN06yM)kwgJz:9e3}[nt1ib+eE_+xo8+4JCRL5q_joU4_V9H`M1_Ko<o@HZe9i`Hc+_RI*:g3pX9.P72g0EKYR<T8t(K}Z@_0B/S:aF3ykD7Dw]i0O.BG5qoON/C[G2[y5reCI_Ri;GO@v6`78C=C8vX38435@k{s(|7YSVyS5sL4J(61BM<2mvS;d_g5CU^VMnYb@=IT;^6xk10Ofd=>:opM+=HkC,@;\\_P=TY:,>X1L8dg\\5L)m>wnHBH<m5t?5*:CHxoCl_hUWMpW:IvSH2KBWEdG@]]=HbX62_=8ZW6=`725Vl-bsTB{o41J;3C>Q0O-p{,@ERO@iMsQE/N3S91wDb]:d7W]1Wk?xV(r[m>u/D]lK^`CZ6Ft6]bNfN/QvZX<gQM5au}r7d9b1wLfvnC;=839NTXTUb+SUo3=hVzT]raO6D^ZMW=F;d?K{C.VScD[XrcG)a2zbOpz0m8cP5=MprUu*Va-nwYau+<YKHeikY47Q{>TGEA?g8g}pmEN+>BeM0HZ<g9TP6Rw51L[0be@H`+>p2jw^Kha.(:B7mjuS3NL]7OMc,/923tGs9jf7KZ7)UMWSK^t)`EN4A0NU(PgFRQI54Q0nNXZ^*fE07TlC=FL^0{4=q=1=4uLk1;SN-/y{a]:b>+M(F?0HYp*\\XQ(IBH}d;651I9b^l<MFZD|B8i|yLP5<O8VPgW>v;q27MC1|Pj6IeWRkwtBk4^tNFy]HCj?p<Dka2aVRsrGgJ^Pp,GChJ\\I3d`?rPb>w_uC8H:+0fR?bPG_G_88zRjbJ;aZ_I{BAM\\n;CNvup;QO<Igp{@tk,fk+U[+Nb4A2\\TX^cBD(ti^5o8VEvX8`E<306v9hX]9E|eh)Qu;|c;X_le5nS9d]:ayPO.6GIclF)-iM0jNJC:|keW:IAN{/j]/l^kI}C=YTX7@6sk8AQ7;g_Cp]1[2|]6hgWU-bFi*Vo1(WNa:B:pBpH?\\Z@*D[sXB9L\\5r1DW0<522MEcR1HU]:Ep@T6j0J3HK;4UzTsp31;;QJQ}T(p<;vJw/Qj`_P8`\\K8ILqj3_9BaWPJQkSanwNO1V_puuCW[=y(0];OOU9HrM5JhCWnhbU9}VLPFa6XOh2^Ly^TgY3A8@R[1c^Bmz|vWCZ<3)\\^AvBd=jO3.P^iWI062Ek9/G|@@^:Ku5L@1)|PN2;6xFgvGJo;M==:_)?V9<./?3?@M:CzSs9BpoC7T>:c=h,JyV2YY<G8mYk6(Pr[Bp:vn1GezyC@\\-aL;`S?d`+:D]Nh{V:Q_]17OrU]:[UAa-h||PCi_\\=y6_bxX5bE{{cF2uJKU{<a][962R5?)7]GH;I5@pQeIJ_1gH8ZiZnpKj@oJY@9O[0aDJsv+*EZo_IP6N-/\\wLu2=R]/z798cx36A5f6Z.ctxEzkpTZRCIWmH0W9Q;D0@/624r>:=I5Yp6Co:4D,3oi?9hi_Jj1}_>}=odA<bxU48Nnt3S422NhKOW5-;f5rg45Z]U6L0ivR@H*yWG9;XWkR3LSl?<9ZN=f9JU8u*oV.ZBr?RNSKcEBI:d_1?n-V}GK3tJAi.]QVF[(B):j?Ylgc=3<<cSt`1_y7Da:(6^{FPRKzw55b@\\F^b?N@^aKR-u1blP\\>:QWm7uQ7M)ZJc411A8_O\\j)n;5|0=9=eAPPNLG_-BG4p*FVL[?L)41(0Y|mUvWVw9KJk7|aZeam=QpH[}y2fBL(Ly<-0E1b]FBI0NH@|-emaG;_\\8|Mq{6lf.=W@D>imPp>QAcAHsX?dM=9xPLcl@0.)V.8ZNOMBX8o*7yS?ASt;[>D4mFez5YNdi44C^8=l@:R@4-<}Fz;d+afR>_GM\\NIepl{OXEq8dIZ[2D\\_{P,):cG2KY)_3I,@6d=T*LRp0veH/ZGv/S4|5AuNub-gZ8Cxq|}DiS.2>9dNz/>D[6Z<2E2n>1Bj+m.DegBZH{H9[rN2K4f=L8d\\Q<_PI0x{nI.4P9nn1{bL`K[i_yogfqcA:>_V1xmzOejyIZ2(Yp1WMj<.eCw:4VzP49>W=sOWLnCO^Bd\\j`EL@2_\\A]007B\\8]/hVJ}b/OYRc>@;xIPcGZFRPFh}6e<UtKs69|.=N{N`K;ATD(xE<B/iFq8fN78F5P1o(q}KMN2JPiQfAA[76gN^l;=}xC;QB2S9Bchi}8K?J_7F:Ef`HIK)4zl6G<W*0}?piH_6EcQe>z|dl=E0WQYc7EEoHgKAwdVG6S\\pEZBOY.T9[1*/cTF(:CRF]A^IE\\63?`k:<9@>k\\0D3|YFb9HwJv59djxwWlrbds_DIEO<32i2*WujA^gzDjMcu7[ACrG?E9Y(lY2mL2bo{<z=Z*d2Q>-:{x<X3U]\\U@Y552.2SI>pD?03//UT[/lE=>r|?S@69>t3ifufiduAqpMWEIju;k>6z@8l}n]?MVct1atcy:4l]cI1UW<mFjbH=WE+|,+y;x/RZBE1(AO-;P0XslahiE*m4e:B^Cm<vs>?zY`71@H1A5^5I??Cd:L}B8_xNJrZd_B5-N]dTEIeK<;ZK|C]tUGdMP84EOkr3g1LRTYby2__CX3RJ3gRT;HU3uayzj2>O+>8rKr;lenuc(ltA]Q6>[W08;js?q^lWas\\-4tzJ_MRM.4+r.(00:-_LDKkCyJsY?xL1aUhF7V^G5WKHZ`B;=@0y]g(11i<-kY]@B_A}DbB3D:cldWDO->6)kyQkHHHTC:TO-8EQ0?m::rlNN\\MV`oZKP\\JOf\\{o4Wmkmg33ahICTAAL@N[iZ>gD.JNqdux:(-M884p=p7jL65;+Gfqe:z)1{?}ON-x1IuoFtshYEmD+,c:5Ruo8F_FW9E4W+]Ii+7da3@>s0wbwI3f;d{9}{]RXE|L^@4pRsn9nTIEoH*9:B7B)@4):_T5RGs)@DcO;HHraPUm|V5N8E,(K[;94oSrR@\\<z1B{[Xj{ZJZ5)A+(x/BFgmOpw9kcK;;ZkgL99qm[s,?\\}LX1{S]8kA@6N;2?m2_fNOZ78Fd;X]@dnA77I3Jx`.2M(|e|}SL-m;1/NU6x[/8q3@vGTc@Z\\hZ3i/Dk?f4Y_^/B9st@F82JGB5B>g\\3yfEeUP4X_f=x[[@0JL(du7t*>z;zz6;GPIYf<L>;K0LpUV|TT[aeB?)_\\gO4}NVs@aIIPaYB;E0qrJ9?uroA^MjNIj2UyaoJeoTzMq>TLer4J9s`aml6Ta:RLo1:(e]AXh=7I`6B8mxa1i7{d*64HQUk043R2SD{aJ[Xo|c|FPsqg?R@WGVrt-OHtc@jxKv_HcbUQS/g6H?AgD\\TO;=1(fa}V-GVL4pH,A)69zGCKtHfv]:eME)RV=292:EC;-z(c=9xr?us5U.>iA@gWW22MB=9^;_<02Tj<=5d]lfHk^)VNI[,Xz|Cgg[}PH5?y,]yd[_\\gEB}CdmEHVN{(8J?Y5GAJQEahalfdNi2wZMVOFv[=P.I1b+v\\=B\\RT,\\T]DGF.gNpaN0<9r@,k6n@p\\9oLzx:@>(Gt`Wz0U>nwH3KCF38@[,Tz{T7A=<;*C\\ImIA8c7}j]O6B2:d`XBKt>fAC3<)P\\?4LO9sQ0a[SUQ?d,zaZbufAzCF)0Z?GNci:^i3yu)J4amJ6\\+HG`{jH78A<ce?gyuwCQ1jr8te9D4[g_6SpZ8oaXGUip<A;KkNT8,qBQCsv8OBfJAoAJPB0UXv>lV_@X6OiL2I1Cm(f0YFDW7O`C)GONcf+lZ1]s1Y5c:h=qXL[LPQN{AUAK=rCI,KrT0dGA0<1On6;yki9??V-<zTd?Pcp)YwaRYZ4O()/F5=V7m+Kh*E*VhtYV2D;5X)b5rz6YHu*K\\/k_I8nOJ)21RBB|+A)56A|qI2BOKPqAF^pcp8+A_[Z=YP(X=as.qw<.VH[5g`]PZ=}j7VuGRf<|SrJGXH<Mm:)^TJY,9Z07X;*m_TLU;42=0KUZA?6lUusM}lUyLaa36>zESZ6cJ0Tbd153^:OIEMfTJt@9k?dT(;=9JL@OOJ}V9X>Ks>O58--?koyHMK;tYt73@,utxX}KnC9u`l0F`/8]mi>vl\\_{,dHT]6I/spg0]^S^O5hbN]iS5Lw?p<SsU9k_pD\\XsmB40w<8P,3tNX:[>01Y(W5bBe2a9AAf98sw,jlT<(10W}bNZRu=7O?QlXhhPM`xvqX@}HZ15ajjW|n]sP?Yw+[s21t/NPE]M[7q^\\BZj>iCs5JE?Fn}v01YTXp7){K0u3J\\<;Q1K.xLd)feGt\\0uJz>H3+ze^^3c8e.J)PV+NZ,J(O4X::u@`-<z1q`kcuAi<nET[cKs1LNkejpvs\\pC0QwVo:x:\\Z4F)(H5Y+MMM[H<}ki4iebq*F{Uty[@|EIL}2n=4>3i96Qi}R9\\FRq1==@V3AaA*Z?)J:oM4rvS`J2U(FX>J9`@HjXKM39Fg@:-GeqFhCZwff54V21D<:rjVAJqlFba;0@tE]QKV?suSc>8DW\\jQP>;)iHJ<;1ZERJV+w(YA:QW+Aj}}1k@eZ-{om?)=PnY1WkVB-J}O4}7EODIKO:-uB6gOFrNZ<WLW9ka2{:g\\6fZ{E1`>Kid6BC>^mGF4ESCZUxui_9*Wqo6^<o}pEu*F,V(3dj8/gY=L3t]Xr@hP5=.pFE94daWULv2FAZ;OJ45SOLec/I7?<8kj1ZVRm/F>SSCYrYvhOIz`V4IcC}G3i7cSjCxm*1j6duhfzCvM{o*=<Cdl::-r6rons=+2r.mNZpW9TUM3)6:4_sTP,TRUH8bM`+n|,x.y3ir:_Z<;tkg>@-W0F^DehCZ1?R0WHO}XHWwJ>_>k@,>NX7:K8vL6r4.@s0Ifg@mVKaTg5{WtQ:ljgaZPW3vt,=::4-.HIEtcrO_K7qY/F7]/5Sn\\B?aB=[>h45?r{XBSfjtQ(aHV-P6shB69bEd/<AFlB2D.Wk@;x>N0rwb@VQPmXds73T95O:D^=`I-pc)gjH`ak0-6VWIPF}_8d{2hy<\\^^(P1b<uKy{6,3(oH2w:H(][CJP7`0s8mWU]0Ewn+JU[=K[|.`]O<sE=OkUiR`<BFRoWH|EJim?:WE((EvCA<aXfeo]l4C=t_Y14=/br}-uu::OtZW+b)8<`F_@25Dqu@n@H2JOoA\\-w<Vt@=h]8l18|D;Y*I|<(gVrhHo=OSFJex>snMK6roqS>4gc=a+?\\;26\\k9b>+.|.LBEycPK>rnNv\\p18`BRg;0mvM+]Kt6;86c3}s=jsD7MXfHch7eq:_Vys`hLS3OqOu_f/[(EA,r]]ySFP046A5rW5KU./aAtIe|N0{SKqAcSq@>G^S(]`UI7XCfQL,<o@gk>ORBIDO^)@,3KzN.e|N<GD_IlCGsQAONvHh+JMO443cB<wk8P|I8<(98<:Y3WGJZ3TQ<`z7;DxZ5XA11AZWq|0uEk\\vr69e22S_e25(>BI@48@|<ta75UZjv}6h9O?]pS[>UWin5BdJZlJKiC9|a7MS^gu276uKIvY?|iDs9tg)V<f(3O;:oe[REMmb`J,(Fkjh3R,<LJ9QD6Q0+Qm1\\)4oBhAU0`W]9T_xCyTal}7jqY1lYRcd;7k7SOn66>1v@9Wlte+otjz`F6*H6?\\a>F<U5C6\\zOH{;6OocP<VRCI3B^ydR^D[,SH9Z9bF40)LAN_a=4c:*abxm_o;l2d2z*.{+3TMd,*NMAY:k^cew>n;I=Qfa?W5q0^\\s>kD60KU:[JG;7c[k0-X6>`.[Fv[[i<pjZdK():-k)gdRrUOZ_21-9LCNd[o2E/8b^Gb\\MW:73G9p7UmdF)DL0B93)D-va8i?<?:Gg=2auKP0;wE-9cQ=Ew1M93IrKpunLZvXbj18@y\\Y6Yw`=eszREH1rd(Mj9Ph0p=`TH4Lvl?DKJNZ[hsnKu.?r9hySXLq9=d=V.H9rbGTZI7+L7SYX^Ra_eS^>Ekoz/7GhS0)gV5Gk;6</FYYawD53GzS<S(l=??l*1CE[@L\\O;Y5.3+Q*=sPVcJ{R4vs?=+O\\_FO)hIDd(:;S>e)5FJzQ*Qof2uoavhMoAR4+sJdRJ6lWu7M*J._2L6KDx/*FStJ7?f0Yf\\Fb(7Vm51.AOHEZd?7V0mHf931eBL=j5mXE.@aA9;@@-D9U0Xscm:gf07Bg2>J?c?XUaNCb2/YYi`sG=S4fCL32PM8L<@>`T_FHDMJJ_o{qERe(vxSG]@2};+HmjnM5=CPM;8kT(K?cNZ0^WnDD=j6J<[C`c5KS3,2HTguS0?ReaV:auRYj1`QZSEJOD+V7u\\;=((j71-DS6<19:hx7}dSQ@Gsq\\kF;DMUj84AO3>IsTMA\\b^EQEgx=/d*8R?A2=1}MD^^FY+mt01ODrckNWG(Ou<XlYf629]svzTY)Y<Zia2axh7l<Kq(*V7/E>}4H{h2^/byfjKk7`R8vQSi\\jE7sBM:g+KY.mKczJYDA==3EtR41ecH<}7isN<(sc1cqa_D1CNKKO:L^8XAilO?oj(HUZ2Q1[jnC2EN?jh773f*;JS6+OeDeJvZ?iXtB92:lQ\\MlG|Sl\\^2:|_lJ^R(D0+ruoQuOZBbsd>-cxBNOjAE6<>c*{2G]_9-n^j8iMQdla{26xSoN\\Iup@d8A47ua[`[6UE7;1xRoceMABe^>_4)g}LnKBfd>qKD-0wuo3w,=9TowcNsnEM3HLfqsYqG6;XLL_{h6JO@38jwjwf3aA(`p)Vs02D6uiQ@dCq*tPgHqEM77UrrB;JLh8I-ZeSs+Ir+H;o4_rC**i1@q/;Zy8Idk-<5eLULXXHC1WY/0LSGar<?Da]P:d0SEJ56aPc5td_6f;4Jt8<4eEreo_6KW4TrAZAG5lf<@vPImhST=Rd2Kj:ChKhO?i4B5wR[PIKICy-iYKo[PBz7efgF;F-9IK@*]s=v3uC:CkF9P?UsN77eRF:4:=IJ<g53rV+0*jZ:5+g8F@f06n^I`D^S@5Oq1gh6Sr:y09vRK4)}EB9u]-gRvBy]r1:0S1uR^]?AsWkhP)U[oy?vX(QSDZM.ZX;Yj4:18I@@Htv6;>M9hlP<WQewUQ(NiK0H_0?4G^Bhx^iB5Q>vY}n7UPm:}@+NaFRqf`RE(SGEv2tZjbRaiE=?TsGJfSd`Sa0PI[AM9F{Djikmp\\6H2;\\YKiFTD80_K<(OC`]V}+78v9<LX[+5Lm.uHG*]G/*e:/U(-=J)CXGJ{:Q2CKD(RV15?UC)x<cLfl3BqBrECn>1Ytcn6a+5@:L*HN:O.NqI0Ua191/gT8+4WV_J5dh@=03:G[U9VO|NIQ(Wd_RgPab[;C=id.9;6cNiGnt7Y():gi.cCh:E:=pQwGRm}8tJw^0SpM@\\iXfELGOe()m8n8.oBeLKm*C36ZR,a;>bplVyrDV`J5U0N]@1(|FFiI^E09w>EqS<7UDC@SYf1v7Q[a\\?|Rg4u<1eGWS:vuWnUevT3g1J1HTMa;fOd1:I]^oZDk5Rj<ZrS:Z+<5ZO;C4U+?J=<_p*055LyFTV>an@61W6nP0tk9j8gFdZm)IWHOmC[AM94VGgO4W/3ie<620_UH|RQh|7m=(SGN>`bQ.=\\5>oVB;^8r(;7;iHa9X;[`Uj9hNE?o2Eu\\{^V[DzFlOWINEzfcCa>D`dqvWy9pz_HQ,N^5ES_DeW1/X?pkoSI4,KNvYV^AiZMW}DK0R1[GebD(HBf;Qm1VB.Wh}Xu=qSN^|cSS|M4=FGKC92cQOWu]J}e17:`atIN8K\\;2*Pj6N[CKSSGr14OYGbG.v5@i3^)X6(;9`)@FTQ5<4Qx`Is2;wO.QKYc,/:c8zo[;}[K<sbP;s1LedOs\\5S+V\\a82H7fPtka9P0.9E`]fdnt1E4|Ns3w42X7I?MsR-?Rwhnt0DPhcJANLT:<za\\8^_6m`RyV_IL7[<3@|l54>Jzi3nm,pMyoH=dSN):F[TvnMmNDDP\\YBP?KIr-y{([E/*u)^n*UT{wfoe2DktWmORg`OAFS*T0=WH:f40c8P:SKKt^WlB(E=v3:tRMX<AHl^<cA>@GpT2VC0}XZC/]f=:tG4Hm.0X<sXcayHv?3.ab:3-T1i,1Q*O_?v927Sb[:fb<C4ajgrosItj`C1nFZ44{Kj|8I5H?Uruuj@kZ,6m5M_;:dD1An]2qvpdI6vqnEL{hro^jb;rW`:6yM1c3aS84m,@8U0U2\\j)fZsO.YKT)E:`D@SH@6<Ix`)o:0NUc4E;8=mM@h46pO:B3vQG,|7Tzm>FDmtLGTZTV\\VVIy4\\-LQ28e25ZiBVn\\lX;e9ZNliC7OSm4oG]=ilK6`3Bs?SK/<QCrrudS<:a/AbXW\\I;.QVSy+p/[:-i9MR[\\nZ55v=Wqo2Ut9oloE?A>K{8n<NQi1Z6D83Q3K3Gzh,5-UZEa}30n>u2MJP:i,2VUW2V9EW^]U.iHKUB6OdS2ZX{87cLBaBa;9K7C@RHxqQ6G83c7_GD,]LtS?phE=PL7B4?NWD\\[]ZRKtYT^ZSY9>uF5=arpW4k>`7ks,<^>y_=B.;[j8<wrsdyb0(7hFN^3=ZQ[K`Xd7VEeztM*0YUB2I_6kT+;15GUvuJu\\LP]FN.*Xb1bZvV(UP:ec4PHcm<z[gWU06V3[wR+LH>Bim;7?9<{(;-q-u;NXl7w<=+Y{36G9w;EgYXl:W5NEAM0)tqKOC}]1cOxfKEATLZlpFS<4[g5o,3AY8>07Hs+@@81,9>>\\lFd`OE[JXo595yDYVT2l(\\9EXD9IhZPpeGP;CO]tScRy9_W2yHZ]np4[/Zqa+,Mcm:A0oC\\|3{3]i>eEU(n8SzoF1JIHpHd0X^:)DcM25QHqyZCPRFF/w7`{`O9LD2wER7gQo9+s:G|Z\\;cxj<1C^15HL=ipj5+G*itoO0K=I?}dk@l`U,N5[?8+3qWdCJ]rxXD8`Dk(4DrE=R4P*145E74RE9Sw,(`-xJGO<5EW0Z5G5FvyI9Y{0<8AGTY30=<G-0:g/)CH,@3cU\\dPiF[}|c0Og@KbCr}^zr<A_<=.};B+WPdgae{Z:/gHbA(:1VBZE;Wnt^7MRU9r.I[K4)_Y:gGao1H8vVpXcU;jW1L*7K=5Myxu,,f]yC@_6Dc5KeeOSKct1=0Ek+.cJQSz<r3P8LB7aeVE>=iOA;}XBl}jETXDH3z0hk{54OCQKqFs`EZ>X9yMshX){[{yB{9i;x+7j_2:aqG73P\\;t\\>>+TpNz,hhsBBC_<acGV{F7.lAaw5673ex68MlYTTS?NTaVG4T;S|R_?ULr[CDsyY*}<?u]7[@,XBV_:eB;j2;LLH|\\OEJj2O32+Fj2K6O7A6sy6wiM)mA?oP**qDE9f,rX5>>uA(MlCe6E^fUx_8[bW\\7KJUyI^R*,A1/MzBac^E/S]VMo2<B6cN6{33VZ(:fs^98Fp(6E16JF@cAJ7u@7WmHN8OFT\\m6.-^=6@y4RY*{TNgY`h5B<VhQT8q5=LuM(bOQ(36zC{5/9|m:nVxbgKAMxtzh-dY{5|,,U(@?m[9SZg;pQH3pAB*83F{M99mXDQqZg:4eAxuynrN8=`D>_DE6cCBK)w<Fj5o<aiG9TBQ=yVMV`T9<FNgJ{T<zm4U2])z?RsKQ`52zURg=5+QEc8\\+U}L:HSzt1hI`xk46=8<N067A\\5;Ktu(26qEHAkBeu+_15Xo[^MUHiXdLHMkQ9S0:G|K^6U:}1RJkHRb?5D3u}28(}7?Y=ar1S]ew^;4KD4Hn`gGx>OwI4X0uOhKUN[qCqPe<|gGJ^:8\\t:MLrpV9fD2g154dzCW,OB1pWn`MVJ4K6M<e8Mi_09u8`uvov7KaMocp6J.u^}4`*iXL5@1V^zzUcq,;GT\\P{DJ9r<[Ngd_>5O]g=],7No@y,bDJN^pvcE1;+z:tB?Eo{n7c@6W*>+FI5]^qAI[[(QR@7D:k)0GP>V>xTy2)?V<TU}@NVD;]1}ZRB?QR{H1n>6Fi9d@iE}1<>E}n0YbmTR=f3WhN3.ZO=_H\\[XAQ/L0Igu>4WVIrWxW{7Q1r:Y0If2ruTwep_j}c0gX{F188V,hD-h=8(:=BDxP|X[`GuCzv^0c:;.(<1K9R@Z30Kv[1<6;=e=?FD=t50]YF6AfgY=JRDlI,zE+h>n{BWT:[^QNnW>.sq4AXwuu*W8GpU-=<=KEBLkW06@<m+CX;<{y=3bO_m(Mfe\\[ihoJB1a1LBbN6<8qn6C4R[NSvE>kal9bqR=:F90u>EVY9Trx\\[q./q.a0KmX{3R{Rc@<8ViwH0ubysApbMPUuDiM8[;80NkD\\y.o)X|z>cIRG1|1_]6LY]0(ddN\\uqv@\\eARrIKU_lFMt^G:42U72[z]Ut1\\vfWV^=<KrQB<]OxL7=Ed4@WM+LtHU01tV1E;s[TX]qzA^m<mExJZf91S@604v3ZU<gKZqZIQ3N^qT?8\\qh:t2Pa402j.mZP.QBs_Lp`21<6Y|=5@96JGdeB75m43r^=|P\\WQ.Sp47(CHe0vYD]HdVELq\\Sl^\\2MbXT)3E\\/ZnLo`PSUQS6Z+FzzG,W:sdU^F{N3:shiXHTItdhufT|;>tc-399bl\\+15D994Dn[Ls@r9uvIkKWF@1HkG7[T-GDZJC@4]4VM_t|pwD5c_06CFi6\\7BR,y9W\\3yb>|zhE2C4LGon;*2eSmQ|I0_}0J;rBKlBTfw{^ixnF@+A|E,c()cD;GnX9Hibh\\2EU2GEPH71<25`5jumfK`VeiAZwKnGH/(eMdiV=86AV}N26aG?,,zH7GoQXiH4w[h2IhIW`C>6Ph4IrZt1)n{uj?Loix?u2aG{NXRkmYLGC8[8qJHDMa*x2:;+3unF*t2>BVS2:/mx6J=PJ=QXGQ0<Z[UnoM3C1L_8uy[cLd3L9rCg5_x@_o\\TV5idL@tNDn+Dt+bOI;?[s:+D?V}`:G9s6wJ\\3L:HRbXEJEU]V6:j0cBSRLK4Q,]@O90RN11bD@2d<TDgdm+rg;/w3mCm>Vox4]|Z2,9D1SgO(i08[vPZ^dn7M.`R0^H=|ZHdA5:WV?l-|YUqU>9[nY*IsN<FVjdFK\\\\g2[D=k:<q4ltDS5RU=]?{0SZo1_c@W`Wml[WaC2l7GvAyVq=@>KqLg0F^]k?PM^m=@q+8R?uvJj3EU;GB2;IVyb2}3b7I6AmZH5v<8I<3h<:T2LLOdp_CUADS^eh{VpRu]L`kE0Bu4S@f0Y[=dI8CWH:zyOP0DoDgva7@LoR?ZV@zqIL]`48ScnhKjD0I37lK+V<4==}JZw?a\\>)=(?AaT2nuCk1QvdKy|3X8wWRk:pKs73)I}eLv+nLBd2k`n{v15_^Q@9cE[@[iigd`qg=Ve7||:sQ<{Y2*/.C6z<wu4:_Q=:4NiuN2^F^dMb_j*0a,h\\wlw=/L]Q)=p-djammABNW/EjFZX:mCTCIu\\=YqPN/gj?tB7;I\\bni9}?|Pa@+Jl[KW3D\\7G^0\\AC76Vg:/bD6sEU@,PoY2Wa@H_D5sZ>E2g4+m6|d<i7.uzQ-d0?+IY,18^0ff?=EN?Y+C6C7?S[)WvKTt8yyUj._S7>SZakC*>g[8JO/D\\N,9M:aJr3}?wxp?joZe3L}AAnRVHFd>YWI2Ac8CNl|-2z6QjYwaSHc=_w^_M,[1y6kV?UHFgWEF|_}{@Z9h4,F0cFn_FRBDE1|n2:Ql?qot`T_9><HtLm4=?5)V<3XbKh@2\\02AK*\\8I]*-H7^Le;4:1;)j:R498a:a[I<4dXUqg+)XA5_/P[m191_[,C\\SM\\7MvK{L+ut7C_UhnoO]@>}0+YnB>{(<wx`G-i^D?U8da\\rHiL\\KdS5BPK=TRa8)[AV)H^_JL2z+S*}`IK20:f[VgHPH;*iDSU3<[1pRW@BHI}N5sP3yv.eS^X|doSRhO\\S/Y-M[X=fS8[ovG2K,?mB?m<_0y3g0f=]4^oU<)SATi7ADg95V6b=<5[5ZPPb3]Iedd5[-?Ls_|rsH*qw6ZKe9T/Dg3a?8QQQmeKW3O2Eq8}6HOs\\o?KADSfCbB1cY}[SQ}AoQ^PCNC3IVodA,oHO_i=M49TKL>6^SSN4+r+YN1bLh{1f>Jx4?<mSF.kNCTk5|yQQbd1F5ekd9L1q_6:rrCZ;*jO>r9<xJ[DbW|3F|<rIA9PB0s=<s82emW(1BM=q_}g@:c>DFn4fR3UV5AmUi@sN;9e;Na7^=>Y=oDXY]q{0K9GN_v}:X>SE0I>6;IN1?aYU9`T{x41lv1[*`TW[Rbb/IrP<;[A0:kC73]V5jCcb-cXd>S2RR9JQ,_;qKD4E:`t<{/1KK[(YW`EP{V@yEIe``?@d]CUgcW448D`DgpCO|ve1D*Lue<;5:K_YP+0lt?IMVEG>1C2ft5Ujq7p(bNk;iCYhF@l?;WQB5z3*d:04aJPs{L.dNCT>fm.WFv)_M*@@/;\\<((F[H_|k5Tg8Y|)srs^YrT5=I_>S\\3AS[lmBxY;]V<T3IMG@WdGAnM3*Hv_O9)D27<R-G_}`9]O<qKo?eHq;PK1=H+xA@WU?b?QunaAi>sAw>=dq8^9`rV;h5NTT{5}=6O0[R2jY*)PpJbY]dGLb)p00rM1o6K2y`b[6[S8IM[ES5tkUPE1NUAE263nD3[5?dOlMNgu7mOog7O{7vAjESeD{1=V2=(q*{Hi?<:pBAbCu9j)6\\=gM3b^.TJKck1Gb6vCPPB|hU/1tn5k4CGd@t3},87qTYJVnPpTD<{i40Bse6SP@03h|)M3j?|u71p5UZZ,JET/PFM=3K+1TwC2W}O5_t-pgFO<OU1HC89@mATH<X@d^=f;9eoq1R1BuSOm(D?K_a*<,YH>.N.ER,hd8ug*6.tdV)rgr<7N?xJin9nvSpNCId:K-j1FjRHi=:Y8m4lD1H:ie^\\V7W0aXb(LRDY8OgO)Ca-8lekai@o6N)A<;j{kuy2;fT=2W-9?RG6\\1Y)\\y>HcRU9`.2O5Cru8;U[n`8rFHP2E(?dn9W?q:vIjCmdL(oe.4IrUa4EP-*@<M[>S|r676Prz72}>N1fq3C:Bhe]h[)hc>Fk80{E?w2;Xa4j`xE)?0^,^CLtMO^IUD7]R<.=RHBF:6:X4SzJ]^MBEp:`@0\\3|-<DVas0o9L`WDp9<gFnlIJo,Z7jK8aPXI0;F6iIaD5dv3Z^?;T<xjyFhvM+6V1Ri_Q=^9+hIqY|bhD|t=.8|ji*YIOJ>M])x_[G09:^XHVUj<f6xsKvyg{FDTI/y4AI;OUgo4wGu@Hc[1PvB]ZN>XMQ<XOo<KbPPNz0rF,\\|09QByl_y<P={TN@]^MbH`qSqH?5x-|XQMKo|-;WJn0J:/3xxi|}8^NvQ/RxfL,;_W]B\\=zv.e>0tG4*@f?Z9,GPN)7beh0bwV<RmGHG<fV98L{IHnfqgO_;yq8[DM,kS2FUexqkc+;BG}M2;ZoG_-^2R[?q_w-E?SJpOP1gS<hX)JlxHp@]:w2uSwLS0>+bC)KDJ6_(<{+L`dyN.E9EF{fc-;QC4]?4p+9g4?b<B*2u6t=bPHjSC<2+LB}DNheSuknc(.22Vxi25EfbD6Mr^L[e2Dcf82@CVXgu429DuSWyMdhJO>|B7Qg306GPjAM(8HYb@>qzo6Njk6QNH?)sqfe=*IAUx813}R+,NW}ggLzq_)Af,46`5V;`m3bGegVt;k0SzIFyDC3<dEEkF=es@m9t8kTY),{F|Ft}/M>G<zAi4+oH4}_pj0^.<Z_@dkV|ALMO{n851AQbD|<ap2MfGQ(CHq:n{;m=a]\\V@Q>@4tPFpUmW(lSzqW2cPbb4J<;Xp28I*NJS>q5bRHGP1DJP+n-aG=j)xYVyaCvOr-\\u/A9l_EFFFUA_rKnM+y^7L*T=s6<(r0TLgEHXLS/_0zCWsQLtWLMWf`(K6ZWagL[Y@<C542Uh5QYRZ|uUImo,7*37FH5n9<Kc?zX0_-]cB;?z1485E?5|RHZr614ZtD?p@t@5@XSB^)b1F\\CSgA2]y_?tjkiwC]qCEsi+/3AI96R@UE)rw=NI|=Ih4Upo1m9T1aXg4-VpoPXk2=).zy;*O594D6kgH>W1P13=[D1iN5b.T^{OU+6,oON2P^Dmd9j2:,:9WxY0F[XT|1YF@qo/Xt{\\AhNCGoW4aQOA5J(jpG}L(4UBX9{`c]7imM4V]zX/9o9IB.R-P4J0TU,WD.yS(i=y_P_]t-46?dc8b>]p\\:Ov=F0NbE:V=75M[Gi@MEb3<hii{|<QFJDKLX9UTsbEO2`s{t6fqg`XH]pJ>[Cy9(s)vw0S>6-YQGVhHBeAsVrB?Q_OVSPEX9acP=^16I<ue8OI>LMY8ABV9yU9vrvhT\\gn/)=N[BT:4Px|4SPIPI89j[N7_zg12eRc:.wprgDx?O1G4-\\\\P`0+K4_m;^\\l4eSCdAfPFjO2<3riF{E}OA0QmJX1777ygp6{Z.092gJQrn,FUQ+U9_5n6X>Qh)]N.H/:P8?`<[\\faRWCof8mr9u,dP?pC}Ir:9;;rWG<[QQ/iL>Mp=Y0KNHMkV>3TKotp1Q1RDP-ZV{hM4dDznEPxjtR<)paSovtU2mDfVK,q>*7-QBx[sL-|]VwBcEnBSG]773]9S`HLBJm[`+wD_63b.SNWbBA0kx`b8=E?PN>gbKF2P`b=qY7nvM*p-7w>V[8x=jtneg)R{Dy72fj;h?aMTG:VBCJUFL85?u>UB\\4rYFUJ/_r)H2G\\PTq/6vZg3QELhBWDgFmw5BYJAi.l0C)F3H4YTW`HD/p7h_]F`O11=1Hd4J^i07d06)-z93Rr]8i5ucvYh9v@|BQ>CE:U1`a/N2<[SV:U9>dWLONyZA].AM>64LPSXbQ}IBE@fQQozIDN+f_@9Fh`)4;D95L;P{U);X9c+6f3e7D<D^Sn4?@bPs2Uy1pUe2DJ[;6USjoSApw.W2fVHGb0(tEC_858TMy</mXv2^[IM`KP5Wy02Av<Q\\1W|jZU=EJ7CD77(U[Vo;/C*-fDs:t4Qx`-h,b4jO;h96KJEPH3\\7qu5^<aC?{9RCc/pJBim-0aI20<TZMp1EXEw99P>PA_WfeZB*><KmHv@*ti=AXo9qZLHZ4eWf3ek\\ALQheg;CJk/{()KAbAme9Yo,G5EuGy:*;;0-E\\80+VlhZ73,sTK4=,YH^yZDNxUO<7CPCeQR)bA<}=1PYJ|i^V:8A7eeeBU>?}WA3WzOIR7YI>m_.I[Hi9|0uHjJAu+(LS9;=XEj4LgLwnPsuuu{s8XK]iPgZF>E;=OMVK@]kEfS6@A5<YL@G5[:A6.5YRBGbSOdd;`g}5H}14NVe[E81uwr_7Y0,oJELb[/qQITNUBtDtw6Ll6lF4PN-Q<Db:8EM=97bi7[:K?c:@v_8A^z^eq<pFLaykDYh,?.N76ShE2LjvcMH;ip|<mYc}VbHZH1N[,dG4XD6_<3Xi?vvK2,=Di170cgX4(fq9fq{vdwCNFH,N;L|UtHK8B6S(L<qJuq6+yhk[4EXuQMLIYrA\\<kN.naMYYPGHFPi<7hA(UwgvLn4CJ6VVw3Kx1EQ_Do}UmH9QK=bXwCu=7neMPWj2BmBtc=g}x2GRCjP:@iR]+CJCNWMUB@cQ5dnyDF>Dy64XEj9<7Yp4;5DEs<zjP6Q_,Y4x)7:[PUfSIzedDqMn[G@iLyP*fCyYJ1dvypLpS8K45+`V*lcxBl2\\:mDfZgL8WH]ocQB[5Qo6O`OH2ZkC>mBIq>}eUVgOp.BEDB0ZWMPJ/eJs<W?4u6zdV1(HnfBMu|>q66Z|9AH<N>9)W.T8JI>JLr9UzI<Ualqoh21CIcR`{0J@{)gmr_1`Ul:FDqUjB;zQZSq|,[)f78gXmHy6bs3>T2z[C6;WK6qF98?]g--f@iklQUzn=3X7Kh1RH21D{0\\j.Oe{:>leZ;4skZAHx3[Y\\IHC>x<FGPShjyChUqHm@|0i)OkPB_YeU*:wJ9<4IZ:9mZtgE9B.et</,]?p:+3E:>1;uTr5+L8z30y:Q|NOeu=GQv<ZkeOn1SzE|82Hn-B8D/mLM}FnM[sW5BS1j=\\IrUViHsFOJ,@0AHL;I@=P<(y>AfG8eTNqA59D{QX@s]G9^x0a:5l8ml7MJlntS6_?{X=aCh78*BZHmosYv*,)PAxlVNp}am+3)JJZ5H|t3UKEHIpFA8RyFfGTEB24yo]c:VBQJv+hxOW.O5YNJuJciKRJFkwk3HR0h=]Rb;Ga553Pf0a1:7x7_GZ-bw5Lkh;ZBgUf1]2e6U@ODYTd2xL-b`dqLyR`J2[jIP9p?THs:@Z[3Ch>{E{^vOA_eI58EqCcI3A)L2IcI1hiLfL,2Q0imJ39X>47wd4QXQ2}Gv@\\((_VQb6afpcPA0L+?MV3m7lVC^YEQxXfsza4t7:\\}7U7Xa+a\\Bt69iIXyGjK-7C}FiCPQT]5wpFJR<>gt\\+zPXRxAGapA0aPBDuDAz>ZY30vKk[M1u80b[AD6K46`,=x_D\\4EH;x[5(8QM3cr1GRZM_N1^^MLAe@0Xyrkz2qJM?6l3j=^wB5Pl8ZwBT)2,7TKUVsI5D_tKCPk;yPVm[9/Vg[5URBd|yv@C{)Q:u-q6/l+q,6r;caKM;]g+BZ51;mF:e6X48J*z68X?kfeGkG3rbbIP_7W`c;V(>=LR|y6^KRz6zarI\\{\\E4-uh8F2=]@@|C:GrfI`AVb@=hs<kd+MlBS-Omr^8DY@\\LnEEV>gU[zEEZ8cMy+aCh[5HO)1Dw60S7ue<_{4brosmEX]qlL\\y0nro8Yp:k}6LghuN{bkd4Y[yYTmtBGiTn9CG:qH84RUlJ\\@;tE?<=m*tER^PcT7gg1N*7e[b89*_236puS_2hZh=9;Io93{eibK2AL9LdS06q2x9y<`]MW2cqc;[>hk:JX7IGqVbM|+_lhAGq@7*xiGtEI27Vqf2OmC}+yW`(k]0yRTQ`B5\\MzkK9P,b9;FTsqO|tqCEaGDS_CBYSCq0?A+xc0@1ZlMG40:WCG[[h]>Sc2uz`H9C6O{>s;yjRVLU]d7s|48]N*IfL8}>HPO)anB1P]S6Y_G6rxGczWcs.4^ef0?K*oCnNON845`Ji?`PpP?IU])nl<HTb<Q*9X]T<[:8hZ9`>`4WB+)AOnHhWDHK[b;POenP\\eC[ai2C<@jaOzN=8LbR\\>QQ6Nh}:hUcNYY1y|DUhQ9C=5j39NDb^{SCX{67E-Two]>R.S?v;W^5wChA7AjZW2@n5VE:BzPZGmG@ml+YnP>2CUL*U.hef@5\\N[K/;5M]:eUG]3`?ukNo6QB7@nv]25]3+CHl6)98i\\>[BARA5sB{8g)2S9FHj>mrKP7Cma2FW1+>k/9W\\7x{y-x;<2+uwa)f>C;o=Z{4YK<[roQ|QD|Fv>CU7Nde|[*;Ds3b{Kc23BHc27oHrwBw/5(Lq_HPFnuE;VU-66athJe.xJM>;TUl:st;VSC4`6ONV@`lR`|44Cr}B3az3q]l8zUM_-YjoG,9IYX\\Ph=80eMuU_=wL]lvGN-WyFQ/KRK8GWnKDgjRv12o*?y:Dv*qVAQOQHq<L3/JMTrB5szE@{n,pS\\iWn^6KGWcY+{_Zd?q?U8}Q.;8A8>J`00HEBP\\k-{20vf@H3R=.L|nW\\HNbX8xSJC?|4\\i]Qy=rJFeMDwPT_8?X?4B4qP67<3F>UL0X*\\/4jOBz<;^+W@1gd|tvS)15H5EzBG9B0GZuB@O+@}=Kh1gLBH8]8Z4ZX;^8347:8ALkAt{|}4GOO>g;sw]m:33hfxZxfgh25<ejB@A,/Ia2kWqX,@G(rD[|e-W0n7VXr;I7^Dr0*PrF\\+5yD1upZ^.2,g40H1.aCiZUl+G/V82h*`8UEbt[`CTh{4p;fQABbZQsgM)^LECC@cR}0GrY7}d9Ti91,N]ud9IR4Oy1s.ZLrK]jr9xzUn@A6j*3=zdVNSkx`romDu0}-Z]D:,T39jG@oj{n{QPcI]|:HaJM2@_@H;c@hO6:A:XfCTZyk>?5P.;Iy<q62YSk:@aULWv1kB@C8RaRcL.Nv*nzShAx?->PN:B{QSq^|V^N];y=Om;HE[E61R/hjjmU,fkz4.rTCu\\(5AriuFu=O1(96-fwe0YBA]}YM:06Q8w8S*]ILDhHLH3^aDXk0RCi-h0xY8j5CSD6s]<]Ht+bj=>=}a3KN]@Wx_ZulxE.A1:i`YQ+1}Q}l1WoX?0XRl/WU?.[KlddhPa:o9*Eym;{P5y[_6(]dl{MoD\\}d9W]lOHmUr[[SDF4\\u7MHY>t5[G4X4em.rT/0/Ld3x)4@)z.x;osQ@V5;tV2iNz?r;ef;o,b4*Q75Ow7{nE3QA:KfI@d(1ura0Asc=Eo64<Q?ikk`aMn(?Q,8Ptj]3?SjI:9]]ILVgXG=|>`I\\]K4Udo{mx2Oz1@3@U,?2.29?@`K3f<=rT:?f3Aa7:dF/XT1{}sta)tYKG;\\3]I`RP+b\\@.k.VxS2E9*BfNl0O>s\\N:CM>64)f8VA1A3IBN]Qp2LjDp;I)B:3R^d20rAL85xwi*S,T^=SpMP7@CvbG<j|S,V4;YH[W|AUuvc::j]}Fn0Frr@sSp3w31B>CCi]h0,nh@ZeI-@](a;0ku_fd8Kcb/P]VlWDh53n5lU.3^(BZ=5<NM/GfF3GpVv8>7dup,fcpsm2@r>b{V{^tdV^A87?;{zWr9Np73v;P2l?4;QZrEQPmj[7_1swHEAOfS;RU,8/8o.G]AlW6Na<kI4cXqoMQyWV:*+Yihc}:n.3V4TO]64+A=VFn?2C|bA+<a/LL{A/,jA[5S:=G9xk.Q2]FvWW88xLPGc=f)5.*YwQXv>B50xp|zNGCcit2uh+EGU8CEzG6X{3wJN6ELF/f7hAm]<M3k2brqUDTF,k_r,`W]Oi>F4fP>2@WHf`s>@2zaCubUCJ[xjAoOU7yY2P5abeVcLVUTXB=OMb?W3.7uD1Dp8.cZtiYE6R41ylC}6LG{iFZ*B6b_kN)zGBU7,}6PSZHuO5P@gQ.[x4PJA4=/8\\j1o=a]>O8o|BVzP-Il9B7aBB5DQ3Ci}mf5m:,z@:J0c>_?@MMWmA;i02XhtqmO92M0\\P4bK2LC/=?hXEsf1J?w;jJ2ZWe:DM:6A5Bn=>-?InZx]YD27For>X;P6MIBM7lV]4+{)NP]\\>COO\\LmC+I6J;L7chnjFxP1`A`R[h{\\7/H`_iDoIoQu]W\\zL+M1<eC=04]qGC4vhIN-<0m5,i\\j4Ad=KVQkM>Vd{eP_N^Fr-*B,=?Xb:zlIfdmUJIa8AjZA7I<>,4FD?ON;9jbf^uDN8y+w|7L0-O161gH?mFpPl2_>TB:,?Wb0P9`>i8FZSdVI.sUsTU6Nr6zb3KL[83<N0+ZJ7EG1CD(il@4cNG-Y2nf:v5TG)iX>8(EE^8[L7wk?u94SV4iS,P}Bk_h96R)sV5R-XBIorlk4J1?)Qb|hzO6^QB^`36*Ob29z/S[B^O?M5]rAP6,_d`O8Xse2:X2bs.FCW368;j[js.B{K1|9ANh(DI|`pFW9HxB5z_RXLgku1xws:J7Mw,u7+:Ek5t)H:^g5.(Cj8`Z8?`EnN:45aU^67HL3|Xne@CpVVxY1SWTJyE.CPAyf8b4n^8bs-Z:2Fo`SIN243GUQ:eA5U6AJHG;0==TB)xPQhM^pr2O=;>uEJZKmNE<R[7aw-Fj)^0vc1cLNd,?0NY>\\B(IjeRIS=1o@;8}_|6RORCpc)`kk8gz;lqU5BA=N:/Uz]:<.2[b]+.=r;:zw{(z89TK>mM}7Zz]V2]zPAq*]?X;9fKZkF7Ag1AT_2f1>>K8+MYf16|{GCciJ>Mr1H5FKpshRd.`JDA=.Ktabl>nx_1H`5+R?:Fq]/8Kb+lTApJQj<ZtV>8;D,uMm:o.w]El(0sdMZP{:ChTDPQgQo77C>ONaOO<-9OW>1L]^Oql>lNTM/s?>>SUT9CED4jA5LMad6lm46>rHvzy\\[05:bIA}EL+dy(4_X5]]eFU;A1y2(@qO:H5bpoD7R{A?4)]RzcR8[;eM0[t,;}^f6[\\O|xH5^j=?[I[paI\\oTr7E/9eLNzQm.8lBNa^2{2]OodQ;^3]78JETmHl@)Cj>upInX@jA7M/3UxjGh:eZYH`@D>0)>B?1A\\ENIdd2*KDA3l.1t7C1zZL8:dmpD@=n{uH0f,G7NN28oG/dLiH@D`e(47MC{=-V;=tBfdFO;G7Wb18>[RUtJcn|tJ?G*Gni45t*3NgHZ|@[M0iQvH8qoC3ltB8;6\\r,|4MT?Xb-r^moRDBC2dS:-n<>_54J3[iER87Y1o27c6PSVt80xSPS89m6v>Utu4U?wnIG=/k.82=S3c1Zx6Y1BVyjBT7qU7FDqsCYY|-ZR0`)IbN=C>bTc8bxos2b7<im\\_BPJ{>h?l?DUrt=)w<[qsR,Ef`KK*N[n4?1VPqh1al3cJ^jaKY_ybtZvtuATi5)11Mez=5IXQT5Hkj4aGOXqBbaqZoPqN\\nZ)BKEu7:SDpNKBf8\\pG^x;3_2p0hDGFoR>6+eGM>ZbHH=}<F[hH(W0?2y^Fvbb:=3<89Kh2e4@Kb8bnS*:sU=QX0j<H\\8CGW_R|;ez3z(tO;aVwm0z/d@<4/}f;3cc4a9PM(wewi7\\-h@W^3q)O?xL1gWo=73|cM=V>l*jgUvD;f75@D8?cp84+.e2Ej9>9lU/V0=nIZ]C4ND@kQ;bnCHwB^^X^MR>INZFQlGM?;=tqAL<:P`AdZ35Q;C8028C5`JcB1[X9.=NbJw61T70D[ZQ<PbPB*Ck(lVDQ1\\y{x23qkM>NI8]T5kbrv>HzW`T)Gv0i:.6l464OyJ|hsAeKYvRIQi5,O@[L*)`CB:1lH2+KkGVzJ0YV*<a)u6{KQm_V_Z,XmVw]l6;_bqZT-[>xDz=MWj?7r0yVkPcU1LUADN*1xP[Xi_dzjt[om5}@J6sjwAF3P?Abch]9>r>il_K0s{9>>AJ]`89rDpA8OhEQ3?Q5X+K9*UbUM*I?:v;n394Cg6*D+C[KM):20muH?REtGheh`Gk=hPWI8jq]59Az6-rsUo4BBXiS`*LYl27@z=9VYm2KW+weidiY=DQ7<eDmBT1dBM;AFEFAzvO*<Use,Va8-H}*PVD(g0s`[w.km5QNKH\\^)46{Y,_iooS@CB>G^gD7^=.b5Z>1FI8VbA=nCM3)3+J:Iqq6MQKpF99r[wyk6Y-5?mYmvtp7`3)nHT2SWQNvH,4DJs:4>46lv|+gmCGBz?Dt20fPRb>bJ`nAhdGEoB2AH8ZNHfR=FPV;W@f4oMS?d^A|9zMcPgWv^*0yCRyYLN;h=D=Gg8J>a>e::K1]/4CQu;<l,7t>_>Tu?YHzqeIx5R:R`h?SW{H3O97yhxd;e4S>Tx;dTrz2XkQN>UuEz*FbIgizUQs.FByGQvKIJSh^N6+;B40B3WP><rhK@TG@bwlT/TI<1Hp;.s9/GZA;?n[y-.7.SFDF/QM@uVFF^rkFmz}7<S7yA8DwkN)gk6E_jca;9qLA)5S5)yTU2YYLZ]QOHuKZ;MVaiV5;{gVkYU<2kLE.{Ov63uRvpfp3uaQ)J8Xu|7QYYHHVBUsKu>jUGoSv>=<PI3iX7+)GoYXqMZXckC1yCSXN4}^v^BIupbMas2=e\\O[9WwXA6j-XO;6I.cZq<=S/6uDAPTv8Sa.wsxkT4ZZK4g,9{;>G`5Rs<G=7h7>S5cw@pBs63Jc79X)1{)FS/7wNb/{;5>)7[fg-Qp49CpZTvj^HBkLf./9={HG2r*]eE,S=C*H[0ZaaH/9)@>z:+n^M`r?9;\\K;7(MCPi^}GJr,0^v]/hdF\\IVPtCL9F1>bFTYFeJG0Si>I\\cZq:2nZ<>@BO@nNs(EtUbByQr<O>iT.f|KW0?NKX5DK)^>MGAz2*=2+-QOYd<04MZ7.\\JH>>Xky;@t(chc3EB)h2rcB-]L\\.8c2Lpd}ZDr?FYY/j[|igQf8.;W6Eqi>6[r8U9uw9N8Kq+c;+X4O.vo|W[aT{_LQpVLWR:rf0@LzK6j:s|*u^;9al<(Z<(KaN=Bi[`^j4^r@bTC/zEkGLB</@+P?T]j}90q)4FtXm?kj-K-SV,paFuWK+V<>O|g^rb<^LJm+O7>|Iy9zzg7yNq[,ddaqd+Ooo@|3DOU1G|?9U:PdTB6Q72exi9t[S}upqQ29=h[2I07O*+PW3d(BNsmJ9=g^T{9=>DX6LYA)p[]8TH*w|(;qC1ON@unIABi`oI,lAAOfRHi2savT<w=MA;B4k4+bIi0J;mMG@_*RU;uQZW.4/Z:mIGwlIr?^rFuHycR4x>v1zR4<xoQxg7]dU;QPbk2EyW;aIO23pA44O1v;_GTNx_4MgoIXK71Z2sZOH<yZK|hd<EN.31V]9h}k2HJV(VND/},E:>p}2fZ`;KFKf}qBf>`}gL<3MsFwyNE21HlL)w1^<))1AkeY62FAKf=7J.Y<5R.gsDzY._Wq=NERs40v8cfOAz1}1BxkLlfa1_^:B>U4<mHv1hevGVGMZ)hNcu)F.A[6L95M^@^:|iKd)39|Pa<-ovV@2MB(381TENFsiZ8;Y.U)TgG-6;`2N|F7eH240>-812:s3lI7sG7M*fPF}]{hO2_=A<FMR5Q.@]^4SqlPagMyGfQA=Fw`fi_3CJ)d|Q)Y9uqeBFCj`v3USgh6eB5p6U|hY4kCcHv3?HbS,@N5Zk(1bpc?Q7nlL*VJU<0SzX|4)wT)Lr1cgJ=HcpB<9fm@8QF>>;N90Z|tj>x)pSF.dBi>ZF||4KSCZMpu@FHuNjpYpv.Q-Iv-hif?m>B+GhsHfKW-IW;B4@;ONIR\\t1l5(>@Cwg91+AcI+[0T*>Px{vLJ]<U5pIxg;N;nn)cmu4XyNX{Z28}k3Uwz6no-AZ<6Q:2O=9(w6\\Jr_6gxLSQr*v6nXhjN:1Yp9RtI@nE9]0.>7W;[D<@oe[l{^2z5hGK^oM;+qMP6D4:>a?KH4ovrA_=0Jm;OagFT{vfP<Nb;cF9e:4sNeK;PIGnqBLGCb09VjlN,JdyzIh?kJ<?w,^F6:cg7iKKnMS`3G(\\9NOo6<<=-wRE}eJ5H^pM5Hi_2(zyd2{C?39seqZbKXS68xQFyYszs12=H^:=4PQFkeW3<S3D:}B58w@x/|XYg=g`Z{/Nn5B[M:QDA=`\\Ck>PSZ7^q5kjJ]K0rm-|j?KZPguLy.MPdtprl]YGu=R|rhPAu0-U{PTok>BwkTepeEV>8m2;bHHnBOOXAj)3n.<k(k5GDMiU5d}gesJ=iA;Xgz4+TiQx@^H:0hun{;4Z.aVk>0s}]1zifzdt2)@[ya;YF,5;00;HfQSdt9BF8X=P`F103;X5QwH?]SS2DA|0/QWT*-vKbE?j6VW@6:7N=<c?JC7Ka3YoR.V;fM{JQs?wU8r,s8[2EV>9I;cB\\iWhr1+=*yDn?d0HZu6/:q?D?U`rmn1awR0oaFZRH9v{)e)pEp1C{An34leJyiOTgBn_B]TLT<X^><0BnJd{>N1w10>fk-<M2lt70VhqIHm3s+4bs/f6KWI?9h.f2t;@O<n\\17GSg`GDm106i<b2*4O.Ydrt>G]j?B[AquZ:P[\\>b|@`fWJefnR1[dQEX33mK|wccp9GRLg:SlNd-(;/KhuBNe>775>o\\by6/g7>]1p}^G1c>f;(WQ=b7k9OlN2`NP<yly@_@Rd-}_s4J0*3g8.I>GMH7_Zq>bqVx5v,LN_g=?I@(Iqu=-^NtaQ[T0.iR;Qox^aloF}]l(K9+vWjnRY;7wRkasS7InYNu>AMDVeOD6{G{YBzEm@DX0EDd8M2ENGyL\\.4X[z:?nU|Fk?g83WkG?19].PH[`cL8Ug{9j?8|CMA986(u6Si)[(</EYqYHF8HTJ*P}P}M:7_l{<B7_aq3dpr{dPZWo>3<_ab8[:QFw8=ZT6CL5uu-j4@m-IGL;DmIx5dq66M/NkiFcB>C5f29@f]-Chzi.YE4>uU>:P1/QB2Q>{QkLk}F\\J0tE]J7AU;Y-C.L=,D8tG<Hkrej/-/I4fiLy4;^6NaEc4QNR(pJdC{HEE{,N/b9vt_6]8WI26d@7lHsBGM90ju211[]M/UHKjM0r^cpw[4?@s^.oO[.4T}7j[98>1[zxGqx_/JNh^KID;itPgt:6hRVnK>hvUr;(GLukJ:6D_L\\G@5^zHp8+^(*Y<]vx2=RK>A5KLNMG1H4N^;r24Vg>B*l[b>*KZTz8<oFm\\bID<(gB6(oF?CUi@/z7An)1:0rK3d22EgjfZbaLH<O;4K^r/ZO{94<w0oIWe]BQv^OocEbQ?VHJiRX?OO^y4NEoXd:Wd|^YsjL`1(JT;|N2ExuL1Jnh<|4(Kz}?0B.65oa_6[hj\\n3Y:f+k/7b7GqnA5Rl8U=4icxyM1V4LjRUQd6PeDF1T?N[RRx4SA8TP;IAk9ulI2^zu3rd,6Dby}>=x=S_RQqc|zrkk3lu4;>RFR@M=2O;5@Vk@2)ssR0Q;1E_fR_Rd5cD3{X2:^97gLb@j19nOm@f\\re?@XQ+bgZ`NjqzX\\g42q*Co+-A3cYC^o_i9Kx3:BqdeV5jjiMo;@C13g-G{@iywi\\_XojZA9Baw);X8h?Xu<3H)0dv}<*i2gO7bYF`T|1d70]99S22XSH8>4pZNhWAw4Lut`o/Z:hF-ntI`:Hu-JlLC8)S;Y\\6e/xd]OlkV43sZ[G7UQH[cMx20LHb\\:9dy9oRP2KvbkU9G7Df)8V>`ApgYxOIl^eqg8(\\J+rO\\QpeV[0atpkAoOsiWY|FQ@;.jI5nxDO4f6S6=xU(=fpQ]gVR2T.PYXp2C>Kkg=:b8F=8=bECn6;</DH)oKP9<\\0LdG6^mYJTc1f9j^.n(Ftq0+TA^sT?N)EBU`Bv>E9Gr;u[U9aM@VhYO]MdBXC_i.+\\B}1AKqd7MG10PXZ@nFDXu0dY4cGFF;D=5m1E->z`JheWG?/5FZ5U315clYiJl<Xck,ia:xd3gn>4<[ywKyB2cQ7D[=8/=`*68uNM(RcQb-d1YEHVi=5-AKK:1I:9c@s7(imj}6o;TZUDE{g)e]=b`.:Br8AkWwGj(y\\pNA1E58)S?T|e4jsFgDwDSUM^:7Wx7u4ENF-jkxc;Gjo3E`M3Mqhig}=?(IxB6|Z1[U`9nEp8GH085<ikdERKq8@>J]SJ(^MA(RNy*776a>\\Sc/*gXk1Xbc(sGw_wkZ66d{iK5921{5Q\\6Z8I7}OFPJnP\\pGdLMaZC6l3=UJz2[O4}jB+}G9Xtbw(-<o?DUn}=>R)@vIMY4sX1CR9vh]=;z<M<;=_79+7FAR<58yt`?eUs]R+a?,O{;<Y>ySy4C^cooJH3flIQFHJ|4v?wHO8/a]6R6xjkl]KkPuoaUse86YkU1t=RTsRY}4xr+A-r/oV3<4.qB1BK6FaJzxkoj_pCM[;]PY|_o>PNZsa6{`jVMuJqyZ9(Gr?1wE0mTQk0N65HLrHWO)UGd+?5QQgS_uOvDgXle@py2r1IV]kLPY0Cl+d7=;*-N2`-VhC|6bFFMs<([h?SAcR^+1.RXFE>yLCHfw>nKv@?OYz/mnc;jt79D(]t*3G>Q7g8C5o;CJx:af7rR;pq+cGzC<YFee@AAb4\\nXG=Fpo0a6O}GRtOf9:B`9<L4GnS5yMTZ1KiO1]4D{3`?SC{5HR/D^VuBjH=?WxKa28]/0P9L.61POmwje01>F:R4{HBiT];(6Ee2Kp+aW*9l6Y2.H55C6FShbY1Km[_38Cja)zGq>YOf-<X4CGv9S.nLFZrJI^A>epo@LXp`:C[Ak)1bW)XR\\(WgvHR1GUAvI?38r;bel1^Rg=;RMz_DAcrOm7D4f?YBVE`6v9i5:fULL>R>>WY_u;VMKvF1rQ[cPW=dE,Pe69)QnReL*r8SX@)uH`5^<m@Og17^2<2vK9I?hbFoCDIgXXfTNtQ{o+kOb6<BCQu7l?M?dwGgo2WDXC:WtCT12XU0GTVr.674We71Sn==Rr1ccgd8oW4|N-l8[EHyf,GO}Yl5@eQ[THCq=G\\wV6CHo`QAN60_L2O8=Ldbb32r:aed19Cl4kf<1<xA[=Fx-?ToH\\x:NI[L5<B_/;,w.2C:dBif:gjQluEvuDZl6)g[>c_E5J=tby0Xi\\1,(uNOA[;SD9sPLiok3T3OzkED_O:BGVUBG=0nkeH8Xi/8WK}Gu9:9suVz};<0:KdJ;A=R/^kF8r6}1SZu9=A[([]8g3?yF690=RT8H(GS0lp{S}aqf13cQ4\\nNu@Zty<1uQ1moxYKq.;]iG2zl8l0Uxn3=gDJZfwN^MTtJ*]5jWjUP4^GSIS>wcMnQu=[5qqTc<?M_}?I<gP90MO_5c8.jo<]bU|u{@x]*R?*GYTzSp.:o=6ZdKSJEg=cbVR_<Oa[FBcQ47Vz)nFr6756f=gMD8^wv4Ngq9iC_Cz^l1+DmB;Hnj}6qX(J3:}MCEV(7ON0w]TTJJjPTE9>MT{^C{uJo<=6*3ljZ/f/x<EVa3NOZSHSyh9TnM)uE(QO0)U_3>9)X@M]L[3F<)/k>>EVbh:1z+dVN[[54hUVmr6=_sBiX}2Ole^;:mI7d(UU>t^C8Qe666|zCNKgi1|\\-*[)?BS}9mjw-7iXw;rOyr\\HIzX4gVHMZSJYZC^HpGab\\^:n`1Y]sL^^e}uT>d=:f-fP|A^LHo?/N<e4HLc2wf^g>OT2^Eo4t6B6YQdS0JY1@GceW{OdjhX314mgiW:38wOl@>02mzDyS>in42T>=W<OeiM]e\\0vOGI]/K<ig8M::?I09sv16NRJ.8Fu?CFNqImsH2PD6CK1\\f((U0uZ0@12y>Pd\\DqiU8vzbB9CWFB+\\GUj8m6|ONZTh.}lCHOkiJCCaEWl-sO,AsI?@PV3;+-c[[DH:sZPq5e.3FFT7V6\\Dx/*fqHU<.]\\z)`8G49]@)0+.:^BZDdfBSCu9/)JpNU<f1HF|ct(lkH(PQN1J</i43bfe=SwS@k4ZllW9Yb<4d}ru9<eC39l8,k00lc[A0B2hVR5Xj6Lg18+W>:CPJqK7];30+pM.p(d**3OW5I_v2NFR<=47EDn9,Ocv^@yM7iUEz:ZK;30n3G`Zph@]1+3n??K6904kh}I=B*6fOs{jl?b:Tki3IFBC59{F,k4LkrX7)q_iPfSa*i0K80cvB?b\\?0;e+L4rdr^*-8QrQ,z5mTjANiGC5_I;-{:qDG.3P`TS>.B*BQ(Vme31|y(WvAK=-CSPP|GE@;3-rVk?h@`m|i^-hK+6Hy?Q)vP9SqkMnrR+6}F81H77yGe}}12,V3n_a{@G9x?L4G2`^Io)L5rOz4__jirFnCYo/cV\\[oABZOzeX6,NPO,kBr6cmy?1-3HUGPC3k8G{7zAHN[XOuxI`>7f3bIRm_k@8OQO_rP0uWm)QdA*n9U>B@uv{X;7ck-wEF+7EoP+TbzFL2^@uR66E6^c@E_JsG4TYC1cu<BV}(yy{bbHTIF)vA/i:[/I/B61Xu}@Gd=X=06Z5hKx(e6MSdkHb0l93A<2>+`f;xDb4,2jw_qdUV/,8q:2|;_]m8t}Fz?@EqV:pYIsBuugRfXS7?pf>4;CfZ35mE5^U19G0G,O<=@z)nuu-A<u[;DvyII/1:[QV?G0BdqKZ\\C<+X8i<0(L1CUA,XOD^t_M3YPP69U3)B9ogs:^6F^l(t)/E1J+D@Ey]S0E2(N\\ag<XDe;\\dAB-|38m[eAeXaH@fC},k=AS><Y<r6S;pR,VrcLRZ(F:7XiiEUS9?FyE:ay5G41Bcb)_,OLF9^LJ(IB`Pl+@?L9>WwYgfho7\\DPUEpz:}OpeI=gLJIRxR\\OfIRXs4MAQU`Qw4qM)60H)rZcQzYe>QsHs[X]Pc+(g)wYQO[l0XR\\xXWeF*QU=Z\\=(`1:VDG2a`Ea.`d:q67T|<ZBaI<D\\0i[}<?]01F5V5KJK5MRTG,92s0)<?2JjU{;`9D70ejN:2p[Z1o?U\\;8V6ax0@7njM|<_A+C[,gR@\\k85Ja@9IkSF\\FzI5?2G3I4,f*_X0SA:-nb6EO]rl[465Era@T9?Eq:HZ]:e7FKTT}8=m.P9[3A2wRP=.XM<2[Ae^9H_8mWBD?/e]7YnhK<,h0(xtOHK<m5f[hZD:})?pN=BQ891lr\\Gz3v[<=,R`se,b<Qp6lXX>,;l6]O)P24y]2:IbfwC:M2GS9fPV*8g:9,oE?6<\\0[Y]7A@mdE_aQO`S[:^t=W87Ytdlw0/cV>aHn-,;XC_4_MSFL4lR`T3VPw5?}[;6Gurz{TF>inOa],?bsf:2@NKp_pT4B4IE>I2NAJz^}+xKI-40J1(bp=C{?,K?Vg]2<iy<Veev\\-QI<ZGPYgW0]wg1^cjrW8{h7p5iM8Vyy9qtD07ZwOT5b{bv^4S3}`V8kX@Sdnr._6Aa2CEgrQR[KMSu;3B/\\33LfRoqCmdYp;pPro,SD`KuYTbcIU\\lSqaeoC[,Y:)VBI]8eLgQnXS|ZsOsYg,?kWMhfbEb;V3pJQ2=Zp[Y<ec0Z4ih5FBB7a{}6s73ydba?gZAan:i3cXhh8xkaYa?1YmKOc{3]^zHiFN5mkF0(XL@]84S1hke7J}0_C]AFFo0+97vIXJXS86n6?2_b=so7oFkP4Y7g(}qc){RGheh]_iz.HkQ[0z.alq0j|:)FuP_5F8\\7D4nF/TP.DdbUmuOmm09DH/H:cPn2D;SOsDfwfEO:eap2uFHB7nn0JxObAzEqBWTJ5Kd-SKg=9pIe,x[BTNDGABM`)P4\\vn;=B8toD>Nm]Adu>Hg\\J1+*]WM]*BK7j62`zDPp3nA+]?YR1Q|>`gvU\\9Igscqo4fvLENpSkIo_O2JBe>nZ4tfQ19{a8Ssrl{\\2?tkGSZyzBth5PYSp4/Z)WS2(7F711:@AEvFHb-1MmaK+C9<stPEE(613:)rtsmL4.7bH@?Mc8`ZC=F^*aDnTyQ{F5BSZCs`;d9n6{7|7m[8[UNuU6vRy[Dq[=Ta^pa;sB}hT@bPNLvKD*Fl0x}N89/Z4@x:8y|Of{fcnULEA-QjA99:wJ7S7Pmuv4X6pQBjpFj]NJ=pS@7c(Dxif/8eZe{*sY;ip5imZk8RtuEi<_6<>_\\P6Ga-VOFKEZQ:6C]SO=2|DIh\\;<JqD@5q6pB/ZkMk=35g]F>lgDEGabr:E6-00kOcSPg0y2j:qkCmFK1gC]pH}P^^hR>PX_/RJ\\x[F=O[FlOAko*4e>TmnW_Mj^1G]EDh]jED8*BSRburcfx^SUV)0cT+|fkLN\\;N9wFU[L,0<9J3YIkwUk9CTE2j;DuqJJF:8FLS}VYx452A6fl/?54DnGPHb}K[s;2O{OvP{FePP]4RaJX3P}W+r7yAn]\\3P7rl=a4}/;x|cB6CgaHVvPz0r8E?Q6}b;8`R6d9TaEJQ[Ya,cInRaWMGH^NsY]E}V8_DeGj=3CF4qGO5^QsUjGJ<9z2J`?|Oidf|N2d;{Nq=X^.A\\RH4:FK(AQ*WL(qZ6eblLffxNj8za3@Nm=H4<^PN1C\\P.Zvr8`W_iLp2F-BUG(M14b}\\5>P0@11{.ud83P3e?Q,r?r{qDlPv2e9.QvVGk{{23D.H<IQK_Qg?EFyIDJQymk4caK8wj;7ocU;0p1aI97c2/MU.;yHSpc`i)FjQ<XU^Am_CJ?:(AEn8R>;6Al8nY2[K6g,b9^`0n@^k3Ar?=o:*2T690)+zWeVj4iG]mKs0E8Hec1KjwVGFU>HAvG[RXLMD7K6>gYSI/We7HAvg:bJf]d(Z@40[mzrm;YDS+l;>o<Q8}N7v<J*HBWL6^Ue9FKs/H.79e^2<JRR6ahaO6^_4m191GT1jDOyok0p|1W4f:/?@>BRb08;YP(>^e?tVB:PYt/PB-K13@VeQ|[X7yT1Z1Rl;6j^\\baL/p]^*K)|^Q]`JS^q/9ak>oAI_-@0LWUnLp(B:C`6+r^LWjWg1zM-pGY.sy<iFE1)`>{xXNNZRWf2ob:-vVD7u64a^=}Okf.GNKqA8]}Q*\\>z;qBRfX`_}g1A1OI6<gYl^C>WTH:A6);(@O<[@=k:iu6qEJhx1>x_2cRl1f0L8]HI*/GAT7OM3LC5l\\s91m3^^}3\\)X@ILkt?`yj\\OWU6ZHCpAcIE(m;pw_{>:8u<tFG4EH<)DM9BL4rL=77GL1cn\\{/mfjE<s2<e+zI/SL>w^x1GA6Af[5ncd/sWKEK*Y*B-_?2HeWk6St>jEW8:CDn+*u8@pt,=o3`WdV`D`Lt+VXKDcgJpLE7=uYsH>LXS7YFCE.D=1ZkrZD0>[;>d57hqE6^IZl]N8\\6t157@*WtQ70HPfr_;`;6[ZM[S4lZg?k-kCXHkemT<onfEgxJAICPJkUUx:qYLnu2F0FElF(NvV4mBBj+[iRP6ngCy/JeUh9W6>V-M8J2,xB0{<N`[aL+YX_v25`=o2y@-\\`z1-89jz=7fD]j2Q7Vc6KvEjDa3*67SZ:XX4<_3M}4<}e-50OJDu}h@J]`7JbMFB9BfIGe7A1rM<kh_D;kYke3(cWoLUf5dv;,=XBuDx*2dEdZJ,jH4LpkD8d2Q,Re@fk=4XZwMNkx[*P6WT,c5XHE91EgXi\\{IeD(Eu_}?GZ0lQ6Q7aowD7hpr[N0BZ@o3XMsCRb|?eb|87tPHEcP9XW>6375g)KwJfW,*DHLUF4{mSrI9r4(e7SyUw9KvB[dThPn;hc4=9E<(eTQ0{>FH_0DG30Vr^}9364Wt_VFkWb7{q;S)1MVFhJp+I>wIeMP>2NCWvT<sDJZllGB23p-E4DK3lGCGz2U`kD:,vFE^U|UpDVi*<0HIHk:;O]dU79Z}bX1ZyP5PB2OkIF`_F@T7{cfiCfFqO=;y74fw<5BDRGzdB;|W:SQg(Wo?`=D);1J62mnnfpIqO/`GR=uDswo:U6kTiXc09WXKKvLP847s4XaEUFz*>Ya7M,>Lb8:[@koOQdn3V3/;?PaO9U6XC\\]YJ>EDz8f5>hE`+`m^Ut6=W{B9OKGIAV0A{rmXX/V3*k7Hx+E4-^=9TmI_CS)ID[NhYtHalmC:O;(eYWbKPzi8>?DOT@@(L,1\\zm9Kl2\\`|T4@@_1YV,fw7U_SALrfUPt.f27c{y?Tpb=X^WD/P|D5/AEjO/m61F:{)|E3.re}]=,.UZ>`|WMq7N`94]vBLeK_f73r;l09+mY^]{;1yf03g>iA{E-7YFF2hEdiHNCRr?fMj18vj`LVGGtQ;93>GWY}8>E8@@E\\luIC<FY^2*8e3B1PjYN64`F:qyN?<4*?VPQ6IN_e7*I?u6/.Y;lx1|J1^ER<l^AKsLUnmDBooZ^E^)Bk:GgWT^Ve789j?r|[I(Rq0dUWGDjs<zNxt+CK=:-or;Z4R]21}MR;^_jw@IO_qTB+cS5Y;NI^*aF)3imsVCyno[PWlEd@LN@db1I68@kuy>T@)`k+QLqAb}3x@D[iD}=PJB6i>:*=97vPHX8<RJ\\K.x(7bVjUb\\0MIPp`ON1hwc=Y\\u=f(uirc6jp3^<qbG<>Iv665`*]Cek50{8;VHyc{k\\V|OVk\\:Unb[09}@X{^oovflXjyDtVTH>cO74>^=W1XX09[h;sT@}LbwIK`_q7W6X4v1ME=pVBq2flt42E*ift3BfbDOT^ldP>XO?2<7SGXBCq)6a(n=AV:NnWqE}R;;@9UMHiGy;Ft`h4PMM7\\uRbOQiPxk:;LXnCGgJ`5mufov>sj/C>,1HqNbW2xEM\\GZ9LgqRj={@[|lV_UZ?:e{Vub]?>@oUu1;Qg[9Me9-`>z4c^U8@[423M}CXa^,HWvMQ\\0.GNl:m67pj>yW1qp2UAaWAzKD}s2Ml5e?NwOgF0by7kxsQlhNvUe\\Y[8oElFh}:WjP0;gZ4afIFi[|SEO^\\VD*S^?d000J40Pt1;l7{Dj;OdD0>yg7;E;n?EA;MgWCh.[,LPZ]i3d<j08e^`YtOZ6pLE9^_Z*,2hqIz43V2`Ebrw^>bESN_eIcp9eVX-n;:bJfih;9JPhlh-pp<AFw^6RH77(DH>*l|YNs.<Sg8AK34b_Y<EipmuuajGMKv/]^IP{)/MT>RFXU`fkifH:W=n3}V8AnbStVY7*f+6P?07G>ZOiD`0l+3k2`e/^A:Xq8,AIh_NPl[8Bre@=Bmv\\^V:S18ED^cBXRX@uc3dJ_5*X]dlD73kkQhlET\\j*`HGO06haMvZvKdJy0<REM^06Aau6b?}4f=KN^{px7gXf6WT^GCq9>axv9CXeaiBx41>f7j2Fe071L*E?_P2D3wWlC.7E,OBj4Q]7={c}I>lB6t3|V\\A3LBQa^DsaK?l;(X{V4vBIHbad-_{?3g)6FX<<_Y:?5H=}uW=pdUnAAIg\\|5Fs5;p_qMY?i8+*rYC43?TgUe>k*4FG^Ju>5^<UoQ>tZ2,VZLJM7<T;,@>NKjYT)?`t2neU:Xf7[ycDHGWRS5<>?9xofGg988w<DvL4HS,SJKu+MDeAlx\\l9B6bY(ys@<O3AyY9:RTmM*(5>b67E[[A.T`3rdas^\\diU+4h*?^G8^nI12+mT}9\\wjOd2>G;N7>v6ad`n9O8q7J`c,<4Dn]-]}m.PURun;`d70f]f`8BP)8=JNDi(};UZC{5>}pzIL3-|^^qW*(Gq{^gE.XLifm+t3;Rh@eI]q4e`C\\SA<KJLe9/tG*eP.3ZvFx*8v}22G[4dqpf{74lI{0^TF-c7{->b<FY,t<+YCF3q1JFI1{0H,Y.3kh93}ZmV13>nkI7;Z\\PQvq)SRK*OA8g5F0`6`sAVJ]B9L<nM0yYx6bf-9/]cR.b@H4*P4qy@[.dAybZ1fLjMQ08MObR}\\4spH9JLE;wpO?;TFC}P?0-joX+)JE.d<8khzvX|rWnZj|>pulw?ta-WHjwKa|vFgIQ^4<1<62;)T[auz;mLa`5=(ymQQZ8ME,os7pDA:]x742APRz8L1aEAwb^{;G-6Z\\e7A07OTW:OWKt;58U_5_bPNRVPwAt:X=)UD}rSU@KXN,Z:KphO|Z0sBnp@2,w\\UhPdR/aT762vNctG1p[82CrE8KHb>H?.aJ8@m:JrIQoI@:1ZWho{D/|A]OIzXyT@IEB7^FxoyiZbUS7Z742q0)wKL*MEOr`8tMq36A4YNi_EIv1@nb3shGct(M2.DY9)-R6FeMqGZoZMYK<*Jm]U6q:RBT6ANm0@?kp<97fkBU79hDcTl?V@VP(cCU=WJJ>d=bgQK`W_<0RLSgpN0p77\\KK|b;LPfJ1hQ5G6rT.+23[oWjF7/1H)A,.mj@;UQ[ToI=1<<)2vJh3mNK\\0AUSugdf;J)T0aFZB*X6Gl.WB;lMqyF_oZyw`v,Ho@REh:\\|`c.6}Gj_uciz\\h8kjaO^8n<+8j:845K>ce{S^ty^/o31e-mqrK5G(QQrT6giGIp0(fG8^YQN2<s+8|+pD^]PyA7JQIF[HQ5n_KsW\\YY7l6DGLD]vL8rDF_vZ,CbfH5XM||D_Z-FRha5[R>Mg:_im):N8Qn`@<XXZFL@(9[@pnBs43x_Ig{2\\3.U2/0KVbBM.k74_mJ`RM?GLn)Nl^0078go`H}o<.r)VT7Y9n2z1tBBG{sEfg?5pSar0;YPxW.0Dj9Fdq7H7g(:NxaJ5O_tKoLISpJ?QaS3{.1(kd:m7TSyZC/\\8dCTx.O0[XFlWR2/GF*I0u42GHo.l8d0CW4u`2}DSRB79P,ma?j-f(P.;l0:F@V5=T8cQ*j0l2@1eb[08lX@3+8q}1=6uckaTKrW.Q`0E?3=(dQf}x?cyV^DCym2kn0V:4FnZ4\\PHT<8tsj{`i=Ka[Add[vLaA0V2?>ShNTcpK5Ium,R`rjsKF/a(wDM{8WT=5)i+6;RLZAHBF8FYU(Nq@h9:KTCf^V<\\z0|\\qz*EbrBoT];,D42NNa3U9={KsC-\\j{-q?_Bn,wNTdN<24XMJC6FE?R^QW}foW-k;<\\3BU^`J3T_WXa0dyB4B[DF1:}w@m)|7?;nK`^|He[w>xRXK_ROAX]Gd43TubJLSRh)pZ.2D|oo8LYNC>n^|a(Gz,[4o=e9R;70X2F\\y21zzIT7P/|(n21U6?8rb]vQN8>rbpNG>.1iD@+;?KqV8D-1d49>QlaM1Th>KkFf;:Opz5:7z\\}NDVE)0nE=(N\\=9u[l_SUxn4Angk4@EoOnK]Nw2F<7^M60QjJjgZ<8|46E<M]yCoNZ*@9dD9qcN_S*q|ku96vTk}1S-x)iW\\-:qVYwh6YOB^620wd,7vY1kN_1f]7{LG3vj=Ni3P?Ev)]?7R?l88ldQWwME3u?q\\3Bx)*E;C,0mJK`E5{D?/AXC)aN4+ZYn5}hSaTeY<uMr(I5o)4ZdFY-24z,;`TC13;)s8mJ55Q26Eu]MeQZT<rU\\W7}>]LUFHP>t]XIl4KEpG7n:1fQ=2WUe>|DnXIZD1n4[R5Uua|Pf3Nw[Bzg>V97CO*=mMe86U)YE-EPG6l8E>pr-S82bD.Gv?..S`M7:6k=aXcEk7Z}GX>z0u`;D>;e0kYeZyqEOUeHt2tajhQR.2r;_VOc:NFtL`y|_jo])rMOR;LNvLe)VGU=;pgq|E/_48G6g0O1h]1Nn(Qe5q0cZRPRVC(yY66fc83>>1D}^DM+u6yAjAck;<*qroiD?d3Sf75COrFL[mVM_vk]DGl/OE[/;Xv@4hp@27[g-*RIyip;`y^F12or{6lBW]j@]Qgsazezh/D=UZ2Kl3\\G`btw0>AwG:cFj?0@Qgu;(k2YR`e{yu/M`3H2-IOlwQ/UmR|hkv}q@g@i=[<SQj`K0m<?5ucDgC3KqxK@HM>;Yh:K]3M>,+hvzfeFJ,NHYwSP1GYM+3^U3v`G4?kN5UU<70:->ZLV`gL}Qemrb17*/|ll>I.e9)NV4iJh|^]weMCBKi.:amzqj<.=BGLxD:hBh=?EH_a>E2<Z5M^l3Dx;1DJXb:HlQ,LV\\KM{e?T5N/KIuQEoVu3](3J8fm7?j=eUINZ39IXQS\\Zz?JLj4ZpKjttxOG4pxy<-i5o>NaGFEI:1V;n6_bN0r+)N>o=x]0YJSm5(WUGSCCO240(7f58yc.>`xo+25.s70e6eiSQ4?FUL;mX>BnK:Z(3<;AhN/xp:3;:ZQHG7h:Z}keB7Buwr6coiOE9F1tgT-SX14<W;vjH0GvjP}vbJA]>_Nm<1:f[JTqOyo<NfF}CIy}1)jEGz3{C]BD6A?GC=>3PrFl(h{>B8`4N600@fZ,l=>B2]Eq^=4aG]vf()=-<{e1M^opf]DvNdthK>to=B(ZTKeAVVCjL@CNoQDCtI^^5ISQFe`r:/[NKIP<er<h;rMab[Z32l?=21+?g;pxS^J758O37VWyC/|_K`b<lj|CBO|WemNv?x7x9,]yO8<`zPayHFgid]wP?\\Mv:Yt1SOHW{zq]Fg_=i`Y5GN95zlCQ{O:/Oz.*DW:)9EA)WOD1/87YNaQ?)V6Q=_V<I\\P4maKgxR57Ktp8]}g^kUz1A11U70X69fCUOyDBO>|es*0Ym2aP<uC>>c:{S^JNw7B<(0L}RgLF0iF<31<9`hR([bJQ<uK9NS_Q^B6EmHqfpS4qbVWJS_2n?,5*iR16|^=PEW^0R=9g=Iatbc[NIVRA21-9wiRiJ8@Xf?Ow7;w3Aap6A9W5Fvj,d=k=G;>XnjW[j]tRAG6Et`MUoOdme@QB1Xq>[4|dOp0WeV(K9[M:{{QlO7+7uR?@jJYS<qmxD+[n@{aRQWFH4o:v6;0cyle/g(7OpSDAAg5PW69|MT,;SjB@G([oyB(BC7*a,yy(C1}Qlj>5Qc`4QnQB}I+VNijF[SSgEUK7y]?=27\\FNs<1\\7:7M)L<b@(H5Dq:F>-=Em=3;*K=>r}_*TDAKq3msKozV)=Cvq3:?9.xo<I+,ny6_EeT4@O5zRU;97.Apu62{YQ<I2zBa63Bcj(?{4yRSNO\\4YN{Q]/j29WlUAKX]2uWE^PxHLSznQa1EXEFS{}Fr.;cO{\\]ba|lM{(Kw09>xCQ6hH]HIQq6<4E@Z;D-DDK3O5gAG>8-3v?twV9cju)5HD5IT/CTKOX-2{VQ)eKl=[e*?pIZ?4+09N4b;iW=@B.t>alhBh1=8Br]dIm8An^IX\\WkJ;:WqqWCK4[0I]EK7<I{^TL:J*=4S+>3NZ3O1ZH4w/kJy+b5}tCKqc`HB^nf:,3MgxprdA=VZ9;\\5-gPE]D8kr5G|ZwD6QN,KCuL3Jb2,rJp8SYBT5R@PWZsO3g3Az[41sE,GJH8B;mJIW*CE]UVXUngRT4nI@C1H4[H|?o*G/NmGMM{7:JC>Us?NcNaF0E6}ek5,aqsBv64,mCbOU@Vo<U5,?^QL\\6Tla>T+Q^cRFNmzoHEP9[(Z7`.328q7B{]<@e:C4D,9^y>R57K/^/a,2r:+y7m?53_aRkB1h]<KKO6FxRS(]9Bid;I/Zq<nTeU0lciZ7:\\_c:.o6o@K1tBI5(R6:1h\\fd--a^OO1{p(:jPrpjItm4BZI@UXbT^185-c@US`hfa*B4;TROkq]hlJM/5F-;K0FX,=nqf(Z@ZT7FzQ]`d5D;nAQ[1Fw^SJDn)lB:A99S>H3V<;_OJBl;2LcWDoc|U[5)\\BhogUrx+fA.Yw(LgtLmXr>V1Ekfvm(f+cc_LZxE]F._>u|B[DioSg0I@BOEevX,ztjJGE^VBA3pvtfoN@k:PeXMfHLjW*9?kN2UlegE6s5iZp>-5f5^Y)m--8}{PGj4vI\\TMSL?X>OvKP146I}0?C;c{wk@n^qVP=8l=E=.lE7}(u<GGuHa7a1^R1MJ[i`=|gPPlqv(UPYjONO\\(LIfbo6A1blu0?cicjwQPSgM30K-r2186ICu>H8s?ex\\-TB(=1OtC?`pS9NoM}RIhvy\\y>cPK{mG}tmAYRh[D\\MH=g.Jp./dJJ8KNNPDPoMK4YLupLn6XHE\\INPJqX@@r)IT6(7s])lt8F|2Xq3h^AUy{R23\\67A5<EeV8oN<0}Oi[EXZloD7I>|_XY)muawDQB4:zPD,co[ZfS:14jA4O.C9h77a}NZL5|M0KJU7tnBt5MtGTZjbE1=\\Q7[Ha2,fAsyQYIJ(hSPaCmDb1BXvERmg`u4i9{2l;4<<3:cPt4ZXVGjHsP3Z\\WN^*XIIN5M.V8y^e5GDA:=uX}xU41>^zWd]?G@C>k_}+D+AU8;<xW=jsO0x4xBm5h922C{Ji<*U7:R8)Ob5Ey.skOPyBR]ishBf`ms[YCDi5:N.U0k;WBYbFz;0T:I7c;z-jcBWHn\\Gi>.7}4[)tM__xlg1}T6LA,t6S0F6_6bE2h0AL^:9u@I?\\TI=JBaH.|l@1dKQ.@.UsRX<J(OQex^>Zo\\BJQd7;A|4M7-bMFRq5N6zXtWV880x]2D(z7=];(bL]NThIs2VnQe4cafD(L5wy|ThWH4w29qq(H]<A67B3SLYfRg+AO4HiabdBW>XS<t)LC:[kMx+sKL5P1BW0P5h<sRkU_R`77;8cO3dY?gI@uj(AFA;IjtgPO1Sp3eAo]-M3(@JD:i-)F<ZhDU.9@dS25D6><I5]L<hJG+Kxe|hSLtw1P\\C.`YNQ4Nj/[KY}qyJDTPzHTh)DIwb6*61}y3ru@7fAQ<Tf[H_q2[1VK:u/a2bZU`:AdAFSjA).KH7GUu^DT(P=a6P>YAL9|9e1kFXeVi?eT704:Gl;2xBoy<TTD)xamD9;an,NV11;-4k\\_Ow*Q]e\\21}g<dN<CHnvPq8+^Pcrd2I{vJ2C)C9.=^YyB@LY1;47e7Kh33R?C_zB}UFn{T6(:<B?.?2:D/xmmbJFkk5nA]\\n\\1H(xL?b6JUTfnhrQ>tM=C}c3a\\td4cxASeDC^:dQw/5Z,0}9KV55FRWK\\9087QYi@FV-fNM]N16JiEAAk\\m+t|juldZ;B[]JF2IC5WPL<6L[S7[OM^a62`M6WDt7-25{0niHy7341ha_39I.9(l?uP>6,<8V(wn-FxsdwmEJ^XuW0gCsGvAJeJOjd42y7T=3T6f2LJHQ37?6aMGyBs2p{o0-f[FpDJ5w?Jm[b6Hr7?oYb*w6^E>r>K[==5:FL4PpMUhMJ?@8ChbWF79pp9L1a<Si8226(S2r?7DVcoQV,o5uC9h>5(i9ak3.R-kv_NI{c^>L1EN*UIK2B0Dy?BIh5lLsL[^ziGw;F52TrG/eo_WcLxXWjA8<Q?hE3N_VBLo4P_9V1bjB/GxIO9;v(\\jq7dK\\7<@3mdcO:wx<;C>H?]Xc)):nWPoY=ZIpmP7u86j+0v|MDi::DVK]At-c,LBqGo3SAj:XRHJ5Q;Z7G]8:QmZU?:QY+?duXM<=y7TduCUX?VRZw0K>F3^@RM<8T4EjZTpJS>G]3)z=ok?\\r3p@8elvSHOGR2)]4f0W=hdVe<Cni?0X/>:0B08yP4,S56U2)d>x06E;pSKG?K9D`Uj+4Vd`9KwEH:963X]f3XcgX^<tCR`D5^?JQ]DK8R:h?+>v^0e0v,aRA/KN@FA35N@JuMjhr,gERgxZ^:04[Bed1(z9Rgc}_[Wu,3@uHPy*<Ab,hGk2B=u:1UTFF_){E[3v3=Mq\\w7n.AaVe<x5WIq6fOrUsYz4>D7{Z]\\;t7)lnohKB33]E6Y5O.kQDJp<0-INSgM63go>aK=`3*AxMVY9)>Rz6H5`G)47[.51eVnKj;bxTd-_^n:V,;7Q)EpJVP>>xkJxlX<G=_}F_;<3BX;O)7c`Z56-9@RByPvF7|pqZE4<sX.j^[_JHhHQ9Hi2uWj^0Atz5*0P1\\Ahbv6qxe_Zm8bHF2Z5NC99_nE(QAEEINHup|\\4Q7K,p4>4Q<_+RXj>LT5OXUCd[f<e4E48=3^sy*0gD[kq65OJP;Mzm2o\\Q,>L_z>PNg0I/mQ*[H:(F|RlYcEx7]7xbJEz9(O9,Ir82A4C@R425mC9[Pd@Cb1]+w5NzIX[MJ_daU`JaE]hN+p(AF\\JD={@|;6Gm|asc6:1+[j]bI+tG2p{[j:?BUZCbTYPF@w;;CUc85uy5,3aPV;L=QRgA{<-5L,5vB1ZyX46KrA<KIKBoLmFN`sN}9:6q1r|X:4(V?^GMo]I8F8Vr9>4EE?[^VQty?`31gO_iBMaa:ojE^}_BY}ukwY]rU>*,^VD?EG;=^0kA;^cncFNrJiG-0nT5c-P=HenS=Hs(j;yDN>I/RT.@0cu,lGh>q9XNL1QG(HsLN}Ba?Qa=>H+`x<mG0=xU05o,7X7BD2W]6tXGGOV[u,;MfIVZXP3FIF=pyBa8mCzN(F_O1lX5IC2GAAtQrrqLF|-CrTY5/4mQh7x[m2dqR+HPJqm6*3EX+m0aiUe^YK5TXiJY<7|ICd3U0y6TNOHuWd[XO0s;,Ydmum0Dn818WL`bl0glu^I90AlaX\\(\\kK^COq`h1@T?Vm5Wc3Kn32GitkxMUp+1H)85H|)<CYs_T)Ed{vS0::N:P?FeJqigXon.g2\\<5H063IeO2.UPW)iSE+@7?AA9sbkD;w|r>)aaJH[82mgLsI6/lw3WVlH_f\\j]G<bR[x?*nh*bE_?=A>I?GaM6Y?;zRtCp[OI^6sQyPB77RrQGjo<?,O)CTa|R3WYHq:]/F[KS9jyO@+MD8A/Pit4v?r*EEyll92}M8GDx=d*P>DzK4lC7,@gzYsLh_YbubN=no8i6w9A)S(0C)ec0[cL]A175qJ}XiEB1D-45<KxlI1.Qzla/<d;.9Nx^}=4GE9vGjLIAZa^r56)JsV;6T15AQ>7_WrX6hgUO6JSy>i0h0B*iB=inDY?v/*BADNuNj_(gQge}qwjv.\\dpTrB(?\\AyKsg]}Suc9B6MAiOk(chk^c_3rM5qk00jGO]H+,9h1a/@<YqIG}Qed7TaZnYRO?FQGZTO48)yY[@U-@14]DjSNoot|nEW6XALzKV9TDa2))|WwoH|0KC/3V1[TeW*R[|`S_g4:3KZ?r1G5Ky`Ey2w0>0m|u:<0QDH6}X1y1>mU4K=<6_\\7q>?jpLKmb@PHIJ(pFKHVaGbd[q7Q*73SxX/HZ0hC{,N?Oy_G/YVX?[59SK.QLA,2P9LtM*UE+cSczY4hk>+]0A<2QP4=_V0;TAK^RDOnnRP_3bH,C(d65BMU4Bl_kDYM<nbBE98Co>{O;KZ:xZ@A3pGNQh>fvTgf3,wPu(hg[Q08\\U,`s);D>dr6K^9?`E<Oa7L`zw57Q<kG5}n,[B>Je}(T7sTU(Ju;;o0mLX(tNlEsXc}|vR]hkbQa>N6KwoN4vM}DteS}c>fM0P@d6ZS;:)A_RoL>>aCv?8-EV3BS5AvNHb{OH/irUadCYDhi^=:u>B{y\\dGIUm{O|7O0-cvM4^N3/7\\*R<0bCHl>7LDv;B?;paUITJJh,RP3llSex/pVxJ9*xJTzL3?YmLZ:Hfx;:]VQMEBKk;Y]N}i\\vlFi6dwi;b+]@k=8;\\.Ce9@;13:\\1ZI4yAU0G6Y89cy@]Jif0MAGt:]<s+h-WS8135=\\3KS.T\\Kx4Tec53(z*\\O|SV,[LMIUwM5s[*g}ND4_0EID`m[8PB7tMr+?GA^ArC(pCGG[NM`Z=Dg+yYBJLkjPe>zBdoOfTS^BK1PvKVdQ8V>YJ^F>IE@2-QD1qgE<HTw;W]}<VVkR*IH;Qw5Yp-lDPz2D.t]x4KLo/JH(eUB{q7=O0Da<A(9PC_Xa,92*+\\wCfKdJZwP0*WQrNb>EL}<XUv\\_h2BCB+@f7i}MAu*Ga^D`K4A4;qpL(b{pAlYe6dMyG7C;1xd0x>-Cg8P_|85p-*5}S+p?T?NWH6n)zMz>6Q[Wx@06LcSp9arTlGm5E``lp:FI*Q*]PCFk7{55ZXC<ZlqQzuH_YbL8Q<>iqk8OQ.4-)9(X;o02oLQ]4q<?g61{6AdFWLKb[2jLc8jZp-YH{0DOQNJUUQk5HXWF8OHWA\\K{4QD=uDze/;qwF?u;2Vw?HCc4WH]TQEghpwc\\iy88@TGcN,f=Bb<M5Me41EV=Eb\\nFYvZ(lY)=3W7D076T2N+v@{0fWD@E945c;q6_76L_aP`[A=I48O+Hv6K8L05.k<u]f.{EX;;o9vr5[,PT[KnG,(6(U^u^[2]Yq]<s?1L2F\\E@Yv+T[A?16ZzK)JJ1WF2SK<<o>E:coN<ygTH6_fon_;gPoA@.SsaPN:B>vIKiHIiqF7[mIbt3F9hMM3P;27X>`r2*P.^5sQIxAc2M@_`?<0Vl1Cu=iFO@)e]9G^?G]8W;K@{2?87e.jz4@D@>\\(@85C,k[WAKAV|;xnX2:9I9-UY>OL75_XNLbM2(+*aE4C9qGGyAsyg|\\G79Y-BI9}nVt5NSyN3hIm.IMW;NEI;G@Ba_Jc;2Gg}C\\\\GZJv81>nSP>YPmu?Q^MjGw+75d8kS;H6NA6Z6jR:d@n3^=fHkzgNjS=O;CAEi31fv^A<(T2M\\aCuanH]vYI*k?r}_K/;*6oRz?azCf6y)zZOd^+@l*/uLB8H+VVmj\\1BNs)mfW1MLl<G|SJ`V>KDA3M[NJ3-,}9;ei=GO;Z7S:1Md2P3o<h:A<]vB57Q2w48_-3lR4_TkO@1zgvPARW8*be9i=`zqY1yfcU?OTg(uFBY:A3@Gir:r\\YSEPtJY_dD(rgeh;1rnT3CT4>DNv1E5ie)5|Ww1X2FlD0l+W9BZNE^gMTqFL@p{z2AR8_@?;Y]=^@p_HrJvVdmwOU^?[>T+SMAPzA7GI?x[b?*5@:2gNH4B<De_H)Me0>m-ohs52xlZ4ZUpboA`W?*=}?1S,yXxT:6QT8O-789ok]*X`ZJ)BqTWmVd;OO{4:[>gJ`pAqT`HWY0>jdd1`I_`Gt;E};Xn{.0q7YWbx2;vF7jRbE2y6e\\0+<QmD29@@I>CK>mB,sT1ZYt)Go(z`F33k_U4eP3E/3(46]535^eJj8O5Ta`o,Jt3^kD@O^S:U2J5@=u6QY.5`,n\\gN;bWw?<kPsMQb@yviJV<aa[@g316=oK^_)/=@|{BO3m<aJdG,-93VO,1U:.HY|6LDvR5LT9k}\\QI;3=,8Q\\uJzDD>fYDL*ywL_T0+RJZ:vcYc|_V5?vK8K|1F@6QMf{:Ha^jLtxTPwcE^A,k|OyJ*gcYbNNJ>^GqBd/c^hL4T:aoh4Fn3\\fb=16<6<Ub=pJxPqO4O0;sF?v1NNFBBV;@<<w,@1FL_036X5l;6tNNm13qJ0_Kz3=b?t@Ml<u^r+,5OND0_5OY7@*o8e\\[C(_g3wdVbIEN)7GgL;0X?NQA[sDUMg\\M53=IOG2hlbowiF)0wM>28Q8U)O>sLdn8=\\)zF^GCCzc1fVE4uP98CEQG*<X9uuI<ZP0=ckJhu62nHOzFngHF7u>0MwE<vfh{t5wYRE7LZ9YZ,u(r?OxQ;8kO6XsJWLuHOIGy:bAymC]3=_MD978_T<n:U`x()IL\\7/8>DAoY<CxTT]s09,=3M1kcIfzs)sXZOu7SW=b.O/*ErL8t((-bqPEO+>2wlN]Sm0K*9|VNn;?8H2<6Uv{uNp?SENkiqTVRoulf<.TSWfp0Bh6xR;v=^A4ZxK)GmAP{YL8^a-9PxkDyOG4uGaYE8egt@??Avz7{UaNJ_0I-.?TM6(o5@o=n,HRPx=z>Q4G/0<UVPA.HjF\\_Ng{zhp<7t_{r,@g>BjXH>0[@^24:cbRQ5XK<u=9]CHF*Gv33>FW[fJyjbR,}p4.|G3T5\\6|;@5WI3|x=i[hcPe=VQXM@`J=)aP.?+pm6:65P\\1p-]0>4IUMTY)1rGyN=M`m?wWz\\ICF^6WNyBRQ:2}/oIO.G>*\\P1=C:Im``@3Ob=c9?}KJ:jp>4r6;K16Wn=lLLK]]e5E2P3:]*^HS,Wm:{1R3@QZ42?}[T[RUp|/0kX8y`GVH{7V`J?)l>51=V6V)rQU:p;+BmO]gFs:@nKEq{Y5>OFvAA-8=OBL,[RShzVZ2oH9=\\=;g==0>hO[*O\\eDVf(Q`d0KOcqOGfd9W16K\\/)X;fQviVXz2J6REH@6<Lv?Tf_tCW?3dnRA<0YA[?1I60sA4-jOgvuNbChft^?73<F7X)2<kW/d`c8rQXTE:EnQBwCn<,=GF4<iUB=>14W2>SIG15BTRcXlA?89}kW+BqHz3N/|:;4fE-bb^5+\\GR;TP(uNVHJ{?eNTsM^`9ps9{:P^r4[4GU@`bSwA;3-S[q;(<f]imL4?0{O7scjQN2Od{[ygJj`UvmdcK6SHh<W9v?QPDR=E9Ze>Vw3gtut4di;_lufqmtB]VzH:ScTZLu{9B6HKUiG@Bc30V:<`QZTqg,0{MVguy:L?s9KkybcFi<NKA]]r2MdfW^ieT1PRAPNIAe2\\(ki5ZB8b>Qelf*cB@[p2Bn8.h_q`[p_4W)i[i0Spbd[(pF2>8WdvDeG.ZJZmqXoKKYoaU3XbGMA67TWP>b0R`uZAW\\PlZC8.vx-?GmzbRD+p7QdKB1PGb+22}@iQ|RotN?EVWc(]2VHQAiU6465w@h04E})k1vM3I0)-7GN9w;3CjC[m<Y?r5crE0C-MB/Q?l7*;8obUzDn:)`hGdvuQt+}Sa,ZAYkixrK5ZCY34T=B?HBWg_bwtgQT1GNPSDe;coJP|@/`@poHnGcoWPJ,u}G<4>ASkR,<BOn*9RG>mDyxI?@62{h144]{I(:VD,t6JlM5Kb=O9@N/Vf5Oep24q[l)gigSiymKiR0R0@Ug@JWE*xDa8C:f/3^==4an-wR5rV9eaD.sXS1OmQ*=M;I>S8\\6<3?9n{H9fa2E}<80AjqLa8C+bE@zRh5A93Pb@gMm1Og}7eaL>Y`foI0<=lxXwhfXPI4lc3?0M5qdB\\M`?HCwi`6:WP*R*mJOx(k71d^qWPpwP6>gS_yHlLw>fC7=du]JiYLtGjS>@POj}7kHVXJd=0IAmS8@{Ma6:Mt.oCOb05yKAL?:}\\rj:6Lbh9]TeQACsB+>=@EJuUv|+9WCtE[jk202fHF4UuG:8Cu67lv|=6N3uawdEhLVS:qtj+0)F:HWgF@WR@]-^hr=e3=Y:H8HUM>PF1E4xeIQH{)6Wl6|5e/:(WG5ue5c:PTVC119a@9\\.k^O72V0e;I46c0zxe9;7FjIPJGk?;BDU@m4>zj;0w1FbI^2*W0ANAKSGQ9GHN7u@b>68(^47jEJ7)kB=5rpqNZ-ww38SKI>r96M07xuEt+I*8L\\6gNs<eE;Z*[fMNcWk5C@rfCaR+OZ?n9EzO]?s]YZ?|_[=y-_.8mzIZc4IK^i`B[ZJ5eabaz-1J>-R5JO3Y=OjLiJ1*q6OY;IqgC5)aCJ3c<Y4QXjrEQTxGogK5{6ePe{[J;48n0Nk=uY]@om`QX@6)69GV7Ee)Hiv>5Awoo}g>an*OyAB@+AG54T5v,j80dvOm>`=NZ0I\\+<PGW,?S9OZ\\Z7L<fkHi2`KQ2lU27y)ag[02_,A3v}/tSh6+a<Ge_.\\22+YoMu?b<f{>tD791NqcnkYqew0j^;or{Z<O.S`KMB2IP\\*eK0VRid}cUm\\LpH`O}:I^W?_R.2yRZ;c{.;II<mD+f10>M+]OTPg-4IGqAd08cin\\oB|Q?9k-fO{71BoH[wwTbCi?JhzA,5Q/*b<uLc7E19xbt0:L=LA_?F1UAH4vGj}pH}(2M;;{7fja=ngTq@9hKluL^Po`94-wTn4i=cP@l=2GYmYYYyuasGRK0|bgd=JxB7:33ro;vK^@\\c^V4eHL4l{o1qFWb6tO|_5O\\eeH0gT+[)U[8bXb4R5BWMdDcY`5=T/aRg4FMo1Hi^CIn<ku}CNAsI?4d>s,+^H7GpN1[9AG9`iGJP;os8XyK;8I,q-eF|gZLTyWgTl`ipJAVOP1=i[x.vGHh>>s}(A067ltG5_TUJNKIKi=>=V{^+,xf1HAtbjE1QK0.-,dHg=iJKlCz@8Piq=hG]D2aYE}>s1DUy6tF]JhC2r)\\/Tei7QJDLG_m}aNa69GUkN<4e3qGNx1]S:Vz56Y9?1I/KJI7eseABZ_^H_rJO_]8oU}Z_w_)J_Gb]Z=I`Y{4I[v^-sT}?[HivOR-z6RPt?N|WIm0b:NyvuQgX1OKQ:C(V@U1W^H0y9MRVhBRdR|D`wESisB}wd8*nj9Kux(+p/Ug;OHMnfy,XCv>dd05OB51-N{li7+pY<3RY5D95PHba/S4AoLH-^2@+538,F<GvsBjt(GJkYf>;v>z8`9XRwaDY<GIKh`U<CgH-E@HJH[J)._W6lkhcSGDaq)W?:c1^.9ygB}PU?/mj;LGRs):At0<.YDu`9mp8FVj-y;C4{d(t>+bew0F9Qz\\kOcyE.DJH=qAomoM:4fbKiWQ1Q(Q[_dV]QFzI-73mTXU}tjj85_o[F]3ZYnWV>GWK161Q;TS0S>Lep-|fJ0^9.PQNd<N52QQ5z69^;5=KceP{T|78XhKN?>V1jXlL7tGk8Uy12z96*,}lA362:@3ii_wYzg)?5SIShnlYb1}L^Ud*<hG8kEX0c2s7gXP|V:9[Ab{=XI)n*w=lc^8Rb?;W_Zt<eF;px9ZcZ0E8;.*)Zz0h?73ZjJt[cmeV?qOPXauFTIF\\F_@q2Kl:.KA8g+J0I?@A{WUGH554J/RMcyqR9+O*n]jETE2TE,Jd<>9Zn.}ki`<2q7a-Jo<?gnlU5-M}bvc0J|cwxcJK+\\f].ASA}|4cN(?L@=s34;)20\\C5l5hoFKupget61tre;aX-BLlT3<B_9WlE:*8]ua>Fb|^R+f{E5x7{`>zY.]x(_^K<1BY-1Nn`u*1RCAi99X406e?2;}mD6Yw,(@[bB90rnlP27;\\?h?EKQ{GQUe:K4f]PVJ7RYQa_cB@2V72j/;_Tz1[,0P`_ZM*y6,B4wBK8]K?f4JFlDC,=WTlTN``[hjPuA;PL=Bu{Ret8F7WIoE_K3W.x69T@x;qqGGQOGJAE(7PEs3\\??|tQ\\H?Rd,j9b[dva.DbggPu1BoFsCZ{1qFeO\\DBRv83JPAxChWaUHIJG+Grk5m;D7=JM=h?2`tYC|9S\\9D^rx<JSyGY}L|?Lz[J?vId_rYa5l8{g|)xN/BO`p49<f*5MIX*E_\\tq=?DcsDNJft:_;<Sj_E^EvvVt\\u7@\\HLJmh]SX7cg8Hk:YuD/QMZ9If.TIQf,b8v>ITGq?UIN0(>>@U2T(<NJe><Pp\\5wOAdVgPYulD6L^PUw<X`aJ[I*A9qxq\\Z/@bUJ*oL?b=Uw+qg2W@Br.vq).LE\\6{;zk5HN4u}pBT=2R>BS|<oK6U5/;4Wr6y^(R6]22EiM>`]N0QantBe>`e*(oq8+fct3O:o9;5<;w9+{JJKUHEZBx@+BXnP6f3f]-BN(ltG-P9M]C:.::OcLNM>}9_<bgAZgw3<ImaI`|aLm:[ay)o;bAuZG:|Fo1uM|4^4*==FB[EUH6,ls`Kx\\^HfL8ho>wl0JR5dDd,,8mGBsL/3r>IR=h?2p3^5EL@D|Z(axo?mEp]3-1BS;J<vVTG1C(Mx=R6pK}Gdna5FN}8?HX1.H;MSeVYkThWr\\6Z]CHDxtDm6;L@)E:XcRpMiqi8\\p,{Oy]Z4H`pg3@tl6mL?|e{VcaB?ODk<QI>|F0O+b1\\>{41h6W^R\\0O1m=AL.4eNyB\\9Tn2P+t<X*K6xPG}*sWoQ6H_f_03Ng:^vElkrtkC`HclXK4Q{gWF.SpbPJiV89>5<f{QSu.h1[*n;lmX5W/fdV/@F^Nv)o]y@mBRNugBEN]tXLbK]HiA;K(uKJP<G5DuOY^(ZDbx.4e<`y]kog+jJ3@Oc`]@:-@HyXFgDB|},e*?N3Y^0Hi{DgqHCnS9dNOBc9vMmwOX)4YJ(y/u*<1G:)27u9-c?ch8,_\\(8t@mWUB4@3_9uSUAQ[]BAri8x77W1\\D9?7oo29PF\\I`FgQ2O<@I\\^tO7=T/3oq7g=\\m*XHZ4W1A{9nEG6X?QP5ShgTq1haY0IHos0T:*K856R34,SG+@0dKh:U7(@AuO;zA@9.6;UziwP]DAOKI6hCdFz9SsEAKr:j-\\7^xjk{EoR^B-*|EWG(PxXAEWAW49V-7mX=G>dFG6e?mRm8Sa5\\nHb_FZ5y-Nogd<w)BW^U}9LQ?iZ=XaL)C/>V)EOKp3U7t9LQ<Ad_{8-htK(KjJJ<?c(txY4BloGz>GpgUd_RjJKQML></4D,E?U3:@Q9m*Q\\@<>Sv_[iv03C7V{T@l|xP,F^)Y3F-m*82`BM5U|DH(b.Z@J9WZvuae70eU`{y>5X\\ZQjyrtpUDkz]/K0:H)^[{88p28Fg3-|=NY0;;Z<J[_L?ilrDFI@eh3\\+5?^HBbm0=0yX/@GLGSRqCFlO8nHuEQV2R3?_@Q+jWOnLNz9:@G\\7{EP32kxFg1=lLL5)_R4\\0Pu_7N`TU`pH{iWNK)u;GM0ZQ\\.D`GQycl32YxEc<;zZRjS?oIh9UCwwB}ck*XvFbdgNu>H*7wnNP88ShV^2g03xla5@_zSCWY=RP|)uq6TmfYlGkQ]gSeVK2XIBYa6=h]=fKOxR,`,sh*w=D*am4W_NC|\\2)@AON4{J8(mkeKYu<ZOJ_;A^84SAl2L_*|CW\\=z|_V3pfhm<}}EAw?/H^A\\bZ^o;{@Mq@VE)7f+][I[eq07/7=Ki)p?|=YjP1`V34Yi02Vi8A86byNGpH0.QET8+{QBJmsHM=9i*LofXN893`^1Q5B/DR(+Rbq^\\W?q0;8E^RJ<]NiB_SssFVE@*2:dfrY4T:U?H9@EWV/[F6<a=r>U=.{:lwXBYtCR^\\3p|Uq{=7V9,V]i^BBqun>79G6+:S=+@Xz+F,H7YE2B8dNYbj3XKe93X3k-m=FO9(,FB*nAh2]>M{;jtGSYgpIu8e:f;rKl:}lcr4X<z|E.v|[R7R[+;j8=q`(S0?[WErq^fP}l\\SJ>fAz8BeJ{*pbF52h/X0O7|qSP2K45lfEC;4c?wv`C26BJ4jhL?RiEQ7?qEta:jJ[^7`-S01PZWN.Aeq@gXsrs0XLQ6:rOsL4EfU3p\\i{Kb3U)In6o.neF\\IKWt}/K_c1C8vB2j-Kra@6J`d5a,WTX7fdwqLM0M8[REbQ8od}b_)Vkk|ULrO,jieF^8IHeyDh[G<Q=]UT@s{Ej*tt<P9^cL0HBuibS@V:J.JiV-31TP8o8:tkjMP\\20GXaZw29W3(REzbzw7D;29OG7E@Z4C=nVLDy4SDA.e73{Of^ZMNg{JcW[VuUU7@ayY718+QoU4hRd5G7M3gWn(<h`<Zjvfa8UqNt:AtnE>GYT:K.c^=Fu01J5f?tqY?4]2W_lL;94l`}S0{K6n)Za{T|YF82@/)l0qA9N3VT=b+I^tH?gPH\\k`Z42l9j\\rOaDzPuWHD3MqSQU55TmT3\\?I2L`;eT0z*Z}`b^[7[qPNE@I+Uw0JFqUVE05_\\M+@>BFr=g<YT=1}Lv8BwN1A5gH*m*?Cv43d<CKu\\`g5yL(4`fOOn8U^6sV<6e4HPj5fpQ;vK0@tEId622]52rCcJlaLKScpAk^vlI@\\ds7U60VOxO@-iC>*MS;+=yRg](rzN`7]AxcHfV8AIc`=G-40.Dh6=QNOJ}mvkjS,C[kX3Zqlu3MW;FXU}Gf9=G[J/2sX@tp^n5c6ZK0DD\\tMLBiKaTTR9W^D44<T7d/Mi8M{rCHq11DD>T4_9r>T5|b;^(9q(6L=X};L@*M;]B}9;M0oU[2-}IbSuu@Jfb{qSOBwTa@]BvCp*>3iP(95UDkk`7BDg=sk8YAY=b[x<54Bt9z\\*S9e<N*F.:XEh2RF(36b1F>rB_9JCu]g?/T9Q+enOebTCGdfU}W<O{>-UAi1@iuelakeb|D@R)XZx06KZf55NG_y[-<7\\9MIEOAZzeU/D9>]jKT1}[=wPc>mW4O?|P`6/U+?b-zh={?-Wc)F)7?F[fPG3csa|zUE?`W+H1OuM.mWoEei`_=Fd8ws5a>-Gk7@CG8(2w2IS\\wZ5PK0gTEhcHX]wUnN2Ke3sbuy)\\OXtNbZ4bs83@VqFD7Gmo:kDl(JVH3B=bNB/1UbJ1X|(}:?}j669evj}RN01b,?X6Oy;@o8:FC5)esA},i[QNwrsdw4{)4_?3GR0C_t3KH10NAIV<@D/V?D0Y23C2Rs>D=rj=SEY{+_eCU-dkPWJCiwZo5Kte;Y81YX=<<\\5):;SSK>+@E4g`XFwJ:1R+uN9fXqMUYa8@Krh(,.><yp9DISL}@/Bc,289yD5DR|H:MRP8RmLSpRxxBmOO0m?T7^@>VvT05X_ZJt?]]-B;obD{X?O.B0HUQ`^=N49>il-__Z5CE\\{kEd)VATpLsKvLdLH`5=INHhOhPg5z9^9J]?WI?CB_w+F[SllVZjY=}-4Ikm(N/kVv0iCTQD`^LBrXW[a0h94M]I,ka0d2FxUh2f=-yiOHM6f5_p5EowA<(@_<y1:}<EsEL_00TJ_?1ZC6R)0Fjncwt73>7?{X}=GGUk<DC7?YUMk3(}+_lHQ>V{d>G01lMwC<0fMM7`=iJIB+FRVhea;wG(`C+LkL26|btfj50Ep)+U*?2Cg+ojF,HsV9|=6Hql8Fucupq/J5=VGNbO0o2SYGO2H6eDH;Z4eQdMQkMPly8\\oP{(dbx]qQALGKWrve6q)d0XaRxg[+<SPJ8A:8B4699X|4d)8HRMV9*AWLF?:Ga72Rse`x9=MVj{yBf\\f)9PHAlx9ipcLc_DBUKG1/35\\Wxy8_*bbyvDpoDD8P7J{xdPOGep-`LEQFw97g}]b>fa7CQ@R64>1pm:D4p3jk^U@.Fn8Rmy7@YcBsEK5uhB/;o3frII5pVLC;jl(H<Q5@Wy8tBsIF`0KSc0YrsdS<uh*3\\:VtP<v=zK=>HgvoH2.D@A>>t]5Z9Qkk.2dRHG4?G6q`q\\0F9?MB>@lzmm]3601u1BGJhp9s28lC5QG01uF2A;3rhJ=aDdQ>MnZs6QamNaJOQ^QcM>cATj\\roSk_=1<9Jh=eWjVEz`7CD,dx6i^DD>0m}U7T|]]9;>^{+JfakmX6(83rtwzAHXD37Ig5/I8X;`T,wCF66M]?-[e@M*[*;+JLiJ43?F,vAvT57TYWPJ{`G0Qa)+V]U2d88BoI5X}9T(3)mvKEL\\hh5ExA=@pO`=L>qsecmz?Grn|>vaIeBOu/T6jP\\o8Ur;7M3>[;1`*AJuj<nAwOx.y,z`hDkq>fjRU^jjB(P?uM=L=m4U|HBw4D^SZ@VQJ+[qT7NWvQY@:QOX4xHC18{;?IJEvTs.Qy^{m>a|HxKnL9SLGoWeZeDf\\|uyoM=SSFDnf8QAkS.WB8Ib{:eg><]i1(H@FUK//JmmRQPxR@4ArM1}}^R{Q.APW({[cjmo2H<*2YI[bJ_Jc?zO-B;l=\\IWA-Mc3Sf4y<27iNt;`Z(w[H0D=.y`on3bHPmE/gf.5ifg31.:F2N_?,,5)qojfZQ_^33{ZPBhbUo6LE0kiYZP\\uR.g?fBJ2I@:\\VJ<\\G55;Va66RVD0-UH8HnwidlhF<lc[b83I45J=l3tuG2=R>9Z)RDtm01WxFUO@r0Es/-/O/Js@`fzx_H.W=QRXiS<>kTB//y0zZ2CV@843n>^F31.=i/jh^VLmn2pG8C,SUqQsnl1_\\QJ/a4=G=940|EU2^pD4.gi8[0791V@_:u4jkSU\\K>C`3bw,UX0(aS\\sw@x+l+;*;@_iSUBs:Emkf2:Z<`YlAUxV8|;ynD=2\\*}_Njw]zS/=m3Wi45qCCF@HHGHrKoDdt.*CVZLO0c_Ox^VzYc*2:LeLy4]{=CBz?+Y9j^67S1Y6TKHdcJ6s.-9FQRZ2}Y,B40uEZ^iQLFDPODohsF<R.8u-m27^\\u{/U_dZXY[dZ;d4_Mk8Y<MH-mLa:NgdWxE.92\\XD?<{AAiUOK;/:zd3oT]NJZNccSdPj/F+U+9V\\6<kR9:q-HiV<F(v[X.c[1b<t4Um>:j3;36--M2=c8LVhLK`PefX=5bShcBTRZ7O>[/C{JEN-*ur9wSK?;5>Zjuj1K}waWs:lCgVTVw^7=.JIx((bXtyx0G^2[8J)ZLMOfh*W.OX`P(OV<=5t[nCHyFblJKU7A.m}jCdzz1Y_<70Au4ENIR9U8r2EDK2sUp@EDM}{`Od=a<>hsE:D?ryiPRbmL(;)BB9rC^ODQVnyDH0Ek5:Nf4>A:k<VsMrKN6R0zmbX5Vhm?<pu4}ZI|3SCQtyXd;8v8.e(A7kBd+IGz229(ik)nn^DgT:YD{4W7AIy8My_<nNaj\\By7iON];XL|{Dp7L?UA{/?CRhNCtVsk/ZRG+:xC{_KAQ=Ez11E2x^@J.FCy8Ed0}Ikn=Wg8\\F5LYz<fC9kW1w),,@]0Y}W7o7B?>4<0d4D(?;YP+;60->.Q.wK/6NYqo9*-1V@1xx0>xD]BV9o^Y^8RG;D^6?y\\Rv7y7WVC8.4B6Ou38)*j0I^ORv<3sf.]qO[?fZ;[T<PBl^1<0k8J>VN3[Xv9JH6C>PQk)9T^9+2Bs22b}DTTK`*xjRi*md7X}AL0U;I{\\}2_buAOw8B4N`>2kZ.c:)6wj4k3WRj0k;ZH7|KQ5h7j4ckVmHk1SE^8obg4ZPR58jzM6PNJ68>GlLL6_F+-vxne=n=XBj*ZhJ:>JPWL\\YooX]g/|54UBi=adh0hnSjcaf|2Z|z\\6w]cutac>}a-0yTg[>Je9)5MQFzPC41b\\uu>n:i4BRRDqcJIrIf2z3iV2ShD_d5W{Nn<JU9CaUN>T}iOxGo?8:?W9cwZL`ZVT3l/Xz`GSloDx]I2l(p:U->8/_Ay+?WUT?ot7\\JgrPENq1{AOOpVWGtV4_ICNW[r2ie,J:lAc8GVXKIqWfXKGZUX?P^kJ0z6M:XJ4Q>_]5clppyh^E^TT=g59PT+gZ5dKRw<u_LeM9q4(LM<-<mo]Z_Y2TsX=5)4OEcK9c8DGCSjIS}>K8nK6SSa+8^k32E06DzkVLB\\TDpBh`xH9UB=F9?d2;=6e=@/K)Im>i>iklE?29sbzK+4R`QfTNsfVy/M1yA^|:M.2RujM@F;0M\\)qmfFAb_Z1/If\\:ae6YBIvB=UOFM15}+*RTBkxw?8wflX2{2L*gZKl3f@(/yOL-{wp])2o0q4{(pF4EM/;RUA{A?jN*0TdtXoS?91Tv]<QsW<M-C?7*01TJs3gXA{b0?Bm=6<+Yhl_>.lP45uY}<UQ@YKeJY4=331(xqkL^3Xf<3p47@O*0KGesjQ(\\Y8f4?Ho0JY@Jj:?kSKv.=U3Ud]gJcnT75G3O7(shjYuReX5ZGOH:2BV.}\\^+_=M1@Y{FJC]T?VVMKT2>f\\gNg-99ukcyX:k<)?pl2Q[}fP7e.6?P+@AH9yW\\kNSURx5D=7SNJRkj5OC=f\\^kj6fX_.x\\?^ZPG3]UB(LwIq(j9:y;M8G:Zq0d5].ch/7mg.6a]Cy7G[f`Z9N2W:}u9jK.c\\.^]^fJ2Fn?ka/P8RjF02v7iy-@fVZWUgCDBg*8I?]X5W`I+TXz8U.qXmVMTX<m)UmRDJ\\[aCFT,AhAq0:v4\\C67j72?ggY^J,|4kbH>]cQ?T:[G8N}>qDGkkrB]hR[p1sn@PERCi<o5E?S8:0kr4eAMW8V\\)^mzYX*xR6H}|/ygXeT\\D[-4E.e>7V7VMqi>|NR2Xp/688aHXtFhCI?j7[MX+Ps`aCM+7Dz>/E9E5q01*mvMyFR@5F5dJ+S{Hc@`PaFMM@U_5ALCxB[1<<\\MoBH=t([>;|=SoG:rM9u>3SiALZbUQW?fNXc7;jU[g7IN/gN9]o6]M`.Qh7Po?{)aBVT0TOzYN9i7`PUOlb8n(Rd3@dsnI3veLdS3_(A?QrsDDRmMH/c\\7ghZ9{F^vaNlfKlE3+]@b}FnPF8{jUP?;``1=?uI9qxVk>Tr{Doi+h_A.jXUX]j)*`E>dQ)GnM8uHs]oGCY82/4|y=0mU52(k);xDO[:z]@RVD}4EUVK(Q5x[x*V:;9D==jwTy8<3fh2;ZH7?-8I;{k6Bl3bOhEfu4U3=q,=V0t5xzV>tFGYT4iG`0Z_,a>OpnPd9JIGTzUdVZ.sX5V4.p5PGFB3L4G08^;`W]q`][NEc(E={;DLU:5A{ru{Oj,c8;HQ?Wk^b:)OB9Gf;47-ul6UM>OhMvSO.hASdlKkhV{/3_ja4QQRFI9-QpFqHDkRdg}w}(LJpeEgLV9RMAhjt,:nM}:l7mJ)3[3wm@5TSF0N7B+.diS5YGfy3x9yo@UjS_iTKJv0TT3TBb<Gy<({6o8;73Q0dk0T}]]64*,O0h;S{qQ7(ZQTXkGZItH*4Ngh:31cW>aI_C=Yc;^45:|`=h5j6f9}DE:n[LGs-6yHF<ZilF\\DCUA?k]@K<EVG5?bNuAH5lpR+4ui{x|xoX^T7;umVJ0c3RcK6v>^W5JstuQD:RU;]/SIhPAC<g(=i.34GN9n0Q0hWz:u|waw2DI0<*9aA_wECISl^qY|d_?G0eic:y9:D{uUT*YIz(FB17at,WBI2l<Zm:v=m2-Ub5LHh9P-E7hiDL1OUJ=U4MI|8xjEOCVkSP?BY2LIAZUPH8]=eM4_=9IltCsQDtM9`1jJx?B)QHRjGl=l_Il|5hcI5n{2HkXTc89p919>3iRXFNm6StQH\\o}](oNvs]iZ}p+M58Gsp=Au73@j=(1`/o:h6l1VBJ^4XsYeSwd22:zNK/Xf;4bsVIIT:I0=-\\1O]3S_,e9sgeI7T>WR2M[00+qMG}ItA>>IgFAw=1}`arvFz@nHQ8TOa0Ab\\IK0pEJ}>89S/J0:{1-A^@B|X^>vF7SDyM|,i5bA\\-aU}Q9]ua0KEKWD/1P3=q+i)HGZ6`g\\k;j2<h>xc]PJqEVo){B.?{<:X*Z/B=^4FB}J{wqjJ_DXS:.`x\\L?_Xf0mB7fOO[(ceB*FPvp|13@9<H0M=52TK_@L\\{9ft/[9Wr5nXJhz6bE[5)hZcoMXqKUvHXI/c8.T.9b7ZQ2AsWT]wmN@,3E=6@V2}8KO@46*6Eyh6|z5Pg4bR.s_dbHLzkX<41=_w+[cYTCO?:PK2ik:GI8vj5BsjOZ]6^gZeYWsC2,0|X3g>rVA{Kww3Yf]a00_>?u_<:uB9fa5do/K>cOMwYu:<00q9)32-:bRC^Rgt^8OZY9GIU`90x4Y7p;eR[/i}@QYC8Jka_9oVL{]v8CAMyz3t_O;<5aiW1xCzd??obnI,?FIQP*}QJ]is3tHeK{RW2`U5t7toQy7H3*fjTw>P?i6lQ)Ne<4Fwfi>HVgs=V8dbDpI-jH}SRbk,K.I8xPArorJs02Ff]1IaFfA8aEQD4FQo2H/^:c41q9xfM2{j2@l,[wE`l^Jlc]R`UsMMC*;CfVOTRAA[IGO=GPXjF89]uII8W1=U<gC@J;dj^C_6^}MFG-BFijORM;_ZZl}\\^C?x6-@]<5BJwM4O>0U)G6ELm8,s=01Khy=y9NzD13FugvEb?ji6H]Jk_Mme\\ar^u3D602617HHO>l1jQIaA123LC,fIOB[c86@Y\\i@?^EY7K2Cc`(G@iT}hLqGXBwJ=8^B3,NN[cOQ-X_;Cw>1?2_2oUFiGNiB>@2jQ],*HxGssm7WrMRD9::3tC^5\\4V{K{Lb@q}|[@o?/?^BHQ[)BM80Y6^\\:6MsS2K>@Y{=9Z1iO:f9=HJFM:e]mzvQrnizL\\tvo-501E7O{r^zcvGL=2(q?wD;kd24Q{J^m[7JHo?vi)v:ehVen]3=J>)\\>k@K_He-CwN3V8|B>{W}8WTZY\\moL9V\\]H>yJ7?`Z=3[YE6v,`s[O:[M.@n=O7RHC_VVRcoAIr88A.)66cYG4q}QQ@zd\\M@qRO`Fz]7LTSsWul)@*QgQG0H8Q1;EwH0H/MHBExk90F@Uo0a@Qs42hJ,31g9H7zUCB0a_IAMl\\GJ>CE[7:hZM5Y-L@D2Xg0\\t/P:mM>\\`zt@\\=zbY-1IQZ`>5:(v6zW{:y,O1j<F5KZ^pe3Re3XR^pB=3S-u;Uip1xwM|X\\MtSv:)S8]GYao@nQ;n^6bFT?;w><MIDS\\1hd0>/>i=WR\\H4P1nJ:EqE1Phi,PzLP0\\OqT6dg<7@Vy=9K[4Wq4`A96iRRYT]=DSC\\WlFB|R:X,4Qqykr8G42I:Z.>J2F8g9pA9m5PR2[Lai+PDj:*|j:)8Dw?4E-,`R1hHmKh0Z_.Nulq]688VP7H:9KPH>e@YWvGFBP7503iM<0lV_+B,FN7.b>E/^o[J=BkmIa/YZI|(Q)X,`gXh18?i7|I7{NM.wQoC)_0WU_I>^QBz.IA)i8u}9}5aTT7Fbzh.^CWM2IQl]KjCqo70j@Jv{;fGK8LFf`h@gh,6H;*7@A9DGPS11aPHIT,iiLkc4,F1{WXi(WGQ{+>fh-O+dRJ7a/K{h6kJN/2U8IFHKOp])8KQOW)`bRQC3i;LVu4A`y9\\FeV[B:olaCGF;>csW;r3|lJ(2lHTaJ(NO254;Kv[A9Od5@AWpak@Ikr\\e2Sr|B0>Q4xHS9.?yo.@XE1DVgeWDFOc,]s]FKZGg24n3fG?8@e5vi+`lgv^2{97S5_)T5+zqgX8\\FLKR^}e2Uc@3MG5::WF-8T\\W(`J8DLmv:Qie^T@_0Cp4,L8}-w/H8)exb>RKs<776R-4:3CXTcRs)(Xv>*=:w4;|(GTL<14^ZLgMt64JE+F[v,`dov5<p7=af}3M}OJ{COkp`Si6qn)VY.:3\\aYFv9H(>g+9B;ykz4cLlMKyc*}gS]m8eBXOkYglkoD.Zojn_?g;m;,MMG`Aj7c0E@UCs51.anTF4==}rS5sU{M6gCm?C<]0`xe9P^fjni5H7dH4Z;jdP8tQ]i3;p@Ka_TK;5OfD`?.IXa8Z)F2>}h4X?jOhORd.Ux3Uf8Rpn;-u*27L`FXel9=VjcfIBy<us[P>N3^_NuyTFmdo>@T[fImhVvwV2BB)+>V|1IbV3tRPvs-B]eP:?H;f?u,rwpJJ/@){YgLo8eo69s2heH4BqTOdFnQJ]>@(v2d69ImzMCMbu6Eufk3N=M?n\\;AKQ.t==Mrf1MXL26NBz*dMuf^PGn.F9:XT:5y:BV9__)K<8gjc486<7Eq0z@qreL<=A0iSmMUS)z<s47q|OBvYn3?i]udo^3;+;6g`)cwu4OJIJQLbPI[=2=DyjB_4LE8TJ(Vby,.S0o?Ku@@5APwh(CVcPm>E^SE<E3j??87uMS:<hXW|}o;Oj1cm^VL@B<hPT[U*J7{nEFrJLL8JSq6<64aGB*nW|?^Y]]0)C}4\\i|4;5:qI+EL;s)Dn){=gIeQ}B@O_R,K8M0k7JjmG:WA0QyJX8OOxMq:4Sdd)CtM385(J@HYs\\F\\Bo^G3;Cns^YH><2G<F(C>Io5\\HE_dnlnPYIZ2;r:AbrhXZD+kLPU9Q23PptIvZQp<;{vcEjd^VABtY?7Jj]cAG|I},[th41iAT>}8q?4`F?LgYfuU1>TRl-IkPofqU.s:|,z^q.SB9hUlG8`UNGx4}ZjxcEEi(dx=4Y(jQ)and-2uchP-w0dN_Vx+Ae=2]2^1NChXJN(Is-KX>;j(/8m)EiKR2691SmQ-E:nE6t=UKcK2,0,7m:|Hz|Pf9sj_?oX1-UUHBP+Vv7Ma*-^M|-XDT9S>Tqi6e7)5*ktGb)SiblR^iC3\\miBDCsoE6=<yq5[WIEYu}E`Q_7xYeRZ]E}(kGlWARIt`]8vtME5V@R45Y@\\Nlnd,Q8M<52V2OwQ3Wc><Nf`8zN|hN?hf3E(Gygps=l^_d3O_YE5_}uyQ3O{^]_PPC8R]]T?tI//T9V\\i/4|I)-h:6\\IdZAZ1|p5NH8BCT15@>0:rAnRgTA;DUJ9k3[+6_kNhvdKZ{:;(M1p83-At;;bl)(O|u[s(vw8EQXlI|6:F]hqu4}[8H5\\K65XD/;uG4-AcUH]5YNzP1\\Y`tgF\\jVo8DuRdz:U;1_H</UcWZ[LD9b)2:fQ<8OHwd?Si;[1l^+t719IUV2N{f]9Y`@}oLD2S5Z<bBCW@ei8O7TWTsATrS:O12v-{Mj8(DS2D]S@eQ^^FrQ^dSL0tm2pS^MPWY60MSt\\H9SW42plK]y,1;LT0943=br3ER^;@2?EDF^I:ITo(DnL>@Z78kGmRD;47Y?<JOLL(wXo>lqWS*3GPM:72s*Wr)QE>V0jzP:?ga\\8b:9RWAH[sUC0/Sy4gF1M5K4}K47CctWbR>ZSePU]h;E;\\s14P?5O]zlCiP<kF*Ay\\Cu_tEADR3BdPk0;hm@|0Q/F?Jkc5REBg,D3GH8bZq0:Wp@[4;KTw*.cCaL46n<AQOKe*8g.gO`Q:,{y-rID^_-rbUCJ3D`8mXhW]`E\\bmSkRDaT9Ij\\4KhD(E.sbL>P3BKYDpSL476KV\\>1ysBKyb.}i5G7dre{\\WBjLen:e0GFUrtFgPIT[Ne4jc|^E5R{35YW/xab(9|>vo0O4Zi8ITm]GM78_N8s6sfBV\\B}N}Q<[mQ82FFsuya<P2:uF4BI<Am9^D8O.eE1CwrRXO6}Q67Yj3KZl.{r8B/g>6=28J2;pA5jtgGEQJ|rSDi@?y+d6aKR4<.G`k@1U_2R.RAvSa0^TS4:<>GBT4OX*LUR]0yAEEnXj88:SOwclM<aNmT9V0F@1eWLHtHiU-=_3jAShn3[[[?:]UYs53A=2D?+_Iv}P:e8_kV3tYa_S<ZAA]Vd(_?FX81Q-)V4LdR?)OweCI42gF-,^[rQfM3OTSyK(<.C6GQN9?Oe{\\N?Xd.VUwqDY2kT_=swhT5EB[/?`0Y4,s33?3(\\G<61_q?@{LG[,]n_p*Or:5bMYNE4pN{=8J<k_B(`>)F-3aoF46e7W:MU_53P>8|,VJR1xskBdEy_0byAtorFSn:4tI@o{acLFi);`x0jVx8;z:B(Ilm_0U;>L3nQI4|BH3FL[d5YNFPE[4S*;ZDVArQ5?hVdEa193@Xk8K.;YE<C>ovHC1ttA5MpW3h4Ceax4;W;d502>@0=BC5`_0TtXwxW;tmT[H(n-AkPe7K4o@KDykuNUzi4fcc`S<EHz>YXZJIUY>zIaEhAAyh`U7P-NBGz7mD<`{[0>q+_qX2HnW:@;<hMMlS3RIn,ggd*l+3Q<OCJpEhG,YFg+1IpR8;CuF\\g4=24j9K4DC+=1z2Mot8IYd<{(EK<x@8qIDDvjFfc<aCg2\\f^m:URJ8p4bj^as7rFmsePY@jL:_VK;vM_7:k0dUDnup-M>ZC6@;7GMa+8d;>{g^G/?7\\K?^_:PgPX0CI|Az9+HlO46zVW0Qo:{>DPia)dh-msE0bZPAA8`;|QoXr4M3@;jf5Y5O4+}YId}]g\\]y]^8{o>sA7@S=f+{CV.,(rA;i33@@@5aH1Fn?fZMdiV=VW/V>dAEih4>uxk0;W7e[64LEBYhEd;=O?;<A@ZlNLKl8FJ`^05R-L>c1q)]auQ3]H(n2J[O@\\1D:^XGFBffAr)0kc9jbSwV@Q)WA=z45bFNorWLP|1I15F^xwwPn2flS0;CF@7kQX)y@^vixcOjp]s<-uM/v\\2cfm:;nMu6IvZ2GJ892N?5o3X)P0;HFhQOWoaLLUC.u>v.^0HLcF^f;ni8ju7tLa3-;FMKQiwFn(=f6Vm3^hE4)EC6NS<f9\\AeI*]Uc^RB5Y+2LupB<rAKhB;*AbX3|j=;131M52aB^wO1K\\[-L1A+?B;`W3LJA;Z^]]Qqd69LKoKV6B`0L5q;2e8KmmQgB390ph@K7C7>wFljPu}YxGg{{x0`9k>mH:WTu8wI|*dfWKs_Po>BPDfB;?{F]6p^DIwpDG?QScPmMXS8/J5K-{PVZYMMXXo[{IA1Jgub7A8SO}(mAB+;c^ODH6:Agy=p^ZURddXX>P\\cx_D^iCpFB[VjKdUDB>b^gR2d5gcc+d)YECtf1*x903672i3W1S39XXt2I4b[Qi;2)PuWWOn*pG}vj?;-4RStjsEuZEg[HY^d/P.@m_136Lzam2\\Fj^uK{-oq<</j*aPSkFs>OKwCgp:S}WVmFv*R^rP-5C]n7i2*/0uYMFmTjj_nC|,iMCE0BZ|KSGXIG__JGZ1M}kUai^]hw{>M3Ro2VN9Y2JB,lj?0Kx*X5F},0Vh,)H3|;tG2mIEWo{U]0x6mB|;[h).?4=Spm4RxrIrqLaP]@Es2P|d1Hah+2ZA>NEaHW_g[Bb0)Mj8.zlUq;.JYZqOoQzXB}UK:B-Jv86.0g*={E*u/fu=aKMi]x}S6OfsO4n;B.9ZCNm9`B0G0gXaV2M|w^1pmxow:_=bN0QJFctV:g^ce@gRYsR4>H}Dsqj7@5`i9kuZBO9vJ==)Yu4Ul2Ww_CaAo4|Mj<r{<_S(DU}=i3Y{:Uw[cv0YO3PP1]0@8*Kw.<{3B7]{qB`.\\BZ>g(HfBaVgMr4I,:;bLhv<XN[}[O8:CUU<yt8D>[T2Q*9-(-jGRB}LxnDzHg>LWEJg3]HZ:M;`Qj9q\\kcgcRNGP9im}RgEwU9w@@ct0A[4l2T_wT:=Jv`5(?=(Sz46KRY;CP8NDp9jZRX;zO>6xt]0RrfcCYCDx37t3/UrS6D?(cE(x\\f?0f{aHxY]5AvqXaOf8=/mcGIl}t5*F,9/TVAEU3]NopKT1N{65R7I,[EfU=OgO:m.`a2/DB.k2`ED`hAj51Il^d7A0@ovWa0T[aM[SIdTnl=1i\\5`a/>pU/bvMZWIcQNG|*`Jj>i{]S4\\9pRW8<p}`_:Z\\Gt;s*;.Efmeb.xpV@5s_;x?q_PfwFm+M_YBZd0LBG<EO5Hkj+)XUHj@5Q;v5O??D]*F@K0tgmOOIB6tK23|w-<bU_i:I+tRZ^\\pLgSD`9v5Q^qO|@_}+<dEKDDkL[VFM)VXP@Q@=XO|VjZY/j_-3\\lYd<NrqO3fR9,wt;ZAWEu;ECkc;ka;Smc7R4q>L]KfL1CC^pwcsPJ17j}b/8N4Os`V4IS7V?pA97Yd78`f;DsO7I48qu`F:1LXK4a4PUa/zf3=:86S-{8*yXV}?u8,IXubsDAr8PZJj42|K5Nj7OmfS1KwoNoXNvLWYARZb\\klQKSYUYSSuXS,48=0G4ZT_n.e8l0S*0f1QceRAfUp|\\pDX+d2T9nh=<bx63gaqbAMi-GnXAO2S1<V?}<E79QZ3([;)A(]khuqCFsnJbuZXT@cLy0Q-VY@7lln2ZF.mWc@qjs8*]DuJeRo(9SJ3>a(@a8C15)43;SfEYS6Q47M@^d5Qn_KF9ID^w72?3g8iJ2hz*fx>1F;Es)<5sY?<+L>X`rIYn[vgdHQQMVmPsx83Nx+5pE]CR_QL+M5cBm{G;{TWls(r]LU`O6<8{mVZ{]rO654@={2_QZZ?@M>LzlM=FS1M54O=sEFzPM;fxdny<fQuY5TkxRC2uV:2hQ(dm<Y[]aWdan\\[nXPY}|XP]/V)=4(GFFnyjGmFG[0oA0628Y+8a>P:KU/8flX};C>3*)R{9wEWhY@l64v|TdvS02J9OhYo645467=(YqD5E_mCKH<In`tVY8).DRP]oFRRPMO==PeIU.Srk0B=7vX7TV^EMj;zb4<hBjo-Q>73SkW3R<j(D\\VDRYK1k8Y\\a\\x{U17^a@|FlBBlhBD@_CS}h)rUELSOr5UX<FwCW7)\\(0=9lO_rnb__B__UnWI?Mgb\\62QMJr2\\UAwbBS8BQQe?=gQ?29eT3XiJ@A/CmEV:vZI:Uhzw\\@POhWvU[[mT4=F6D<4gl_qJ|?BuP98D4xG3B}rVD7FUZlEzFzk:b{K1.ZUlcYn^CJuy@m-jv`NT6@KPlQQ*i19RwH`z1Vy<w3[Zy8`5eJ^L]se2N0016s*I+f;d5IU.SgEkS0RGeuQJ,kW_txDB0cJm86jyFp7ZCyPMueSwDM7<1XvO>RF]4Z{q_[5iZ8G?92=Q(\\V|F4x{lJ2xHfr2ahE5C|cJz2bwLU{K5}SwULv`/(CeyA\\@93\\]4ULyF4uqwj\\_5oE^HTwz>F-x0SGU/T=OnR^RyUR_10Fx73|S`E8kd3wd@_h|O><5kMTO[b;dE{h[ar6TLa*7{q{r[-@:pe1C6>2|p]VZCONWs}575P^_;JPO=e)<6F6V<mO:=AMMQd374Y^_fB4=7]YuvE0?_Bpvkc1{Sp78aR/JM0cZP?ZH1{u\\BdP+u7SjS3=7@{a|Nv?yvmm[H8sQJ@4m2)LUFwmc_9o^a7iFW[8;\\\\4aHYJ3olK<MRH5Ya}@j3{Es)\\WIaRGi7cuNK18W9_7:{N<31Gb*3k_fvD.]O<MV0PBa4B`-_@Ou?hEAR9@?3Dv*QPIDbAQ(_8J(uACK94r4J]YY7+1ha>OIJ3@{E2t@Nqh+:Ug>[=n?|lG}W>4<lz-?=CFiO/LFh>\\-[o8XJNXxfed*2oEOFg9ul7(6GchNuEfKYxAbCX<7y8*1/DkCp0?uXftT.1ucb3R*jIWD^Z=1NOd^@ZOP<TCbwm<3OGX-Nk1c0_4O(xYRG=+QaGEDQww]eXI,9IX80Dy;Fud3Sy3@n7@vDL_dT.v0>ol<AQwyS?kMgOd@Nli)zP;2a6^Jo6sgBA>.ROZhti|;BpH8Mb2mWkIn;EoqIoc9a+kcLAN1<}8q0i?\\Nlx<Fnm=/US?N`yK{dU;409Mt@Zr@DkVcMCp>n`_Yc;Q2dcIoT\\L_CUHMK58DVefbt/Uai.*nbZV8S7<q\\[HErgBaaoSTJr`0UC3i{6cY6)=r(mbpTKOr1IWj2=[uAj:1oV=7,1ptGOP>^(:Eg8ODvFSS98seCZh5\\GB;UrMI-Lx=kd9B_310VJN+m^)hC:+A0A93BS{_;M0RPCvM9V;ARw3j{=o[AQ^q]L0??Z;d}^S?L4OFml:Pv3`6,_W{[<HR0{Rx\\?r}<MyP;AbH?i]=s[oAPA`yL]3OF21jo1GPl:*{Dht+0CT54@0C<Kaz3ZwF,A*\\NI^Cq:^:R5)K6AX27MrK,H2)l34YWN,N=W6Dc5tqaPe:n9EFD*CJssCu`.?2:,CIrO<.Q@7266x2b?qbR1K}Xlfd^7r_B{>=kE7Yf>;NhDCL3DN[y8+QhA2|aJW4<3akv5GT*{2[[oFOOIvG3kCnS?j3p3*2+a[Of\\dOChf7O+V:5;U\\Jw2zY7Ys-bSbyC,`3I9qO5e4Io2uE@HWEw:LX<Y[Y;ZzfueF`<w[:v>lY1q)UY=?Nz,:=xIJMq[V6_z}|6OJ_*32D{x?u}zcU6ait=m]SBwH{>]Q`5dWSgo@]tWF6I<t+haxgn`k_onH,?92(AJ,KRlq2J;@KXeI4/{B{0s?;mYq-odM<E-ZOHw>yE_6ZZHFEFy1KLSQyrWPQ}M|RF/@wM?>AhR]@7c-X|f25,=>h9gwFO6e-mZ6C_sGN1U2^IOZaF0T==J/`V0GMIUTI1oXaA2fXIfMHG_b7:5x.RL>*OxD@<iKtl)7Uocvf1]]uv[6u|\\aR8:*2B2s}VhmhPtU=nXkRdJv-^RN?X*iv],hL[o?O4NU..0>nFJKxAh<P35W`q[E0DL3V30m[N=2Yq5^v>Fsq31dpS:gJT.rb8dD+7AE=a*]@mwf|=qtZ6*>G4OYS@ZAs@6_}l2SV6bfa+KH*-<43Dc8m+==Lhvazu5?Dw0B^OCJh8F<Bynl*^wM2al`80nh6u0saSE*NoGAPT5:i7DmnSSeSQ5D5S*D1W;xv5I/XHWbOj1jM=k(6nI6e4i*Lr)XVitYf4fOr8y8,hF{ON(kUK9D*qH-s)7U6uWMg/3}BzlOL1N)BhkJDHjvmR=,Pm[8lbr\\HjCXByC0ogXEgL7\\l>t6k/S5DT7/IS<eo.<(Wqa6IHl>Yd@wNKoy76orG9F{uTC;DlAMV}vaHP;O{>35O6@^HFRJCugwWdJMdiZb0-rp-hM?X9*Z?G3vMKm@fz_Hze74hss@Cc]Vc[])g^@6E2b]\\l\\3H,v78TppMo>.(TQzXXb)E]VU);gAGnj]N;isV[0c5K^9E6\\yhCBVG8bncHOF89?k19C(@pZ;NYyD6.2pL-sSci@un@,L_m@HS,PB(Q\\5C]vHF*EMHBY3*|9}V;IPn\\qfb3wb1Iy-YIT5Q-_i8UQmda.ALC]MD6<0?WSh.g1pR;fE>.`2{KN-t@g{]X;20ilu>1me=uz-G:3jXWoaUN/1Wo`8fq:LCrEfkM:xR4+)iGOPUZUS=,jEbZ)zF+rL=3geo_Tp/xlLUkS[5Q+bEfv[bZ^*XCn)X7rGzW\\X1Z[:iz<NzQ:,?fMA64P`zO9M\\*2bPC^*Fc18Y5Aeu/D\\D==2Q=6|B-,<Q^D?pH3Bf^\\?3GZ]2y1nQNS>f3m)`e<fYn>;}3F([]jXM8]6gM=K<kpqG2u9eG13v5@C8tun}Rr:^Y}?cou^3`GRDaY4FE\\IyL3p_0Y3*HLNM2ZAYu{O8wuw)ACB(@,gMRkd^F[mO@c`)tQN,A6?ZIn;Z9NUt\\a2K+oA>y0l_t,W34TciOj/FP7ZvjJ]2dqYrhcj8UGP3qGUZr}3G(2cIX_eD}izuC2IGO(9P@\\3((d8StKyN:.I|ER6GLOX|US{V8s5+W6DIEQM<WL/g1+4K\\SM[46/K.SkETH?z4mV3KsJ3Wam@0I<tc=e*5QDoo;Q1hGiGjWRK^]M,1s/X\\]7V@\\oUtKbd`IaNf?:?=>qr=qUW^{CaU0Lk3JTm)^BdZBm8ghxOEyKa<A*LLH0JLp;q;=}:JWoM4tj0CJ`ubfkqRK3])h4]H[JQ(D?Y(Ip{+h@rmr7bbS<FJC=Xi?7BAcJeG:c40NB6g3R276TnwFK?D[}MLAil<2YcN`NO{1;0>-zwtDD8Ai_gdFdz+_8=6AwI;^YVUe.GgA<>q[CNJxFXXlr@AEyoM8EoUaG)07h`>[ww*{[aq8]H\\DW<T|IzE=dc@EfAEUFc5A;TD8gUZF|aGWa_\\|c{jaYS\\M.5nJ{UN(?Ts-i>*Ny:C8Z`fUHOZ[W)x>811Az?Um|pYax:f9{5Sv(d=Ck_e]a6UX\\3Io3r8>fIy5B1(FvA?GFJ.F<5?M3L-2W7\\l^T(n|ZO{fNdIDLk01b<J1@\\hA_3aO1D2oxKdihBPM>][o3()ta6um\\4oSx}ykZj\\MFkQhZ]sM3WQI-2qr^\\@s.Qcfqko2c]cF?k\\}cWc;Hp7.>If|f8/\\N2)S?pT:{\\e8Yr6Ebv(*lSbQ(pck?Z?1F]o/cl+b1u0VX}|O`10]4dCWr9|,1FpsBNjmywTrF,<h7:5<Uz*toT}*6x@{U9w5dINdE7SEuWH1*N)9(NSO8@Rxg3=R^3b@St]7jyFWE`|8-O8QeT5G7L`]U?3K)MH2|T:K5m1dl*u_w-a8:R6IcBCBp)9GI_m.NKNC7>i6LN`.U:@[R{:cWM`^X8N<v6Kg0Q<@2v}/7MxgUs=2tn?*2qUJ1d-v\\6TN[rRSG@2x?`r^tnavCnd@2vKiJEUBiHfe>kuH{J9kBov3S>:8WF22b+UNKtKx{8cPiMQDpXK4SKY62h2/]vqE)D?aT03DjuxI.7Q0Zrb[+|A)eQ1tF4O0o1Z=eRkA04G>m-n:}07WUWtvR8[0FO.an=PS8AM09^FQWP+p\\QX>N0EM?<P5LF<A>?[\\<aciIAJN6n5=t`e:TK7MGpWWDb(IH`JTZg6KmE/Dj|oZRYe4;44L^oOkYtj:Uk9q;1KT?9Ir0Xe\\nMg8D_u.?\\@UqV=w,h0I_4=|A@`A*LeQ8Zv1AJ0{4pjy@n9:}H<Cs>5}uwEP=04FypPGS@F=`}unxCC@C)W5?_Paz)2I{N:o:|6M+WAHzNNPMXEt?o9*y]Ys*`wR6GuO-^A<q>)v|EzltSPm,B@^KE+[j=k=fl.OPY[[aS9[(OXn,dhVxFpBP4>mH6_uRr6+:D,nR>7z>{sfMJ00z\\{?(A=R4d[OG?[?4+-aoB.H-zO13}2=h{SU(0|ix8[YFEKKRT`z)L3\\5;dx;NHS_xW93g|;DV]+E[05iFaMws1}UHS>\\ZS4;[hkkBlv5xQu0ZOkfe+IO\\G>=KRz[7(OWE>?U/0:A:E}F(S@vp|6qa@9>b6\\v3^bGc>l]bUOL3diRA[J/hPs)uXH|dm@Gr3[eT7d7at6Bk058OSL8lA|LE>0FJD_VTb=5uj1LR9{[9oWtLkfkJ5`b607y)?VqS4BBV5{W:672jJ|E:d@>kuGS[8Q9PNM8|Lo@X>BcWB6;ESLjkgG3lF,fSFL<;.T=L?nD:{Px0saE6,L^m*3)F,;@6.2S>UFYURQ^B265-IHMY[95<iWHDD4:]A9j5FtBO:/33OTd67Q3ull,2s\\oi_`.(nAA\\J5|<trCj.O5v3?RO4ZL-W/guGN5s^FO?NFEc\\8Vv?VO,zUTTX>6NE6t@i)0JGPf}+840g<0Adq`82yZW*y)*:8I763DX66)8FZ;9itJ^G,Kl8sXU=Y47yFt>>oGH|@7\\tRi;yz<4:@Td8L0e=^CRYWA)3f1cfOIg0HGEFRn-0Ve_;)pSv:CW@7@7_`eO_RtZ]T8/PdpQ8(+t.g@b{=^NZl^UMpdd}CS-,bjj`rq68}s[<5?.=GA>b.o59Fn*Nw:fh@ZCRdQB6J|8KsTqh[:i^\\VT:4_g3Md9EXGmYaBeljh=jJ7T\\XDf+WT*1MD?b;:vwO0[<GGz6ckxEL)B.<jNx9.M]t9yzeLNuuh6@(A{R3nb}UXvJ2H271jr@,\\lr7Lf@THg)wz=?53M@80@Q{)mB5hBc1]^bZ])h<=i5Fr80h^\\VeGExDe4U`MrLR[1RjBMIWQ4:]i_zE{__.TZ,O21RA]PvgH7K24z5^7^[7a`{b{RI4F-z<sZbJ,?QU:H4c+=Y;<ikihtMVId)CT}Gqns9OJ62]{N1L3:fbKAfELgy9cW\\X8}a`HDIS1XL}1o\\KIC?;;w>qP}/mLNBdeW(*51\\FK7I)Wbl_9c`Rikg5Y\\vV+5)(zAwfUBd1JK9Q><VI\\@G03ZN3iE7?FL8mvT93lK<Xi[1;EHK0H+0(E4oSG94@1<qA8HkqUtzLMrTWxcmxf4QKQcPXM@AI+v6o02<|c}76`c7Q8Yu:meLN@1-=E]3,6u]h>5?rDH.@5q?\\qQn7?fMu7k}E3r@05UYDbn=G_TG>]xSKG<>94,6^pKr=^>:keeT6T73`Cjt?+jLlRkeCN}CH]viu32>N[FCtm(5d:d6rXB>9Y32f.I;;{P}sCd+WG0\\CQYS@M,([>xTO;cYyFqnt_AmG;3M@F94][VA`AX3Khx;c.Kb]TLp?@.]HYVYPG)24fN,>}fHHEhg];CYFE51Rw|>MCO<)6Eo<V0AYxu5oujgC]OOvVSz`{y}x.DF^vzRJvg;tzp]7G?+g\\@fsM;?@:wJ0qf9v>El\\D^AQ6QObM[ey9o:/SVDrHF`83.`msj94BVo=XC9]hIWPk8Hb3J3a`YE>j,i6(d2Ky{hb?+kLS:1Fb3^ZwlAWzc2ktIj0g9-9TmN]@WXPN?pSE+UI@=F3c0BD;h`0rY@Z20EvGFBHlkD5ZUiQ;CmM[lFF]E;n[:NwnkgXuuIM5>K*Vnq)|jzzLqDT>_}As7-N1Q>th-96YYB|Lo+S1NJ7vN5R_S}_DT4e@hEs7N/XYLkBgoc3I_j<qI6M+.y9CR>0XI6<OJw+}U7e8d@XLAd)t6OBFLZT7(4VNyANy{MM*X,vbJ8sSs1-dE(B=?hZ^irkJC/d2(@^\\4-[uKLxZY,VeBAU<H=l8i0}01?JpP8UsD@yMx^pUz(DLXjoTxFUrGhD*{KmQFmw.O>52C2Q(rfHOoMiE@d6S{SC9?1t`Jt5w-5uE\\jAlH6]xQTs8{:>L{O8@3{O[1X[8MYxz7<cIAFjf>\\Lnr/FX8k*H1-<WeELVFcV>*uS=rCrk)3ieZSD}8*`rWcit3B69dM26,)8IZ?tB=HbqGyFu:V,T8Rp9W;-0W1F356L@NY-+|[5P>UD]I{?C0|X*HfQ1h[6ShLVNU2>9`5@}=3sH|Vj)6_F=Ql5QQQBM-0OP7P3<0D]G=iP:w@]Kzs)1>bYLiUX64`o{KBW3@<c85P*N,9`PLyE?9dx7,Q[PuHpIMo)uS;HSAKiv7[|vJm]<eL4Q(u97+2VGA^nIHk}V4WdAn=;Yy_+Bx6`?4P2G4B3@5werwBsB6A,x93w)7ETH3.,cKI2njPpt;[CR2[B6orAX0oL5YzStd1{-M]JyM61IA73H@eVH7L.mRU0[jY2RrhX`<*Y/4n8{/lZIE:7.47b=bK]-[D/dC|/VIs4<6KhLJ;3T9_;:rSMx[AMFb`jp)EI^CgOI;jLRzcz47026TR1Lh]ycWg36pijTzd6LkpA=;UPcTUKyaI^`2S6{6GKE6KHE7`+8yDX3cn>xArAD<npom;YbQV<GZ]3g5rkj97NH+P/By71;AD:Mb+a]16;^5EUDIWcuTfFu`/G1G*1W3080o1+etLpaS]2OEM^kK{AbCuD/Mi7KHIB74?BpgClyi{t|nWQY{3^<=}(}09XO0:W8^u\\,(CV7zv57k:O?G-h3nXxkD33Q>_;Ckq1Bzd97iaYA`d<rb1]v1F8pI9z,C<cST?6;D`\\\\ASopcAEN*GHMH_^lwR(A.QsP?8h,S5F2_4TeCw2.1l9:d)<w]}]a992WXKhUtu8mlap}:<;c0V,3Pj=A?wA]2V(vJ,deNKg|C)1OkKzklqX,-vAFwAz0FVZ2-x?`RBFMLI6P6x{z^tOr=:g+sb8uH;0N>F3J1l,`5,}-}_gUD}p|fsE-niG7Y{R;Ys<q{1k06_v48B:]IeVWRdi/49)OJBP?fjKIM72nN6IAWNsw<1`k;lEH^P>X982U0x.]z>,t|Y1{=M|3?6vC8o(gFDY@<YKxAwT]BH8Bx86<42YChV];vd4Cs;W_yeHA8AjgbLr:m@yc9Gg2tJ:PvQhqDx/s?gEPeG5Suk[?[53Vd^oBQ?vel=LCN/^<f49>rq3]<G|K,_:]vMCL=<<D4PIE:ucd8F(*E2C^A60{ijeI2Q4Kq@epJJaI}WG|FM@?D{9vP0EAFw0KP4j>`(_kf59XWvd4sEx?gL_Z]^bePrZ{3kO8vMy9\\]8O0Rz?B?|l3PU6lC4g[-w>eT12\\Q^^TV`I)K71KO0,rN]ib9xK=XrV?GlIo1utbgKsAf<;e;P:<.=P=[0go<[jGr77?3i+7=lVCk]QyNJUZ]89>(leu{u2aLma:+Zq^OaEiZ,cpvUm,0=64>\\j8v+?\\sqxTaV;J-e>@4;ZRic(d_ekQ=AY9h26qWGu0O0*v_b0jF59P(Gez5Mm@54MB`?7_2?B9IX8b9`sjJ<]fFNb/|0,oFp>?=:X]aW1eK8)R1xkd6S:j\\RTsCfSHqLF77p`t1^r\\]vx9y}bC;D2(^g808OQEO0;2xX1ICA?z`?x/bQyBuaS<4ZxTTB1yco/y92y9900({_CjPf31Q+dftApI()|1RN793^fxj?xG[[4qv),-b3?VbM1Qhg|>TUabAe7NnO\\X0>H]SYxTF=pD|dM<2CN7hbCY9f;w]D]L|Gz:2Bhv_+h/r+2j4fm6?I0Ba1J04llJkr/d62(|6x{F;-FF9r;OlP`;J_>:`FJgmCgY4qpNIN15\\YOs?EQ@8AbKr;MY<)IKCu6N]iZ12OgWe{FkS<GqlbMfFROme`uaSXYEw.k.|Yj]={G\\H2KfD7e4R|{(3lF]9hULQi6B2\\KrQ/VDT:IAAz*gP-PHBhHl<tVUwNn-3Dh2B1kel+Y6w4`}z\\p>3>cIHUB>9.7;.LW3j[9X+a0zE[PMD`?QQK<MYY(Q`U`<J:<DvDEwI-y60(YuUGfP6TVJgf;MkW5e?Jf2E,E4X15|BsLHSkT=\\eZtxi1YB4P.ztFEX4(,/-tF44iKVLhSx40XnbrW[oea@oAdlU_];4(5QuM}aN4A6?i>euBd/s=6/Y6M(yD)XW>2M?8+L_29/*?R0jFdP\\_=C8}ux<SB5:3]bQB5r9hWB.Yxe*VHGT/@Fa80l+3ajg>4Qv>lhR`]51c*q4:t709>>pO1yCRC]v8Ee?1FBU*FS@:J?BWf*[94AP51|^_9j8k-z24]1<\\FGO:L*^<fB8RRSJpPO[91OWm,M,vqY/MIf]84qVm2A`0FdGc=bE,nuEae,71`hh7s8zK?,^A}?E1;i8:u^Q[fw?E]P2AXW+rjtt)EIoiIf0fq3n/JAJui|VA^vk59X7bHbf0KVV_JGx)wn-F/jm2@+v?nhtA}sV3Ac;;x<8rlJ}7o:CWU:Klg@2JUw9gO\\ZPD|H8>3;WBRFRRKgZ*cId:mNkE1y@:jc7;9)wD8zGNHEK6\\D^3=L<[|2)I29K=1BIGD\\g@GT35kVs9)D<bhupEPT`+}BP)`B^xBOC:])ZxEEmD{U0kSS7Z?_3PKSDVBa8CknV]bWV>N[<r*cp;Cf7b/wXVWXP:YY9_p)C]Vo?Evn6JRIMbS{[T|Y3q\\[K-RcXK8)dwCIjuD@Tdy^5ixjG7<D,?=L21zdMnL5SFqDkB2IXU8F0KJHXJEN=qX+g585XNOuq-OqKSM1i:+uH{kzY@=dg\\?GH5{2{CEgQ)C{>GE2+JCD`BP1L)6PMCjd1NEDFNT/_0^zJ5jY/T=}-ws9GM)?wyv1YnfQc0na^GYJ<NUif`5+i.PV-[i::6>ooRe94x2ABQVE10dElkV06an:xbdQEUN)D}bPjDuv]EN0Vtce<BCKke\\kToWgGr*_[>7*@P+AUD0LxLYejLbp.P\\K6I1aLWMv^EI*?oL}EYSS+L,IDS|_Sc:kL;E4@M+E77<\\1KmZG8o-6CF_U@FXpJx>?_QXVB\\g;R.`f0(dNpshCT5<9VFWm?J-2la4=HN.V8MrU)7I5FhoUa_^:8[ai4A5]]56JxDylzxVmQjB7@b?9`;f*jm>jQjL7aher6@tdx{<1e^lAK16Yn|fS<uhZcCH8jfC8}a@s?B(Jk^2N;^UIHG;fJ)9m5A;DpdcZqri_J^`js5llj@HFnys9KPMnqMF2N<LNHz6}6ZCdDJ|u6UK(yRi|`UEQbO>0`30rgEst5]eVOk4g9DBFO8,t.`e3=a+@EGq}*fH657xl_ZF1RrqEv|c4gC()4To<\\Q6rT49L]/BZSBr=JECEN/IMnq2Wfv.AC\\mE|n,:YMp*>i=rar=at6BWq2W|s:e@h:G5*;Dt7I:m\\MFCXs_<@A@bKg9>YVW.`BG]5*3+HmmEK[lU.Ym;@N3C8Zc\\Ed-m-i<p,BLfJZ`TDKp]R:J@/0,x2Th4]6n:>3jLG_ZgO|?6XtQfBAFGF/sHI@Q<2`=0Mc8o<O3>1+oX8dNIgn9_3(E;:f92w5BKEVv_Wz=k}:rlTR.S;RL9{KxGukN2KTQ6V6LQ2kg4f6B[VJFM5=FyE9E@g3H2xR?cK7Y`EYB[[Dz{+RY<-U*DCK:6sII*5=7C6Q:p?>)X2Kk-P7WNsV`,U1=7lfM=*i}aKVAjAip;zI8-X@V_/RMxe@HX-d6PE^*1klQZ4}_KX;5[uEPDOtO2RPGQRiu0:7+^E=|+1_SSB\\=WIIDGlr>ow^)pfI96fY7M\\FmSF7ZlLA39D:S6I2PN@U@a;8Zu3U6FnIMAKzJngYr>}:EvJ,}I2I-DL7oq3ho?rId_l=Hwm2ZQBt3N87*\\XGZKR69ZC3:B1[43>z23,CoD2cLzBrQL+A/;yJoY(dug)K2-Fyk7TN>fFZJW^L2b6hD<yX@Na:2T_ZA`H;FO]6,;uf-NOOVU7k}uEH7V*-;0HOMCJa6>(I-fL0^FrLW^K}HPW57QGfMzC64cECLR?OKTAG/mQL1FM409nr`b9loxph8ad_3RLOpxls>Ye?j]w>hl1TwXTr+VSp:+q7B<b4v.}7TbYSOV/6Y7hI@?>Ck6Z8vW5KeYu]70IfxkAuU8{aW_S.xWoJJ3Vsu]b<WHUgsHR31=sz-KIAuSSUQ[^XfE43pbA^6@q{Q9y>B6*PO^ujXE1r`Kwgh*xQB\\Jh.Asjl5s>TvULM-LtrepF`vczZ7R4.pwrDWNYi5CdmkFG8IW[YO=IZAM@X]18-D1FZ/i.Rb3@lIkVrVv`fG1=WZtrBQBW<M5@[Sa[]RgT8I[cmjx=1,B7h8V1d5DGzW4hs;1Fpt8KLM6oV\\:nWql}-KFi=x<P7/:5TQ233;C/R}zk{`7YxbmJ.xb5Vve;UA0/@]|l=MWgA?93lA0(:CuoQuj^nwuj;:L]WpM=.Dgoan4/Ki7LBdt@_.<`;Q(17G@P2\\P.zb(=:YaI>fK^[dWFd};=7RbOg[a4xBaKnwHjmGP^O|@T[Z>C*]rXA4<|,HN;XPT6mk\\[Jf);1vSG*B2RXfbF-v.BUvLJO1ZO@KYuOE(Unsw=Hx1SiY`[sFTcX)2YmzR^yG@:3fqO:(e;989.VvY2}J`ERQ8C|PurN\\1aNIyyiCwwGH(\\xX_LFyz+uYLJ>L>kE3g4IF\\YNJWEr6BA2E.*wrL9_g:@cOS*b?VcFJ:KBX^usJ=@1O_>[gTks)HcXi^_deuN.GhuPTGQK4TLm]5?@eEJUQ37:-w0kLt.QDIUv[o1I(/o/g:5[3Ju+XM6p:>*L>EK:43@Q<5[46XUWi[V)V<W3|ANI4[|HCgjK9D<ztzj4.4Hmn=unr^cSEDyi=HINw-H1mO65an<6>FqA2e?N=y8eN_jq<YfUEDWJQ|2:I8V9rOS?XE1T?pFV.kix_{-pY<B1?X6VzZF(Gk-JFY<7E@@l)`Bx99@1`d3Z\\PGP3\\2]rjY_T2\\*GH6g3U@^7oU\\r8nkI5<jz+@GT9xMHbGHD8P\\?;EOUl0D)C+dOR-<@zjhA9C.^0G[Y3:4t1:S[Qek0l0-}auVN8jgYcyl}(J99Gp3hB^mnQIpm(0>HsGBo0lPBtgT^n.VQP4LmHxr}ydWxwjm]Bnffcl6Q,EpU{b>7ZZk6@;N^eAL2ml;9R6-JO3+5@7s0`AMHVEduM?0@KCc6.r;+H6q=sTem3pA)a.;6r]DENNCI<2s:q263G96vF7rFaZ0(=k7GF|/8hWI7hSD,U.d^PKk7S+HaRKC0A2JO=Y7=yI<[1?j?AvGZ?K8oCh9Pax{=O6LQA8fP`tGt+XM]}[h34Y]Poyv)3F4C/5qr2N?d[<]>:\\CeZKjlA-@t6W*U]1FAMj51N4vuf2r;p>`7ccrl>qbKOqRt[4FFOK9`NLlNtK<*GQ6.?i>jN>wcU|ISwEr{Eml3*9Gafczv8fJ8zfirrBq:3XLHz=_i:UPXLmkMB`O5S>XM{\\HgT0HEMLC|gJ|_-u\\zLMB27MWWzWCIGmAb4Y4iBJIH<RS4o`>sz8SBGZFILV+Klj.7_qM){)Q;=CYyRKv4I(QVDX4[XPe>=cma1,e/k_=WZWEZYP3V)7w<}cYqeC.v_Fu;9:xl`zo+n6}?-^:`*jt^qbruuT(1[tF^_5a=;8[Rs@XA.UoruUD:JUKICKpp}+=ZNn]iEO|pS>x?VodHDBb28]7C4r)mSF}5AvW`JWy5P4Rp>T1,9P_SjRhFxz(=nB+)>dTslJ=|X}vq5x<I;U:4Z/86z:;M;C?=+{Z8RA9<TxyEX|t7R_4UQ0=V8wDYWTW,H_^(6MrG7O_sh[nG@zy=XlEDYFo\\B8m2wF\\nUdl-;a6n9G4JHapC,Q(ox[LPCxpdKw>H:+KhgT::D2GBIVl:^Om843]3T4>S>?nD:RR^wt[:.8w-9[M0+05GDJ<}@`UG6Zj}X68*jFSJw;?D:K8<f{?LQRXNAK6jq0*?S>?9KrVnF:zhY8A@rP*2\\GbKk_ymq)P6UArjg?Izl0m43tT[9Pf;B}GD_RYDXWQmK@I,k`WBlWJWF:Y7BSt8CGC@o=jGm2lSzk6WV,VYHzIcHlxQx_+Y,aQkyUbR90h^9FgACYJ6x3qR3?w,tv0,M\\QJ\\I3R0a=d>H>7Y[hX5v0pOij6X=6]I+j*E5T.lLN^*rc3^=rvK-9xJc<cL33_bi62fdR-7+}n7mCgt`5pY@MEa2P:fnI@8d{o9`JBIHOnXn_aX38[>1APx?K<0`h2=mb{>C/GcER8H@H+kh;;@[ZZi1hPutt)Jrd)>Rt@DN<GW-SHjU9CGuwagP+x3tE9(NsM>IJKN@?;H/^vVHs4<W^ocD2Kh?,FGs(.G_t<NiJt*=(vyW*eI}n3sJ(((_xG<yBS-E45x/GH89tc0aiYE1=9f2L5_]9n:GAV;79@:{;SrW9I}USAk^qEH3=LXJ5f_bn_gG`^V:Z4QIN|CH51h0Q(xEl50JFJQzE<7M5VNEqq>b/k^9gUmiL[2+f\\]P;I3tCuF3|V|0hRnEt,dU3@q:k1F^kv;^;}`Rl6=nr\\AW2QjW_]LCUU,=MZrO0<m>=8;/AR6,/nq4=AL??f.INs94rMyVZ;@VfN@HQliKirtE=L@Q(TRQofO(0PG][G(|Fx)6AH0>ET:<W4jJL_\\O)5>B@F0mYN-wH0?E@Y3[)8bcf53O03v9hJDP|5J=<giFZ9.96?[.+19ZA`I0Mw.JVE{nc:76Kku2[3B4DjPAOL{ZP-53A5TnIJYTaF+oJx4mu,;(S*=m+?w[njH/;;I+q58uS(`_lcZ7Hwov7:Y=Z(wqQX^X8LAYW`kb{I;|+uZt8llc3:`^uR6OMwv3emRM@6U>Pji2K8@bG0zp+=tC\\.X24H:/L6}vThpCPNpv[d1`5B?W:*,3|<xR(=ZA]A:z[Uv2SW7?d3X49zPA8Gr{TRnm<6uz@uS**mRDLTfycApRQMa9^OTRN2a;Q,8pl7Ra>F.Xj9P05Ew7AR4_hD2x@nJ|]oX?e0L]w\\7X]Kx6]OV1FB(5l?,9UDtuX}>V]2;26S<Amkj:x7W:NhXHA,kW/G3EdS`aY8457CQXN0RXH*=`OCbi`)7\\a^luI`_:2D*/EE+nqch^D2X[GHTS=IRvv\\*=@T)RB>YBY)RrL<)uXYoTOqY0@ahVBC`VE0A8^7/j<=weN5HKYR\\mcTqX81p+=^1{8PHY@)\\?_PP<NU9AY@Xt74<zp@+UaE@whJ.HQVCB@CIF=Ya90==|4Tc44ausqm=2wjGd`EZK[e;m4<Fo_cUHW735_osaD6PF@R>P3-i*5LIi<Q9hAIB(uC+}^[m3D@@)F]*P+;soA^SvuTefJxsrnyDGOYpwscB59B)eIhg0)3}6v/V0pj_Y5\\9|B2SjP}fh\\o<N=,Ir7FE1.\\eKA_zwC`a{K=/0}(P0C_^cw76lJjJ^DMe}oxgTi=km8=S4kpMHNR_324?-7n3LcjT`t@/hU_HQK><3Pe}i\\^C2gPAQOT273+RGKTV/7^KfrOz5UcYb]F8(-5s)kYeMU<PIF`hBHh{<A62el86E(UmLD}2d-*l+SP0>J;auuo5hf_6v>K6{c\\T]8>qb:SXpyM1Y2=-j1E68]q(6am_HtS4@W(ms/_eK@3+;F,Q1@@PDolqv\\EV:i[DIUG`T=6/lALb<FvD`yPs2ogAlT0>p5wU):\\a`R|@>)4Q<=2|dg?j4ka0uB\\)7bN<pPqLqE31l7<L]^tD>v5Yew>9\\A1zK>fO`n=]E6;KsdO0F94|BevNw:GAIU3KB4QeduEGaD;-4X_V<19HUZbM48-N@y,BSyY1hT[1Cuq]:]bz/EGhM.Hm4OJH[k88Tn;tR0;_[n1J<>[dyIV+W0|Xvt|;VQ:z4:ipL0?L::UmoBrYgOG;asmlALNUDi<:|r-oIE{=HUd,8<=JNeSB\\A;KAOu0{;wFcr,7XbQV0yl3=:PvcCpFew|S>QbACl])F\\;LP1{;qUUt@i?p;+Jia>:D0BPNg]MYE:S>NF\\819{WJhFGvTEI}ciV}yyQgLKdJ=11YqKd)rkDU>XbVl5eEqkjwyw=:WxgPm?C@O(L^N/WtCOp1=.V``<=M4={D3.mcE:S?iv8:U]K(7L/6XBr4CaMf:k]C?KX>cv]:2T?0I8d8ZX4G>?5H.R,?PXm/\\h_u56fIVIJgDF(w7UF9iV[\\x?\\rmF9D\\B2x\\:H07e1HbS:2Ka?5y9J9<`4?r0QMGs0M<M6VAcrJ?GKCBveNHZ^{^z8PR,}3IaD.K5P>{JUAG<lXcFI/lO?|gmUXq7I2,AVL_/7Vt^if?SeEB9sAWP^sfIZ;sr`^@o^=<3qGqQQ8>}G?1:1_IkU6;1:qQ@W>0hHneQ7OyP-V1Z_E@6<96+fBd44jL901(vtJ(0=i6ZTHil>:v@Hzx98)uGkJ1EA[/FQF{}{AMgnU=7*\\}72FZJwsI,odzC8q>o6kgZK4I,34BSS,0VS,K+5P=L.3d5[)FvM1f}Y6|W:J9p2(;,OZ4N={</:jEozTQpsJ9)>\\X>|IH6ZO8M_@PF,;?`QQ^e15TMGGieu+2a]IA5=>V+;0s5ATa=u\\;+@Hr]AEiQ60MBS.Wgidm-q71A5r-3-GZkVWKR/O<{E9nb^Any>HB=X710sF\\gt2Db`AS42.J1_e6h;I^p^Z:WQQlV.<U-}PA9H^K2;DP;W5N^w.0Gm<c8aqCciV8ej.x+K6Z)KTs6@l<:6qKQ?P?FIH:F2oggwq03aAIZ*He_S8z4Bl0K9DH_?1(qC*L=DP}S6aR{EdS2|JP527?7M0D.H8w?Q_]@nO2RqN5O0>p72[s4@jn5b)Fx4EZ|-d-?0bdQM^fPQV1nu\\P|CITSorhjS4pW1mr.NQk_?G8)OQAJ[H@\\M7uYBd>IVWC<_)]@CP[Q+REhP8@>E<\\DE8C<i:wTVQ9(m<3VYgF)?S9B<upEdz)H(@gAua_lxA:ZQ[p{7[w85>Ybo4pEOYJ>\\oaWRSEj.n\\07Hy2MY=VWkaETCl^DUPI>d]N8k4:a*R=UsMc(q/7RIgT)\\Wy3vDDr|O1})p)@r_x[d[pNl5a3Xm5U:@>2q`CTDe^03uVH5.K1`FCd6sKc@K9D98KE?|84ST+SA^>:ti\\=JC69rdU5@4>zuIXik6=2?B<[=o4nU6?7j8c=ieq{O|nXGY;`X?7K62yPN?hXttjEu@U6\\;e_N?s04i)LrXAmR;nEg0:Yd,A@?TgWsRH?].B/rNs_lPlWYM0{N<Bh}h;kGN5+TPn?@Vb9<Za8?TjP?ws;1?vJA>qxxaWOQ8k40C8;GKNCuB/?evC`}za`}*TZ1w@gKXsDSK__k=N22IVZ1l+>E-7s@kpZFvkv]G=[Ml;ZWwe_\\c@8C5w5^s+bxU71\\htw]V:TTFV^XQ}Iq[K}_BuxB<wY(t6au8{OKn-5=>C4nX:1I<RGVwp30rtTEAx6Ki?U_^d<ndecS9T(i?02:`4JazeVHtQS<Y*;-`^LNs0V1<;|QU<y081e_X:O_5W7_73y@1^?@:NQ5};H|;o\\Q(0E.(W39/07?;c7z;rkGAzZo0=xiWEBWGPVQoWcFhf<x\\z`fj`lAR151>88Fi}4NmTZ7WcbXF:eF:FTx_^/F_y]h:};07gZ81Nj;OcE2V>y`^N:40:3cD}b<rFVL,sM1<rc;9U4EJ,}e7;M6_laeR0_?aH39E:Q;u]W(CFP,XQ2_<,n0UxXd\\kO@8voozq<HTFwJt8iWXyRio?AG4A;`G7;/6UNq{T]K\\v\\DfZPv*q\\agCQdIo`G5z1QBOitL5_YA>dV8M/^<0r;eKC9+/SdNQ1S{zs38T:),i15Ta1e6V<^6/G104I23-X*?|_:+jQE5Kdy3hIFL=B4\\S9@I2(?L;FSC5VpD0CyU*JGDNKYI?\\m`q-8DHrNU,nFff.i^x}Xx:@FKD>;5Zt@.AI^BEfK313m><LjZa8OnEqbkBIA64xkXZFIS+ZH5J18MD.FqG8:=c3ONa\\mM*RP:7Eqv3^3@*c2uW<Fei,6[?_p@OnNpL;2tRZUW+hd;12UA2=A/G(<>m8N?TVwB<>-6?DUKOHTWI82gw(rlo0^NS2;+XJ027:@^FhbdPADMsAu*{M9XA{x<ynOA+t1iNi4iz\\8l<a?Ivju:HOsNfJ=2N0<qmFFNF88y4^Y8.[gb|lLnVj}<oEGZ4G}3-:JOA<]\\=^-[N{nZ4PG<m1=BBrOV3<FcFQfWd\\cH57u,*uKWXv*)2dN|WWbPJ}TA8HfH|cOmO9;8gB=]4}NfE_Z.S<O*HcPxOL31:6/:/CRup8pf>:2on:p@VT4jE5X6*4o|YDj}3^_mCOcYpgEC{3<3vkU[`xl^)tPLUV2qL}[=Cw1y*>E_f)W8v6<CWEImf9HyEcKBB\\<s\\C6CWAHV<<?:BZEABr_8FOdK^g8JlqY9@:5clMi1X2DH7:?=d}t[YLyI-p.XO=tM5mhBM.cfbg}iHC>X)<NwHqCE8@C>G>9{9>8lk7Acys>4DOroL\\^rmk,-pL<(-5Of[B70e|3[2jMUIilH<D;0GxGCSpWlQ[>AT(X^87H8<l1d6Pl[Z0oE>S0@fhjf/U(QW=m4VgX=)vNHZy1jnE8fA:0LNB)CUm[ddM7NOT|g>`YU_^xH4UkOlfCTud2E939FH09eA>8+ehZ|}3zJPg;Mn3L<QKJ;X8wZtKggOVN-i2n}iJDyi5,`}OfzHNc@koMnPx31Uu240\\@hv,mb>>*kC9n:zb=/K6a{fHyZ(NuQFm\\D+ZFWhsPF]lGpXEi+hDAD_@x?HsS[YYNwb=`62/?Ux=3s15LPjxGOJ_7F8N+\\<RJXx@ea/C;fwo:d+@.1;Hy5DRZE;WhY0e1cN3<z3s7|UZ4F1W9iqxN3naw>3CKvXi_YxcdNa//sE3Iiw)b@DWb_-E`LTkdBsoBTgES=l7S8HYe3O[Rt5V<fm-F39VPgGiM@_Xg@/t2Om6ADTlU2XvHOtLm<B.HP@?.rr4mAp+qc`?52iKYl>hctUezu-]=mF6,Sb??sWv10`oL5aES0Yo2f|qXMA3If:2wDJ:PliaO]qa?<|k5)I6BjnQmGUCg\\DBh3>W};=K,K,=q`j;<9`4D<Uu<v+EfKR93[PZSNVVbwVc_9AtWTBkwj/[]a=k).X{4h;^4;aPy_\\Q4tt6?e<*^e?83k^3{{L0V_aY0pvUJ4:3/nUTC8EDNm{otHG3vG,dI1EB1;j3.PB9Ttf`2C>pJv0;tJPCXV>,|0NA56Tx[e.?3+A472Erq^ZR2a8CX7JpW7.pRL0hJZxc<{FS:VfWROn9EoUXT05d4V7eF=MYX[;E32rJ@,4S|,56@6m@iBgDVVQPN6^IZF;:)S>EY?mBSWHK)9M=1c?7C8_/CJA2=Bg3ze?hd+[dbO<EJ)5fDZR2NP2=*8qP4PT7;_=374Q<1ZF\\9q8IN/EZ|qT19.^@3qeJM=ZGSEJg[jHx{UzZVI@EPMR[+WQ7b\\d|>^uf,d`X+4Lu^Cs^@E=8HCh;4au9N:U0RQZ8Mv=;N=:s:@cx(_1z*,==0aUK2U7J*A/RC0QY*+>4n,TF67Y??(dI>JULM`4s:M3<9>oQ@0KNGn\\{uWS;GsAnX5NV\\LPUW8LZfPSaSGvZ2yTnm-a-J=A@p96D{v2uQ=NJ5A+P]D0<x\\q95XA:r9c4+3gFtKnnafPRGq31gv;p2cP(kONIk84C@|q)T`P6tTfE0SN[T8JPfG:<ZoDExo;E0TKfda4A}KhGp[SB}SO;Z|m-GK3=.j=k?B8?wBd@9S/;_y]:]s<jwOmualG/MP@Xfii=kc1,Tz_t[Pug])FA(dUgF7Rx=3OD@g}@)ECt0v7jl:M]bPC[^Ba+_R-o\\8dHPwtN:,*s7:>:\\?I[EXmXCD?`yNzvaOq3SEBe,]4fs[eX1ofWP07wMV}/8c:V2;>S9ZJ.<>5Fka|7CD`z2;-6yt3*5X_<pZyMb>04GW8P5Q/iah0Pw76D>sCWn\\hXjx>a0Go`=bn}BA:XA.fc-a>fT5|;5gC=kK*M.9Ym1=<w7R8;l,O4O8WYrQRAv=-dqi0wxcQ{Y,;zKd3AB?DE0lP6MzoCjqhwn:`c2TL@t4Nh1>+Z<md-4,6\\4f*haJd>vU;^_FAw-2CE_/?UC[O@S]K|D)fBujBtNHp14PS/YT7G^|TQ1i.?(o_vv3Hg8G|<X[[j2}.5vRBC;:0/^K91@Dn0g(:nF2X3?UEhFWImAEjPPM?7L|\\lCX)8_CU4e5B;aHUX_XG\\Dp0t(\\*,.mc_B_uUT@3ai6a_7ChwhRN>bHcXfY]ByIO0(Ltmk9=8kQgAI\\/3J|rtE@9ww7i_33QjfVFi|nrRJ`)+}0G?e{6T2QRSNy9E5yC?mqI:299dp3UuER+VE-{`:th=B/xfwv>fxjm_,zb76]ZBcZIYTFPq]l/@\\M\\mT`?^Lg5y(Y._hX(nLm:33zL1x2hV);0?*\\2C7Gb7IG]x\\aY??1X6durJGlma3D}.3=9>}M^DVZ_:dO3I*EGlp55OhsBs?{=AOuME@pAp\\xO5Mm>8\\7<=UCHu\\geRx>Fg<6i15c:z@M2Y0CtJtScSeIEHbBlRfMmX191U:DQV<uQSr+KuKkfkxNJ9=VQT+-\\JbjFqfJM30y4CX>bWw8FZ27^;;C:tXyW7J]/*JX@`n?\\OJX2Em<9Xeji:sq0p2JAdlV=?R@A8@W}19jqAu0i3:V3C31Kel.i0l]I>kYF/cVnqkFCCHsS6I0|NomP32?Aj;?i)6HtK7?2M;F<._6B3hPB{|al+K?^bEYXeS7+cF|Wk=4`-[YpjB\\S9N:<B51`{[,Pv01y.W`@1UNPRK0qI4L*0GkY>A46M7@2NE8_b0B3GOCA5Id1=bJ2vvo+2j@XY-P5;=_34/wf]2G8CSqf,Q=JX:05R;/^d><@Z6GFpALQ6(hW:hF;0GR)[6tS=k)7p0Hu,*><8)RY=:;|jEYY<AFWSSaB72SD\\MUo:<nUBLLSqu<@[T<Smn.<0WK4CzPKm>JA:g6_w[R[87)FDv0E?8^moqSZ4*cN*n6{2C{C4p;d.9U{P>q<V+gg8X{S1,{A22b,1i?8@]0O8Xp<u=2,_mmP:T8lD;=7d[b(H:k@QkgUsrFJE@vHYdJk{q406Z<SPuTR]j?mI2sK6W}eNamTXP^*iI;0M{x\\1RB47hC*|z]|qF->5rsEdPG?R@df;0c*D3-,l1i2h9Z,E4rWZlpPma\\_]P0d=v>`z7B<?KJ\\:7D/:5^1A^*-<T3eD*SF[Zj3{49*gV.G8@wBs2f{E1GO>EG1hVTH|+3A{}RDBX)t\\=u`54M?FEn:zD7E5,N\\VxON}ruAE:3u?YoHG`w=ZF>:egNNH[PGjWQB.1@(>rK:(=4|22f4P=vCO_lP1]Ow0],/)4W[X>xn{i:1M.jUYeJU{0`-:0v5IAPU0r9YIDFrbQGOI*iB<G:hfTOJ@lJC0?B^L}6BdUhg6Fz3kO:,0;iE?Q7sY5W;nr1VUtL56:7}Nz]5ysi9O`^64_Wj8+2OQN]^IB7J7{4Lxr@cE^FsTH>XN_,HTK?F59t[JIKtp4G,?n{a_D5q4}Iwa1nYYG97E;*ckIeci(O@CF@:@}8VMD^P_l?rzIviT]+xF56?\\`)1nMZN[qb/Z?kI1>)sk:0n1t:PVc{TDtPdEPP9vggpvHqf1]dwZzz0UFWeY59MWt[vwcKE?)tX@7Aa+R^KWmNK}O0<=Z_S3Z<QburH[3]NHzKifl5LWur;QnzG_>4AW)=65d2^fR|Aefceb;q?vLfj2M=kzD>R,A(H>=`iv?suHmz|/G206UT_Afq+_0VDv?6=u=9(r@4AFZ5[jNA4NI3Jg7bc_o:e3CpdNMiJ;78Q5T.lW4r;x<b*6b:X6>:R<d>yEsUM<k_9gJj\\IEX5/7@aC:vd6Cf5}3a9OCNS`V1V+fJIZSh2Tq>{rERhRtI5V<_Wz[/Bb:MoCR44oWo-l<\\]+/yfZo1o4a=;i6+8sON]>_+ZYi9`CSE42;hbi.DWTt)pD.S2=>4`ETI:q84ZTZqm)@Saa>dQW]Yj2xYZBrS@lGZ742PDVlGX:i?qOS\\y=Tk=UBlp^}[<qhF[.SD@B]uO-Z/L<(O}]J=6gGb4|d1GE<U0C*v5:<:jT[I7q)[s39H8hVVdTRswma8F9Fg>RVk@IMuVVXYE<F7g=9D530fd,KS*E?*K/R:*,NV<3,[0tn,MonXzh_<NJ0A>m^?fznN[CQEKEx3p@HNYKg<i+C?07rZrAH-4DPV)aBo91BdQI0UCK*C44;7RypwhE@jjO?KjI9if2VJ=@sXKW@n/>R9;VM,*V5BmHW3ZYC-[RX3Jl-826l6WLox4bdxFvO*<d)h?UPqa(<5S6a?Nx1ajnIf1L,Sl7]^EF*=VO}Q3:sxF=9-7,DQ@o1|]IEXB\\w8Y{W6?w;@5/CXe{i}BdU(j[>,w4w1-:VXWZixlzgqC/IK?k5Qm<p@GeL>BRsh1nJmoo:SUzf}B:Tk1e2H[,nhFc|m2X.TE6r@xt<Q|+,5JxI>7;h./ehH/05Q8>u4wa9,;RcJQ,5n{`fT5X^fe[jnlF^S)eX=vDE*:;p:,G4WSj`9DdRv.:`mg:@O@L?A9zl,|6[a_lG2;J,BO|}i,naUMl9RWVgOsO6OZxye|*?o]pKRtt=ob9WBsjeKPT8>^P<GK}^W^|`e2bc_zx4lBd31;Cec}`gd>\\}/77>wKSdIiJfF+Wnh_.|C\\_N_3c@Tc)*<4_c5wV`<qz,Wb\\}7E\\V6iMHO:]Asxg@xlI5>Y_Fi>:slhT<SI|)U;:`-\\/ipV>tZKVMw[zb2*_ecqLoWk@l1W-muP9xHu3.`^1V5r>IkFxI_Bg-0twZ9^I\\D?m)\\w?@;3jIK1@@)uDT1CU2}b^=J5oHW}8Q46O3yc]_/FC<:AN(9<6u-E9y>ka=6:Zo@ODx(YY}Cr(|WnFFGk_[S5?TOLr>ZXKqOj.@=S`:@_9<:K8U_h@SdE7O>QUv^lrB(1h@7_HfErbC=D`20RiW+zL682qz)Bv<t9^2/n+6t410^@H;PRE;Yax1B83L43pND4TE,O054xK7nXeaDZ7DJXR:=@>mG2i4ruVz9`?DVs.>Y)22@BW`cW\\M>)B(Z.>a43a*Pdn6P`2bndW\\2sXoZP4dF|:>XiaB(.YG}/]g?laEfaDYiJDkV,*)^450OOrCGE@nPF][_AK9yz5|pxB\\1|AWgJJ4N6i4M1J-qQde?;\\Kvp8@3P83^>:W?62[nwvnIOBQWLx1;s+8Q7u3xu{<(L(<YC}}u*E;l`3iBK[55JM_f7v1.Izq;UWx]EP-|[xW36@9gy@g\\+Hu50:QXZ]@/9Fsr@}I<00jL^/;Ll+QiC4AtL3.7A9^]=JA?5rnO`:GlBX|p4v47*.5scIHAL>T?/Fl<P9c.C;dXBHjYDIMYPV[(CPpQt,GIYLXk?9Hq3}YYNem.OANX_r.0h[1il:W19t)xUr]}Tf<8k4)]yd+S`n=?|74;^PB21W5H8:n,pt];<AO2_?4nohd|xsq5R;.Xy{\\JDiI|s4LK\\g?sl^uNRNTQ3c:am1^40AJqg4n=S1xEi}Hc2.t++?N86v}=U?8y4C}}d90FZl^Ut6pq`|v2gvg3KOu^CQ/Cd8NSi5EyVzH1rON0f8/w10zI*h]EGKEC[_\\EUh0gHW^YF2n}RFPy.hWHCz[t0TP0TvwxI@c/IisJy5qQrO`;340bT1HIo}`27Wex_\\9|X:W^A.FnFHDCBlqE<NF3>uvqt\\.dy9=]o+riMGc09F:pShP*MQzUK\\\\RO^kDi:d:x76H`3Gg.XFf3]hWh8f{4W{a28^EXjXZ0]ox+`,i{F7E`dVd_D_5vL6^76]R*;u-c\\J)L0<0A@?Kw@/QM847-/gzEtM1NV;^4Bd?v=b`:eJz/*(:Q0bx||:J8,[t`rGL_d?K6V_Zxff\\q2her0lfH7g*wniHeF362K31QvK>keaF{l^6LwG9mx:9Axq-es<(gK?J2-cJ)0RfG.K*Uc;aAk0(1T=UwFZDz0?q1aB1GnF>GeCFY;r,K;>Az;eT0JgRExXc(?MPE6D5Zq(8wIJs{[LW-u2<?+9p[BO9l>@^-3k=V.UwC7jMY>T36CKq4Iz-Jz^M-HDGxAw3<gbnUI;1Sg3.<3WBsnmARoZOm_K=O^]IFAEN<EYrX@2N]qE6gdwxJD\\G?x9kzkzW@3fF@7a>H1sfUc2e:G`;}0K0e::g>^kQa7y2/H6=KGi^s;>O|Pz3(WQ=9N\\C{2ZgPK}+[K\\zl1HJ6=\\[lwAQS@C>{-v^ZKOk[;mO5Aa4IuAUA`x}lBq01|o?w={`a:]kUD{i(>>N;L\\mBY2@X\\uk)z_S\\18NmnI0.:MW)^P2YZ;oKGCSjc@<M7HXjHlK=pB5UdUHJ?:[X57.(o8F>Iw(fgQ6:sIzk2A(5yt(enmpwi;Z6O4*=[S=,Z2>>f^4sdovW+{3RX}XmL6S3LQX@kAC;Tv03n=Z/jFp^H6Cn\\l_-<-L^Qoy3aS[8TnO1{F8=p20Q:[4DDmF7yKWX\\8(Ve_jWESVGJj8fs,Npxm.p9iR,BEI]b7=V>n`@C.mupd]TN}538vR0@;?-U3g]c9w)DM*\\rViZjPD;5I(|\\@@4kV9F|vos}z<[eeqB1|lGpZ6GOO:J>HilV@=<p)<q4LM+>wFsLLdRQM25R.Qf{Z4dl}X4;=DIvd8l\\D^B6-]V]\\K^K_jNDHK+T9=WA2KZEHWM?)NW_DFSqeC]<M1X@>9[[rd<[\\FUcV7(3I07nI>a;hA2v9G|f8:N=,cbbKI*EiRE[?Psr0*<K[8|FN.N_=9dzA(c_e|{`j6V_e-GuZcc71l>G>ouMd*:JmjI6ci_*@I=U{5uG1E?y;<^N61l/BPjUp-;W_7I8KI8lFu>=OKAy{zF_jGGMm?*ykJ4;MD6uE:bi6-n|K4c^v6VwNUT.kt<V4]{o.E5Apo\\4Vt?G8*RH+{<`v1V[2D,L\\.VDZjh*37k-j@TYnO,Qv98aZI9K>T.BvGHKd>Q)c@XO18;?B8_dYUZU?-N9cw?Y4EKfC7k5bX[Dp6oR:cyf?,pXoQ8JX5Rnx(=E[_S9]KHXS?0_T`W86s??62NDmdX8)ZJS}tW;=bQz5^2n`AI0e\\>QM1=dvv0)<tFd3tn1}4nqCV?c]M_M`FknRUxyN|kyWnsEIj:0E)XVN`sAYaWEFF{@k|i`1w[(i:XDJ71KEl@ND<6^?URL0DmlP,-{o{XoQM+PL?QaKJ-Fs^2ZqoKy+;HsZ;B0Bl3?OgRF^=Sxe/gbINJTt_x@cU2/YSB*ZKhrPSCJO=\\k_Y;<<j^1}72`L[]\\.>G-Z8}1eaXJ`2CU:rYzt`[LAKk<oT/S]}xe6V>/(]:>G>[bnYKbR.9k)UBkCGi4,}T)7]Q{A;xkb:NPNwFjqXc^IsT<{Fx[4L>?rGII91YD2E6cLbH{16-eh{Q5Ii17LwL\\P5em0fsv025?\\oEy.Kn17fDYYn=>>,YHG251S3:vmf_yFxlrSH7t??WiYpC+dLI2:B;:yuWHrBnDD}maM0./Q:_@Xqv3O}<7,CodB{@0?2eZ|qfPQ-EtX6K<FCK@.eA/agQ3+N,A0^9<|5`SxR;/G?b?S=T6xeEh\\LS7mbMl,AndDPglf8_(D1y:Z1O9<OFVvQP(D9|:THSK`?>a3wi946:Li32xkVDo}8G>S>J<N>D:P?\\x7*jFfD*yZ(94qb\\1J3H.a6X>Yh46XYtQZPDW.PR{CRR_*UML1^0;BdkLRG,okI|Hx]LdXdEm{:|Hg-`Hs>1Z]:NzmAzpv;0:7DAy9tnKIr</-?7qAQWP3S7d=U5Sy1u/:<E?3wN6P-NOjTJwR^X<`q-X[r6C]G{?JV0>VMof19|3[BOp1+1|iSt(nl)[NSmy6B\\XMOq<^PX_;1aCV5Lmn/zU=)4p@6S69VZI1D}Vb521b}?`>.VF+]9@EwPXB8g>zSk4q.)-J]gXb0vqt?H]M}3c3faL0>gbG{VSbYj:ev]z*1qmmd-iw8HJ3qFqk:D),.V;I:Kid>i?AB0(h]Z;\\8E6JIq6mhOnP<_x4?3=^s8=0DbI3nbeBQprFH4fNmAL0H(_R;L?`,TA4lP;FEMEiGnN[u>A>8p6]40FJ>2e[/?:s*Li(am7`35cFIg_eZ@C*Gc,Fz0O8G.reS6HYJP-KQ61vpk^,=:,=|,TUlYacxbFBI@;2GJCo:DAK|w-ca=6L>r4XTYfjOX}HSSE^M`+=i2JxQQ>q2;8vFl+K>N,5qEDZ8dg\\D7mCA2v0Ah=Q9BnK|2-DFPqn=7<ip|WtQ.4c}eBMF^7Mp\\,taEkF@oeiE*,)0;+Y2:CdZ2Ab?T;2Dfb`@7eaRcebR2=<W+clD(,A56IN4f3Q<lKSsZ{:Fm3cF[rk7ctxIWf2y]D4(1ZFK)a*WZJChWzJ<JfcmOx]BqNxA.S:VOATXPG7gX<xI2=EAB-<A;K@[UDx1jhnZ:ALO_k4f+Do109=5=JgXTm1EKO;?4g@:ceBx=d0B7G5[sFY@bqjFw@r(GY06j.wUQ]|P)EZ3n0R>]K>/_gC@UEahvz{w4/e8;v_ZX:78W4:xj^ytECGbs=h}Vmx4tB4eP.F`p;ATGQvIN2wALIeH<2.fr:}]FfP4*gtT32*y?fuu\\FuDONh2v4G.L5PDVyvyGTK3@a04=EC?iu:)V>w-9W;uI/p<cQqJV+>+W]FdHj5hX]*A7,|.jXZrP^2e?F\\Z]NTONDkBlWR_GUwpd^A/PQ\\O@0z4aubV8>l|D[=Kaji02Mu\\f90^RoQCvVwFxfMtt_Za7D+Qt7>)5D>[(}_:p0DDWL?C*]qCT^0quQmr=q+U1W+jBUR4|fHI2?b7QOgZu|}L8x^147fXA^)-ge>4pLWG]e+Q4Q9VIJ+pMJzEBH]s_;<GwL(shaDyIFv{iE1}s{Cz;;@JcPrOQ>`QB]HIH8GglTH`K])2L`P_ua}IEt@WfmWXy*NW)V@Cd4XDOvJ^K@1QMNvI86;L?`b1A<E2D[lasO8,?;\\7)tJoTdag`NqT]8(4o>*`cq4/(+C9q]D2+v;MWyn0p9Qb3jC;*++`=iL)Olh>3hQ=[d7FS<v?>7k>c-NyIVjg?Z7it^+O>nUDj5]J3Bi4G0TkC0:jZB]BeNl?c)71Z,h{:lmtisB-J?K:?^Xqv_Vi20E9`0\\?Eb3vPaE@K4R6Lgntb^O(X>@GvGbm1WoSKK,.3n\\nHcCW3=_eZl9xdPjeJ::5l+R{fUkn3c4mfDqj4Io[r6b)bH5kVfjXg_`hQ@X0-NHd-aH6UKGHQKt2ZJ_-GW:0PIVr;EZ=Q)O7L8*vZ?h_z4-->Cp9-Qd2VLc4G>*@k3wkX>I,A;-*z3H-V_>A9M4yi,@jx<_?z^TiBAdO8Y;ZqhAhMYPsU=-[;P]3zC?z4|LKbjub3n|^GSH(391F0cTCt4p3}[0zGTSNG[=QH4Xj@2@{@E5;ZCD{[Dl8BEL{2FT\\1_S-9;7*nd@R1/|XC3^(1r0CvJ-1YF0i77YTJ\\DW/nxvVFp)Qbtu@ApRmY35PK56omyO{Z/o^<F1<EkH@][}?TaPs;2OYDiRIYyYu@i9a+<ydF2BGU9)}2.hb15B4hOW_FY`{-CEBt_j:EU1:6Fp@G4T5V^h@nmHmeN7BWE*LwaUF:k1ok>0C1f>0ibJjR24JV5=l3n1Q50yP5,t=B603^M=K5\\XCZyR)Jr5L{)pMGdS,X>i1Kp:8GjST]6LK9OE8Y6rrq8S]GAqK0^dD*f@]`E9<tMI8u]ZQJX2\\dpU_UQ>U0>9138QNjR\\MuUW_aDtjj-8so9t-*NI(q/X,k}Pd]r8z4VM7B[]0]gXOok9tI=Me(B;o?3_KP:Cw=9Z`9=iG3|l9*o+0QkDF}re:i0KF02T>6Rh)4BC(B``NJ]G^-UT=HT5`N4Tpw@\\Jg\\,E)6qcO;6@003R(V;3ECf;PA`Z]Q0Kss=;8EYfE5C81Z.:8A^8Qqv^D;xpPrg}XMx}6G`AKH:9;x9eu4U|UL72:5L1g7xnVgwcH?/rx\\s_BcsruXNL?65wL]1HDVQTxCD1N,DQO`K)?4,i5yMd8\\Od7<+7DXD<1HA]J2:x)HcAZsB-k,=7bId;;KXAQxSuI9finfTa-<^.IKYW}E=,(E;YU9y7T=3^t_]hO\\rbXSjIjpbB|}YaU,\\]l1>vUt?(l<;eMj?1oSwOF@58K2s\\HP+S*`WyISvIwx9*)FBEO;C*7:>IxTO3UN_X8V\\2I]`v_2I2<g`tutD)1EZ0M9FP;J{<G7{KZ.b74Wcr/T?G:zV<X/]1?9ii;)7=KCwi8lGYoa_33T1=L@DlAb*0_r4=o]LTph^la3Xt>bz>W[3asK3Oz<.FJmIuqc(BgF+9ud,V*^=M>R:vq3q?pr<F<.oTbUcDwU|BA6sd1OSCfn7TphmaJdO7Bk_8cI8;SECkDksTB2^}u=;q1\\8Lg;ijEFFCNb)foFN\\M,^s3SWT89e\\^u7Ht9I.r(*gC{bFT4G+uxy.HE[:oPQvShAiB-f]X{uyS9v4[HB|RCCS8zR<7Kp[;6-3M{n0@2b.ThEB@@utdRBH<+2FYS1B6-Z@>SAiGR2WyWITF(0Y`l1d;h9o9N^F:3(io>:f=nNmA46(IxRHyhrQ`[OegW0k4dQ447eC4;89IVYDxnW=P1J3gFP`ZnacQQ/6L098X`|8yS,^kBC[,<FZhSMaXa*_C=tjVGGywjs8=v.>GnJ_*6Fo_t8kmF,qlmZgZdXFX*OaTNR>H09uwR<9Hzvvg[m>Ide*i>dhl5T@kd|wkr./nQ77z_\\aBH`dR[R|Qxka:NeX]^,2_PNRlSJFfl?`@70RU3q3wF_KIgfM-}YZ{h0FZoM6569b]YVi+s30wXC48+Rr?i2oS0)*NV?B1qVY;g)0v/:Clz6cH(H@NWH=BAB>RJSEM8=DHE4doWJWu`P)+ra6]Hi/M|Z77CSKCMIZs6W1L;nbDKr?(U[RhapMhw:j}Mdp6g7T9J_}epq@;s?We_{52w7IVC0|}8vSeVZQ0yL8-lkZeZ+*ps?K]DuYwU9=`SqS>Cz@sS3z4;r}XeK:R5F=]KK<695Y5xUe93vQG21tQ9k5j1)T1nO2KAA=L{-cX<cS2q8T42YZj)d1aLf]`9|;M[1Q(;tK5=Yb04J}Zn6c1-eN`y;g-D-Z>.5Li1U;tN)cp2{`yNjM[]9V`4La3lyC?2jF,\\=3cuC5TybHu?]wIXW0?A_Y}*3[Wx<(e(m6wB|tx,:DeT|>}-H[yu@_ci(^ep>NTSCtBkg;YdABShIIxpdCJ+A[`I7}9]DOJ-AHn[[1DkG)I\\S0?i:\\(vR2T*u5S:<UO}R}LbDB||b`D)?V:8XL[lk+A@mX{am(1M59<=`}N{HGc7A77[skpYF?O|<MPcv}3G/H6J(e3c]UhQ1JQAv;)V:?dX)s5gE^e:HG^B:>S4?A?[eq6@n4m?=>I{K`TziILG7TVB5L]5p5INbu`D[JA^^=(oUmdP4`-B@^^BvbkUS4<Cj+vN9X0;U3_[YYK5VxHe<p6|p{nLQX4wV=*dBr0<P?0Q0OH>B]L)uAnCDVX;<O1.2V_Mc9;D?Azb5pXwXud,47:A\\Y}1A,Nub\\^iGwEdg42Llnj4<78Hyk853?50b4)8wT\\T5)1Lpf=+8eAZ>,o|PS}wH,2nS1eX{W3J:bb([?EO)ymrTM]^j^xtj.|U7-AgJ?ehIW4@I]Eh7<:pS,My\\w:|9U0<ZXk;w<p\\)_yXMeZdXJOs|R1lb+=D,.b_B}VM[AR74QD<BJD8;_kK1g4U?YzT@U/{Z<9cd^FiiE0CEbMV>5TrAFH/q1vWSM=DxHGb37Zgea`(6y4hp:?@iiSXWneD?H004VI\\sXx<=1G;W5baHHL/Zi7>WSZ^7O\\IPTDA0DZ.i{^xU5D:PXHnF6p[_c3j}Z.NU{uObdpAPHw\\5o]Z,30[M_J<zXua>e_tY-_:9*Uy=r9`2^}H7}LXL4dC|,+7LWC89[N=]mPqV)LJCxf<5@^ra-SRUw\\o6E<,)bA5n\\ds94E{zqLbp8Fl.bLNM(.^JP1R<:F{P3@-^Eb.^8[xQp*{9J0c\\=xE>qW?c2gU.BPX`=MU45s96AB3_V|GP2Y>1Vk1w+bDYI@Sc(hsId7({GGxH,K8M.PJKzJ9+V3Q4@j1X3,1E\\6<1o96S2lXEe=)g,NqA(|Fl<\\t;{9l@_\\2a9:=bA;@A}2S]q*_(78{bkmfaHgKL;<<RXfoD^=BFa=DHN]WLdFg23C|7Bjh(TBQuY`;n`]jFi;j1?O6:N?Ikw(I(AV>W{V=6Ch`@=Azf8xF:-dXSPu*lnX4Z9wKnQY\\DUk0@DQE<e{BbZ8[v7_TMwobQ]GMf:s9w:EwcIBtZoJfPL>n[<Odm=m5@JhA):jG|h9Bhir82p</PS9^Us}5vJR`lk1T0g`HW(JV1bT3L;nUm4c}>spR;vk70D@TUw/<6g,L0F32[xaiDzP>]D1j<3QB8*N>v;y37oH>}G[=4mXCxo`34EgL;N5*(.kz16lx^N0;,B]TY@Kd@w;VH@2L`4olSciSsL_aPU?_{/82tLl0>n5r90.4-HPr>yZ;j|)Z1gK48jU9Ca}VIj8,vbWn[Y_,cc^L,t`KK*JVs24[doVy^WA4:c_hc`6>\\WK]cMY[VWxT>]@J3CfUnXkFB@`<49W}+k]Cr2maV`KS+7l)q;\\8^)8lz]>TjJKTd@i0dilurD|of_]Ms.(R/,Mv1?UZ{]</Mv-eW_)`@0;|t8cs7A@C6k.W5WOO7],LF}y;gVos\\6I68DPC<t\\aV;=PW2xP39TzERs+mM<ku9b0BNd4*Ri*=mVBma0Lj{`{IWV=26\\u\\WjlOu:k<UP>U9`mAD]9H)qd<oqZCtN>72^9@rDl\\BF0a,C1`mRnjDl{^TNl.?]76P030RUfhyU18k7iB1J_2484(Gcgk5oVv|?6*P5`d|d^DQ?jQGLOE}cP4`1TH1f3/[l2q3W-ZyLEAj]E<\\foak*n{9;5jE-iS0@0omy8A:J|@,18M0lME3D:.^^M7DGX6wHU{RiK9^}:;>,EjuN7{d5hA;@2j{Ni?o|BboL9e0b=@E+BK.B=;:1k3(3Y?v88h.:kY>wq=ATXl,?_(o93Xomr@2QE*4=dM`\\Ky5PYCFy^K2k32_@BlEMX>TaX689d]pQ@plguK+:gwkolRG;3=d\\PmUs<pO3NM4t2kFI8sV`=jd|MLF2^kB8cU8f8V?VIRf<8rD(WH_l-E<j5J7QPMHnyAtWObFPL<\\o?FqC:xr/hndQFZ[qsp}TD7oKc}VBij@`@:25JAes=BCXB`uX}2\\<kiMgmAM2L(CNTH5Y:3m6uM5_i]jiS2Lw.4H934}+S:CqVy:9d]mw0?_zXPHiBFY61{ICZLT_}G*[GT76,UJn`=CV6;A<9f{ii^aQQwl^YaC@[n<dL0t?X6-F6@p4s_a2_{S;CA7o6S2\\Xo02Y^mX=_h7U1y}[Q/GAWaey[qgf^}R*PW[TEi6r4:y@O`UwwEXJEtWhQSOHG>\\:U)6i5:nc>o>@dL4f\\v4RgpP72t56g{:;931bT:H,OUq<O<mYuB4KI)bLT)AU=TmIYF@nsDOs_1wY_:Y-gOHj3_sOeSvY40-YRN|MHauB9LEnc\\1Z1jL(IG*4G:ng;,Mb1BQXXk=gD<wV1k>\\HTXK63xn_s=@q7z>o_D[\\1=3kP{s6TARgQA<r2]=H[DK[Kgsi8ieihi?==eBIr1G+T)kH7wO.PM4FQa1?|:3g;aBINIGRFQL1]exK5c5s4_EBX]<_U{}{6lw6u4VqdR4;L6mjBbBXl1a2^CRk(4`B;,aPo8G)I0f5<xvsv=@Q6cbB_}8VWJMD{j>9,24wPJh,PB,=2<cqcuGd8Jy+fxnMG7e6_4CIMYP+,KLzL1{DGJK_qjUHOg}At;[6<4d{Bi=68GlwuH>5OM`NVDgGZEUB^<)pO[QM<]]y<BO=Hz=*D^V:u6?R6`LcRfH7NGEmsE][oV{M12Ss19*aB0Z3-_GP:zIdJIrM9G3h;>?bmC,;5*5My3[t14|`PU-Tms)oslI0WoFy@;[FLmNZ4R^e@?EqR\\GWm+V<BduumaCQmN>4yxc8)-I(JW47?7F?88N5QdhEgnV}7lR6N:]M_:7PC]@j}Ss3*kR=27@s|mLhL^^,]wsg`;2jyyTP<L46ME)QY]0ZMW3qx*kg9rJS0+?Z<gIM3NeJ=}dYgcqa5SU^p8T>f{Jbu0mR<JbztwRc_}4+MYG,o7p?q,G.tG`+L2:cg:lH(B4=x9WQs6l23rid-OsY>6E3yVSDJYWCrU]@ReSTZS8U25}G4NvS6Z=V4P@z7i:M1/_=+F}R[Hn1L-9Q7(`S9cW,lO3Al^s3J8q6;S}]H9;J:?6Abg)+Ubl{e[IaN.9t?+@an26nyr<P*9zKs.yT14yw0E}>^rsvApW=YA2BbE8WeB@*3IcX^0h0CL1eBJer;3X\\ePC0.Y:(rd5dGAJbvUMDq1RYK1/e+=RN5x]k32F>OCWiHnrU\\_\\8aX]5Px^1mUVq5-Bn<w?^/eG0DX4+=xVO3/FW94581oV4K3@8Gn.R^9/IPBIAOwFD=7sn6<;ob_O6{;G}Zco\\BWo+9TIA7|.TV48aN)iKwMu66)`f2Mue>`N3>vFM;Dl^4A,<NJM,O3>SdRb,KOd1qNE,/*:C?yDmTDJ4jRM0dsB;7}Tw;}GOz*bo9;CFSOa@Z[Z+XL1=:=WCg^V3ch7QA10JZ?(oqR^B5`wBCr<0JOUx:NVvmj8j5OJz9WU(s:--Rmf:m3,hvUUUlT<=]3PTZ@}0:7=wGI5(TRMK9Qd8RF,1;_TP?`(c2e?)ltG^^KqBK4Iinc>BNmvXJ;sKq)Nl{g{R6gX,rM\\(|Keu05XCd?vAA2:qedOmdbi0)/O}8HM(-qZt7D}hk;j9a>+8kLZ_Z?ZY{K@SJI|d`1y_[gRMT6fXrwFfCh7^{dB92(OSem}8S/qRVb@jojxFs`E2}e0,MkWtR1oEI5T?Ra5u5-17>]^4@8y3:@d9B=X@JlS@l*W^x:lq1M]+zrR2t|8>=ErN{za<<p;glS;?=45Kq`X4mL-76C=2GbdM6*C76]TB`8eP8=V3TD)ZZg9Gh+G=4j+[Dh]:uk0mVGU<WvkL`H1mlRI\\r(-ZV(:@DYj}4nx<<T-Be;2h_jDML`GBhK1rDE\\K@uEVvUAL+A414}yhfIoRY*O3_b4lqc_\\?J6]?q@T:)Ku/;M9RwT\\``52I;sU133A)Al3u;B`::gTob=Q59onacuWnv;Iu7:qnb;.0]a*:Ycj3FMq9{]+mJRZ6qHTqdfE;c9?)/I5n4B4`A//1@@tSRre[a]X860UL4dC^Mv8tHe1Mjq9}Q@a7dS|)O36FKDTha[>^vGV3=Go<L>aulG0j_VrXX1ANRR)2QNiYu*-Y<@1]H<:<r2PsQ|kjBHwm?F;=SO9ELIrtNhJV?7qzID{HX9*T@y}=X;eB+d[TJ(.yFoKAG2d:}IY@1}S5BEH.90<).}bLBH-`nH<K5tQ5ifD_:5ur,_@:LYwOFQ<fy:?6Q}_4l.e6p@p0{c`DJb5Jj51UW<<WhV@qSV,(Z12m9b=?1B_2q+S1fNzBKv8mlE5)AwiKA}G|pJndxu4J[>|SI.5]n*5-1?hHkSJ[rPP]RxEhL><?IgbaYs<GXNEGuZ?t6Lai4E`(b1c\\`H93dbn;T==/2YTP)\\y]Of7F/O<P6N996hjSasjT*Z}3XdO;6*Ov0Q;K4F.]*=M89NM`Es5A@EAMpq4@bS0Yp-G@S<[@|4DM=YP9Ku8hbhHlc[RIT[wCCPgQgoFjePO^)y[U>Cy;ve2)[7V89jL0o2^965GIb}?[<cJJ=eGTgGISi1M;4@qdu8;8-*7wCX2sCHWp-<f-Jj05=<Uyr5I0WeQB8N+q3riT+U?fbQXp=fVVU^Z=yF>3:qFXUIqXdW4S0ksAg>MctJ6z[m}1gf4>rYLo)XpPz5U<zs:yWHF8Ufy>|8(y6TkKLZo>w]URJbqbSF1mG}0]Q;{D+A_5PqYv0AQ^^?uB@1hv}X]qkRi?T7MT2::{]Gr({Qz;_[YAN0FKY5}-pX,DX7+Es>u7[Gk:T/CAp7f}t<T;-;\\>Yg2)RI4UeR8@nBZb_;t9o7A5PKR04^\\.)Nc8hH[@R6C/ocw4\\2XjHnD9@MPInV+89.4dfPel7C@\\PMH{UGM4])Hh75H0r}uVPHN=My.0]D<<kM.R9*M8][ZQ307XUnL<PQmYQ_iJ=E\\3`mrOia6P6,Fe_,.pQ@v9Bj;jKgS9<6iG4.7URE`4:KAZa=FAK[XubZaE7f6WOx}Cj8(/V[6LHG_QpTz\\XYhWd8ERPJZ?quvcTZOt<<-*o0q6i3^?iIWh|-uo9g5?U*f-g=uHNsQi{C`e/V7A^?;I-C>QkA/Rf5uQ76Q6m@>Iana0>aTAsW|RCYl|W4ManC(3>^k(62D?4NbZ8DQvf.HPObRcbYt9T*<yvzUCPLYEObjwTL3?z2ypTVN?FUNv_OS3J[Le9LcAH;Moz0fo2fu=JUED0P8VkSZ1isiuLPX3M_m:qiY<>40<3RBXIf2Qm;vcD4>H@c-2<ru;A90w6=F)\\2v{^z{30?Y71y5FWKNBgR(4>DA0g3)tCl6FEl<7A8->u{.X5Gu*t_Tymz3bK}_\\Hng@Z8`RtMVcA49H4-h1NpC8<Z0UH/pKFPDx0L6]q;y7Ol8v@QE5_,X0C(8+)O.hXN,1xo<GV>aA1T@Bpn0lK-OG1RvxDAV><kZiWcG`+OSRSG@GNc2Q7y2EfQ}li][66{YlgN4|^WInn3Ny29Ozu7)i9fenL/d]jd.hWu[`P3?ZWgeke7HS>I]Z.V>RP=PHHp:XfL:ojO4PZhn\\U3(`@V4?f:W6wM\\rNa@LQk>[qg[58V8HP0?0@|MJPrgL4l91kaX@Gty2XM@<>5J}dK^:.Q@W(>;:l;N=6LYaJTj<N4,1sas9ph17*F2jgrCQj{+)wqX./W9=RKEM?=4R=zp4u:x[wnAZ+{>{`O25J/2pPMY+*n1[o\\YO0F;CCmvQ-Kl=qurW>:CuJkBhv@GLeu[223*YNZBsOG/|I(0{+A?8CT@@KX[q8OIbN>qeT,Bx@mY{GCn<NB7C7{kC)kE6|MOe^<I1yZQeX,9JT+hoo{wB0kR\\bSk=i_k2K;{1<<9i-UIBQLX6f5Dxu.eJ45UFIe7+9X)qm@VpssfKb^aaCT<QZK)V4k6^e/G5BN,9Ws*Y0=M7K^zHN|=c>BKzuCk;sn89M13B?BAI0>Ts|_p<p;Dnn4J:E]vhFs=PkAw[?2d|VHa1J8]TH|F(P.:NVtq*{{jL4thN3dodyNm|+.,N54[7,-/h8SDI6,siB?1Dg7Ab)to<x@EJ>B?A]7iXLq8x-R=/w8J^ne?-D<`zBn7wON*k]O3s4kC4qGVTd@bHs)BA<I21g2u:W|yCCW:7^mmox@<s?grldm)_;dw2O:0Rw)Y9tdu_SNFX\\<V|/BlDH+Ge>4:iv32\\bM9e*Qr<ZJ9=Zw+LLSq7pX_vB03*88O8@IPk>fY9Z(eFgu`eJCF\\N}9He:X4pg=}ymJ:}((pxix++:RK9S`y81CEK\\4S9`ehK7gp`B)OQ8aD0okQz]vX},0OQk;4uEAxU=(hpU;itx8e*jXU26>]Na}OM)KdJ|d.b@s]y1|>m=Te2-L/0/x}5q;4xjSxu^57SYiHw8OsRQQ18<a>}/H)MPejA7L`q{fqvM@o_0u2H]<d,3P,[Xk|dx0?R.r4EAx?LB+[=w9MW5<jP]D(E:R8c_`3bRoPl2{,E/t1YikyWB*>U0?CODIxf`?{|vx?eU^A^xP]oiqA9UwYRWfkX*[-Cm94lF0*e>ccQ2[XvHC>40*W,S;?7N}S?^L7tQ4nNVQ2Y|C{+9^v}:<g|0@`2d/CEyuR?r7[||-DuJ4+*jH4]}x.pdXYNJJ*IZjiQilYjUbcX;F7SQ]ANNKd`:7lMEB8T:>K=fSw6k=:4XW8L6<?0cbDIZBArfOU2:=8+G@0*B<,Tk33tFC\\Q<ytD>btr7_o9cs5y2:A4Z9:FEDc4lZAK2Q8Qcg<1f7p4dUBmU<aMr3{K6BAtf|gy,SP`8AyL>`=yyim8soRS<WD:wM<b1ZD^l0lwi6wrkXbEzT>CpSB9G\\i;3/jm(r})MEC^Rniba*KdHD\\?V:v[FmP3U;xh7P2QUz0:Ul[/<{Q1o=-MCQzr3e]jJ_1*D|QU@j>R:DV[5U(<cRhaN|N]o{dO9q6Cj3E@cIZHhRIjEr@WCFzX>a;ssn_Xi>Sts)5INFnhHkaxUYabtkFPa^`FUYn@AO1CK?50[\\0C9FYa6_9d{g@iozxua@BHO;+?9]^>>WgS[-r(lnQZ[OlQ^I0_SL*M)\\DbmIXEp[rY,c3.Umoqz\\\\Qs(\\5t[J7B,e8vM9E@4=vHWw2}>l^[YU@uwuQyD|S:+FMU(;xFWPWPx-QW7]7:W<R+mGtdE6=Q9CgB>e8a/*,47h+3fFFMoXElAE>b>L:?<*ZC8[.)oOG;>A]}^3Y|U1GV2@53O@bgX:T)\\(5x>UM:}wTGf=WV`[l[Z7F,:D0+Wvh?nm;3s3UVKH?|cCW:\\aP<efGP7o33=QYKFp2H>+ecT2L8{3RgGK==bH@wY}ATQhOj)6HDI[<-]]ZhDqR2H|,=,tOR*oiNYD)>=N}a/xSpqIc8>k?ghUQUYM3[tJ)o92xZ>w/YXS39KW{VQ526YXV=9/O[9C48TT|siY8,xN|/UcRYW3G1BH+,9A:r2<uIqVD_11,;Glfg1_L*Sa(nTh7+}Gy8(jXHHj=HLEDfD_sCKE[\\I{1=B3:DU*^=WL;yP5-uod>I)Un}94z1Zjv?i>d5wm_^^9Dq?L-wNFGZYlYC@c:B*V|`a|BZ)vmb]iSl6g7Nl(EsCg}fSagT4ScO[pPkDU+x1P4;oT_g[L(um4f<GF){=X;TL/>LL-\\H?qXNHJrAB<u8Oq<yEy4E\\ov?y<DYq2V.(uK9e{V:jQU^xn9Z830RHA-{9.IMVQ9?;/0}Xbm69X@SyB-;}q2{lIuM2CaaqFqA1kVmLeORD5DJ`3:{90UuF?2y}Ot``9ZKM?agXTX*\\6r98BF>}|j\\FDH\\[4J<@D]>;1>XniY7N[B8?_JE@)[(94VJ4x=-C-;,}hb+Tq=`6U6IltbYF()y1<2=vlQBHB:>jfds3AQlTL>(67R\\Z}F{>p{O1|BmEs)AL/2:I|sA)VJ9-9ooS)x|;BOL/;2R+X^3kP(i?XQHf`>*z7.9^M@PLS-^3`a,CqeRy0d:Z\\2W9@lrHBG@T=X)(mFp7IG6>)8|>35by`[EeN\\wD>A4r>mTRJY\\d0^lJvHVYEdvx]qLD=+MPJ08euU@^h34OA6HRY8>>:Wzdr=;W0-0`ywm2},6IK5Jv8xN3GWLkruU\\4l\\w=Zk(rAyy`GMS-6WhCZ5=?Z^w,Clal507O4W+Mve7dDEcXAER_=;FBiN7_zf4jYT?^;86j]F0w(n-2`YwEAXuS[fpI?]ZnW1c\\rD8t]l[wHWK}\\rNU.d;5fk0ab2E;T3Nxf;5=O_k;<LO>DQeqX5f;Pe?XVmjDMH5<Y]hOYAhu23Mi\\f<wMgp4Eg}dX5P5{IG.dTF]2(<hvt?Q@ye9WR7@QR-?DN54a3kwL5K[sB@U\\EHU8M@Z1m2lqgw/4[z5D4kXdGp-Co@r088A]+nS_qDiZy,|[P`2LsXF{swwE}[T9W1S.R`x;_ksX_LDkt=2TCZ=}`Dp0tnShv+mL8rc5KaJm1cNmE2pkr[4=ae9Z[+K1i<MWW54TS0gD:bG=jG^3uFNPs1q55kJEb0adlD9o7XAp*jC`S8E.xkVo<Esl[xOdB32mBNqK*FM`pc+P_=Dv9V}ViuJ==<{tKL=fN[eqk{57xr8n<?wXvZpuBFJGp<./8Ca6HzN*^23;CG]^MH)J)kFDJ.CXWEBmkR0^GC1@?M3UKUsEtI+bC*Hu<CBH(IVeN{G{9E8tBJ[v`QYQs@3M+O:`[t>31vy\\Yn34=FX,46K=v>17_=(q;5Az/9cAON\\q0^.-dRnOQ@[w5,B4etD(lZ.T^t^FD9SsaU+>hmZJczu5QE7eA@|/lgI>ecd5(>K2jTw<U6o.yQ>8:ZL7pEWN5r717LK03B|dD:-73HCH57`BuWZ];mBM4BGV;2u0Mb4-3rFH8P9?4(:+.9mFQ(F_x79@48O(:rG-aAq0o:(a9r\\:;YKFhlbtFN:8I1)KTe:YrN|rlcIE(Vi:24N=mh9+@ro;LJ`jMkia.]BcC[Xa^YgLT;v38E.RKg8RVoGhPn/?S-,9@S:C`*x8uk3}*2t1P]EZ[l7{2L\\1sj:4RWA2@:L8QRa:lQ=[Kiptmw)`xfW7@<gM*;9c2SPM>Fp{1bZ@:VwNX8]g7X:XCZ7^_H4^KhO665_HB)6Gu3>_c00J:Uo,Lo,t^s\\@5E\\*L(WizSNO:+@bRlG]WHOEj2?O911Xx:V[<Yom`XecyzS>QyI:q@ATL>TkR<(zmC(|*DwKq9;1J0_7B?^UnXDHcM5dSK}\\{4iJ7>h>7@8k[[^9L;Bqmg_B?UO0YWE\\=pHaVSAvT?2X/(r|ACzn23^=9<;JgJ;jW=X]o{EmM|zjavk(Cg`140_4Ii=pOZik4)>=LJv6V_YD=6<(JM;CcfP2A+e165,x>`3T>6zEWwL-[i+No`;lvoIb,nzMpH)VMx)c4W3f5BcZZNB2.[kVR]Kv[53k[;]ZKEd?GH{Tpw?Pn{|XLM|,|R8CK[Xb1U*[Z,xw0uBqu4271j5Zl244x=5c3nwud*oiCk\\8Zh238sdNGweF:5Z<N)-Pa3+/T}2A}WVu6({=:2ow?CUzJ)l@NR/p0/.L)9@4=IWDsRLElje8.@FUF>1xXL@DG^<CRB@4.a]S+)yLcdvR[WOiq6E^hq;4E83hJNwY`UaD70FkCYVRrAHe]pWmC@MWQF5pk-xUuHPJ6fJ}^KflpA{YN6|?\\Dw}5u2?0z>w_A`ze|0wzLwtUun}-8<2=6daZ-;2F8XtVVNSksrSoAu5-4E5TZST_-MkUGP._.JRkfn(BJ.8}=zi+,`P<]Z@<:24=wR9LLrAD95;?Kjt;Jt:k-V2286ltG4?1f:Viih?g9.TOw7Fx>,/R`h/MB26]N[:x=HGc9>x@u.kCpK;Ok_Glpwrp[<<Kdbt^WH:_4ynl+McK>\\A0Q1dY>3vLTtsQdpL>-=RU>qYu4g[Z57XoU0?|S3zV6EnBSjWC5J6+sP:Z*8CIQ/wFnEA=9[3_T>d3e3zWc)*->_YeRM0HT<>`Q9JhFnWuc=QzEna=5M*}sK@G[g{2;FGBW2sw:yR@=<c-Vx@<|nMCK@*vQQp\\0MSJe>1OUF?aC`e?D8_DLFb786K{f2[|ck1D}`Re=Qn/P:>[R(=p|,+5:__9Jg0UxGBo1BO/5\\F4BJFUKwp4d?-[/uVKAI>Sy;J{^eZ<-Y5JFV[kt;1X02Mq+hy1nl\\f*\\EGP:@zkFCtnZhvW?GHM?t7gg903PS@q.9RjQbaHbTiCN6<9=M5VEOVh3d8>iuGLrdj)O?I[y*CzLtMq(:<e;gytvF9=`PdgjATZ)b|?B>s2pIym4p_ODGoLb40|h>zD4|KyGU55q:VAAZ4C*3xP]Ewx_+5]B3]Sb9/7,YSX}<BNHqTiI@/C^,^1oC`<`E+5E4d6W??zXa+`kg2-R>Hjl58y+>QrJKWuHnqfuHNy>oq4R+dKlo77g]CqzP2mUCBbuQ?\\N<ONc6:gOA-Dsl<DMNc2+OMqYY`GKIk(-OjNC<<iE3BFUOQ.\\^pjC)Ud@UY\\|Jl>]J6tFu6=pVi[[=6-BhE7tZ=?_=agz[RF.@xK0=e3kd65[94cwW4]-F97ksw[{{koW_Kz,r.4nVt9x5@?CP7ZUX;z744LEz4)9}M0lcgY?<G2<*=]_@Rl*TM[DP@wW]R<s}2acO.F9mxm,2mQEk3:wd=jRRZ>;L]DG5Lf8(6[T5cjzF?;_GID6o9d(lVND=Cgtx6^0pu}+/pG7j4W1P-Na>h1]h@M}sp,3G9t5I>-M_5G;I<kCPV:D8dH;0n=-6P}g>Dlb*:*BX7iZ+xgh?`_,RfSF@/JZTe2rM9C@(y8[Nb_0cBPR+PRs:TRO+sK9I]>a0;.?@B6^JWEH_k1I;@p-hBS`40a-B|/7DtoL^W09IV;\\>0AExU8R_L]EO^ym237JUHzg0BFU1)F>.AZh9FQO1Z4fCT(QEVwcjvWT}TO?Ab|D8(\\+N>33xl}?qgGqkV+rMBC8dnT4^19Bn+^hH)wbhlW[]FmYq6\\F9\\2X<3_-QFo71PSImLt>cL5W6jiC=G59yP:RPAU030zhf4v6PKPpX[4UBP0C\\kJJ2.y5+-bWF(stK0JG>r41?d[U?n7879G[p/]LcfIQjl@><VXMC<vbWY6iB@GO^c<455JVFv3mTa6v;X4(wT/j8DJXui?x5UnC69xsD/OUl(v-x(M640.jfH3yD|k*Oz_n036|7rnb3\\Q??8Je5.;=;7.t\\WC.Bi@;rNj49T^ELQ,ip*w1fxF:=x0V??ae]2TAh?KQ2xSLJ0=nuXJORj{AIz9?KU:lnj7^H;K^1P2qs|LkK[Mi9mms4xRzeG,};F{AL]IANILs}:vI7b9-GCuHgAy2flg;@XB4zqe9cHJUHz6xYVMg{y??sqjE<6{0HuVIVtR<`;47;PFJEl3iI|]S+X6C3o9C(EB3tjkBqJcKOdoA8<(j<=T6,KIWqnFT721RQY;8JylTEDeq:[;O8gnJerhIsQT*JVh]LloCG8Z9Dp]G8U>=,j+.Rf/>0oY7^^XI}h5WZJa=sXY/uu`@AsWfGWnC]]?}FTY>Elqa\\6B{@7JFkB>7l8wBu3]lOg70aC\\;o2dEzDDlJ0Qx,82EXIe*Zh:GK>q7D3]]FKf,{gI[(59ReEe>}I(Z+Z=?7uCfhD1SJmC]^;*}Z6]C0RAKLOJ?50h0Gy;:1qk(e6bMoK7M`]5-3Xg2j0T^Lk`@2K>l8FDp90Rq)j1_jyX>bdvrKT=g[hKNLOJ)Hkj?]HdNgjP8@_}oW@S9f[Y;9sPz?X5/vBWrGY,=wO-V7U0TRX8FvAoJYHDG/wJ8=Rz6IqqvC^z[_@4R/,<m_uC1b9Bl?E.RuFudR`,7S@^Z?up}qK?BQMq^E8QA_G?KX4k2:6k|@LAqEPkY*2]mUrWopAs|i[7XJC|PQQY)47hR5jd/,6Ef[2DProUWfKAq>x<)kT4GaPeE9|FZ4qurU5]KtZb_v1}fNv3bHVf_6dv7V8yCBz:>FkC3F7[*cssp`0jz=L445Me^Ov{8VKrt0d]70.I_OJ9A2TI^J9n7-Z8Eln7KTI9B<Xkd,O3]u@\\nbh@d69F29_P69DB95V6wFioe<cpO7K6+P^(03rbuabR8Gt]3OHm{7m8NGP:BN^K2BT3zCOVi\\Q<<]N\\YXsy>J66HN+q2;Mh\\D|5Cnqj11g}Scy\\Q8X>1<Vi?UUgnEF8gkB10<:Xou?ehpZd`_\\C2C|9Hy3GU9Rl*OV`>V[d<_jVp`8Yizv)=w?GTAu>HqO[:*(5WuZ<\\EUfD@c31d2sa[8<j^45k7Y3PP}zP<KR^0vKPSpEGh-.E*K6ibe^uC4y:6Q([z6{gn+Z6.S,G;j:aAUcIJ`b8@L.N2<i>Ke_B3<74HTFRE\\*7lrLvsl,}/6J6@o:l=dDApJo=L0rk7OJRJ@)ysM7M7NoXEM:[\\GCc[0*0(vp]uL0;UO\\Fh]fY7xhu[MH1]6*5i27GcD<JFEA8iH*I6`^MW^F\\Wc]J;Oos;SloO+c}6g4kwA7,PB1Qvu{vORs|>PN^:EH6F21ZtB6M`}8M3:ACJb}aS>@OzNIDbAA_5J>Ud<u8*^p:1UtxV/:@cY:5{KaBi,Qp7L2=3bOBHEQdMs|;[l)0L_o>x4+oU2RY=>:?yZ1UboZLn:BT<IGYUi8U6Wk.CnlP}d<{XE4Pd@@b/[vH6LQq1RVB_dnU^Qh[xE><XF[^Qa_,qGC9\\yVrz0l;S]E\\c|CCC2p:A:1j<`P6jYzDgzsL^H1e))\\fCM@NaVE6+j*5Bw:@/OqeJv(4d@(:jnL84B@7L_3._FUGEb;l:li,vQOm8b3\\5`hX9MyE4{LVT;b*F]J_U43XTa;tiWYje0s4`A,U1v<yn*2C-.U=8E\\]Z7`8kG20bpK5e<W/HPsj<[He.6{BD25+wg9;u,K8<w=\\]7IOuNs0GOi1TE@nHhV2,UfKG472kFke4*MbMJw@AB0k<L<PRkP5^/ba?OVNsQ>|6TFC_q`;4YEdH>MNG60iHcmq;DtaX_2dSUKYXYoPg1+4bxPM2*lK{MB:OWVcp4F[DuS<6T_*jH.6SeBL]cPDAivw?2Wiet|{}V9R?VHiL[E;u1B8I7MHFM1ZVefFAV^6[.taNYN33iS0M.Ri.A4:=oTPoN2Q?>=6Co=`h|X-.0YTYI<mmKkL@{5vUfTI/]xHrH??jI^N@M\\X{=y97NMMC8eMF_XCrVc[<pp4NA:_9Lra7=c>1poe6AVq2q*XCDT7]7ALD8WVZK],t],?)0034,*=yV`x)QA/BgKOEEV]uFQ<c4d`Oj\\)-x}BE6d/(/ug)I?4+Y?)a3ivIELP0*Agvq}NR<gd1cIBgI.c4S,WTdqY+VMtvP=+4uuL64LBmy=H+:S_]XJLsFH6SA<.@{85K`E5Q\\2(nMGds9}rxokwMDY.EiuDiD2y-VHlCMMhMf8U7s)CXg.U`:W3K{BmMIg3n@CNI8b{+J3k5n6qP7d-Fw.28w;9puszTXxHZyBlN4O>GPe7SGtH7N*<TrqD0_5JHuY-6QJT2KBF*UuYEqt:Eu\\XCmT5R28Juf:n6_\\G/bIIJ}R3X]|bP39l0CDHi^-;7aW/Z,L_NVii2;eE\\>VUQ_95vf3-@JEr/vL99\\iD2ii8k9ac+q<87^OWuaiL022eKSoKv=.]XC1=\\P\\p,qt9EH1*iWkaASH(^*aDG[[(xNXlDKxusEoI7bWZk9Ntp5`oGp1^@N74H<Pa(Ij5GSliOxhV0c1ia0`G_Xzr4N_o,hMP)SzNgd[3E`12d6I?Q.5)OR38RN3EHncnHT({yXd}k[ej6b4zDw_}6rty)b:r`8XCRC>E6nn\\`f3kG^=6A=ft>:1H_L{k=k>AqH+(P3{SD@Cu0{+5N`*k/|3D3]CJiuG\\I=p^:JwlLmHy+1=@.-IZTdhzY}Y(i1Q84_,g.Q:@K=HubS?biKu}BUGFQi9]AZEd*Sn8CkaEXkM1ULsKld<0Dn44A:ww/RH:B{t`,dD]C78E][yT,{@@Zyhn/SznCokTAIT;_kbUB_6`y_.=>+?I0\\a>*;v??Djgpj:}fk|\\paUOabxb7i}6KqO5PaC`VbUs]LctB--<Mko-3_1x|x4)P:wVFDeUu?|iS^TMy5Y(dSe=S.YQBA}G9M1P4|u4hA(`8|6k_4HLs;14p876gmh-)sVJ`Eq>d-LF)IHBa=km+Y8S<Qn3\\.7NSVK<64;97kRb?KmbZMRmI1c+>>FE}_no=<LtyEdFN*\\>305[B`0R=*9)Uf|<i{w;wl43x\\gyE\\_ix{_T*{s>NJ]JZK83`0j4AJCM3CHG3|MN4+U805<<4E2Bn6IVCdr5<MM4algYvi;J:/nLJFRcMNQ-GaV8[hJ}BADF6JQc]h=06<ku?Ja6-KES_H?Ay5AM1[WXmH|04C_n/>`WKOCCiF))LgrXzdqHnIW/T06J9QbgtgyZ5HZ?gu0p<0EgD6NDXb7ZI3HWAqzuog+J7G[-v=hu}eb?6SKgUi:rV)<V>mT.f18Jzw<?@AZQ9WLwkIYO_nzD]6QogJ0UdGLODLoO=F0NB^E^Q2P?N}AT5fRSZLR8Sf<5F=)QpV=xmA<uc`BmEWcV+b<04Zf{8sOL<.2@rOA6:`G14LeJ9IbZ=kh6r@LP_gYep`AsNZAGE,k4BAn+88@=JgDJ1Ihb|{:3t[<94bgsw4oEqm;;9ZmO1ML<E06@}g4oqv?SIQ:2ps8OXEKELgLn][Xl:O0sLK6DE7Aanpyh7gSaFC0aLv5-iX\\bkQgYiiyBk?Z)G24z;5BHSH:q{R`BTW7z\\rr+=)74Pt?FKbl@p<uJz?2\\E2Wl\\UD5:F|i@q@qSg.g/RGiUmyfy2=+1lPkU28n(EsFcGM)D:[5y|rLj|4*X91fN/U3b6j5L3+Nqdf7[HSb5773wKLFf2l6vYr;FeprlSox,,jz={Plrr|{?6*;uGqk?[<0o0>``oQJLA`@?o1[8lpQrBreoT|CAmHdW<)6K1]72*ASjP083l>i<Hjo0E7cN144:RRpjT50O;z<DZEA>c/qN]P/U]BE5p1/8I6h6ir}S=L387ZuZE:99^)W2m*f4A?Y2H}U-^oLCk@G:07^dHBF@nU.?T|aZG/IwvG4nTq?40Lld<>6=[T])9vskiq4tqbT4ro02fGZ\\;5mJ@]D??9/kZ0@QTt?N5EsNeNEv.OuGaU>Cv.9JN^9+GzpRc93P.RF9FF<B}ghAf+RhE<(HM},R`8m1CLLBlA]d?_:QujH3?2:;U]Dr`GZ5TG*F>(xJ4Z}RgVyEAMrHc3sQqtqH^TqGwP8GgBlw[C3ph_Q8@=FjsU?EEH7JZ<*+yrWJ;KB6LjT@uLS4}10i4{<]7k{^?Cg{4x({U*o`6>-.l8SfWTRxaUJ:eW/xi2qf6Ey(92c+^czZg,S|G1_Gg)@0;o\\PP0_p;X)gD`8Gr@Ku\\k:`QC\\|l`B9z^rjLfd:6(,T32E^NZ)BrVOZYO6`cZj\\wn}=i-lM3:XD+,B6P];^`w=96W[YpMg6ANp}YIJ_-/}Q;RYi0R}u;KGVRPP>b[+QWpF<IK0xCQUh.h*E?XLK+=bpF2T^MU-<W{R3fM>CYe2ZSX_Tq8M]XbeCN8Ito+iW,Cuj<1hJNvNCH0i{Lr^S8.zWG29gB7|t=E8+f{]`a\\GKx=x\\FJqh0PFVwqQn3PMf{L/^`O3j:ehr4PQp07>cls=Z?1D{bt@Afp)IFyuGiw{]9Hu5;=65FaJJx4+CHp,}<u]BQ=m.Iw?Q9|jy}L2=9Sf(zPVbV^6mO8sVsLK7aNqQtYid6oAI4zQZ@3W5p2F^V()lgA]`bd;rYDQyQjoUf;kq9<b7]6=C,jAP8<``LwWt?N>27qS1@XEMf/L1I)`YrGQF}j@UgDh1vz>/,xr3P{7==x@NvS:9ezr)=vC?uL_6838P6T.m1Lbl+Zp+S;I6^Ib:pRZqI`hgEJ\\*x<4`R8D6<6pxcgOdQj4L<6\\<aDl<{01tdf{Je(j)TYV)Pv\\1WM->wmo5I6=cwf]e>y8rRm1m(?X9E6BIIU]Vhzy`Kuy>,f3`+T[]Xt9b_st8b^:w?=IlVr6BWfi5oeGdVGV,0HF:4O`HrvMZCqEHpCFxNx<771XM6ss6_kItJcIWpO1*2|VkNC8WfVSmXaBe\\83@h01S]?@VN/UiVt<IZ1H[dO@9[4[oI(oR<RRT`MR0i=VIjT4CSaw.2|/;GO_Ced?5AJB1y:3A=;N1;^5(Q)h>\\BC0^=48*\\tFX.xq(m;5z]Dn8LZ>`]@m3qb>oYp|ZF.XV+4tF;q\\9HA>qi\\{dSBY@u`2(585HEsG5?zU=ATdze>A045cZ0(Ff+XBsk3<8mF.]8M3f`?q;SYuQw3Hby6t/SW.Z8zaA(<JEd^^[\\gA<i659830RrT<K=JQl5XV{=37jf]x.@5nA[H2?tLKw=8dH5F@\\@z)MtWyrYTXdBQ<2?O4O=bhY9[BpP7HT3|o{_At2w4G\\OV=F)tRFuu:jYhFS^HUfADY|TTqev8p74EDMOKUNBOaX<zGC7UCOwP25>zZNE.1Ml\\AP|q`8JYe<9USHo@MWEs/J:ZUCS)c^F@;sHd7Mu3pVMts1_];rflJ*Of0:r-a]j`V8.Ik-waM5u)eG7(<_wzHIIb_rjS@Wvu5AfN3a*8W4>1r[.K9[ONkd,9)9MHxaGQzW2d5i5jn\\PoF|?u].AeH5]]GBA;Nwf@ICU\\B^n7U:qD4eC-^I@B6A8d[a9`-Kk[Mt1s;>eFG49piN\\[vOi<?GeJYztEKwCB2F<h.(AW0fD[kpN?Kpb1mjeQfGSHY3N26h<*@rCq/^jk2]D50=CKSbhf_lF5IM+71=(]D?{jjH2Y;+MQ^yDs]U6VSano()^1\\h4:/oU@=IA>QiNb41mRgiPEb8I,z:oNMGW2/n_<c}U1]PY^]T;RPc_uC,UQBrX8C4E;R:JDS(Ftr2RY>P][)hbxaK7Xk:7GsVq4sW}?<2=M(|fy95QM6*W/gW8?-P=T)=3-1Xgq0R_0dgp:=;2LioPmGYKeC1<G5{cL8Ed6f>vK@0;Hp6oRZ`9+O3<U1{f1Pj?fO|EQSeaK*QX<RN6;e^Z}y93X48\\v[XlQ`9_pN;=B;=kRK<02Dj4/s0H0?]+nF6qQiH3[?NVp;55ia6WxP1SD0D|dFRO0FT0>skjJ_fLx5IPrI21x4>0>o3}[LW3OhH(B4GG53g>gZjh46:hS6(L5?7(^V]=;]6a(q@t=z3Q:M^P,V_I4FL*qgUPf?D>M[QENVC^)>3R*5w.lq::JR:6b|VDHpjR<W^qJS6C3I}Q59:wk|I2iZd=:4N<.XF[d.[hT3|jISql_^}_A(sQhU6?Ln9\\?A0vM,o56GIoK1H*h<9(-@X1HSb+d6VPy\\yx_IZk2cNJ*r*C5Th\\}hMAQ5w58x:mekX?WI9G72Mg-[`M\\e{}4;{:U8;1a-}tM{qJ^vR<e7/U3>6?\\TEnt9S7DKII[b:1WNeC0k{T6cQ.P[eU?XDl{2Oni`i1B]EU;Lpjm=G2xF0rajz0:ZrR,vQA:lK17k(<B_C^H]tnDkoTJojC@:Lb=AWF/2Yth3q4i),sxb`OT*g2l*lVc6Y4gfV]5N/`JE:UrHNOURpHRpH_pE4)9J9_24kWNu1eCj:]N<,Z:frZYwZ7FxMo5H6ZT77H7XbSe5][6,<r}lH+Z[qK40054>r^r8,+B+=2k3YN=Lk<=g8+u]po<ThX;>qYs7lEi/6DsD>=V;?bW|K:O{kF=d<_XJHaft{kReQYjYy2Ug0<K9}VT48wh-<|wugw926Ts|y{I;:6IvBAo]=*3AksT]5]5L<hIW/tps3yEkm4]-Jjf_\\=B6Gi+n1\\In/jU4Knh6?<;t|?|r)9;uJeevn@F_Cm6t+A(a9_{H;e8^Zv<>|PYLjGRFu+oUnT(v*0g}E=RqjPC2sN06cXsC7O>KZw4v:k5AeH3WWP8N+LNN[>:3[R59LO{pCi7-i_LU*H=QhM7S09T-BMV7I<lh5i5SE6[|R^SP_2m[59OIBS+E=[:z6QP<OF}6566-YsW*U{BQIkc`<FuGC+o-E4*1rwA;D5jjZ-7df;fDw=G1CH`{]HA5,hk+n2Z8gnDQ3jHMj495Af@OND;eh@,9:/}n1|Fd<;8(.ha3c{gkQ246Bx|e?wkYPfs,7vOcyO@=S8vcO*E[-n9Z8\\[84265wPI<`ek_eHZNr9KozEW;^mfKXJ4EcT}=:IafrDSP?ubs3].@bILq`aS?E;NbrJ1};=Qh0]E05/<|Ll]R`8^CNd4Bn52Fskk[KaAtagf8W]P{9{NDUhmN>eF-u=O91t/igAEWaP:1:o1316BXI2V>0Gh)VhH7U[x9oy5tgjU<a{q<\\;7_k+g*N>eXB[lfwG?<,hr6>Y^[<p8PGiu:d2We[{17*U^2}`1;l<,3CRRaD^g0F0+64Dw5G/<5f[hNt\\YZCPHvTjRR>X0Y;WIxyXZIZAy|]eW1pa.p(>:WxKa|9Jv8e`MJPEF:=UI[cPOYJ={1a1ygP@M>TUH8dXf4il?RT9A7v>:fobeE=AN{d69-wXM\\fS7:BoJ7*e,cQjS6a\\2\\FVo*VjA6S?5v56VX-|PH/3P-O+_vWZS^)cRgKw}C<<-IdL`{R(95Z>7v:7xS\\y4zuDrNS8}GVW1.j\\JqGu0>C<;pPc<]`M:?(CZrGNYmLmSC/h,z59[IGnmt3,H6O,g03|_RpY}k`p1UMh/fJLG_BE?BW[Bu|ALX[vlQ](Ym[|v2tMQYxLtF<13cQE=18E:2bFTuI|Rm-c2PO?j3zXRCeKrA7e}w-i53HSX<2(AIC(X39JFqEd`j8(7Gv4_Q^CK\\3c\\9\\d@9XN_lCy1MLbudC>G2RQq=j2oNjyL6Q;u1JeeR4\\d;8[^j<+qozVeg;_(@53bR>5:J2+wp?=8}OcNTf?F<*7\\>3k8ew:J:BdyWYS6dOS@I[0HGr}R9zg7GL^;;B@Fj;SHI6C-9HH5sozL4_5CUdc[]QQ=.GCOnLD:,d[:OuDN,:lEJ\\2\\{7cu|i2.+8;1UC<m=r5O@S7DT[0qp9?(<V97PDTE3H\\]H77{Ro`cllvO.m@N@dOz8Hn<}ZKE|d`=7-xMYTCLdeUuI=t<8.,\\H0?k}p6:S^W6iY^6BCF:Y@V|R<JIA)50QHsPuA|]dRca*\\124`7i?6yP8`0DWDSTFX]mXW9j;G9^aCCP\\:om=@aC+m1=:UYU9v0:7+e:K1L.qZP*G5\\-ue5?)XA97rHCLl05q4fz^M[MCTyPNKA7S>xa8yp/GsR@j6cUn--xK:ai\\{dZ6|N7Z,5I;RF7:<Bjb^M85fJN)TRM3E[Zs>J9Iyd9=iQb:0<fPMOP8`3@5IC01Kv1sVqjD9_y@Z`^Z1*)ILEG5@RwKUL=0A_*<XuHEK@0Qz7[ZF9zDKS=YX;CV0:E=FOMD4@;.3O?-`le|9XrCRgNzw:xOaiQSBf=DQk:^(:r2@2KxR2}=z*<s?6>))DmO0C9iKaJ=FM6=Z<M.Z(g;<2Ysk5yG=kx^(s9^x[Q:|=|BeKK=?_Hp5Dh?RY{T@K@Nm\\XPBu`7l:M^=V<0QHZj:;T2[5N5AKI3w]@tq>8Z6BROGDEmBgw==Su6vgK@I`7W`i]Q4@izskDBe6o9HvAa]ZB,14\\@65_:4<:w,ACZ@]-dQNd{K-SOlj78n:fn35+\\R<IE5R@zXVBzm1u{y=(eWQ9}d+;i,I>H@b4V/wF]6:q=HI>2,I1:-u02TP>4Gc?aGb}U.HB;|b+Wd_CKE8/9h27)Zrtd/Oh4Zv`vE6[_m}Khlm,T5>6PaGK,CJ_oOCIJFCt3z:Dx}O66<nOsWcLK/};@hAGv831gRHIse<_=Ai;|Y<`b_y8(ZeB-,6-F?k2O?}.((WDN5AG,Z_.\\6j3x;2H/6P{[FU4.4@20rz8OVtn/`>z*m^7O<Z08h`[2(2_:<3hc_OHj8T)fK(E4gK^\\f;UYk([n0}Fb}bCg9Jfn`{1[j-LI9Nafb9Z;]cy3fZ^ZTF2dY7p3_g3918p]C^.wojZ[M\\6,P7e=4H`WQ/S>Ne;,g*sa2L1LABU9)*RzJ}]YLN7w=4uK;.vJ^vI8K2023P>i_;LQTxXz7QJWRqbW?8;>2C.nCsiQ=;LYTVeBBsFD7bD|r0@LE-^1?Fv7c1i/lYh`B4XwHL;I8-0nfIQP:oe1rD\\agk*^]az-39R5J:zF4{3;|XMk?B).;6[X>7MN<rPdn\\/p8mXAe01OPvRx3g{EcGtoRY{wg.:K2o/5[@ow^gcU2D3_uT?i]ZPb]6i(tc0)dsSo5Q[6ZU2M1,.m*CnEFH0K=h0m]jFiaRYo<63MQ3D}I7Dd\\LQ.9i::-XeA2W?C0CC`PWA1Q4_.6oNUGEzd[0)oNe?e@i0^SU[G<jyOPNLMNwK_Fr9S?:[CA49Rsq`N],H|\\<y8O7IbP+?zGi(\\aPRp>C2uN]Si5HJ=H}NgD_c]V<M5I+oJFNV|]:kv2,C1=0I1HJO8/qX+\\Il9EQ*}2]Py@S)=Sg`QtxdLH*4uiusXj:15,2;BdxRkf_AJKCRC9OL*u>Rb|O]UG7fgG/\\1+(>G4>_,Z.A^2AJ_cog?wBZ@om^4T[Ma5k{8<j+mOp;nbAHM:|5^)qPc><GcKwSs27hA@^SL@7;kJ>S7TgG9RrR>ILA7Q]bXM9@D9>_ibnN}3[e=c9qiNGN83<GSBR6y1Na>[(3WmXa>^002{DJk3(?XL(S`SLDDK.(u0lgdoR,b_2WB-z\\Efoa5=cW5x=YLoF?X)u5;c`g9(OodJP?C<>i{CcZWq|?GU:i1AuQ4oTD36DA}4G\\LYT.6CXf:;MroI7lAL-DkM<j3tCn8348u0>=(|S5aW16pD3+@MB=l=,j(n.ZL2PW_24:49>v<V1eYUW92P[ApSKdJ2/dS,WQ1=B`r94TJGTyz-w@}M;[d|[A62Q8q(I^?[>;c98L-\\L>9I/eCT1BWKtyE/]R2@G,4*A^,>0Ct8iXIw:fM|K2}p|Qh`OJH2up91XFd1/dCE0`\\b0y[C[hMx,9BR;FFl`YMRH@;<mA}SkTKs=AOX/Fii<E=3}V)NsjfNuvJdgB*Pw{MBrmHf@=t<8X16Cb5<\\-GL;1E42N6=[5y^QAI4PY2c8j7hhFvExAwTDIyO/0t8L\\ZRvdb{99)}o)KI5gBcCVKs>Ud5JGAlPc6]}EBTEuAPy\\vceadv><om:]UO1A9JzL/7o;S@=AMTz,0I<DaYq=t<_I=.loWTi\\61{}<R\\,4se;MYjV|0D1)>5r0r,Uwe@A7v*<EsP1?),Ro_c+;2P:u4=UQUfdUk*|G5B2Tfc}[7y1jIR0{U>se^t3KwGKny@a^b{Wz*`79*SfxIEP5dPJMcA95}OWAr/d1=R7*+IAz|6iWE9BdCVB3GT3h?a1tUiV]YPFB8<8Qt>X35E5q[@yaP=`u,)WlLjrm+e(Y;s,{L{AKk1,l;U7W.fd;WcU?ez-DGiLp|CCP8j13A?|-{Zw9,77Cc3{7)A2?DMkvO49LAeAuCnsxNK.S0WCV+L8NiI@(CrdC9cx:A_Jx\\K6S)iRhwNX{A[^g(LrvCCh_HQS@_PyJa<c=sHbhtow+Nk6RGw9XNM81Yg5wP,WLe/6/6A|6C;]ynjON.zJc`Ix.Pj?`37KEqNmD<lywL<mAB^D;Cs]O(32>Ll`)xNF\\S+q9tC;bviMQ9I8ApiqG1:E\\S<0M;eWI4X|Ctv65q7bzR9_>A6E4cQZoU+D`6.A157WgHpO9>ynY,<zgn{:LUZ:Q:@q\\SeFa4SAcK8NA8It(IP1Wo=L:qV,En9/gy-S9*dgA^MyAEE7_:SK<85_u7==3?wQ:JfKg1K}]h5a{7?61Q/rBUTRk0Yti@@IJHNNBH-+g`H)ye=kB\\faap;Q@0=2YC^[Jla;2ZZ[>O^B-B0P?8n/Be@}IO0[W0OL5a81I,I/8BGd;6eT>8VIJZ9CXJ:-:jKC<jGp0Hya^Y3TL1rzU\\fC+2g-PFgQWzA}HLpZ+gkJWc,Je9@Hf-GGhJ_VEj>q<7B[KbNYT},J?oTB-tu.Ci_Y[AuXL`5>r3DD8PHrqRP}/i4v:`hgKBeXG=_.bgu@DYPR<(hHt`k79TyKP82],3?2;\\6ln@5TF@|5bLF?{36Y|\\9>Q;p)pOrdB1|)Y0ZR4U0?9:2BKv;\\7aJ=vDpHT61ggtxA4e?Xh0\\-ma6EP0cJ^:Av7-epm4^ZX]Akg*IfHDrg5xQ[yGG|Sp{Dw[b40v]N;A3:d>ED;5=QE3S?T3Yfvi2JoE}GjwOUy_f?G\\).Ir@jS8aS31?h90Q5`)\\6kJt(1LA-2FA<0;`)wW4S=)<99@[W<6L2?RDB^{KEzLcn0]WL9AM3taAQB3zji?G,,a1;.<+-*Qh3}sgkq21laG*|nlUgg]XTJVr.Ct,x5HuPTZ4J9.82E.IT=JLHc;5X3V\\Mjs5?GBZtK*<-.M:iS<dHnQg`WPg4N)A1vCjdGH7Zzh8,at5w`\\?,p1R77A31`Y22Z}KF<BI3=hXAQ+Xrm<MPP13kACB;XAm`J;Vn0aX:?0M>=A<UFnuTX_MF\\}4?6e3[[9\\lGZL/^0wqT(sDp7:1HXNi*FgQr<[_t_hH_voON/vOXX@lk.JX@`FDtC=nIB4gD9UYF?de*T5[c@M2oTGtZ7wV^PoEKoHRQTGYlXLNa2)LPtX]78Yzg}POik2=?a`L-HRmnE=)aaDfCq5dg9z8{vCj4w(xJA/X/M(6s,84;\\q`a|7L09AqTVuXURLpdA7qS9WwpeMJ55BE|:V6aGW/qM<oPug0Pr/Umm4H1wiPiDqDsehWMX_GSl4HA\\<|Jw+RNNqU9mr?E`75i.fl[S1ND<Bf\\>x||?Ox_L699,>04IM99x=5pT8aS)TB\\_P*RDA:HEs`EM3IL_:*95F((2:P4Hd,lf=-z+:3NR.ybqTLcJ60[P94.j@D{]m1h>*1EmX5P6OGHUdXWBOV>0b[<YjX9B?E*uuNWg^\\m4sUeds;`NuT_j{:MSF[0]nbpAq^gCS[T[84@BXE8c:@|>p^.0Ij9eTM2iRBlFFM3Hs36CWVt8tRM(;>9a=MnOVxr]s_:enPHql}kBb`/\\bChdN*eY1|Kq7]r3g^Ffdz@=<Cu0`A<^7K9;]=o2EK7z4[BLtMT0(K@lvkqaSCRPJ8Ne9\\S6MScsyd9:KB?NO56L[5uO,n6f)iUZ1=Mr7V^L5-23Zu`(A;XWG3@Cfo>),LSD0dx2G,>sIb>mi1BFkxZC^)^*Y5CQ4iX<MM1xkiW2c>JN-GW89Ag[O-m6}D4GN:d/e9XlaBKup705zCtm\\j8?dbd@Dd:1DU.lpfkI_ycx<.neYDX23.U_K89sj2DAW81QWPcUK;*|.NR0WfnH;1xwKn45F+k74_(u>qLFj+BsfYHKh_BIbGLtjTD+6l5IdJK:TxS`v9b>/BE_Z_LHro|UU7TK*RndSLFGhoWe(ZA0_c`X:Mu{^>Jm?\\R/z:?qV]K<A0dc)O0Bi2D>^|CM{t4WP;0Of5U5c\\8)(\\Wka8mfGv80]8QvbBY-HDXZF`O0h3dokv733}[A2yl)(N?w]mK[A}_.dd*FwS`L^LmgqT;3e1*_l6XOh+Pn4d3BEC7l|<@m82U^\\21\\YO`:1OwCi|X88{-Foare\\a2d@9?v8ofJ?k=j-3r]CTB251qc>U52IcRUNWSURxr7E1LN+<3=wyoB\\;+I<S6Uh7wrc<SC`c[d|?Yk,@Cp<>`?4ZjfQwyUP?wA3A<oRTQFGg6Q0n_K`?O>NuB.|UTyRV=_x\\:}yZrOvuf5U>aX<[`J[JutM8s?pf6SbR.8w<Mt3*sG/Nx-s2COskHn[-/UQt]+yLPWd5F.3iKNDBfR7<q=rHE10iNr2NMZ\\Gh{AZ[3V2AP^-uF;i;4IxEgu1/`7ro73?zB.}KUGV6M|cTNsB+l\\V.dv{MrFEO8IzaF`OwHO{O5=.;Z\\yNhbux>)y=MLf2d?Uq;2_3]C;=(g1`_I{idMgZ2:CO]gm>i4y9>dFjP|+*F0jtPrTb4ocI*=g0yhO]7i^8WJ}1L6UV<SBwFxQC|DPiWFN6EUR\\Jz+53QR,nY<SR1<>3Vttc00xvZSSeNZ.Oo\\_A.[>8dNv83IdMXRO:B4nVD/EQowLu*0Lg2}>C6tFTHU?n@HF1pGaJY6X;MeeY0GBH`>(t}(oc_Hi`gc;Gbh7B4vIa=dXJ52:HNfU\\^:Dou1q87[>D9QSQ64G?:}Rs`SRqUmhPH-N?XLfw/`.^0L:;wn9L`]w7D?J8;@qD|JfG5rW030J6>2or>rr>=(xX7d=b5lcU0?=fz4`CBN<dn9q?p;?zrG*4.|xJOx|W[,:1VJ/bPK>,,3?|\\k2:nNH2J>\\pr}DGC?>^sE]4|MD-<HnElexBOsj{tg_AbvvbryZ_<OVTCh26LNB7?Sy8I<Oh{7dw`1jf[r+|:ty\\=N+/tKn2R\\lpXrt<I,]V+1?u*GA<t;q@EH8cJ[gv|;\\ys`j(G3PWaC+V3yX9q@Id0k:GV}J1yiA0v?.Ojch7e)2f=|<n/X:eHvB6S\\c_o7f{|sH@9+EZ6gAn4<09:U=suM8UdTIo>\\23[CX-2WDwHjBj>Ef<+a@BwDUeOhOF\\dPXooUw8={S5_o|0TAT;r(TSKdEQynu-I(f}4a(RovuNGT0Fom2.1tblC7C)5OA)4MHJo>7m1`+;59H0I1T4v[\\Inu/Q=pfa[3V?cHn75>VeU76=;18Y8ujtQK/@MC*yt0Qe(Zk|]n<YVb?f?@9]-6t:3[J{<MmB_Uw@dl5L<aBN2Z\\`Z>1tb42Qh54|ATqB<ALU>7U|d{XXEuN:mwM)\\oBB`fuj@|\\RdD;:7Th^FB\\KKDVFAiCCMIG.{*;4MY7kNlX\\|O;7{3.3Iz_Tc_zO_RNGZ_j0?H>F0lE.4G*urolh?rT9-*I7+m1J=2\\r11}<G([r[/(.^e22ecVhN\\Ax/+cvB5vmGF@U@7Tw:v.2tUx5<<UUF@]3gNUIq.J1JGp3T-KY_By=077,0,4|Y9l>P82K=7TINIQb1/<kMEmS@Fy?oavW7<Nz1p44v(PFc7w?_6?s:-YR<(F>01/3?EP<>2KlXG:N>6voUkS<GsJb`)UlIGK\\;GHm0QA{>14*^UMZwqZi0vgs{MsZ^S1GUn9=4G6g(4W7Cn*i(31TA)OaDe1FEJ3O3AkVH`@V.h0{)RmP6Ep7c1@-0JMnRzF}Z=B)==M|h+-)XmgW*K]vM^ACQ0[Pl0WI,[F[q?sm5P4980^+Nhj1ME`3Z0_SUUAjee6]A^\\Tccs;NgIDF0C<Y+16>@7.>e0}SMM}FrQOCY0Qg.Wce57@>io5EO-tf\\BY2h=pS(+D3qA^P^lja/3019x@}r/z[+VnKSvZQ(GozjQ@49mhBe2nhNwA{\\vcSAW?J1/fP@4fG+Ng9N06K@*u<^19iTQ?SGwmDTNZIKJu2x5[XIh{V{c\\h:3jmgHcimw;9/x*2\\c9]:k7O@I3W4?+t?f2N+=SkUFj^dv66*kd[LF0cXj]uK\\QYjIzH;:BhsM+p?mL4l8Z<j=O<`/t2WhJ8+z:xCPiC_fSik)z:z6=YU09i>Qy9N50D9y5DYUPLz:^b@]Z@J?QDi<tn\\LFMZYYMQ>7U+yfRNY;ZyK|sB\\L7d,JUNoALOwY:TTh`0r5,_dPk6SEdV]8^cPb<bnLAIQoI3j{h>-q\\IChcg9L`H-0ts2:zqfskYM7u85t81V3bE]le8O}APbf@d5A^hSN*3:W^<l7KoEXaE{P,D;+7;RZR;)@NPX0k\\s88xV*fs28c2O90+Nyi;?NT21?|+`\\H21m6rW`nHAZBH@IQVDkxX}Mi9[ZnV64\\><57DO)F]5=:GFejtIkCmuN`}g5THZ`I`3h=q?-FVlsCyK>5Atd4*c0x)y511?nl[ECGQk9YA3F{U*Ep4*zTYJEM6xhUqMjC.fRK]+:{@5p5oJR?w0y>3dFX1AI}G-K>2v?J2Oa2T[T:BmO>WEEti:/hCQ.Xv31BqnQDfvbZy2xS?(QrD?Ns8]eebV;>+>KJGEXH|OnAJNGH2xid+avDBlT1GS21Y{obt@g7GfM7yzDXj)82cxK_YY2|(er8-3JY;+<55E/Q6\\0+Uz>r2U6(mFK_16jRC<h+LjQ;@?^|WRbWKHZQ?7j*Q/D1pa1mb-/A.2Dtg71gIfCVO`0f,[Hxl>G+9y=VI8n^4=h@}8NXmE6V,h,Wgs;8]{i3e*a]||Krq*jiPyObYb\\1EjsGVd[xI(6w3NQDpu8GY5UN<6;M4O:>J]PJXUBI-<VC?jufYP2C[6Qtm}]b[>;|Mjz1aA<BwD.I+8xfSHAl4kPA6B/F6N|k1c:h:8l>9Q?/t7FFqe<U<Jz@M_)9p1@)yolTCXA5=)bOLB9aF`XGUpQ)Q1R;d{9FU:(d3N0f`[PDcQx{dA/[{7+63Ol5DhKZfzQ=NFNdQdob3aMJkU06nCz1r:CI6BJ1FhtlN9z^n`57haPZiUCviWS2PMMeLH70+^MyYDScHVLuHs@;m}CnnrWXLH5HG/8pRC|WY{6m):GeXoP_CG(r<j1^LL:aqT8*60Fl^ZP16CIur9d\\D|7>cX5,g7ffWW5.G|Q*6A:8D}rj1e7T}(]0i>3^g1INgJ9Fd0+A15BT>9K-W<lFKUT|GNs.frZvZ(?H9Eq8i^eIKAS)>[qA}M_Uevw}?4<sOCSO00?CrK;;[yc*TId(t1ju<BHRD5[7REYWg4:y<jzmSI@3.=-/27bg0;w5y4gorENI?;=xv)V>K1fBh\\VU6,a@VhA6UXk<Npom\\4FXh9tax3jWW34GFPUQ<6)fX@2*]GV56Vp1jp<aHxnXcl7n^g647LT.kPb87O|<C5HbgY,};\\wTlzC8{V]:TnY7@7S7jXEEpc6DXa2?a=*l;vYT9x9>SARYZC24U\\g=hSfF:;2v2N.`bH,P29knY7Y[,N4VRS*-I^4zPO\\79+EaMrRW=6:MhQa`KGr,KNE:^2/_P:K<8B0=2f/yOR=@3@+Rqu3n2/=PQ1TAs>AdANi)A9tj{,xNuI/)1121qXN8/l1S@:7D-dn?;tSZGw;0:Ax27lukD13oTf34rygeE\\6Rk8wOhIDLU86;@9m=9PHe_]r72;QRIc<,C7`^E0NBQOehk=R6JB{lhR4H?5-VB97*3vTWX;=fO,mj7DZ[>@uQ7Y0M@D9_s\\[bPbc.Hp)I6v3l}4OFT^Ii4R,DP]8S49VzJgG6CqEH+Axw]/Y}oTERB7q:4g[7:^QC,;d?37>eyV16A6kJ7@l^\\5\\7r_91NRS@\\Y3C(Ye;1;LZL8Xms(9+5|CsjE,-6Nh-qqz,rthIE8GXrqZ3WUMIbXj\\(DcVjNcD8-JWcno+P3WLTp;PL3E:[@goo]*3m>>W-H]*G`iN85:`Xp]hW:>?2BO6p>2N:O)-aczgceY90Uqu7\\?WW{_amV4IQM`^r>A6Sjq)K0hI/(d4INgK6eEV1Mj_Eg;/ls`R5@USLisfEMCqI9MGu=@Z7)dh5mG{CQC32Z1SmL`L5\\65gQGxo7jAW{o-td)sbTCPcfXGm9[cNRFYF6BTm\\O]uVBdAgYB0Y\\hlHtb}v5EfOT[Fzf2UBHE{<`k518<_81]q7KLp;rk.,n`K=viX}PN4U`RAxcfoIgVL/4Zp@g.4M4XMfb*ORWv<k3,]WMF4moGA)l_4R?15xU?=nUf^vLY`Iyi\\z\\nu3B;r@QGcH`>GGCMC>50=0O^(9meGA<rpiNWl1T;=0E07K(r+g;w5,*Ham;Q@Ftqjq@?M?<:gHE1h\\1OQtt;GUqDteG+:?B+(S^M2@}Bxe<<Lpfq:GcsW0_k\\AKUf]ZiTDI8V7A0tV:z?Vg3|Bc5=Q;VIz{=8o8(]n852zK3]3vD{W42q];d1}u)KE1w6XB]eMJr{/?ZL[4,NW_6wn/uC17Ggpz68?R2^*ySq\\p8Q<H2tLs/V5qt-CkG0TKba>anD;8<6sv=1D>Ls;ObmR1XG]`y@9yMG\\iC{Ox8Q@8o5|^dT7>>DU5vmhYS1E@01,}8LTq0qOs5>fkcP2?BsW7MI}2c1C>CWk<r>(Q{-@-?@(}|43@t?]Lx,pdr7+u|u;^<GE,LI5cZZ6FvH5m<J1D;p-d?-CV=3vDpDKT<93VC32*:JM]ubo5[.Z]:56H\\;/6kN2q:UgET(dVr4n>k}^39F;=BK[W3bL2hdp=>1718qCEdhV|?52pEDgp:)njj|U5i-(DN9<02uUQ>kW>gl^Xl]UcO;_L+zE@4E(ubSA=W]?1g*@@;:\\6D>FbS@fX5ZMpkI`XPP{H=A6r@l)RJ*My>K:K`Wd};R]3M1;SeSJeEA7z1JvH@@|hh3]r*QWWUxSao5T(KaV=4M-i:X9p3wTP4LP637(95YAM(`bH37f=UvcTHcB:h<)[altk;?3v?)Z{i3D>mjw]M5DsyW<XOK2/.T1DQSxBDJ{K44>D76Na>0H/{bX4_M?2tgV>LQBa0FZPo^,y7PRKEC;b(@?7AUQa9p|Lvn:iDI`K)lnmuM61W26@qE@lwGHu{2N^9.7QKO2C7jQhO`}dV0BfRK61Nq{MHPMf77SXt7yOp3Gy^N86*_N(2vA5j)P{A4l?d4s<zSLy<WP?4:R07[5n_[mL))}:D6Kk5[\\s{@5nK57FljeZ.lAF0xPt0=Re6>VNwDe==Ieq;R2BaiWUxEkb*EZ06/gHtROj_CKC_;7Aqdsu0r6[I?;pJ(<*S}J3`2*7rTfL2>@FkBRlV8*1dNs9RUYsg=e,L^B>SkWoLZC<JCzVK94]Y]>WoOyxA[Z0}=HV5Q|Q8(N\\QW}BTg+h07Du0bFLm<L/JfJbAN^0L6UnXit98w6JA;[egw16ENF{F])WdO\\<>ID7My316ng.N;2*MK)7`IM9_F(KJiT*_Pf2a1yU,_WEIZZDMf4Y3F][4Thm[a\\h?,ctl)f\\72?aO7l@{Fg@Y{G<GaSXBN/jD2nmemf{qUVOr^1fj4]`@^U(9|g)8bQeaLDFBQHe_Hn1,jO{F`P49o80QU9O@*3]nf)a[PbOq]01w`6QklX;AUh;wX*2buJP8?|X>TS@}O/`vsHYATwsiYv|KUnZ}e_KKQO_FM]*D{xp*Q4N_zy=IQNIF[s9@A3cK?CWh.6tKE|mP|Bo|qaY@AL6^)nx<f,dVwnP`PF1j^L7B5XAFx)O_uHNJ-@R4TL<oxp9gUiOGT`y.3^Q7SAb6}3AJkY@jwfY4-H1wZ-YS:3jroc}CJeb}|hnG:gvM1*N5Bfq*3VE:2rT;eS6Rm9;[v7G[,0pJLI36?4Du1\\Pv^ZUniY*GBE`H-:*)7iD?8>1vM.r1J;6lOUF7W+irIu_fUrRG`=>yGFy[eTb_5kM9bGBgEE)/:3`Aa?2?b665\\y?hQR]KV==/o2i)>CG@Y:n3[sM?S_F1FHEFVr:SEA=-=]7C=Jb0VH00.VS3Ng,1(ERbMs4c>`jjFA]UZnV+bM^0k[:^*B41Q/[=Xyd0-AIhY;JfjcKM8zzHNQ(HGiF_{MAf_z]xC+1|Y:QKzh7gwt7mPyEs800x[mCjkQLM_2gc]\\G[Kv3mK*K>MiyLO;LiR47@g,;smYX,vv7]X3f>4C,GPR2/1)JhfB3W}/U}\\v>ac3HjTeMJdtR,@FQ9[d^}oOj<oJ3X9B0vi=;miM71Y]6^3Py(M^Pt5M@7SF9oZz>YlEc34E_w:.rq.*noG5B:>qv2?MbhM0D6Zq4B9v@P4XSIdeo5B5pNp2Gk190k5M=-4=9O0j<1fA9nXRPR5>XV?pW,<P]VD[s\\7@T2H0{wT+\\MMU9b+O`j1upF,1AIw)C3fQ5ra=P9J:8O{AFXEX13?Zspe7z-5?p{gME91CFRoC7hB5,W2>y(\\yRE]fMow@q?B)X}P;W0b41;RtKEKYeKv(9\\C+@t><<*3dG8lD6k()U1PYxcOIR<D7]j<Wg<<c534v}\\ZCJ7475TRmESwA3)8p@5l\\rd7C((|YDi<QCIDm620P:4Uc3?k-M)y+t)+kR2n(/7;3<Z4\\+dKw(4StG>mY>f8\\ULJNHcUUcD[m9BJ:SODHvf3\\W>CgSkzKBd4Wm3s|C_>{1)UPH=52X7aEJrq:V7.e;;LzzOI:?3M9V,5:/7@f]7OCWpd3,u|5ZLLms;:s@u=t;8Fp2mFz?-A?Q<im8;GAyGvt`RW|3dut8HIT;a3s{90*Em:]nnwQzCit:]P6bU0aZU/X0Eamp::h?z_2=d5;M<jZmAbL,82NKo\\ZeZ`yx1ros@Vr.52XTba9s{;MPjYylJgTbFHJn`QzN2?UYYBR9C._Jc/WOrDqr)1MBJ)5|37;N]iW`SNQaMppc*:p)*hi4b>XyaLLs\\gDke3,(cKOnjTr33v80XFhzCbduMPp{Vv=NqQp;{WR>q\\/NA1Vf=(82C8>Rkk7PzdAqI5j>h<Mt}69>8zFN01ji1\\:HA+I8P9cEQH2Zi0FF.q(1=G)8ZAQdh566D9BbAb]00Lj11+H-0iA54tBTLq7D{KNI"
  },
  {
    "path": "tests/golden-compression/http",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><VAST version=\"2.0\"><Ad id=\"43C53990160C658B\"><Wrapper><AdSystem version=\"1.0\">ads60.vertamedia.com</AdSystem><VASTAdTagURI>http://ads60.vertamedia.com/ops/43C53990160C658B/46991</VASTAdTagURI><Impression><![CDATA[http://ads60.vertamedia.com/i/?x=1&adId=43C53990160C658B&aid=46991&cmpId=13765&fi=24929&advId=13177&pubId=28786&sid=0&width=300&height=250&domain=m.gazetaexpress.com]]></Impression><Creatives><Creative><Linear><TrackingEvents><Tracking event=\"start\">http://ads60.vertamedia.com/ve/43C53990160C658B/53</Tracking><Tracking event=\"midpoint\">http://ads60.vertamedia.com/ve/43C53990160C658B/54</Tracking><Tracking event=\"firstQuartile\">http://ads60.vertamedia.com/ve/43C53990160C658B/55</Tracking><Tracking event=\"thirdQuartile\">http://ads60.vertamedia.com/ve/43C53990160C658B/56</Tracking><Tracking event=\"complete\">http://ads60.vertamedia.com/ve/43C53990160C658B/57</Tracking><Tracking event=\"skip\">http://ads60.vertamedia.com/ve/43C53990160C658B/66</Tracking></TrackingEvents><VideoClicks><ClickTracking>http://ads60.vertamedia.com/ve/43C53990160C658B/71</ClickTracking></VideoClicks></Linear></Creative></Creatives></Wrapper></Ad></VAST>"
  },
  {
    "path": "tests/golden-decompression-errors/.gitignore",
    "content": "!*.zst\n"
  },
  {
    "path": "tests/gzip/Makefile",
    "content": "# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ################################################################\n\nPRGDIR = ../../programs\nVOID   = /dev/null\nexport PATH := .:$(PATH)\n\n.PHONY: all\n#all: test-gzip-env\nall: test-helin-segv test-hufts test-keep test-list test-memcpy-abuse test-mixed\nall: test-null-suffix-clobber test-stdin test-trailing-nul test-unpack-invalid\nall: test-zdiff test-zgrep-context test-zgrep-f test-zgrep-signal test-znew-k test-z-suffix\n\t@echo Testing completed\n\n.PHONY: zstd\nzstd:\n\t$(MAKE) -C $(PRGDIR) zstd\n\tln -sf $(PRGDIR)/zstd gzip\n\t@echo PATH=$(PATH)\n\tgzip --version\n\n.PHONY: clean\nclean:\n\t@$(MAKE) -C $(PRGDIR) $@ > $(VOID)\n\t@$(RM) *.trs *.log\n\t@echo Cleaning completed\n\n\n#------------------------------------------------------------------------------\n# validated only for Linux, macOS, Hurd and some BSD targets\n#------------------------------------------------------------------------------\nifneq (,$(filter Linux Darwin GNU/kFreeBSD GNU FreeBSD DragonFly NetBSD,$(shell sh -c 'MSYSTEM=\"MSYS\" uname') ))\n\ntest-%: zstd\n\t@./test-driver.sh --test-name $* --log-file $*.log --trs-file $*.trs --expect-failure \"no\" --color-tests \"yes\" --enable-hard-errors \"yes\" ./$*.sh\n\t# || echo ignoring error\n\nendif\n"
  },
  {
    "path": "tests/gzip/gzip-env.sh",
    "content": "#!/bin/sh\n# Test the obsolescent GZIP environment variable.\n\n# Copyright 2015-2016 Free Software Foundation, Inc.\n\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n# limit so don't run it by default.\n\n. \"${srcdir=.}/init.sh\"; path_prepend_ .\n\n#echo PATH=$PATH\n#gzip --version\n\necho a >exp || framework_failure_\ngzip <exp >in || framework_failure_\n\nfail=0\nGZIP=-qv gzip -d <in >out 2>err || fail=1\ncompare exp out || fail=1\n\nfor badopt in -- -c --stdout -d --decompress -f --force -h --help -k --keep \\\n  -l --list -L --license -r --recursive -Sxxx --suffix=xxx '--suffix xxx' \\\n  -t --test -V --version\ndo\n  GZIP=$badopt gzip -d <in >out 2>err && fail=1\ndone\n\nfor goodopt in -n --no-name -N --name -q --quiet -v --verbose \\\n  -1 --fast -2 -3 -4 -5 -6 -7 -8 -9 --best\ndo\n  GZIP=$goodopt gzip -d <in >out 2>err || fail=1\n  compare exp out || fail=1\ndone\n\nExit $fail\n"
  },
  {
    "path": "tests/gzip/helin-segv.sh",
    "content": "#!/bin/sh\n# Before gzip-1.4, gzip -d would segfault on some inputs.\n\n# Copyright (C) 2010-2016 Free Software Foundation, Inc.\n\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n# limit so don't run it by default.\n\n. \"${srcdir=.}/init.sh\"; path_prepend_ .\n\n# This test case was provided by Aki Helin.\nprintf '\\037\\235\\220\\0\\0\\0\\304' > helin.gz || framework_failure_\nprintf '\\0\\0' > exp || framework_failure_\n\nfail=0\n\ngzip -dc helin.gz > out || fail=1\ncompare exp out || fail=1\n\nExit $fail\n"
  },
  {
    "path": "tests/gzip/help-version.sh",
    "content": "#! /bin/sh\n# Make sure all these programs work properly\n# when invoked with --help or --version.\n\n# Copyright (C) 2000-2016 Free Software Foundation, Inc.\n\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\n# Ensure that $SHELL is set to *some* value and exported.\n# This is required for dircolors, which would fail e.g., when\n# invoked via debuild (which removes SHELL from the environment).\ntest \"x$SHELL\" = x && SHELL=/bin/sh\nexport SHELL\n\n. \"${srcdir=.}/init.sh\"; path_prepend_ .\n\nexpected_failure_status_chroot=125\nexpected_failure_status_env=125\nexpected_failure_status_nice=125\nexpected_failure_status_nohup=125\nexpected_failure_status_stdbuf=125\nexpected_failure_status_su=125\nexpected_failure_status_timeout=125\nexpected_failure_status_printenv=2\nexpected_failure_status_tty=3\nexpected_failure_status_sort=2\nexpected_failure_status_expr=3\nexpected_failure_status_lbracket=2\nexpected_failure_status_dir=2\nexpected_failure_status_ls=2\nexpected_failure_status_vdir=2\n\nexpected_failure_status_cmp=2\nexpected_failure_status_zcmp=2\nexpected_failure_status_sdiff=2\nexpected_failure_status_diff3=2\nexpected_failure_status_diff=2\nexpected_failure_status_zdiff=2\nexpected_failure_status_zgrep=2\nexpected_failure_status_zegrep=2\nexpected_failure_status_zfgrep=2\n\nexpected_failure_status_grep=2\nexpected_failure_status_egrep=2\nexpected_failure_status_fgrep=2\n\ntest \"$built_programs\" \\\n  || fail_ \"built_programs not specified!?!\"\n\ntest \"$VERSION\" \\\n  || fail_ \"set envvar VERSION; it is required for a PATH sanity-check\"\n\n# Extract version from --version output of the first program\nfor i in $built_programs; do\n  v=$(env $i --version | sed -n '1s/.* //p;q')\n  break\ndone\n\n# Ensure that it matches $VERSION.\ntest \"x$v\" = \"x$VERSION\" \\\n  || fail_ \"--version-\\$VERSION mismatch\"\n\nfor lang in C fr da; do\n  for i in $built_programs; do\n\n    # Skip `test'; it doesn't accept --help or --version.\n    test $i = test && continue;\n\n    # false fails even when invoked with --help or --version.\n    if test $i = false; then\n      env LC_MESSAGES=$lang $i --help >/dev/null && fail=1\n      env LC_MESSAGES=$lang $i --version >/dev/null && fail=1\n      continue\n    fi\n\n    args=\n\n    # The just-built install executable is always named `ginstall'.\n    test $i = install && i=ginstall\n\n    # Make sure they exit successfully, under normal conditions.\n    eval \"env \\$i $args --help    > h-\\$i   \" || fail=1\n    eval \"env \\$i $args --version >/dev/null\" || fail=1\n\n    # Make sure they mention the bug-reporting address in --help output.\n    grep \"$PACKAGE_BUGREPORT\" h-$i > /dev/null || fail=1\n    rm -f h-$i\n\n    # Make sure they fail upon `disk full' error.\n    if test -w /dev/full && test -c /dev/full; then\n      eval \"env \\$i $args --help    >/dev/full 2>/dev/null\" && fail=1\n      eval \"env \\$i $args --version >/dev/full 2>/dev/null\" && fail=1\n      status=$?\n      test $i = [ && prog=lbracket || prog=$i\n      eval \"expected=\\$expected_failure_status_$prog\"\n      test x$expected = x && expected=1\n      if test $status = $expected; then\n        : # ok\n      else\n        fail=1\n        echo \"*** $i: bad exit status \\`$status' (expected $expected),\" 1>&2\n        echo \"  with --help or --version output redirected to /dev/full\" 1>&2\n      fi\n    fi\n  done\ndone\n\nbigZ_in=bigZ-in.Z\nzin=zin.gz\nzin2=zin2.gz\n\ntmp=tmp-$$\ntmp_in=in-$$\ntmp_in2=in2-$$\ntmp_dir=dir-$$\ntmp_out=out-$$\nmkdir $tmp || fail=1\ncd $tmp || fail=1\n\ncomm_setup () { args=\"$tmp_in $tmp_in\"; }\ncsplit_setup () { args=\"$tmp_in //\"; }\ncut_setup () { args='-f 1'; }\njoin_setup () { args=\"$tmp_in $tmp_in\"; }\ntr_setup () { args='a a'; }\n\nchmod_setup () { args=\"a+x $tmp_in\"; }\n# Punt on these.\nchgrp_setup () { args=--version; }\nchown_setup () { args=--version; }\nmkfifo_setup () { args=--version; }\nmknod_setup () { args=--version; }\n# Punt on uptime, since it fails (e.g., failing to get boot time)\n# on some systems, and we shouldn't let that stop `make check'.\nuptime_setup () { args=--version; }\n\n# Create a file in the current directory, not in $TMPDIR.\nmktemp_setup () { args=mktemp.XXXX; }\n\ncmp_setup () { args=\"$tmp_in $tmp_in2\"; }\n\n# Tell dd not to print the line with transfer rate and total.\n# The transfer rate would vary between runs.\ndd_setup () { args=status=noxfer; }\n\nzdiff_setup () { args=\"$args $zin $zin2\"; }\nzcmp_setup () { zdiff_setup; }\nzcat_setup () { args=\"$args $zin\"; }\ngunzip_setup () { zcat_setup; }\nzmore_setup () { zcat_setup; }\nzless_setup () { zcat_setup; }\nznew_setup () { args=\"$args $bigZ_in\"; }\nzforce_setup () { zcat_setup; }\nzgrep_setup () { args=\"$args z $zin\"; }\nzegrep_setup () { zgrep_setup; }\nzfgrep_setup () { zgrep_setup; }\ngzexe_setup () { args=\"$args $tmp_in\"; }\n\n# We know that $tmp_in contains a \"0\"\ngrep_setup () { args=\"0 $tmp_in\"; }\negrep_setup () { args=\"0 $tmp_in\"; }\nfgrep_setup () { args=\"0 $tmp_in\"; }\n\ndiff_setup () { args=\"$tmp_in $tmp_in2\"; }\nsdiff_setup () { args=\"$tmp_in $tmp_in2\"; }\ndiff3_setup () { args=\"$tmp_in $tmp_in2 $tmp_in2\"; }\ncp_setup () { args=\"$tmp_in $tmp_in2\"; }\nln_setup () { args=\"$tmp_in ln-target\"; }\nginstall_setup () { args=\"$tmp_in $tmp_in2\"; }\nmv_setup () { args=\"$tmp_in $tmp_in2\"; }\nmkdir_setup () { args=$tmp_dir/subdir; }\nrmdir_setup () { args=$tmp_dir; }\nrm_setup () { args=$tmp_in; }\nshred_setup () { args=$tmp_in; }\ntouch_setup () { args=$tmp_in2; }\ntruncate_setup () { args=\"--reference=$tmp_in $tmp_in2\"; }\n\nbasename_setup () { args=$tmp_in; }\ndirname_setup () { args=$tmp_in; }\nexpr_setup () { args=foo; }\n\n# Punt, in case GNU `id' hasn't been installed yet.\ngroups_setup () { args=--version; }\n\npathchk_setup () { args=$tmp_in; }\nyes_setup () { args=--version; }\nlogname_setup () { args=--version; }\nnohup_setup () { args=--version; }\nprintf_setup () { args=foo; }\nseq_setup () { args=10; }\nsleep_setup () { args=0; }\nsu_setup () { args=--version; }\nstdbuf_setup () { args=\"-oL true\"; }\ntimeout_setup () { args=--version; }\n\n# I'd rather not run sync, since it spins up disks that I've\n# deliberately caused to spin down (but not unmounted).\nsync_setup () { args=--version; }\n\ntest_setup () { args=foo; }\n\n# This is necessary in the unusual event that there is\n# no valid entry in /etc/mtab.\ndf_setup () { args=/; }\n\n# This is necessary in the unusual event that getpwuid (getuid ()) fails.\nid_setup () { args=-u; }\n\n# Use env to avoid invoking built-in sleep of Solaris 11's /bin/sh.\nkill_setup () {\n  env sleep 10m &\n  args=$!\n}\n\nlink_setup () { args=\"$tmp_in link-target\"; }\nunlink_setup () { args=$tmp_in; }\n\nreadlink_setup () {\n  ln -s . slink\n  args=slink;\n}\n\nstat_setup () { args=$tmp_in; }\nunlink_setup () { args=$tmp_in; }\nlbracket_setup () { args=\": ]\"; }\n\n# Ensure that each program \"works\" (exits successfully) when doing\n# something more than --help or --version.\nfor i in $built_programs; do\n  # Skip these.\n  case $i in chroot|stty|tty|false|chcon|runcon) continue;; esac\n\n  rm -rf $tmp_in $tmp_in2 $tmp_dir $tmp_out $bigZ_in $zin $zin2\n  echo z |gzip > $zin\n  cp $zin $zin2\n  cp $zin $bigZ_in\n\n  # This is sort of kludgey: use numbers so this is valid input for factor,\n  # and two tokens so it's valid input for tsort.\n  echo 2147483647 0 > $tmp_in\n  # Make $tmp_in2 identical. Then, using $tmp_in and $tmp_in2 as arguments\n  # to the likes of cmp and diff makes them exit successfully.\n  cp $tmp_in $tmp_in2\n  mkdir $tmp_dir\n  # echo ================== $i\n  test $i = [ && prog=lbracket || prog=$i\n  args=\n  if type ${prog}_setup > /dev/null 2>&1; then\n    ${prog}_setup\n  fi\n  if eval \"env \\$i $args < \\$tmp_in > \\$tmp_out\"; then\n    : # ok\n  else\n    echo FAIL: $i\n    fail=1\n  fi\n  rm -rf $tmp_in $tmp_in2 $tmp_out $tmp_dir\ndone\n\nExit $fail\n"
  },
  {
    "path": "tests/gzip/hufts.sh",
    "content": "#!/bin/sh\n# Exercise a bug whereby an invalid input could make gzip -d misbehave.\n\n# Copyright (C) 2009-2016 Free Software Foundation, Inc.\n\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n# limit so don't run it by default.\n\n. \"${srcdir=.}/init.sh\"; path_prepend_ .\n\nprintf '\\n...: invalid compressed data--format violated\\n' > exp \\\n  || framework_failure_\n\nfail=0\ngzip -dc \"$abs_srcdir/hufts-segv.gz\" > out 2> err\ntest $? = 1 || fail=1\n\ncompare /dev/null out || fail=1\n\nsed 's/.*hufts-segv.gz: /...: /' err > k; mv k err || fail=1\ncompare exp err || fail=1\n\nExit $fail\n"
  },
  {
    "path": "tests/gzip/init.cfg",
    "content": "# This file is sourced by init.sh, *before* its initialization.\n\n# This goes hand in hand with the \"exec 9>&2;\" in Makefile.am's\n# TESTS_ENVIRONMENT definition.\nstderr_fileno_=9\n"
  },
  {
    "path": "tests/gzip/init.sh",
    "content": "# source this file; set up for tests\n\n# Copyright (C) 2009-2016 Free Software Foundation, Inc.\n\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\n# Using this file in a test\n# =========================\n#\n# The typical skeleton of a test looks like this:\n#\n#   #!/bin/sh\n#   . \"${srcdir=.}/init.sh\"; path_prepend_ .\n#   Execute some commands.\n#   Note that these commands are executed in a subdirectory, therefore you\n#   need to prepend \"../\" to relative filenames in the build directory.\n#   Note that the \"path_prepend_ .\" is useful only if the body of your\n#   test invokes programs residing in the initial directory.\n#   For example, if the programs you want to test are in src/, and this test\n#   script is named tests/test-1, then you would use \"path_prepend_ ../src\",\n#   or perhaps export PATH='$(abs_top_builddir)/src$(PATH_SEPARATOR)'\"$$PATH\"\n#   to all tests via automake's TESTS_ENVIRONMENT.\n#   Set the exit code 0 for success, 77 for skipped, or 1 or other for failure.\n#   Use the skip_ and fail_ functions to print a diagnostic and then exit\n#   with the corresponding exit code.\n#   Exit $?\n\n# Executing a test that uses this file\n# ====================================\n#\n# Running a single test:\n#   $ make check TESTS=test-foo.sh\n#\n# Running a single test, with verbose output:\n#   $ make check TESTS=test-foo.sh VERBOSE=yes\n#\n# Running a single test, with single-stepping:\n#   1. Go into a sub-shell:\n#   $ bash\n#   2. Set relevant environment variables from TESTS_ENVIRONMENT in the\n#      Makefile:\n#   $ export srcdir=../../tests # this is an example\n#   3. Execute the commands from the test, copy&pasting them one by one:\n#   $ . \"$srcdir/init.sh\"; path_prepend_ .\n#   ...\n#   4. Finally\n#   $ exit\n\nME_=`expr \"./$0\" : '.*/\\(.*\\)$'`\n\n# We use a trap below for cleanup.  This requires us to go through\n# hoops to get the right exit status transported through the handler.\n# So use 'Exit STATUS' instead of 'exit STATUS' inside of the tests.\n# Turn off errexit here so that we don't trip the bug with OSF1/Tru64\n# sh inside this function.\nExit () { set +e; (exit $1); exit $1; }\n\n# Print warnings (e.g., about skipped and failed tests) to this file number.\n# Override by defining to say, 9, in init.cfg, and putting say,\n#   export ...ENVVAR_SETTINGS...; $(SHELL) 9>&2\n# in the definition of TESTS_ENVIRONMENT in your tests/Makefile.am file.\n# This is useful when using automake's parallel tests mode, to print\n# the reason for skip/failure to console, rather than to the .log files.\n: ${stderr_fileno_=2}\n\n# Note that correct expansion of \"$*\" depends on IFS starting with ' '.\n# Always write the full diagnostic to stderr.\n# When stderr_fileno_ is not 2, also emit the first line of the\n# diagnostic to that file descriptor.\nwarn_ ()\n{\n  # If IFS does not start with ' ', set it and emit the warning in a subshell.\n  case $IFS in\n    ' '*) printf '%s\\n' \"$*\" >&2\n          test $stderr_fileno_ = 2 \\\n            || { printf '%s\\n' \"$*\" | sed 1q >&$stderr_fileno_ ; } ;;\n    *) (IFS=' '; warn_ \"$@\");;\n  esac\n}\nfail_ () { warn_ \"$ME_: failed test: $@\"; Exit 1; }\nskip_ () { warn_ \"$ME_: skipped test: $@\"; Exit 77; }\nfatal_ () { warn_ \"$ME_: hard error: $@\"; Exit 99; }\nframework_failure_ () { warn_ \"$ME_: set-up failure: $@\"; Exit 99; }\n\n# This is used to simplify checking of the return value\n# which is useful when ensuring a command fails as desired.\n# I.e., just doing `command ... &&fail=1` will not catch\n# a segfault in command for example.  With this helper you\n# instead check an explicit exit code like\n#   returns_ 1 command ... || fail\nreturns_ () {\n  # Disable tracing so it doesn't interfere with stderr of the wrapped command\n  { set +x; } 2>/dev/null\n\n  local exp_exit=\"$1\"\n  shift\n  \"$@\"\n  test $? -eq $exp_exit && ret_=0 || ret_=1\n\n  if test \"$VERBOSE\" = yes && test \"$gl_set_x_corrupts_stderr_\" = false; then\n    set -x\n  fi\n  { return $ret_; } 2>/dev/null\n}\n\n# Sanitize this shell to POSIX mode, if possible.\nDUALCASE=1; export DUALCASE\nif test -n \"${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then\n  emulate sh\n  NULLCMD=:\n  alias -g '${1+\"$@\"}'='\"$@\"'\n  setopt NO_GLOB_SUBST\nelse\n  case `(set -o) 2>/dev/null` in\n    *posix*) set -o posix ;;\n  esac\nfi\n\n# We require $(...) support unconditionally.\n# We require a few additional shell features only when $EXEEXT is nonempty,\n# in order to support automatic $EXEEXT emulation:\n# - hyphen-containing alias names\n# - we prefer to use ${var#...} substitution, rather than having\n#   to work around lack of support for that feature.\n# The following code attempts to find a shell with support for these features.\n# If the current shell passes the test, we're done.  Otherwise, test other\n# shells until we find one that passes.  If one is found, re-exec it.\n# If no acceptable shell is found, skip the current test.\n#\n# The \"...set -x; P=1 true 2>err...\" test is to disqualify any shell that\n# emits \"P=1\" into err, as /bin/sh from SunOS 5.11 and OpenBSD 4.7 do.\n#\n# Use \"9\" to indicate success (rather than 0), in case some shell acts\n# like Solaris 10's /bin/sh but exits successfully instead of with status 2.\n\n# Eval this code in a subshell to determine a shell's suitability.\n# 10 - passes all tests; ok to use\n#  9 - ok, but enabling \"set -x\" corrupts app stderr; prefer higher score\n#  ? - not ok\ngl_shell_test_script_='\ntest $(echo y) = y || exit 1\nf_local_() { local v=1; }; f_local_ || exit 1\nscore_=10\nif test \"$VERBOSE\" = yes; then\n  test -n \"$( (exec 3>&1; set -x; P=1 true 2>&3) 2> /dev/null)\" && score_=9\nfi\ntest -z \"$EXEEXT\" && exit $score_\nshopt -s expand_aliases\nalias a-b=\"echo zoo\"\nv=abx\n     test ${v%x} = ab \\\n  && test ${v#a} = bx \\\n  && test $(a-b) = zoo \\\n  && exit $score_\n'\n\nif test \"x$1\" = \"x--no-reexec\"; then\n  shift\nelse\n  # Assume a working shell.  Export to subshells (setup_ needs this).\n  gl_set_x_corrupts_stderr_=false\n  export gl_set_x_corrupts_stderr_\n\n  # Record the first marginally acceptable shell.\n  marginal_=\n\n  # Search for a shell that meets our requirements.\n  for re_shell_ in __current__ \"${CONFIG_SHELL:-no_shell}\" \\\n      /bin/sh bash dash zsh pdksh fail\n  do\n    test \"$re_shell_\" = no_shell && continue\n\n    # If we've made it all the way to the sentinel, \"fail\" without\n    # finding even a marginal shell, skip this test.\n    if test \"$re_shell_\" = fail; then\n      test -z \"$marginal_\" && skip_ failed to find an adequate shell\n      re_shell_=$marginal_\n      break\n    fi\n\n    # When testing the current shell, simply \"eval\" the test code.\n    # Otherwise, run it via $re_shell_ -c ...\n    if test \"$re_shell_\" = __current__; then\n      # 'eval'ing this code makes Solaris 10's /bin/sh exit with\n      # $? set to 2.  It does not evaluate any of the code after the\n      # \"unexpected\" first '('.  Thus, we must run it in a subshell.\n      ( eval \"$gl_shell_test_script_\" ) > /dev/null 2>&1\n    else\n      \"$re_shell_\" -c \"$gl_shell_test_script_\" 2>/dev/null\n    fi\n\n    st_=$?\n\n    # $re_shell_ works just fine.  Use it.\n    if test $st_ = 10; then\n      gl_set_x_corrupts_stderr_=false\n      break\n    fi\n\n    # If this is our first marginally acceptable shell, remember it.\n    if test \"$st_:$marginal_\" = 9: ; then\n      marginal_=\"$re_shell_\"\n      gl_set_x_corrupts_stderr_=true\n    fi\n  done\n\n  if test \"$re_shell_\" != __current__; then\n    # Found a usable shell.  Preserve -v and -x.\n    case $- in\n      *v*x* | *x*v*) opts_=-vx ;;\n      *v*) opts_=-v ;;\n      *x*) opts_=-x ;;\n      *) opts_= ;;\n    esac\n    re_shell=$re_shell_\n    export re_shell\n    exec \"$re_shell_\" $opts_ \"$0\" --no-reexec \"$@\"\n    echo \"$ME_: exec failed\" 1>&2\n    exit 127\n  fi\nfi\n\n# If this is bash, turn off all aliases.\ntest -n \"$BASH_VERSION\" && unalias -a\n\n# Note that when supporting $EXEEXT (transparently mapping from PROG_NAME to\n# PROG_NAME.exe), we want to support hyphen-containing names like test-acos.\n# That is part of the shell-selection test above.  Why use aliases rather\n# than functions?  Because support for hyphen-containing aliases is more\n# widespread than that for hyphen-containing function names.\ntest -n \"$EXEEXT\" && shopt -s expand_aliases\n\n# Enable glibc's malloc-perturbing option.\n# This is useful for exposing code that depends on the fact that\n# malloc-related functions often return memory that is mostly zeroed.\n# If you have the time and cycles, use valgrind to do an even better job.\n: ${MALLOC_PERTURB_=87}\nexport MALLOC_PERTURB_\n\n# This is a stub function that is run upon trap (upon regular exit and\n# interrupt).  Override it with a per-test function, e.g., to unmount\n# a partition, or to undo any other global state changes.\ncleanup_ () { :; }\n\n# Emit a header similar to that from diff -u;  Print the simulated \"diff\"\n# command so that the order of arguments is clear.  Don't bother with @@ lines.\nemit_diff_u_header_ ()\n{\n  printf '%s\\n' \"diff -u $*\" \\\n    \"--- $1\t1970-01-01\" \\\n    \"+++ $2\t1970-01-01\"\n}\n\n# Arrange not to let diff or cmp operate on /dev/null,\n# since on some systems (at least OSF/1 5.1), that doesn't work.\n# When there are not two arguments, or no argument is /dev/null, return 2.\n# When one argument is /dev/null and the other is not empty,\n# cat the nonempty file to stderr and return 1.\n# Otherwise, return 0.\ncompare_dev_null_ ()\n{\n  test $# = 2 || return 2\n\n  if test \"x$1\" = x/dev/null; then\n    test -s \"$2\" || return 0\n    emit_diff_u_header_ \"$@\"; sed 's/^/+/' \"$2\"\n    return 1\n  fi\n\n  if test \"x$2\" = x/dev/null; then\n    test -s \"$1\" || return 0\n    emit_diff_u_header_ \"$@\"; sed 's/^/-/' \"$1\"\n    return 1\n  fi\n\n  return 2\n}\n\nif diff_out_=`exec 2>/dev/null; diff -u \"$0\" \"$0\" < /dev/null` \\\n   && diff -u Makefile \"$0\" 2>/dev/null | grep '^[+]#!' >/dev/null; then\n  # diff accepts the -u option and does not (like AIX 7 'diff') produce an\n  # extra space on column 1 of every content line.\n  if test -z \"$diff_out_\"; then\n    compare_ () { diff -u \"$@\"; }\n  else\n    compare_ ()\n    {\n      if diff -u \"$@\" > diff.out; then\n        # No differences were found, but Solaris 'diff' produces output\n        # \"No differences encountered\". Hide this output.\n        rm -f diff.out\n        true\n      else\n        cat diff.out\n        rm -f diff.out\n        false\n      fi\n    }\n  fi\nelif\n  for diff_opt_ in -U3 -c '' no; do\n    test \"$diff_opt_\" = no && break\n    diff_out_=`exec 2>/dev/null; diff $diff_opt_ \"$0\" \"$0\" </dev/null` && break\n  done\n  test \"$diff_opt_\" != no\nthen\n  if test -z \"$diff_out_\"; then\n    compare_ () { diff $diff_opt_ \"$@\"; }\n  else\n    compare_ ()\n    {\n      if diff $diff_opt_ \"$@\" > diff.out; then\n        # No differences were found, but AIX and HP-UX 'diff' produce output\n        # \"No differences encountered\" or \"There are no differences between the\n        # files.\". Hide this output.\n        rm -f diff.out\n        true\n      else\n        cat diff.out\n        rm -f diff.out\n        false\n      fi\n    }\n  fi\nelif cmp -s /dev/null /dev/null 2>/dev/null; then\n  compare_ () { cmp -s \"$@\"; }\nelse\n  compare_ () { cmp \"$@\"; }\nfi\n\n# Usage: compare EXPECTED ACTUAL\n#\n# Given compare_dev_null_'s preprocessing, defer to compare_ if 2 or more.\n# Otherwise, propagate $? to caller: any diffs have already been printed.\ncompare ()\n{\n  # This looks like it can be factored to use a simple \"case $?\"\n  # after unchecked compare_dev_null_ invocation, but that would\n  # fail in a \"set -e\" environment.\n  if compare_dev_null_ \"$@\"; then\n    return 0\n  else\n    case $? in\n      1) return 1;;\n      *) compare_ \"$@\";;\n    esac\n  fi\n}\n\n# An arbitrary prefix to help distinguish test directories.\ntestdir_prefix_ () { printf gt; }\n\n# Run the user-overridable cleanup_ function, remove the temporary\n# directory and exit with the incoming value of $?.\nremove_tmp_ ()\n{\n  __st=$?\n  cleanup_\n  # cd out of the directory we're about to remove\n  cd \"$initial_cwd_\" || cd / || cd /tmp\n  chmod -R u+rwx \"$test_dir_\"\n  # If removal fails and exit status was to be 0, then change it to 1.\n  rm -rf \"$test_dir_\" || { test $__st = 0 && __st=1; }\n  exit $__st\n}\n\n# Given a directory name, DIR, if every entry in it that matches *.exe\n# contains only the specified bytes (see the case stmt below), then print\n# a space-separated list of those names and return 0.  Otherwise, don't\n# print anything and return 1.  Naming constraints apply also to DIR.\nfind_exe_basenames_ ()\n{\n  feb_dir_=$1\n  feb_fail_=0\n  feb_result_=\n  feb_sp_=\n  for feb_file_ in $feb_dir_/*.exe; do\n    # If there was no *.exe file, or there existed a file named \"*.exe\" that\n    # was deleted between the above glob expansion and the existence test\n    # below, just skip it.\n    test \"x$feb_file_\" = \"x$feb_dir_/*.exe\" && test ! -f \"$feb_file_\" \\\n      && continue\n    # Exempt [.exe, since we can't create a function by that name, yet\n    # we can't invoke [ by PATH search anyways due to shell builtins.\n    test \"x$feb_file_\" = \"x$feb_dir_/[.exe\" && continue\n    case $feb_file_ in\n      *[!-a-zA-Z/0-9_.+]*) feb_fail_=1; break;;\n      *) # Remove leading file name components as well as the .exe suffix.\n         feb_file_=${feb_file_##*/}\n         feb_file_=${feb_file_%.exe}\n         feb_result_=\"$feb_result_$feb_sp_$feb_file_\";;\n    esac\n    feb_sp_=' '\n  done\n  test $feb_fail_ = 0 && printf %s \"$feb_result_\"\n  return $feb_fail_\n}\n\n# Consider the files in directory, $1.\n# For each file name of the form PROG.exe, create an alias named\n# PROG that simply invokes PROG.exe, then return 0.  If any selected\n# file name or the directory name, $1, contains an unexpected character,\n# define no alias and return 1.\ncreate_exe_shims_ ()\n{\n  case $EXEEXT in\n    '') return 0 ;;\n    .exe) ;;\n    *) echo \"$0: unexpected \\$EXEEXT value: $EXEEXT\" 1>&2; return 1 ;;\n  esac\n\n  base_names_=`find_exe_basenames_ $1` \\\n    || { echo \"$0 (exe_shim): skipping directory: $1\" 1>&2; return 0; }\n\n  if test -n \"$base_names_\"; then\n    for base_ in $base_names_; do\n      alias \"$base_\"=\"$base_$EXEEXT\"\n    done\n  fi\n\n  return 0\n}\n\n# Use this function to prepend to PATH an absolute name for each\n# specified, possibly-$initial_cwd_-relative, directory.\npath_prepend_ ()\n{\n  while test $# != 0; do\n    path_dir_=$1\n    case $path_dir_ in\n      '') fail_ \"invalid path dir: '$1'\";;\n      /*) abs_path_dir_=$path_dir_;;\n      *) abs_path_dir_=$initial_cwd_/$path_dir_;;\n    esac\n    case $abs_path_dir_ in\n      *:*) fail_ \"invalid path dir: '$abs_path_dir_'\";;\n    esac\n    PATH=\"$abs_path_dir_:$PATH\"\n\n    # Create an alias, FOO, for each FOO.exe in this directory.\n    create_exe_shims_ \"$abs_path_dir_\" \\\n      || fail_ \"something failed (above): $abs_path_dir_\"\n    shift\n  done\n  export PATH\n}\n\nsetup_ ()\n{\n  if test \"$VERBOSE\" = yes; then\n    # Test whether set -x may cause the selected shell to corrupt an\n    # application's stderr.  Many do, including zsh-4.3.10 and the /bin/sh\n    # from SunOS 5.11, OpenBSD 4.7 and Irix 5.x and 6.5.\n    # If enabling verbose output this way would cause trouble, simply\n    # issue a warning and refrain.\n    if $gl_set_x_corrupts_stderr_; then\n      warn_ \"using SHELL=$SHELL with 'set -x' corrupts stderr\"\n    else\n      set -x\n    fi\n  fi\n\n  initial_cwd_=$PWD\n\n  pfx_=`testdir_prefix_`\n  test_dir_=`mktempd_ \"$initial_cwd_\" \"$pfx_-$ME_.XXXX\"` \\\n    || fail_ \"failed to create temporary directory in $initial_cwd_\"\n  cd \"$test_dir_\" || fail_ \"failed to cd to temporary directory\"\n\n  # As autoconf-generated configure scripts do, ensure that IFS\n  # is defined initially, so that saving and restoring $IFS works.\n  gl_init_sh_nl_='\n'\n  IFS=\" \"\"\t$gl_init_sh_nl_\"\n\n  # This trap statement, along with a trap on 0 below, ensure that the\n  # temporary directory, $test_dir_, is removed upon exit as well as\n  # upon receipt of any of the listed signals.\n  for sig_ in 1 2 3 13 15; do\n    eval \"trap 'Exit $(expr $sig_ + 128)' $sig_\"\n  done\n}\n\n# Create a temporary directory, much like mktemp -d does.\n# Written by Jim Meyering.\n#\n# Usage: mktempd_ /tmp phoey.XXXXXXXXXX\n#\n# First, try to use the mktemp program.\n# Failing that, we'll roll our own mktemp-like function:\n#  - try to get random bytes from /dev/urandom\n#  - failing that, generate output from a combination of quickly-varying\n#      sources and gzip.  Ignore non-varying gzip header, and extract\n#      \"random\" bits from there.\n#  - given those bits, map to file-name bytes using tr, and try to create\n#      the desired directory.\n#  - make only $MAX_TRIES_ attempts\n\n# Helper function.  Print $N pseudo-random bytes from a-zA-Z0-9.\nrand_bytes_ ()\n{\n  n_=$1\n\n  # Maybe try openssl rand -base64 $n_prime_|tr '+/=\\012' abcd first?\n  # But if they have openssl, they probably have mktemp, too.\n\n  chars_=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\n  dev_rand_=/dev/urandom\n  if test -r \"$dev_rand_\"; then\n    # Note: 256-length($chars_) == 194; 3 copies of $chars_ is 186 + 8 = 194.\n    dd ibs=$n_ count=1 if=$dev_rand_ 2>/dev/null \\\n      | LC_ALL=C tr -c $chars_ 01234567$chars_$chars_$chars_\n    return\n  fi\n\n  n_plus_50_=`expr $n_ + 50`\n  cmds_='date; date +%N; free; who -a; w; ps auxww; ps ef; netstat -n'\n  data_=` (eval \"$cmds_\") 2>&1 | gzip `\n\n  # Ensure that $data_ has length at least 50+$n_\n  while :; do\n    len_=`echo \"$data_\"|wc -c`\n    test $n_plus_50_ -le $len_ && break;\n    data_=` (echo \"$data_\"; eval \"$cmds_\") 2>&1 | gzip `\n  done\n\n  echo \"$data_\" \\\n    | dd bs=1 skip=50 count=$n_ 2>/dev/null \\\n    | LC_ALL=C tr -c $chars_ 01234567$chars_$chars_$chars_\n}\n\nmktempd_ ()\n{\n  case $# in\n  2);;\n  *) fail_ \"Usage: mktempd_ DIR TEMPLATE\";;\n  esac\n\n  destdir_=$1\n  template_=$2\n\n  MAX_TRIES_=4\n\n  # Disallow any trailing slash on specified destdir:\n  # it would subvert the post-mktemp \"case\"-based destdir test.\n  case $destdir_ in\n  / | //) destdir_slash_=$destdir;;\n  */) fail_ \"invalid destination dir: remove trailing slash(es)\";;\n  *) destdir_slash_=$destdir_/;;\n  esac\n\n  case $template_ in\n  *XXXX) ;;\n  *) fail_ \\\n       \"invalid template: $template_ (must have a suffix of at least 4 X's)\";;\n  esac\n\n  # First, try to use mktemp.\n  d=`unset TMPDIR; { mktemp -d -t -p \"$destdir_\" \"$template_\"; } 2>/dev/null` &&\n\n  # The resulting name must be in the specified directory.\n  case $d in \"$destdir_slash_\"*) :;; *) false;; esac &&\n\n  # It must have created the directory.\n  test -d \"$d\" &&\n\n  # It must have 0700 permissions.  Handle sticky \"S\" bits.\n  perms=`ls -dgo \"$d\" 2>/dev/null` &&\n  case $perms in drwx--[-S]---*) :;; *) false;; esac && {\n    echo \"$d\"\n    return\n  }\n\n  # If we reach this point, we'll have to create a directory manually.\n\n  # Get a copy of the template without its suffix of X's.\n  base_template_=`echo \"$template_\"|sed 's/XX*$//'`\n\n  # Calculate how many X's we've just removed.\n  template_length_=`echo \"$template_\" | wc -c`\n  nx_=`echo \"$base_template_\" | wc -c`\n  nx_=`expr $template_length_ - $nx_`\n\n  err_=\n  i_=1\n  while :; do\n    X_=`rand_bytes_ $nx_`\n    candidate_dir_=\"$destdir_slash_$base_template_$X_\"\n    err_=`mkdir -m 0700 \"$candidate_dir_\" 2>&1` \\\n      && { echo \"$candidate_dir_\"; return; }\n    test $MAX_TRIES_ -le $i_ && break;\n    i_=`expr $i_ + 1`\n  done\n  fail_ \"$err_\"\n}\n\n# If you want to override the testdir_prefix_ function,\n# or to add more utility functions, use this file.\ntest -f \"$srcdir/init.cfg\" \\\n  && . \"$srcdir/init.cfg\"\n\nsetup_ \"$@\"\n# This trap is here, rather than in the setup_ function, because some\n# shells run the exit trap at shell function exit, rather than script exit.\ntrap remove_tmp_ 0\n"
  },
  {
    "path": "tests/gzip/keep.sh",
    "content": "#!/bin/sh\n# Exercise the --keep option.\n\n# Copyright (C) 2013-2016 Free Software Foundation, Inc.\n\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n# limit so don't run it by default.\n\n. \"${srcdir=.}/init.sh\"; path_prepend_ .\n\necho fooooooooo > in || framework_failure_\ncp in orig || framework_failure_\n\nfail=0\n\n# Compress and decompress both with and without --keep.\nfor k in --keep ''; do\n  # With --keep, the source must be retained, otherwise, it must be removed.\n  case $k in --keep) op='||' ;; *) op='&&' ;; esac\n\n  gzip $k in || fail=1\n  eval \"test -f in $op fail=1\"\n  test -f in.gz || fail=1\n  rm -f in || fail=1\n\n  gzip -d $k in.gz || fail=1\n  eval \"test -f in.gz $op fail=1\"\n  test -f in || fail=1\n  compare in orig || fail=1\n  rm -f in.gz || fail=1\ndone\n\ncp orig in || framework_failure_\nlog=$(gzip -kv in 2>&1) || fail=1\ncase $log in\n  *'created in.gz'*) ;;\n  *) fail=1;;\nesac\n\nExit $fail\n"
  },
  {
    "path": "tests/gzip/list.sh",
    "content": "#!/bin/sh\n# Exercise the --list option.\n\n# Copyright 2016 Free Software Foundation, Inc.\n\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n# limit so don't run it by default.\n\n. \"${srcdir=.}/init.sh\"; path_prepend_ .\n\necho zoology zucchini > in || framework_failure_\ncp in orig || framework_failure_\n\ngzip -l in && fail=1\ngzip -9 in || fail=1\ngzip -l in.gz >out1 || fail=1\ngzip -l in.gz | cat >out2 || fail=1\ncompare out1 out2 || fail=1\n\nExit $fail\n"
  },
  {
    "path": "tests/gzip/memcpy-abuse.sh",
    "content": "#!/bin/sh\n# Before gzip-1.4, this the use of memcpy in inflate_codes could\n# mistakenly operate on overlapping regions.  Exercise that code.\n\n# Copyright (C) 2010-2016 Free Software Foundation, Inc.\n\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n# limit so don't run it by default.\n\n. \"${srcdir=.}/init.sh\"; path_prepend_ .\n\n# The input must be larger than 32KiB and slightly\n# less uniform than e.g., all zeros.\nprintf wxy%032767d 0 | tee in | gzip > in.gz || framework_failure_\n\nfail=0\n\n# Before the fix, this would call memcpy with overlapping regions.\ngzip -dc in.gz > out || fail=1\n\ncompare in out || fail=1\n\nExit $fail\n"
  },
  {
    "path": "tests/gzip/mixed.sh",
    "content": "#!/bin/sh\n# Ensure that gzip -cdf handles mixed compressed/not-compressed data\n# Before gzip-1.5, it would produce invalid output.\n\n# Copyright (C) 2010-2016 Free Software Foundation, Inc.\n\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n# limit so don't run it by default.\n\n. \"${srcdir=.}/init.sh\"; path_prepend_ .\n\nprintf 'xxx\\nyyy\\n'      > exp2 || framework_failure_\nprintf 'aaa\\nbbb\\nccc\\n' > exp3 || framework_failure_\n\nfail=0\n\n(echo xxx; echo yyy) > in || fail=1\ngzip -cdf < in > out || fail=1\ncompare exp2 out || fail=1\n\n# Uncompressed input, followed by compressed data.\n# Currently fails, so skip it.\n# (echo xxx; echo yyy|gzip) > in || fail=1\n# gzip -cdf < in > out || fail=1\n# compare exp2 out || fail=1\n\n# Compressed input, followed by regular (not-compressed) data.\n(echo xxx|gzip; echo yyy) > in || fail=1\ngzip -cdf < in > out || fail=1\ncompare exp2 out || fail=1\n\n(echo xxx|gzip; echo yyy|gzip) > in || fail=1\ngzip -cdf < in > out || fail=1\ncompare exp2 out || fail=1\n\nin_str=0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-+=%\nfor i in 0 1 2 3 4 5 6 7 8 9 a; do in_str=\"$in_str$in_str\" ;done\n\n# Start with some small sizes.  $(seq 64)\nsizes=$(i=0; while :; do echo $i; test $i = 64 && break; i=$(expr $i + 1); done)\n\n# gzip's internal buffer size is 32KiB + 64 bytes:\nsizes=\"$sizes 32831 32832 32833\"\n\n# 128KiB, +/- 1\nsizes=\"$sizes 131071 131072 131073\"\n\n# Ensure that \"gzip -cdf\" acts like cat, for a range of small input files.\ni=0\nfor i in $sizes; do\n  echo $i\n  printf %$i.${i}s $in_str > in\n  gzip -cdf < in > out\n  compare in out || fail=1\ndone\n\nExit $fail\n"
  },
  {
    "path": "tests/gzip/null-suffix-clobber.sh",
    "content": "#!/bin/sh\n# Before gzip-1.5, gzip -d -S '' k.gz would delete F.gz and not create \"F\"\n\n# Copyright (C) 2010-2016 Free Software Foundation, Inc.\n\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n# limit so don't run it by default.\n\n. \"${srcdir=.}/init.sh\"; path_prepend_ .\n\nprintf anything | gzip > F.gz || framework_failure_\necho y > yes || framework_failure_\necho \"gzip: invalid suffix ''\" > expected-err || framework_failure_\n\nfail=0\n\ngzip ---presume-input-tty -d -S '' F.gz < yes > out 2>err && fail=1\n\ncompare /dev/null out || fail=1\ncompare expected-err err || fail=1\n\ntest -f F.gz || fail=1\n\nExit $fail\n"
  },
  {
    "path": "tests/gzip/stdin.sh",
    "content": "#!/bin/sh\n# Ensure that gzip interprets \"-\" as stdin.\n\n# Copyright (C) 2009-2016 Free Software Foundation, Inc.\n\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n# limit so don't run it by default.\n\n. \"${srcdir=.}/init.sh\"; path_prepend_ .\n\nprintf a | gzip > in || framework_failure_\nprintf aaa > exp || framework_failure_\n\nfail=0\ngzip -dc in - in < in > out 2>err || fail=1\n\ncompare exp out || fail=1\ncompare /dev/null err || fail=1\n\nExit $fail\n"
  },
  {
    "path": "tests/gzip/test-driver.sh",
    "content": "#! /bin/sh\n# test-driver - basic testsuite driver script.\n\nscriptversion=2016-01-11.22; # UTC\n\n# Copyright (C) 2011-2015 Free Software Foundation, Inc.\n#\n# This program is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2, or (at your option)\n# any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\n# As a special exception to the GNU General Public License, if you\n# distribute this file as part of a program that contains a\n# configuration script generated by Autoconf, you may include it under\n# the same distribution terms that you use for the rest of that program.\n\n# This file is maintained in Automake, please report\n# bugs to <bug-automake@gnu.org> or send patches to\n# <automake-patches@gnu.org>.\n\n# Make unconditional expansion of undefined variables an error.  This\n# helps a lot in preventing typo-related bugs.\nset -u\n\nusage_error ()\n{\n  echo \"$0: $*\" >&2\n  print_usage >&2\n  exit 2\n}\n\nprint_usage ()\n{\n  cat <<END\nUsage:\n  test-driver --test-name=NAME --log-file=PATH --trs-file=PATH\n              [--expect-failure={yes|no}] [--color-tests={yes|no}]\n              [--enable-hard-errors={yes|no}] [--]\n              TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]\nThe '--test-name', '--log-file' and '--trs-file' options are mandatory.\nEND\n}\n\ntest_name= # Used for reporting.\nlog_file=  # Where to save the output of the test script.\ntrs_file=  # Where to save the metadata of the test run.\nexpect_failure=no\ncolor_tests=no\nenable_hard_errors=yes\nwhile test $# -gt 0; do\n  case $1 in\n  --help) print_usage; exit $?;;\n  --version) echo \"test-driver $scriptversion\"; exit $?;;\n  --test-name) test_name=$2; shift;;\n  --log-file) log_file=$2; shift;;\n  --trs-file) trs_file=$2; shift;;\n  --color-tests) color_tests=$2; shift;;\n  --expect-failure) expect_failure=$2; shift;;\n  --enable-hard-errors) enable_hard_errors=$2; shift;;\n  --) shift; break;;\n  -*) usage_error \"invalid option: '$1'\";;\n   *) break;;\n  esac\n  shift\ndone\n\nmissing_opts=\ntest x\"$test_name\" = x && missing_opts=\"$missing_opts --test-name\"\ntest x\"$log_file\"  = x && missing_opts=\"$missing_opts --log-file\"\ntest x\"$trs_file\"  = x && missing_opts=\"$missing_opts --trs-file\"\nif test x\"$missing_opts\" != x; then\n  usage_error \"the following mandatory options are missing:$missing_opts\"\nfi\n\nif test $# -eq 0; then\n  usage_error \"missing argument\"\nfi\n\nif test $color_tests = yes; then\n  # Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.\n  red='\u001b[0;31m' # Red.\n  grn='\u001b[0;32m' # Green.\n  lgn='\u001b[1;32m' # Light green.\n  blu='\u001b[1;34m' # Blue.\n  mgn='\u001b[0;35m' # Magenta.\n  std='\u001b[m'     # No color.\nelse\n  red= grn= lgn= blu= mgn= std=\nfi\n\ndo_exit='rm -f $log_file $trs_file; (exit $st); exit $st'\ntrap \"st=129; $do_exit\" 1\ntrap \"st=130; $do_exit\" 2\ntrap \"st=141; $do_exit\" 13\ntrap \"st=143; $do_exit\" 15\n\n# Test script is run here.\n\"$@\" >$log_file 2>&1\nestatus=$?\n\nif test $enable_hard_errors = no && test $estatus -eq 99; then\n  tweaked_estatus=1\nelse\n  tweaked_estatus=$estatus\nfi\n\ncase $tweaked_estatus:$expect_failure in\n  0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;\n  0:*)   col=$grn res=PASS  recheck=no  gcopy=no;;\n  77:*)  col=$blu res=SKIP  recheck=no  gcopy=yes;;\n  99:*)  col=$mgn res=ERROR recheck=yes gcopy=yes;;\n  *:yes) col=$lgn res=XFAIL recheck=no  gcopy=yes;;\n  *:*)   col=$red res=FAIL  recheck=yes gcopy=yes;;\nesac\n\n# Report the test outcome and exit status in the logs, so that one can\n# know whether the test passed or failed simply by looking at the '.log'\n# file, without the need of also peaking into the corresponding '.trs'\n# file (automake bug#11814).\necho \"$res $test_name (exit status: $estatus)\" >>$log_file\n\n# Report outcome to console.\necho \"${col}${res}${std}: $test_name\"\n\n# Register the test result, and other relevant metadata.\necho \":test-result: $res\" > $trs_file\necho \":global-test-result: $res\" >> $trs_file\necho \":recheck: $recheck\" >> $trs_file\necho \":copy-in-global-log: $gcopy\" >> $trs_file\n\n# Local Variables:\n# mode: shell-script\n# sh-indentation: 2\n# eval: (add-hook 'write-file-hooks 'time-stamp)\n# time-stamp-start: \"scriptversion=\"\n# time-stamp-format: \"%:y-%02m-%02d.%02H\"\n# time-stamp-time-zone: \"UTC0\"\n# time-stamp-end: \"; # UTC\"\n# End:\n\nexit $tweaked_estatus\n"
  },
  {
    "path": "tests/gzip/trailing-nul.sh",
    "content": "#!/bin/sh\n# gzip accepts trailing NUL bytes; don't fail if there is exactly one.\n# Before gzip-1.4, this would fail.\n\n# Copyright (C) 2009-2016 Free Software Foundation, Inc.\n\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n# limit so don't run it by default.\n\n. \"${srcdir=.}/init.sh\"; path_prepend_ .\n\n(echo 0 | gzip; printf '\\0') > 0.gz || framework_failure_\n(echo 00 | gzip; printf '\\0\\0') > 00.gz || framework_failure_\n(echo 1 | gzip; printf '\\1') > 1.gz || framework_failure_\n\nfail=0\n\nfor i in 0 00 1; do\n  gzip -d $i.gz; ret=$?\n  test $ret -eq $i || fail=1\n  test $ret = 1 && continue\n  echo $i > exp || fail=1\n  compare exp $i || fail=1\ndone\n\nExit $fail\n"
  },
  {
    "path": "tests/gzip/unpack-invalid.sh",
    "content": "#!/bin/sh\n# gzip should report invalid 'unpack' input when uncompressing.\n# With gzip-1.5, it would output invalid data instead.\n\n# Copyright (C) 2012-2016 Free Software Foundation, Inc.\n\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n# limit so don't run it by default.\n\n. \"${srcdir=.}/init.sh\"; path_prepend_ .\n\nfor input in \\\n  '\\037\\036\\000\\000\\037\\213\\010\\000\\000\\000\\000\\000\\002\\003\\036\\000\\000\\000\\002\\003\\037\\213\\010\\000\\000\\000\\000\\000\\002\\003\\355\\301\\001\\015\\000\\000\\000\\302\\240\\037\\000\\302\\240\\037\\213\\010\\000\\000\\000\\000\\000\\002\\003\\355\\301' \\\n  '\\037\\213\\010\\000\\000\\000\\000\\000\\002\\003\\355\\301\\001\\015\\000\\000\\000\\302\\240\\076\\366\\017\\370\\036\\016\\030\\000\\000\\000\\000\\000\\000\\000\\000\\000\\034\\010\\105\\140\\104\\025\\020\\047\\000\\000\\037\\036\\016\\030\\000\\000\\000'; do\n\n  printf \"$input\" >in || framework_failure_\n\n  if gzip -d <in >out 2>err; then\n    fail=1\n  else\n    fail=0\n  fi\ndone\n\nExit $fail\n"
  },
  {
    "path": "tests/gzip/z-suffix.sh",
    "content": "#!/bin/sh\n# Check that -Sz works.\n\n# Copyright 2014-2016 Free Software Foundation, Inc.\n\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n# limit so don't run it by default.\n\n. \"${srcdir=.}/init.sh\"; path_prepend_ .\n\nprintf anything > F && cp F G || framework_failure_\ngzip -Sz F || fail=1\ntest ! -f F || fail=1\ntest -f Fz || fail=1\ngzip -dSz F || fail=1\ntest ! -f Fz || fail=1\ncompare F G || fail\\1\n\nExit $fail\n"
  },
  {
    "path": "tests/gzip/zdiff.sh",
    "content": "#!/bin/sh\n# Exercise zdiff with two compressed inputs.\n# Before gzip-1.4, this would fail.\n\n# Copyright (C) 2009-2016 Free Software Foundation, Inc.\n\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n# limit so don't run it by default.\n\n. \"${srcdir=.}/init.sh\"; path_prepend_ .\n\necho a > a || framework_failure_\necho b > b || framework_failure_\ngzip a b || framework_failure_\n\ncat <<EOF > exp\n1c1\n< a\n---\n> b\nEOF\n\nfail=0\nzdiff a.gz b.gz > out 2>&1\ntest $? = 1 || fail=1\n\ncompare exp out || fail=1\n\nrm -f out\n# expect success, for equal files\nzdiff a.gz a.gz > out 2> err || fail=1\n# expect no output\ntest -s out && fail=1\n# expect no stderr\ntest -s err && fail=1\n\nExit $fail\n"
  },
  {
    "path": "tests/gzip/zgrep-context.sh",
    "content": "#!/bin/sh\n# Ensure that zgrep -15 works.  Before gzip-1.5, it would fail.\n\n# Copyright (C) 2012-2016 Free Software Foundation, Inc.\n\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n# limit so don't run it by default.\n\n. \"${srcdir=.}/init.sh\"; path_prepend_ .\n\n# A limited replacement for seq: handle 1 or 2 args; increment must be 1\nseq()\n{\n  case $# in\n    1) start=1  final=$1;;\n    2) start=$1 final=$2;;\n    *) echo you lose 1>&2; exit 1;;\n  esac\n  awk 'BEGIN{for(i='$start';i<='$final';i++) print i}' < /dev/null\n}\n\nseq 40 > in || framework_failure_\ngzip < in > in.gz || framework_failure_\nseq 2 32 > exp || framework_failure_\n\n: ${GREP=grep}\n$GREP -15 17 - < in > out && compare exp out || {\n  echo >&2 \"$0: $GREP does not support context options; skipping this test\"\n  exit 77\n}\n\nfail=0\nzgrep -15 17 - < in.gz > out || fail=1\ncompare exp out || fail=1\n\nExit $fail\n"
  },
  {
    "path": "tests/gzip/zgrep-f.sh",
    "content": "#!/bin/sh\n# Ensure that zgrep -f - works like grep -f -\n# Before gzip-1.4, it would fail.\n\n# Copyright (C) 2009-2016 Free Software Foundation, Inc.\n\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n# limit so don't run it by default.\n\n. \"${srcdir=.}/init.sh\"; path_prepend_ .\n\nprintf 'needle\\nn2\\n' > n || framework_failure_\ncp n haystack || framework_failure_\ngzip haystack || framework_failure_\n\nfail=0\nzgrep -f - haystack.gz < n > out 2>&1 || fail=1\n\ncompare out n || fail=1\n\nif ${BASH_VERSION+:} false; then\n  set +o posix\n  # This failed with gzip 1.6.\n  cat n n >nn || framework_failure_\n  eval 'zgrep -h -f <(cat n) haystack.gz haystack.gz' >out || fail=1\n  compare out nn || fail=1\nfi\n\n# This failed with gzip 1.4.\necho a-b | zgrep -e - > /dev/null || fail=1\n\nExit $fail\n"
  },
  {
    "path": "tests/gzip/zgrep-signal.sh",
    "content": "#!/bin/sh\n# Check that zgrep is terminated gracefully by signal when\n# its grep/sed pipeline is terminated by a signal.\n\n# Copyright (C) 2010-2016 Free Software Foundation, Inc.\n\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n# limit so don't run it by default.\n\n. \"${srcdir=.}/init.sh\"; path_prepend_ .\n\necho a | gzip -c > f.gz || framework_failure_\n\ntest \"x$PERL\" = x && PERL=perl\n(\"$PERL\" -e 'use POSIX qw(dup2)') >/dev/null 2>&1 ||\n   skip_ \"no suitable perl found\"\n\n# Run the arguments as a command, in a process where stdout is a\n# dangling pipe and SIGPIPE has the default signal-handling action.\n# This can't be done portably in the shell, because if SIGPIPE is\n# ignored when the shell is entered, the shell might refuse to trap\n# it.  Fall back on Perl+POSIX, if available.  Take care to close the\n# pipe's read end before running the program; the equivalent of the\n# shell's \"command | :\" has a race condition in that COMMAND could\n# write before \":\" exits.\nwrite_to_dangling_pipe () {\n  program=${1?}\n  shift\n  args=\n  for arg; do\n    args=\"$args, '$arg'\"\n  done\n  \"$PERL\" -e '\n     use POSIX qw(dup2);\n     $SIG{PIPE} = \"DEFAULT\";\n     pipe my ($read_end, $write_end) or die \"pipe: $!\\n\";\n     dup2 fileno $write_end, 1 or die \"dup2: $!\\n\";\n     close $read_end or die \"close: $!\\n\";\n     exec '\"'$program'$args\"';\n  '\n}\n\nwrite_to_dangling_pipe cat f.gz f.gz\nsignal_status=$?\ntest 128 -lt $signal_status ||\n  framework_failure_ 'signal handling busted on this host'\n\nfail=0\n\nwrite_to_dangling_pipe zgrep a f.gz f.gz\ntest $? -eq $signal_status || fail=1\n\nExit $fail\n"
  },
  {
    "path": "tests/gzip/znew-k.sh",
    "content": "#!/bin/sh\n# Check that znew -K works without compress(1).\n\n# Copyright (C) 2010-2016 Free Software Foundation, Inc.\n\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n# limit so don't run it by default.\n\n. \"${srcdir=.}/init.sh\"; path_prepend_ .\n\ncat <<'EOF' >compress || framework_failure_\n#!/bin/sh\necho >&2 'compress has been invoked'\nexit 1\nEOF\nchmod +x compress || framework_failure_\n\n# Note that the basename must have a length of 6 or greater.\n# Otherwise, \"test -f $name\" below would fail.\nname=123456.Z\n\nprintf '%1012977s' ' ' | gzip -c > $name || framework_failure_\n\nfail=0\n\nznew -K $name || fail=1\ntest -f $name || fail=1\n\nExit $fail\n"
  },
  {
    "path": "tests/invalidDictionaries.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include <stddef.h>\n#include \"zstd.h\"\n\nstatic const char invalidRepCode[] = {\n  0x37, 0xa4, 0x30, 0xec, 0x2a, 0x00, 0x00, 0x00, 0x39, 0x10, 0xc0, 0xc2,\n  0xa6, 0x00, 0x0c, 0x30, 0xc0, 0x00, 0x03, 0x0c, 0x30, 0x20, 0x72, 0xf8,\n  0xb4, 0x6d, 0x4b, 0x9f, 0xfc, 0x97, 0x29, 0x49, 0xb2, 0xdf, 0x4b, 0x29,\n  0x7d, 0x4a, 0xfc, 0x83, 0x18, 0x22, 0x75, 0x23, 0x24, 0x44, 0x4d, 0x02,\n  0xb7, 0x97, 0x96, 0xf6, 0xcb, 0xd1, 0xcf, 0xe8, 0x22, 0xea, 0x27, 0x36,\n  0xb7, 0x2c, 0x40, 0x46, 0x01, 0x08, 0x23, 0x01, 0x00, 0x00, 0x06, 0x1e,\n  0x3c, 0x83, 0x81, 0xd6, 0x18, 0xd4, 0x12, 0x3a, 0x04, 0x00, 0x80, 0x03,\n  0x08, 0x0e, 0x12, 0x1c, 0x12, 0x11, 0x0d, 0x0e, 0x0a, 0x0b, 0x0a, 0x09,\n  0x10, 0x0c, 0x09, 0x05, 0x04, 0x03, 0x06, 0x06, 0x06, 0x02, 0x00, 0x03,\n  0x00, 0x00, 0x02, 0x02, 0x00, 0x04, 0x06, 0x03, 0x06, 0x08, 0x24, 0x6b,\n  0x0d, 0x01, 0x10, 0x04, 0x81, 0x07, 0x00, 0x00, 0x04, 0xb9, 0x58, 0x18,\n  0x06, 0x59, 0x92, 0x43, 0xce, 0x28, 0xa5, 0x08, 0x88, 0xc0, 0x80, 0x88,\n  0x8c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,\n  0x08, 0x00, 0x00, 0x00\n};\n\ntypedef struct dictionary_s {\n  const char *data;\n  size_t size;\n} dictionary;\n\nstatic const dictionary dictionaries[] = {\n  {invalidRepCode, sizeof(invalidRepCode)},\n  {NULL, 0},\n};\n\nint main(int argc, const char** argv) {\n  const dictionary *dict;\n  for (dict = dictionaries; dict->data != NULL; ++dict) {\n    ZSTD_CDict *cdict;\n    ZSTD_DDict *ddict;\n    cdict = ZSTD_createCDict(dict->data, dict->size, 1);\n    if (cdict) {\n      ZSTD_freeCDict(cdict);\n      return 1;\n    }\n    ddict = ZSTD_createDDict(dict->data, dict->size);\n    if (ddict) {\n      ZSTD_freeDDict(ddict);\n      return 2;\n    }\n  }\n\n  (void)argc;\n  (void)argv;\n  return 0;\n}\n"
  },
  {
    "path": "tests/largeDictionary.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include <assert.h>\n#include <stdio.h>\n#include <stddef.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include \"datagen.h\"\n#include \"mem.h\"\n#define ZSTD_STATIC_LINKING_ONLY\n#include \"zstd.h\"\n\nstatic int\ncompress(ZSTD_CCtx* cctx, ZSTD_DCtx* dctx,\n         void* dst, size_t dstCapacity,\n         void const* src, size_t srcSize,\n         void* roundtrip, ZSTD_EndDirective end)\n{\n    ZSTD_inBuffer in = {src, srcSize, 0};\n    ZSTD_outBuffer out = {dst, dstCapacity, 0};\n    int ended = 0;\n\n    while (!ended && (in.pos < in.size || out.pos > 0)) {\n        size_t rc;\n        out.pos = 0;\n        rc = ZSTD_compressStream2(cctx, &out, &in, end);\n        if (ZSTD_isError(rc))\n            return 1;\n        if (end == ZSTD_e_end && rc == 0)\n            ended = 1;\n        {\n            ZSTD_inBuffer rtIn = {dst, out.pos, 0};\n            ZSTD_outBuffer rtOut = {roundtrip, srcSize, 0};\n            rc = 1;\n            while (rtIn.pos < rtIn.size || rtOut.pos > 0) {\n                rtOut.pos = 0;\n                rc = ZSTD_decompressStream(dctx, &rtOut, &rtIn);\n                if (ZSTD_isError(rc)) {\n                    fprintf(stderr, \"Decompression error: %s\\n\", ZSTD_getErrorName(rc));\n                    return 1;\n                }\n                if (rc == 0)\n                    break;\n            }\n            if (ended && rc != 0) {\n                fprintf(stderr, \"Frame not finished!\\n\");\n                return 1;\n            }\n        }\n    }\n\n    return 0;\n}\n\nint main(int argc, const char** argv)\n{\n    ZSTD_CCtx* cctx = ZSTD_createCCtx();\n    ZSTD_DCtx* dctx = ZSTD_createDCtx();\n    const size_t dataSize = (size_t)1 << 30;\n    const size_t outSize = ZSTD_compressBound(dataSize);\n    const size_t bufferSize = (size_t)1 << 31;\n    char* buffer = (char*)malloc(bufferSize);\n    void* out = malloc(outSize);\n    void* roundtrip = malloc(dataSize);\n    int _exit_code = 1;\n    (void)argc;\n    (void)argv;\n\n    if (!buffer || !out || !roundtrip || !cctx || !dctx) {\n        fprintf(stderr, \"Allocation failure\\n\");\n        goto cleanup;\n    }\n\n    if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 31)))\n        goto cleanup;\n    if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 1)))\n        goto cleanup;\n    if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_overlapLog, 9)))\n        goto cleanup;\n    if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1)))\n        goto cleanup;\n    if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_strategy, ZSTD_btopt)))\n        goto cleanup;\n    if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_targetLength, 7)))\n        goto cleanup;\n    if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, 7)))\n        goto cleanup;\n    if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_searchLog, 1)))\n        goto cleanup;\n    if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, 10)))\n        goto cleanup;\n    if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_chainLog, 10)))\n        goto cleanup;\n\n    if (ZSTD_isError(ZSTD_DCtx_setParameter(dctx, ZSTD_d_windowLogMax, 31)))\n        goto cleanup;\n\n    RDG_genBuffer(buffer, bufferSize, 1.0, 0.0, 0xbeefcafe);\n\n    /* Compress 30 GB */\n    {\n        int i;\n        for (i = 0; i < 10; ++i) {\n            fprintf(stderr, \"Compressing 1 GB\\n\");\n            if (compress(cctx, dctx, out, outSize, buffer, dataSize, roundtrip, ZSTD_e_continue))\n                goto cleanup;\n        }\n    }\n    fprintf(stderr, \"Compressing 1 GB\\n\");\n    if (compress(cctx, dctx, out, outSize, buffer, dataSize, roundtrip, ZSTD_e_end))\n        goto cleanup;\n\n    _exit_code = 0;\n    fprintf(stderr, \"Success!\\n\");\n\ncleanup:\n    free(roundtrip);\n    free(out);\n    free(buffer);\n    ZSTD_freeDCtx(dctx);\n    ZSTD_freeCCtx(cctx);\n    return _exit_code;\n}\n"
  },
  {
    "path": "tests/legacy.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/*\n    This program uses hard-coded data compressed with Zstd legacy versions\n    and tests that the API decompresses them correctly\n*/\n\n/*===========================================\n*   Dependencies\n*==========================================*/\n#include <stddef.h>              /* size_t */\n#include <stdlib.h>              /* malloc, free */\n#include <stdio.h>               /* fprintf */\n#include <string.h>              /* strlen */\n#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_decompressBound */\n#include \"zstd.h\"\n#include \"zstd_errors.h\"\n\n/*===========================================\n*   Macros\n*==========================================*/\n#define DISPLAY(...)          fprintf(stderr, __VA_ARGS__)\n\n/*===========================================\n*   Precompressed frames\n*==========================================*/\nconst char* const COMPRESSED; /* content is at end of file */\nsize_t const COMPRESSED_SIZE = 917;\nconst char* const EXPECTED; /* content is at end of file */\n\n\nstatic int testSimpleAPI(void)\n{\n    size_t const size = strlen(EXPECTED);\n    char* const output = malloc(size);\n\n    if (!output) {\n        DISPLAY(\"ERROR: Not enough memory!\\n\");\n        return 1;\n    }\n\n    {\n        size_t const ret = ZSTD_decompress(output, size, COMPRESSED, COMPRESSED_SIZE);\n        if (ZSTD_isError(ret)) {\n            if (ret == ZSTD_error_prefix_unknown) {\n                DISPLAY(\"ERROR: Invalid frame magic number, was this compiled \"\n                        \"without legacy support?\\n\");\n            } else {\n                DISPLAY(\"ERROR: %s\\n\", ZSTD_getErrorName(ret));\n            }\n            free(output);\n            return 1;\n        }\n        if (ret != size) {\n            DISPLAY(\"ERROR: Wrong decoded size\\n\");\n        }\n    }\n    if (memcmp(EXPECTED, output, size) != 0) {\n        DISPLAY(\"ERROR: Wrong decoded output produced\\n\");\n        free(output);\n        return 1;\n    }\n\n    free(output);\n    DISPLAY(\"Simple API OK\\n\");\n    return 0;\n}\n\n\nstatic int testStreamingAPI(void)\n{\n    int error_code = 0;\n    size_t const outBuffSize = ZSTD_DStreamOutSize();\n    char* const outBuff = malloc(outBuffSize);\n    ZSTD_DStream* const stream = ZSTD_createDStream();\n    ZSTD_inBuffer input = { COMPRESSED, COMPRESSED_SIZE, 0 };\n    size_t outputPos = 0;\n    int needsInit = 1;\n\n    if (outBuff == NULL) {\n        DISPLAY(\"ERROR: Could not allocate memory\\n\");\n        return 1;\n    }\n    if (stream == NULL) {\n        DISPLAY(\"ERROR: Could not create dstream\\n\");\n        free(outBuff);\n        return 1;\n    }\n\n    while (1) {\n        ZSTD_outBuffer output = {outBuff, outBuffSize, 0};\n        if (needsInit) {\n            size_t const ret = ZSTD_initDStream(stream);\n            if (ZSTD_isError(ret)) {\n                DISPLAY(\"ERROR: ZSTD_initDStream: %s\\n\", ZSTD_getErrorName(ret));\n                error_code = 1;\n                break;\n        }   }\n\n        {   size_t const ret = ZSTD_decompressStream(stream, &output, &input);\n            if (ZSTD_isError(ret)) {\n                DISPLAY(\"ERROR: ZSTD_decompressStream: %s\\n\", ZSTD_getErrorName(ret));\n                error_code = 1;\n                break;\n            }\n\n            if (ret == 0) {\n                needsInit = 1;\n        }   }\n\n        if (memcmp(outBuff, EXPECTED + outputPos, output.pos) != 0) {\n            DISPLAY(\"ERROR: Wrong decoded output produced\\n\");\n            error_code = 1;\n            break;\n        }\n        outputPos += output.pos;\n        if (input.pos == input.size && output.pos < output.size) {\n            break;\n        }\n    }\n\n    free(outBuff);\n    ZSTD_freeDStream(stream);\n    if (error_code == 0) DISPLAY(\"Streaming API OK\\n\");\n    return error_code;\n}\n\nstatic int testFrameDecoding(void)\n{\n    if (strlen(EXPECTED) > ZSTD_decompressBound(COMPRESSED, COMPRESSED_SIZE)) {\n        DISPLAY(\"ERROR: ZSTD_decompressBound: decompressed bound too small\\n\");\n        return 1;\n    }\n    {   const char* ip = COMPRESSED;\n        size_t remainingSize = COMPRESSED_SIZE;\n        while (1) {\n            size_t frameSize = ZSTD_findFrameCompressedSize(ip, remainingSize);\n            if (ZSTD_isError(frameSize)) {\n                DISPLAY(\"ERROR: ZSTD_findFrameCompressedSize: %s\\n\", ZSTD_getErrorName(frameSize));\n                return 1;\n            }\n            if (frameSize > remainingSize) {\n                DISPLAY(\"ERROR: ZSTD_findFrameCompressedSize: expected frameSize to align with src buffer\");\n                return 1;\n            }\n            ip += frameSize;\n            remainingSize -= frameSize;\n            if (remainingSize == 0) break;\n        }\n    }\n    DISPLAY(\"Frame Decoding OK\\n\");\n    return 0;\n}\n\nint main(void)\n{\n    {   int const ret = testSimpleAPI();\n        if (ret) return ret; }\n    {   int const ret = testStreamingAPI();\n        if (ret) return ret; }\n    {   int const ret = testFrameDecoding();\n        if (ret) return ret; }\n\n    DISPLAY(\"OK\\n\");\n    return 0;\n}\n\n/* Consists of the \"EXPECTED\" string compressed with default settings on\n    - v0.4.3\n    - v0.5.0\n    - v0.6.0\n    - v0.7.0\n    - v0.8.0\n*/\nconst char* const COMPRESSED =\n    \"\\x24\\xB5\\x2F\\xFD\\x00\\x00\\x00\\xBB\\xB0\\x02\\xC0\\x10\\x00\\x1E\\xB0\\x01\"\n    \"\\x02\\x00\\x00\\x80\\x00\\xE8\\x92\\x34\\x12\\x97\\xC8\\xDF\\xE9\\xF3\\xEF\\x53\"\n    \"\\xEA\\x1D\\x27\\x4F\\x0C\\x44\\x90\\x0C\\x8D\\xF1\\xB4\\x89\\x17\\x00\\x18\\x00\"\n    \"\\x18\\x00\\x3F\\xE6\\xE2\\xE3\\x74\\xD6\\xEC\\xC9\\x4A\\xE0\\x71\\x71\\x42\\x3E\"\n    \"\\x64\\x4F\\x6A\\x45\\x4E\\x78\\xEC\\x49\\x03\\x3F\\xC6\\x80\\xAB\\x8F\\x75\\x5E\"\n    \"\\x6F\\x2E\\x3E\\x7E\\xC6\\xDC\\x45\\x69\\x6C\\xC5\\xFD\\xC7\\x40\\xB8\\x84\\x8A\"\n    \"\\x01\\xEB\\xA8\\xD1\\x40\\x39\\x90\\x4C\\x64\\xF8\\xEB\\x53\\xE6\\x18\\x0B\\x67\"\n    \"\\x12\\xAD\\xB8\\x99\\xB3\\x5A\\x6F\\x8A\\x19\\x03\\x01\\x50\\x67\\x56\\xF5\\x9F\"\n    \"\\x35\\x84\\x60\\xA0\\x60\\x91\\xC9\\x0A\\xDC\\xAB\\xAB\\xE0\\xE2\\x81\\xFA\\xCF\"\n    \"\\xC6\\xBA\\x01\\x0E\\x00\\x54\\x00\\x00\\x19\\x00\\x00\\x54\\x14\\x00\\x24\\x24\"\n    \"\\x04\\xFE\\x04\\x84\\x4E\\x41\\x00\\x27\\xE2\\x02\\xC4\\xB1\\x00\\xD2\\x51\\x00\"\n    \"\\x79\\x58\\x41\\x28\\x00\\xE0\\x0C\\x01\\x68\\x65\\x00\\x04\\x13\\x0C\\xDA\\x0C\"\n    \"\\x80\\x22\\x06\\xC0\\x00\\x00\\x25\\xB5\\x2F\\xFD\\x00\\x00\\x00\\xAD\\x12\\xB0\"\n    \"\\x7D\\x1E\\xB0\\x01\\x02\\x00\\x00\\x80\\x00\\xE8\\x92\\x34\\x12\\x97\\xC8\\xDF\"\n    \"\\xE9\\xF3\\xEF\\x53\\xEA\\x1D\\x27\\x4F\\x0C\\x44\\x90\\x0C\\x8D\\xF1\\xB4\\x89\"\n    \"\\x03\\x01\\x50\\x67\\x56\\xF5\\x9F\\x35\\x84\\x60\\xA0\\x60\\x91\\xC9\\x0A\\xDC\"\n    \"\\xAB\\xAB\\xE0\\xE2\\x81\\xFA\\xCF\\xC6\\xBA\\xEB\\xA8\\xD1\\x40\\x39\\x90\\x4C\"\n    \"\\x64\\xF8\\xEB\\x53\\xE6\\x18\\x0B\\x67\\x12\\xAD\\xB8\\x99\\xB3\\x5A\\x6F\\x8A\"\n    \"\\xF9\\x63\\x0C\\xB8\\xFA\\x58\\xE7\\xF5\\xE6\\xE2\\xE3\\x67\\xCC\\x5D\\x94\\xC6\"\n    \"\\x56\\xDC\\x7F\\x0C\\x84\\x4B\\xA8\\xF8\\x63\\x2E\\x3E\\x4E\\x67\\xCD\\x9E\\xAC\"\n    \"\\x04\\x1E\\x17\\x27\\xE4\\x43\\xF6\\xA4\\x56\\xE4\\x84\\xC7\\x9E\\x34\\x0E\\x00\"\n    \"\\x00\\x32\\x40\\x80\\xA8\\x00\\x01\\x49\\x81\\xE0\\x3C\\x01\\x29\\x1D\\x00\\x87\"\n    \"\\xCE\\x80\\x75\\x08\\x80\\x72\\x24\\x00\\x7B\\x52\\x00\\x94\\x00\\x20\\xCC\\x01\"\n    \"\\x86\\xD2\\x00\\x81\\x09\\x83\\xC1\\x34\\xA0\\x88\\x01\\xC0\\x00\\x00\\x26\\xB5\"\n    \"\\x2F\\xFD\\x42\\xEF\\x00\\x00\\xA6\\x12\\xB0\\x7D\\x1E\\xB0\\x01\\x02\\x00\\x00\"\n    \"\\x54\\xA0\\xBA\\x24\\x8D\\xC4\\x25\\xF2\\x77\\xFA\\xFC\\xFB\\x94\\x7A\\xC7\\xC9\"\n    \"\\x13\\x03\\x11\\x24\\x43\\x63\\x3C\\x6D\\x22\\x03\\x01\\x50\\x67\\x56\\xF5\\x9F\"\n    \"\\x35\\x84\\x60\\xA0\\x60\\x91\\xC9\\x0A\\xDC\\xAB\\xAB\\xE0\\xE2\\x81\\xFA\\xCF\"\n    \"\\xC6\\xBA\\xEB\\xA8\\xD1\\x40\\x39\\x90\\x4C\\x64\\xF8\\xEB\\x53\\xE6\\x18\\x0B\"\n    \"\\x67\\x12\\xAD\\xB8\\x99\\xB3\\x5A\\x6F\\x8A\\xF9\\x63\\x0C\\xB8\\xFA\\x58\\xE7\"\n    \"\\xF5\\xE6\\xE2\\xE3\\x67\\xCC\\x5D\\x94\\xC6\\x56\\xDC\\x7F\\x0C\\x84\\x4B\\xA8\"\n    \"\\xF8\\x63\\x2E\\x3E\\x4E\\x67\\xCD\\x9E\\xAC\\x04\\x1E\\x17\\x27\\xE4\\x43\\xF6\"\n    \"\\xA4\\x56\\xE4\\x84\\xC7\\x9E\\x34\\x0E\\x00\\x35\\x0B\\x71\\xB5\\xC0\\x2A\\x5C\"\n    \"\\x26\\x94\\x22\\x20\\x8B\\x4C\\x8D\\x13\\x47\\x58\\x67\\x15\\x6C\\xF1\\x1C\\x4B\"\n    \"\\x54\\x10\\x9D\\x31\\x50\\x85\\x4B\\x54\\x0E\\x01\\x4B\\x3D\\x01\\xC0\\x00\\x00\"\n    \"\\x27\\xB5\\x2F\\xFD\\x20\\xEF\\x00\\x00\\xA6\\x12\\xE4\\x84\\x1F\\xB0\\x01\\x10\"\n    \"\\x00\\x00\\x00\\x35\\x59\\xA6\\xE7\\xA1\\xEF\\x7C\\xFC\\xBD\\x3F\\xFF\\x9F\\xEF\"\n    \"\\xEE\\xEF\\x61\\xC3\\xAA\\x31\\x1D\\x34\\x38\\x22\\x22\\x04\\x44\\x21\\x80\\x32\"\n    \"\\xAD\\x28\\xF3\\xD6\\x28\\x0C\\x0A\\x0E\\xD6\\x5C\\xAC\\x19\\x8D\\x20\\x5F\\x45\"\n    \"\\x02\\x2E\\x17\\x50\\x66\\x6D\\xAC\\x8B\\x9C\\x6E\\x07\\x73\\x46\\xBB\\x44\\x14\"\n    \"\\xE7\\x98\\xC3\\xB9\\x17\\x32\\x6E\\x33\\x7C\\x0E\\x21\\xB1\\xDB\\xCB\\x89\\x51\"\n    \"\\x23\\x34\\xAB\\x9D\\xBC\\x6D\\x20\\xF5\\x03\\xA9\\x91\\x4C\\x2E\\x1F\\x59\\xDB\"\n    \"\\xD9\\x35\\x67\\x4B\\x0C\\x95\\x79\\x10\\x00\\x85\\xA6\\x96\\x95\\x2E\\xDF\\x78\"\n    \"\\x7B\\x4A\\x5C\\x09\\x76\\x97\\xD1\\x5C\\x96\\x12\\x75\\x35\\xA3\\x55\\x4A\\xD4\"\n    \"\\x0B\\x00\\x35\\x0B\\x71\\xB5\\xC0\\x2A\\x5C\\xE6\\x08\\x45\\xF1\\x39\\x43\\xF1\"\n    \"\\x1C\\x4B\\x54\\x10\\x9D\\x31\\x50\\x85\\x4B\\x54\\x0E\\x01\\x4B\\x3D\\x01\\xC0\"\n    \"\\x00\\x00\\x28\\xB5\\x2F\\xFD\\x24\\xEF\\x35\\x05\\x00\\x92\\x0B\\x21\\x1F\\xB0\"\n    \"\\x01\\x10\\x00\\x00\\x00\\x35\\x59\\xA6\\xE7\\xA1\\xEF\\x7C\\xFC\\xBD\\x3F\\xFF\"\n    \"\\x9F\\xEF\\xEE\\xEF\\x61\\xC3\\xAA\\x31\\x1D\\x34\\x38\\x22\\x22\\x04\\x44\\x21\"\n    \"\\x80\\x32\\xAD\\x28\\xF3\\xD6\\x28\\x0C\\x0A\\x0E\\xD6\\x5C\\xAC\\x19\\x8D\\x20\"\n    \"\\x5F\\x45\\x02\\x2E\\x17\\x50\\x66\\x6D\\xAC\\x8B\\x9C\\x6E\\x07\\x73\\x46\\xBB\"\n    \"\\x44\\x14\\xE7\\x98\\xC3\\xB9\\x17\\x32\\x6E\\x33\\x7C\\x0E\\x21\\xB1\\xDB\\xCB\"\n    \"\\x89\\x51\\x23\\x34\\xAB\\x9D\\xBC\\x6D\\x20\\xF5\\x03\\xA9\\x91\\x4C\\x2E\\x1F\"\n    \"\\x59\\xDB\\xD9\\x35\\x67\\x4B\\x0C\\x95\\x79\\x10\\x00\\x85\\xA6\\x96\\x95\\x2E\"\n    \"\\xDF\\x78\\x7B\\x4A\\x5C\\x09\\x76\\x97\\xD1\\x5C\\x96\\x12\\x75\\x35\\xA3\\x55\"\n    \"\\x4A\\xD4\\x0B\\x00\\x35\\x0B\\x71\\xB5\\xC0\\x2A\\x5C\\xE6\\x08\\x45\\xF1\\x39\"\n    \"\\x43\\xF1\\x1C\\x4B\\x54\\x10\\x9D\\x31\\x50\\x85\\x4B\\x54\\x0E\\x01\\x4B\\x3D\"\n    \"\\x01\\xD2\\x2F\\x21\\x80\";\n\nconst char* const EXPECTED =\n    \"snowden is snowed in / he's now then in his snow den / when does the snow end?\\n\"\n    \"goodbye little dog / you dug some holes in your day / they'll be hard to fill.\\n\"\n    \"when life shuts a door, / just open it. it’s a door. / that is how doors work.\\n\"\n\n    \"snowden is snowed in / he's now then in his snow den / when does the snow end?\\n\"\n    \"goodbye little dog / you dug some holes in your day / they'll be hard to fill.\\n\"\n    \"when life shuts a door, / just open it. it’s a door. / that is how doors work.\\n\"\n\n    \"snowden is snowed in / he's now then in his snow den / when does the snow end?\\n\"\n    \"goodbye little dog / you dug some holes in your day / they'll be hard to fill.\\n\"\n    \"when life shuts a door, / just open it. it’s a door. / that is how doors work.\\n\"\n\n    \"snowden is snowed in / he's now then in his snow den / when does the snow end?\\n\"\n    \"goodbye little dog / you dug some holes in your day / they'll be hard to fill.\\n\"\n    \"when life shuts a door, / just open it. it’s a door. / that is how doors work.\\n\"\n\n    \"snowden is snowed in / he's now then in his snow den / when does the snow end?\\n\"\n    \"goodbye little dog / you dug some holes in your day / they'll be hard to fill.\\n\"\n    \"when life shuts a door, / just open it. it’s a door. / that is how doors work.\\n\";\n"
  },
  {
    "path": "tests/libzstd_builds.sh",
    "content": "#!/bin/sh -e\n\nDIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\nECHO=echo\nRM=\"rm -f\"\nGREP=\"grep\"\nINTOVOID=\"/dev/null\"\n\ndie() {\n    $ECHO \"$@\" 1>&2\n    exit 1\n}\n\nisPresent() {\n    $GREP $@ tmplog || die \"$@\" \"should be present\"\n}\n\nmustBeAbsent() {\n    $GREP $@ tmplog && die \"$@ should not be there !!\"\n    $ECHO \"$@ correctly not present\"  # for some reason, this $ECHO must exist, otherwise mustBeAbsent() always fails (??)\n}\n\n# default compilation : all features enabled - no zbuff, no legacy\n$ECHO \"testing default library compilation\"\nCFLAGS= make -C $DIR/../lib libzstd libzstd.a > $INTOVOID\nnm $DIR/../lib/libzstd.a | $GREP \"\\.o\" > tmplog\nisPresent \"zstd_compress.o\"\nisPresent \"zstd_decompress.o\"\nisPresent \"zdict.o\"\nmustBeAbsent \"zstd_v07.o\"\nmustBeAbsent \"zbuff_compress.o\"\n$RM tmplog\n\n# Check that the exec-stack bit isn't set\nreadelf -lW $DIR/../lib/libzstd.so | $GREP \"GNU_STACK\" > tmplog\nmustBeAbsent \"RWE\"\n$RM $DIR/../lib/libzstd.a $DIR/../lib/libzstd.so* tmplog\n\n# compression disabled => also disable zdict\n$ECHO \"testing with compression disabled\"\nZSTD_LIB_COMPRESSION=0 CFLAGS= make -C $DIR/../lib libzstd.a > $INTOVOID\nnm $DIR/../lib/libzstd.a | $GREP \"\\.o\" > tmplog\nmustBeAbsent \"zstd_compress.o\"\nisPresent \"zstd_decompress.o\"\nmustBeAbsent \"zdict.o\"\nmustBeAbsent \"zstd_v07.o\"\nmustBeAbsent \"zbuff_compress.o\"\n$RM $DIR/../lib/libzstd.a tmplog\n\n# decompression disabled => also disable legacy\n$ECHO \"testing with decompression disabled\"\nZSTD_LIB_DECOMPRESSION=0 CFLAGS= make -C $DIR/../lib libzstd.a > $INTOVOID\nnm $DIR/../lib/libzstd.a | $GREP \"\\.o\" > tmplog\nisPresent \"zstd_compress.o\"\nmustBeAbsent \"zstd_decompress.o\"\nisPresent \"zdict.o\"\nmustBeAbsent \"zstd_v07.o\"\nmustBeAbsent \"zbuff_compress.o\"\n$RM $DIR/../lib/libzstd.a tmplog\n\n# deprecated function disabled => only remove zbuff\n$ECHO \"testing with deprecated functions disabled\"\nZSTD_LIB_DEPRECATED=0 CFLAGS= make -C $DIR/../lib libzstd.a > $INTOVOID\nnm $DIR/../lib/libzstd.a | $GREP \"\\.o\" > tmplog\nisPresent \"zstd_compress.o\"\nisPresent \"zstd_decompress.o\"\nisPresent \"zdict.o\"\nmustBeAbsent \"zstd_v07.o\"\nmustBeAbsent \"zbuff_compress.o\"\n$RM $DIR/../lib/libzstd.a tmplog\n\n# deprecated function enabled => zbuff present\n$ECHO \"testing with deprecated functions enabled\"\nZSTD_LIB_DEPRECATED=1 CFLAGS= make -C $DIR/../lib libzstd.a > $INTOVOID\nnm $DIR/../lib/libzstd.a | $GREP \"\\.o\" > tmplog\nisPresent \"zstd_compress.o\"\nisPresent \"zstd_decompress.o\"\nisPresent \"zdict.o\"\nmustBeAbsent \"zstd_v07.o\"\nisPresent \"zbuff_compress.o\"\n$RM $DIR/../lib/libzstd.a tmplog\n\n# dictionary builder disabled => only remove zdict\n$ECHO \"testing with dictionary builder disabled\"\nZSTD_LIB_DICTBUILDER=0 CFLAGS= make -C $DIR/../lib libzstd.a > $INTOVOID\nnm $DIR/../lib/libzstd.a | $GREP \"\\.o\" > tmplog\nisPresent \"zstd_compress.o\"\nisPresent \"zstd_decompress.o\"\nmustBeAbsent \"zdict.o\"\nmustBeAbsent \"zstd_v07.o\"\nmustBeAbsent \"zbuff_compress.o\"\n$RM $DIR/../lib/libzstd.a tmplog\n\n# both decompression and dictionary builder disabled => only compression remains\n$ECHO \"testing with both decompression and dictionary builder disabled (only compression remains)\"\nZSTD_LIB_DECOMPRESSION=0 ZSTD_LIB_DICTBUILDER=0 CFLAGS= make -C $DIR/../lib libzstd.a > $INTOVOID\nnm $DIR/../lib/libzstd.a | $GREP \"\\.o\" > tmplog\nisPresent \"zstd_compress.o\"\nmustBeAbsent \"zstd_decompress.o\"\nmustBeAbsent \"zdict.o\"\nmustBeAbsent \"zstd_v07.o\"\nmustBeAbsent \"zbuff_compress.o\"\n$RM $DIR/../lib/libzstd.a tmplog\n\n# legacy support explicitly enabled\n$ECHO \"testing with legacy support explicitly enabled\"\nZSTD_LEGACY_SUPPORT=5 CFLAGS= make -C $DIR/../lib libzstd.a > $INTOVOID\nnm $DIR/../lib/libzstd.a | $GREP \"\\.o\" > tmplog\nisPresent \"zstd_compress.o\"\nisPresent \"zstd_decompress.o\"\nisPresent \"zdict.o\"\nisPresent \"zstd_v07.o\"\nmustBeAbsent \"zbuff_compress.o\"\n$RM $DIR/../lib/libzstd.a tmplog\n"
  },
  {
    "path": "tests/longmatch.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n#include <stdio.h>\n#include <stddef.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include \"mem.h\"\n#define ZSTD_STATIC_LINKING_ONLY\n#include \"zstd.h\"\n\nstatic int\ncompress(ZSTD_CStream *ctx, ZSTD_outBuffer out, const void *data, size_t size)\n{\n  ZSTD_inBuffer in = { data, size, 0 };\n  while (in.pos < in.size) {\n    ZSTD_outBuffer tmp = out;\n    const size_t rc = ZSTD_compressStream(ctx, &tmp, &in);\n    if (ZSTD_isError(rc)) return 1;\n  }\n  { ZSTD_outBuffer tmp = out;\n    const size_t rc = ZSTD_flushStream(ctx, &tmp);\n    if (rc != 0) { return 1; }\n  }\n  return 0;\n}\n\nint main(int argc, const char** argv)\n{\n  ZSTD_CStream* ctx;\n  unsigned windowLog = 18;\n  (void)argc;\n  (void)argv;\n  int _exit_code = 0;\n  /* Create stream */\n  ctx = ZSTD_createCCtx();\n  if (!ctx) { return 1; }\n  /* Set parameters */\n  if (ZSTD_isError(ZSTD_CCtx_setParameter(ctx, ZSTD_c_windowLog, windowLog))) {\n    _exit_code = 2;\n    goto _clean_ctx;\n  }\n  if (ZSTD_isError(ZSTD_CCtx_setParameter(ctx, ZSTD_c_chainLog, 13))) {\n    _exit_code = 2;\n    goto _clean_ctx;\n  }\n  if (ZSTD_isError(ZSTD_CCtx_setParameter(ctx, ZSTD_c_hashLog, 14))) {\n    _exit_code = 2;\n    goto _clean_ctx;\n  }\n  if (ZSTD_isError(ZSTD_CCtx_setParameter(ctx, ZSTD_c_searchLog, 1))) {\n    _exit_code = 2;\n    goto _clean_ctx;\n  }\n  if (ZSTD_isError(ZSTD_CCtx_setParameter(ctx, ZSTD_c_minMatch, 7))) {\n    _exit_code = 2;\n    goto _clean_ctx;\n  }\n  if (ZSTD_isError(ZSTD_CCtx_setParameter(ctx, ZSTD_c_targetLength, 16))) {\n    _exit_code = 2;\n    goto _clean_ctx;\n  }\n  if (ZSTD_isError(ZSTD_CCtx_setParameter(ctx, ZSTD_c_strategy, ZSTD_fast))) {\n    _exit_code = 2;\n    goto _clean_ctx;\n  }\n  {\n    U64 compressed = 0;\n    const U64 toCompress = ((U64)1) << 33;\n    const size_t size = 1 << windowLog;\n    size_t pos = 0;\n    char *srcBuffer = (char*) malloc(1 << windowLog);\n    char *dstBuffer = (char*) malloc(ZSTD_compressBound(1 << windowLog));\n    ZSTD_outBuffer out = { dstBuffer, ZSTD_compressBound(1 << windowLog), 0 };\n    const char match[] = \"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n    const size_t randomData = (1 << windowLog) - 2*sizeof(match);\n    size_t i;\n    printf(\"\\n ===   Long Match Test   === \\n\");\n    printf(\"Creating random data to produce long matches \\n\");\n    for (i = 0; i < sizeof(match); ++i) {\n      srcBuffer[i] = match[i];\n    }\n    for (i = 0; i < randomData; ++i) {\n      srcBuffer[sizeof(match) + i] = (char)(rand() & 0xFF);\n    }\n    for (i = 0; i < sizeof(match); ++i) {\n      srcBuffer[sizeof(match) + randomData + i] = match[i];\n    }\n    printf(\"Compressing, trying to generate a segfault \\n\");\n    if (compress(ctx, out, srcBuffer, size)) {\n       _exit_code = 1;\n       goto _clean_buffer;\n    }\n    compressed += size;\n    while (compressed < toCompress) {\n      const size_t block = rand() % (size - pos + 1);\n      if (pos == size) { pos = 0; }\n      if (compress(ctx, out, srcBuffer + pos, block)) {\n        _exit_code = 1;\n        goto _clean_buffer;\n      }\n      pos += block;\n      compressed += block;\n    }\n    printf(\"Compression completed successfully (no error triggered)\\n\");\n\n_clean_buffer:\n    free(srcBuffer);\n    free(dstBuffer);\n  }\n\n_clean_ctx:\n  ZSTD_freeCCtx(ctx);\n  return _exit_code;\n}\n"
  },
  {
    "path": "tests/loremOut.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* Implementation notes:\n * Generates a stream of Lorem ipsum paragraphs to stdout,\n * up to the requested size, which can be very large (> 4 GB).\n * Note that, beyond 1 paragraph, this generator produces\n * a different content than LOREM_genBuffer (even when using same seed).\n */\n\n#include \"loremOut.h\"\n#include <assert.h>\n#include <stdio.h>\n#include \"lorem.h\"    /* LOREM_genBlock */\n#include \"platform.h\" /* Compiler options, SET_BINARY_MODE */\n\n#define MIN(a, b) ((a) < (b) ? (a) : (b))\n#define LOREM_BLOCKSIZE (1 << 10)\nvoid LOREM_genOut(unsigned long long size, unsigned seed)\n{\n    char buff[LOREM_BLOCKSIZE] = { 0 };\n    unsigned long long total   = 0;\n    size_t genBlockSize        = (size_t)MIN(size, LOREM_BLOCKSIZE);\n\n    /* init */\n    SET_BINARY_MODE(stdout);\n\n    /* Generate Ipsum text, one paragraph at a time */\n    while (total < size) {\n        size_t generated =\n                LOREM_genBlock(buff, genBlockSize, seed++, total == 0, 0);\n        assert(generated <= genBlockSize);\n        total += generated;\n        assert(total <= size);\n        fwrite(buff,\n               1,\n               generated,\n               stdout); /* note: should check potential write error */\n        if (size - total < genBlockSize)\n            genBlockSize = (size_t)(size - total);\n    }\n    assert(total == size);\n}\n"
  },
  {
    "path": "tests/loremOut.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* LOREM_genOut():\n * Generate @size bytes of compressible data using lorem ipsum generator into\n * stdout.\n */\nvoid LOREM_genOut(unsigned long long size, unsigned seed);\n"
  },
  {
    "path": "tests/paramgrill.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/*-************************************\n*  Dependencies\n**************************************/\n#include \"util.h\"      /* Ensure platform.h is compiled first; also : compiler options, UTIL_GetFileSize */\n#include <stdlib.h>    /* malloc */\n#include <stdio.h>     /* fprintf, fopen, ftello64 */\n#include <string.h>    /* strcmp */\n#include <math.h>      /* log */\n#include <assert.h>\n\n#include \"timefn.h\"    /* SEC_TO_MICRO, UTIL_time_t, UTIL_clockSpanMicro, UTIL_clockSpanNano, UTIL_getTime */\n#include \"mem.h\"\n#define ZSTD_STATIC_LINKING_ONLY   /* ZSTD_parameters, ZSTD_estimateCCtxSize */\n#include \"zstd.h\"\n#include \"datagen.h\"\n#include \"xxhash.h\"\n#include \"benchfn.h\"\n#include \"benchzstd.h\"\n#include \"zstd_errors.h\"\n#include \"zstd_internal.h\"     /* should not be needed */\n\n\n/*-************************************\n*  Constants\n**************************************/\n#define PROGRAM_DESCRIPTION \"ZSTD parameters tester\"\n#define AUTHOR \"Yann Collet\"\n#define WELCOME_MESSAGE \"*** %s %s %i-bits, by %s ***\\n\", PROGRAM_DESCRIPTION, ZSTD_VERSION_STRING, (int)(sizeof(void*)*8), AUTHOR\n\n#define TIMELOOP_NANOSEC      (1*1000000000ULL) /* 1 second */\n#define NB_LEVELS_TRACKED 22   /* ensured being >= ZSTD_maxCLevel() in BMK_init_level_constraints() */\n\nstatic const size_t maxMemory = (sizeof(size_t)==4)  ?  (2 GB - 64 MB) : (size_t)(1ULL << ((sizeof(size_t)*8)-31));\n\n#define COMPRESSIBILITY_DEFAULT 0.50\n\nstatic const U64 g_maxVariationTime = 60 * SEC_TO_MICRO;\nstatic const int g_maxNbVariations = 64;\n\n\n/*-************************************\n*  Macros\n**************************************/\n#define DISPLAY(...)  fprintf(stderr, __VA_ARGS__)\n#define DISPLAYLEVEL(n, ...) if(g_displayLevel >= n) { fprintf(stderr, __VA_ARGS__); }\n#define DEBUGOUTPUT(...) { if (DEBUG) DISPLAY(__VA_ARGS__); }\n\n#define TIMED 0\n#ifndef DEBUG\n#  define DEBUG 0\n#endif\n\n#undef MIN\n#undef MAX\n#define MIN(a,b)   ( (a) < (b) ? (a) : (b) )\n#define MAX(a,b)   ( (a) > (b) ? (a) : (b) )\n#define CUSTOM_LEVEL 99\n#define BASE_CLEVEL 1\n\n#define FADT_MIN 0\n#define FADT_MAX ((U32)-1)\n\n#define WLOG_RANGE (ZSTD_WINDOWLOG_MAX - ZSTD_WINDOWLOG_MIN + 1)\n#define CLOG_RANGE (ZSTD_CHAINLOG_MAX - ZSTD_CHAINLOG_MIN + 1)\n#define HLOG_RANGE (ZSTD_HASHLOG_MAX - ZSTD_HASHLOG_MIN + 1)\n#define SLOG_RANGE (ZSTD_SEARCHLOG_MAX - ZSTD_SEARCHLOG_MIN + 1)\n#define MML_RANGE  (ZSTD_MINMATCH_MAX - ZSTD_MINMATCH_MIN + 1)\n#define TLEN_RANGE  17\n#define STRT_RANGE (ZSTD_STRATEGY_MAX - ZSTD_STRATEGY_MIN + 1)\n#define FADT_RANGE   3\n\n#define CHECKTIME(r) { if(BMK_timeSpan_s(g_time) > g_timeLimit_s) { DEBUGOUTPUT(\"Time Limit Reached\\n\"); return r; } }\n#define CHECKTIMEGT(ret, val, _gototag) { if(BMK_timeSpan_s(g_time) > g_timeLimit_s) { DEBUGOUTPUT(\"Time Limit Reached\\n\"); ret = val; goto _gototag; } }\n\n#define PARAM_UNSET ((U32)-2) /* can't be -1 b/c fadt uses -1 */\n\nstatic const char* g_stratName[ZSTD_STRATEGY_MAX+1] = {\n                \"(none)       \", \"ZSTD_fast    \", \"ZSTD_dfast   \",\n                \"ZSTD_greedy  \", \"ZSTD_lazy    \", \"ZSTD_lazy2   \",\n                \"ZSTD_btlazy2 \", \"ZSTD_btopt   \", \"ZSTD_btultra \",\n                \"ZSTD_btultra2\"};\n\nstatic const U32 tlen_table[TLEN_RANGE] = { 0, 1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 256, 512, 999 };\n\n\n/*-************************************\n*  Setup for Adding new params\n**************************************/\n\n/* indices for each of the variables */\ntypedef enum {\n    wlog_ind = 0,\n    clog_ind = 1,\n    hlog_ind = 2,\n    slog_ind = 3,\n    mml_ind  = 4,\n    tlen_ind = 5,\n    strt_ind = 6,\n    fadt_ind = 7, /* forceAttachDict */\n    NUM_PARAMS = 8\n} varInds_t;\n\ntypedef struct {\n    U32 vals[NUM_PARAMS];\n} paramValues_t;\n\n/* minimum value of parameters */\nstatic const U32 mintable[NUM_PARAMS] =\n        { ZSTD_WINDOWLOG_MIN, ZSTD_CHAINLOG_MIN, ZSTD_HASHLOG_MIN, ZSTD_SEARCHLOG_MIN, ZSTD_MINMATCH_MIN, ZSTD_TARGETLENGTH_MIN, ZSTD_STRATEGY_MIN, FADT_MIN };\n\n/* maximum value of parameters */\nstatic const U32 maxtable[NUM_PARAMS] =\n        { ZSTD_WINDOWLOG_MAX, ZSTD_CHAINLOG_MAX, ZSTD_HASHLOG_MAX, ZSTD_SEARCHLOG_MAX, ZSTD_MINMATCH_MAX, ZSTD_TARGETLENGTH_MAX, ZSTD_STRATEGY_MAX, FADT_MAX };\n\n/* # of values parameters can take on */\nstatic const U32 rangetable[NUM_PARAMS] =\n        { WLOG_RANGE, CLOG_RANGE, HLOG_RANGE, SLOG_RANGE, MML_RANGE, TLEN_RANGE, STRT_RANGE, FADT_RANGE };\n\n/* ZSTD_cctxSetParameter() index to set */\nstatic const ZSTD_cParameter cctxSetParamTable[NUM_PARAMS] =\n        { ZSTD_c_windowLog, ZSTD_c_chainLog, ZSTD_c_hashLog, ZSTD_c_searchLog, ZSTD_c_minMatch, ZSTD_c_targetLength, ZSTD_c_strategy, ZSTD_c_forceAttachDict };\n\n/* names of parameters */\nstatic const char* g_paramNames[NUM_PARAMS] =\n        { \"windowLog\", \"chainLog\", \"hashLog\",\"searchLog\", \"minMatch\", \"targetLength\", \"strategy\", \"forceAttachDict\" };\n\n/* shortened names of parameters */\nstatic const char* g_shortParamNames[NUM_PARAMS] =\n        { \"wlog\", \"clog\", \"hlog\", \"slog\", \"mml\", \"tlen\", \"strat\", \"fadt\" };\n\n/* maps value from { 0 to rangetable[param] - 1 } to valid paramvalues */\nstatic U32 rangeMap(varInds_t param, int ind)\n{\n    U32 const uind = (U32)MAX(MIN(ind, (int)rangetable[param] - 1), 0);\n    switch(param) {\n        case wlog_ind: /* using default: triggers -Wswitch-enum */\n        case clog_ind:\n        case hlog_ind:\n        case slog_ind:\n        case mml_ind:\n        case strt_ind:\n            return mintable[param] + uind;\n        case tlen_ind:\n            return tlen_table[uind];\n        case fadt_ind: /* 0, 1, 2 -> -1, 0, 1 */\n            return uind - 1;\n        case NUM_PARAMS:\n        default:;\n    }\n    DISPLAY(\"Error, not a valid param\\n \");\n    assert(0);\n    return (U32)-1;\n}\n\n/* inverse of rangeMap */\nstatic int invRangeMap(varInds_t param, U32 value)\n{\n    value = MIN(MAX(mintable[param], value), maxtable[param]);\n    switch(param) {\n        case wlog_ind:\n        case clog_ind:\n        case hlog_ind:\n        case slog_ind:\n        case mml_ind:\n        case strt_ind:\n            return (int)(value - mintable[param]);\n        case tlen_ind: /* bin search */\n        {\n            int lo = 0;\n            int hi = TLEN_RANGE;\n            while(lo < hi) {\n                int mid = (lo + hi) / 2;\n                if(tlen_table[mid] < value) {\n                    lo = mid + 1;\n                } if(tlen_table[mid] == value) {\n                    return mid;\n                } else {\n                    hi = mid;\n                }\n            }\n            return lo;\n        }\n        case fadt_ind:\n            return (int)value + 1;\n        case NUM_PARAMS:\n        default:;\n    }\n    DISPLAY(\"Error, not a valid param\\n \");\n    assert(0);\n    return -2;\n}\n\n/* display of params */\nstatic void displayParamVal(FILE* f, varInds_t param, unsigned value, int width)\n{\n    switch(param) {\n        case wlog_ind:\n        case clog_ind:\n        case hlog_ind:\n        case slog_ind:\n        case mml_ind:\n        case tlen_ind:\n            if(width) {\n                fprintf(f, \"%*u\", width, value);\n            } else {\n                fprintf(f, \"%u\", value);\n            }\n            break;\n        case strt_ind:\n            if(width) {\n                fprintf(f, \"%*s\", width, g_stratName[value]);\n            } else {\n                fprintf(f, \"%s\", g_stratName[value]);\n            }\n            break;\n        case fadt_ind:   /* force attach dict */\n            if(width) {\n                fprintf(f, \"%*d\", width, (int)value);\n            } else {\n                fprintf(f, \"%d\", (int)value);\n            }\n            break;\n        case NUM_PARAMS:\n        default:\n            DISPLAY(\"Error, not a valid param\\n \");\n            assert(0);\n            break;\n    }\n}\n\n\n/*-************************************\n*  Benchmark Parameters/Global Variables\n**************************************/\n\n/* General Utility */\nstatic U32 g_timeLimit_s = 99999;   /* about 27 hours */\nstatic UTIL_time_t g_time; /* to be used to compare solution finding speeds to compare to original */\nstatic U32 g_blockSize = 0;\nstatic U32 g_rand = 1;\n\n/* Display */\nstatic int g_displayLevel = 3;\nstatic BYTE g_silenceParams[NUM_PARAMS];   /* can selectively silence some params when displaying them */\n\n/* Mode Selection */\nstatic U32 g_singleRun = 0;\nstatic U32 g_optimizer = 0;\nstatic int g_optmode = 0;\n\n/* For cLevel Table generation */\nstatic U32 g_target = 0;\nstatic U32 g_noSeed = 0;\n\n/* For optimizer */\nstatic paramValues_t g_params; /* Initialized at the beginning of main w/ emptyParams() function */\nstatic double g_ratioMultiplier = 5.;\nstatic U32 g_strictness = PARAM_UNSET; /* range 1 - 100, measure of how strict  */\nstatic BMK_benchResult_t g_lvltarget;\n\ntypedef enum {\n    directMap,\n    xxhashMap,\n    noMemo\n} memoTableType_t;\n\ntypedef struct {\n    memoTableType_t tableType;\n    BYTE* table;\n    size_t tableLen;\n    varInds_t varArray[NUM_PARAMS];\n    size_t varLen;\n} memoTable_t;\n\ntypedef struct {\n    BMK_benchResult_t result;\n    paramValues_t params;\n} winnerInfo_t;\n\ntypedef struct {\n    U32 cSpeed;  /* bytes / sec */\n    U32 dSpeed;\n    U32 cMem;    /* bytes */\n} constraint_t;\n\ntypedef struct winner_ll_node winner_ll_node;\nstruct winner_ll_node {\n    winnerInfo_t res;\n    winner_ll_node* next;\n};\n\nstatic winner_ll_node* g_winners; /* linked list sorted ascending by cSize & cSpeed */\n\n/*\n * Additional Global Variables (Defined Above Use)\n * g_level_constraint\n * g_alreadyTested\n * g_maxTries\n * g_clockGranularity\n */\n\n\n/*-*******************************************************\n*  General Util Functions\n*********************************************************/\n\n/* nullified useless params, to ensure count stats */\n/* cleans up params for memoizing / display */\nstatic paramValues_t sanitizeParams(paramValues_t params)\n{\n    if (params.vals[strt_ind] == ZSTD_fast)\n        params.vals[clog_ind] = 0, params.vals[slog_ind] = 0;\n    if (params.vals[strt_ind] == ZSTD_dfast)\n        params.vals[slog_ind] = 0;\n    if ( (params.vals[strt_ind] < ZSTD_btopt) && (params.vals[strt_ind] != ZSTD_fast) )\n        params.vals[tlen_ind] = 0;\n\n    return params;\n}\n\nstatic ZSTD_compressionParameters pvalsToCParams(paramValues_t p)\n{\n    ZSTD_compressionParameters c;\n    memset(&c, 0, sizeof(ZSTD_compressionParameters));\n    c.windowLog = p.vals[wlog_ind];\n    c.chainLog = p.vals[clog_ind];\n    c.hashLog = p.vals[hlog_ind];\n    c.searchLog = p.vals[slog_ind];\n    c.minMatch = p.vals[mml_ind];\n    c.targetLength = p.vals[tlen_ind];\n    c.strategy = p.vals[strt_ind];\n    /* no forceAttachDict */\n    return c;\n}\n\nstatic paramValues_t cParamsToPVals(ZSTD_compressionParameters c)\n{\n    paramValues_t p;\n    varInds_t i;\n    p.vals[wlog_ind] = c.windowLog;\n    p.vals[clog_ind] = c.chainLog;\n    p.vals[hlog_ind] = c.hashLog;\n    p.vals[slog_ind] = c.searchLog;\n    p.vals[mml_ind]  = c.minMatch;\n    p.vals[tlen_ind] = c.targetLength;\n    p.vals[strt_ind] = c.strategy;\n\n    /* set all other params to their minimum value */\n    for (i = strt_ind + 1; i < NUM_PARAMS; i++) {\n        p.vals[i] = mintable[i];\n    }\n    return p;\n}\n\n/* equivalent of ZSTD_adjustCParams for paramValues_t */\nstatic paramValues_t\nadjustParams(paramValues_t p, const size_t maxBlockSize, const size_t dictSize)\n{\n    paramValues_t ot = p;\n    varInds_t i;\n    p = cParamsToPVals(ZSTD_adjustCParams(pvalsToCParams(p), maxBlockSize, dictSize));\n    if (!dictSize) { p.vals[fadt_ind] = 0; }\n    /* retain value of all other parameters */\n    for(i = strt_ind + 1; i < NUM_PARAMS; i++) {\n        p.vals[i] = ot.vals[i];\n    }\n    return p;\n}\n\nstatic size_t BMK_findMaxMem(U64 requiredMem)\n{\n    size_t const step = 64 MB;\n    void* testmem = NULL;\n\n    requiredMem = (((requiredMem >> 26) + 1) << 26);\n    if (requiredMem > maxMemory) requiredMem = maxMemory;\n\n    requiredMem += 2 * step;\n    while (!testmem && requiredMem > 0) {\n        testmem = malloc ((size_t)requiredMem);\n        requiredMem -= step;\n    }\n\n    free (testmem);\n    return (size_t) requiredMem;\n}\n\n/* accuracy in seconds only, span can be multiple years */\nstatic U32 BMK_timeSpan_s(const UTIL_time_t tStart)\n{\n    return (U32)(UTIL_clockSpanMicro(tStart) / 1000000ULL);\n}\n\nstatic U32 FUZ_rotl32(U32 x, U32 r)\n{\n    return ((x << r) | (x >> (32 - r)));\n}\n\nstatic U32 FUZ_rand(U32* src)\n{\n    const U32 prime1 = 2654435761U;\n    const U32 prime2 = 2246822519U;\n    U32 rand32 = *src;\n    rand32 *= prime1;\n    rand32 += prime2;\n    rand32  = FUZ_rotl32(rand32, 13);\n    *src = rand32;\n    return rand32 >> 5;\n}\n\n#define BOUNDCHECK(val,min,max) {                     \\\n    if (((val)<(min)) | ((val)>(max))) {              \\\n        DISPLAY(\"INVALID PARAMETER CONSTRAINTS\\n\");   \\\n        return 0;                                     \\\n}   }\n\nstatic int paramValid(const paramValues_t paramTarget)\n{\n    U32 i;\n    for(i = 0; i < NUM_PARAMS; i++) {\n        BOUNDCHECK(paramTarget.vals[i], mintable[i], maxtable[i]);\n    }\n    return 1;\n}\n\n/* cParamUnsetMin() :\n * if any parameter in paramTarget is not yet set,\n * it will receive its corresponding minimal value.\n * This function never fails */\nstatic paramValues_t cParamUnsetMin(paramValues_t paramTarget)\n{\n    varInds_t vi;\n    for (vi = 0; vi < NUM_PARAMS; vi++) {\n        if (paramTarget.vals[vi] == PARAM_UNSET) {\n            paramTarget.vals[vi] = mintable[vi];\n        }\n    }\n    return paramTarget;\n}\n\nstatic paramValues_t emptyParams(void)\n{\n    U32 i;\n    paramValues_t p;\n    for(i = 0; i < NUM_PARAMS; i++) {\n        p.vals[i] = PARAM_UNSET;\n    }\n    return p;\n}\n\nstatic winnerInfo_t initWinnerInfo(const paramValues_t p)\n{\n    winnerInfo_t w1;\n    w1.result.cSpeed = 0;\n    w1.result.dSpeed = 0;\n    w1.result.cMem = (size_t)-1;\n    w1.result.cSize = (size_t)-1;\n    w1.params = p;\n    return w1;\n}\n\nstatic paramValues_t\noverwriteParams(paramValues_t base, const paramValues_t mask)\n{\n    U32 i;\n    for(i = 0; i < NUM_PARAMS; i++) {\n        if(mask.vals[i] != PARAM_UNSET) {\n            base.vals[i] = mask.vals[i];\n        }\n    }\n    return base;\n}\n\nstatic void\nparamVaryOnce(const varInds_t paramIndex, const int amt, paramValues_t* ptr)\n{\n    ptr->vals[paramIndex] = rangeMap(paramIndex,\n                                     invRangeMap(paramIndex, ptr->vals[paramIndex]) + amt);\n}\n\n/* varies ptr by nbChanges respecting varyParams*/\nstatic void\nparamVariation(paramValues_t* ptr, memoTable_t* mtAll, const U32 nbChanges)\n{\n    paramValues_t p;\n    int validated = 0;\n    while (!validated) {\n        U32 i;\n        p = *ptr;\n        for (i = 0 ; i < nbChanges ; i++) {\n            const U32 changeID = (U32)FUZ_rand(&g_rand) % (mtAll[p.vals[strt_ind]].varLen << 1);\n            paramVaryOnce(mtAll[p.vals[strt_ind]].varArray[changeID >> 1],\n                          (int)((changeID & 1) << 1) - 1,\n                          &p);\n        }\n        validated = paramValid(p);\n    }\n    *ptr = p;\n}\n\n/* Completely random parameter selection */\nstatic paramValues_t randomParams(void)\n{\n    varInds_t v; paramValues_t p;\n    for(v = 0; v < NUM_PARAMS; v++) {\n        p.vals[v] = rangeMap(v, (int)(FUZ_rand(&g_rand) % rangetable[v]));\n    }\n    return p;\n}\n\nstatic U64 g_clockGranularity = 100000000ULL;\n\nstatic void init_clockGranularity(void)\n{\n    UTIL_time_t const clockStart = UTIL_getTime();\n    U64 el1 = 0, el2 = 0;\n    int i = 0;\n    do {\n        el1 = el2;\n        el2 = UTIL_clockSpanNano(clockStart);\n        if(el1 < el2) {\n            U64 iv = el2 - el1;\n            if(g_clockGranularity > iv) {\n                g_clockGranularity = iv;\n                i = 0;\n            } else {\n                i++;\n            }\n        }\n    } while(i < 10);\n    DEBUGOUTPUT(\"Granularity: %llu\\n\", (unsigned long long)g_clockGranularity);\n}\n\n/*-************************************\n*  Optimizer Util Functions\n**************************************/\n\n/* checks results are feasible */\nstatic int feasible(const BMK_benchResult_t results, const constraint_t target) {\n    return (results.cSpeed >= target.cSpeed)\n        && (results.dSpeed >= target.dSpeed)\n        && (results.cMem <= target.cMem)\n        && (!g_optmode || results.cSize <= g_lvltarget.cSize);\n}\n\n/* hill climbing value for part 1 */\n/* Scoring here is a linear reward for all set constraints normalized between 0 and 1\n * (with 0 at 0 and 1 being fully fulfilling the constraint), summed with a logarithmic\n * bonus to exceeding the constraint value. We also give linear ratio for compression ratio.\n * The constant factors are experimental.\n */\nstatic double\nresultScore(const BMK_benchResult_t res, const size_t srcSize, const constraint_t target)\n{\n    double cs = 0., ds = 0., rt, cm = 0.;\n    const double r1 = 1, r2 = 0.1, rtr = 0.5;\n    double ret;\n    if(target.cSpeed) { cs = (double)res.cSpeed / (double)target.cSpeed; }\n    if(target.dSpeed) { ds = (double)res.dSpeed / (double)target.dSpeed; }\n    if(target.cMem != (U32)-1) { cm = (double)target.cMem / (double)res.cMem; }\n    rt = ((double)srcSize / (double)res.cSize);\n\n    ret = (MIN(1, cs) + MIN(1, ds)  + MIN(1, cm))*r1 + rt * rtr +\n         (MAX(0, log(cs))+ MAX(0, log(ds))+ MAX(0, log(cm))) * r2;\n\n    return ret;\n}\n\n/* calculates normalized squared euclidean distance of result1 if it is in the first quadrant relative to lvlRes */\nstatic double\nresultDistLvl(const BMK_benchResult_t result1, const BMK_benchResult_t lvlRes)\n{\n    double normalizedCSpeedGain1 = ((double)result1.cSpeed / (double)lvlRes.cSpeed) - 1;\n    double normalizedRatioGain1 = ((double)lvlRes.cSize / (double)result1.cSize) - 1;\n    if(normalizedRatioGain1 < 0 || normalizedCSpeedGain1 < 0) {\n        return 0.0;\n    }\n    return normalizedRatioGain1 * g_ratioMultiplier + normalizedCSpeedGain1;\n}\n\n/* return true if r2 strictly better than r1 */\nstatic int\ncompareResultLT(const BMK_benchResult_t result1, const BMK_benchResult_t result2, const constraint_t target, size_t srcSize)\n{\n    if(feasible(result1, target) && feasible(result2, target)) {\n        if(g_optmode) {\n            return resultDistLvl(result1, g_lvltarget) < resultDistLvl(result2, g_lvltarget);\n        } else {\n            return (result1.cSize > result2.cSize)\n                || (result1.cSize == result2.cSize && result2.cSpeed > result1.cSpeed)\n                || (result1.cSize == result2.cSize && result2.cSpeed == result1.cSpeed && result2.dSpeed > result1.dSpeed);\n        }\n    }\n    return feasible(result2, target)\n        || (!feasible(result1, target)\n            && (resultScore(result1, srcSize, target) < resultScore(result2, srcSize, target)));\n}\n\nstatic constraint_t relaxTarget(constraint_t target) {\n    target.cMem = (U32)-1;\n    target.cSpeed = (target.cSpeed * g_strictness) / 100;\n    target.dSpeed = (target.dSpeed * g_strictness) / 100;\n    return target;\n}\n\nstatic void optimizerAdjustInput(paramValues_t* pc, const size_t maxBlockSize)\n{\n    varInds_t v;\n    for(v = 0; v < NUM_PARAMS; v++) {\n        if(pc->vals[v] != PARAM_UNSET) {\n            U32 newval = MIN(MAX(pc->vals[v], mintable[v]), maxtable[v]);\n            if(newval != pc->vals[v]) {\n                pc->vals[v] = newval;\n                DISPLAY(\"Warning: parameter %s not in valid range, adjusting to \",\n                        g_paramNames[v]);\n                displayParamVal(stderr, v, newval, 0); DISPLAY(\"\\n\");\n            }\n        }\n    }\n\n    if(pc->vals[wlog_ind] != PARAM_UNSET) {\n\n        U32 sshb = maxBlockSize > 1 ? ZSTD_highbit32((U32)(maxBlockSize-1)) + 1 : 1;\n        /* edge case of highBit not working for 0 */\n\n        if(maxBlockSize < (1ULL << 31) && sshb + 1 < pc->vals[wlog_ind]) {\n            U32 adjust = MAX(mintable[wlog_ind], sshb);\n            if(adjust != pc->vals[wlog_ind]) {\n                pc->vals[wlog_ind] = adjust;\n                DISPLAY(\"Warning: windowLog larger than src/block size, adjusted to %u\\n\",\n                        (unsigned)pc->vals[wlog_ind]);\n            }\n        }\n    }\n\n    if(pc->vals[wlog_ind] != PARAM_UNSET && pc->vals[clog_ind] != PARAM_UNSET) {\n        U32 maxclog;\n        if(pc->vals[strt_ind] == PARAM_UNSET || pc->vals[strt_ind] >= (U32)ZSTD_btlazy2) {\n            maxclog = pc->vals[wlog_ind] + 1;\n        } else {\n            maxclog = pc->vals[wlog_ind];\n        }\n\n        if(pc->vals[clog_ind] > maxclog) {\n            pc->vals[clog_ind] = maxclog;\n            DISPLAY(\"Warning: chainlog too much larger than windowLog size, adjusted to %u\\n\",\n                    (unsigned)pc->vals[clog_ind]);\n        }\n    }\n\n    if(pc->vals[wlog_ind] != PARAM_UNSET && pc->vals[hlog_ind] != PARAM_UNSET) {\n        if(pc->vals[wlog_ind] + 1 < pc->vals[hlog_ind]) {\n            pc->vals[hlog_ind] = pc->vals[wlog_ind] + 1;\n            DISPLAY(\"Warning: hashlog too much larger than windowLog size, adjusted to %u\\n\",\n                    (unsigned)pc->vals[hlog_ind]);\n        }\n    }\n\n    if(pc->vals[slog_ind] != PARAM_UNSET && pc->vals[clog_ind] != PARAM_UNSET) {\n        if(pc->vals[slog_ind] > pc->vals[clog_ind]) {\n            pc->vals[clog_ind] = pc->vals[slog_ind];\n            DISPLAY(\"Warning: searchLog larger than chainLog, adjusted to %u\\n\",\n                    (unsigned)pc->vals[slog_ind]);\n        }\n    }\n}\n\nstatic int\nredundantParams(const paramValues_t paramValues, const constraint_t target, const size_t maxBlockSize)\n{\n    return\n       (ZSTD_estimateCStreamSize_usingCParams(pvalsToCParams(paramValues)) > (size_t)target.cMem) /* Uses too much memory */\n    || ((1ULL << (paramValues.vals[wlog_ind] - 1)) >= maxBlockSize && paramValues.vals[wlog_ind] != mintable[wlog_ind]) /* wlog too much bigger than src size */\n    || (paramValues.vals[clog_ind] > (paramValues.vals[wlog_ind] + (paramValues.vals[strt_ind] > ZSTD_btlazy2))) /* chainLog larger than windowLog*/\n    || (paramValues.vals[slog_ind] > paramValues.vals[clog_ind]) /* searchLog larger than chainLog */\n    || (paramValues.vals[hlog_ind] > paramValues.vals[wlog_ind] + 1); /* hashLog larger than windowLog + 1 */\n}\n\n\n/*-************************************\n*  Display Functions\n**************************************/\n\n/* BMK_paramValues_into_commandLine() :\n * transform a set of parameters paramValues_t\n * into a command line compatible with `zstd` syntax\n * and writes it into FILE* f.\n * f must be already opened and writable */\nstatic void\nBMK_paramValues_into_commandLine(FILE* f, const paramValues_t params)\n{\n    varInds_t v;\n    int first = 1;\n    fprintf(f,\"--zstd=\");\n    for (v = 0; v < NUM_PARAMS; v++) {\n        if (g_silenceParams[v]) { continue; }\n        if (!first) { fprintf(f, \",\"); }\n        fprintf(f,\"%s=\", g_paramNames[v]);\n\n        if (v == strt_ind) { fprintf(f,\"%u\", (unsigned)params.vals[v]); }\n        else { displayParamVal(f, v, params.vals[v], 0); }\n        first = 0;\n    }\n    fprintf(f, \"\\n\");\n}\n\n\n/* comparison function: */\n/* strictly better, strictly worse, equal, speed-side adv, size-side adv */\n#define WORSE_RESULT 0\n#define BETTER_RESULT 1\n#define ERROR_RESULT 2\n\n#define SPEED_RESULT 4\n#define SIZE_RESULT 5\n/* maybe have epsilon-eq to limit table size? */\nstatic int\nspeedSizeCompare(const BMK_benchResult_t r1, const BMK_benchResult_t r2)\n{\n    if(r1.cSpeed < r2.cSpeed) {\n        if(r1.cSize >= r2.cSize) {\n            return BETTER_RESULT;\n        }\n        return SPEED_RESULT; /* r2 is smaller but not faster. */\n    } else {\n        if(r1.cSize <= r2.cSize) {\n            return WORSE_RESULT;\n        }\n        return SIZE_RESULT; /* r2 is faster but not smaller */\n    }\n}\n\n/* 0 for insertion, 1 for no insert */\n/* maintain invariant speedSizeCompare(n, n->next) = SPEED_RESULT */\nstatic int\ninsertWinner(const winnerInfo_t w, const constraint_t targetConstraints)\n{\n    BMK_benchResult_t r = w.result;\n    winner_ll_node* cur_node = g_winners;\n    /* first node to insert */\n    if(!feasible(r, targetConstraints)) {\n        return 1;\n    }\n\n    if(g_winners == NULL) {\n        winner_ll_node* first_node = malloc(sizeof(winner_ll_node));\n        if(first_node == NULL) {\n            return 1;\n        }\n        first_node->next = NULL;\n        first_node->res = w;\n        g_winners = first_node;\n        return 0;\n    }\n\n    while(cur_node->next != NULL) {\n        switch(speedSizeCompare(cur_node->res.result, r)) {\n            case WORSE_RESULT:\n            {\n                return 1; /* never insert if better */\n            }\n            case BETTER_RESULT:\n            {\n                winner_ll_node* tmp;\n                cur_node->res = cur_node->next->res;\n                tmp = cur_node->next;\n                cur_node->next = cur_node->next->next;\n                free(tmp);\n                break;\n            }\n            case SIZE_RESULT:\n            {\n                cur_node = cur_node->next;\n                break;\n            }\n            case SPEED_RESULT: /* insert after first size result, then return */\n            {\n                winner_ll_node* newnode = malloc(sizeof(winner_ll_node));\n                if(newnode == NULL) {\n                    return 1;\n                }\n                newnode->res = cur_node->res;\n                cur_node->res = w;\n                newnode->next = cur_node->next;\n                cur_node->next = newnode;\n                return 0;\n            }\n        }\n\n    }\n\n    assert(cur_node->next == NULL);\n    switch(speedSizeCompare(cur_node->res.result, r)) {\n        case WORSE_RESULT:\n        {\n            return 1; /* never insert if better */\n        }\n        case BETTER_RESULT:\n        {\n            cur_node->res = w;\n            return 0;\n        }\n        case SIZE_RESULT:\n        {\n            winner_ll_node* newnode = malloc(sizeof(winner_ll_node));\n            if(newnode == NULL) {\n                return 1;\n            }\n            newnode->res = w;\n            newnode->next = NULL;\n            cur_node->next = newnode;\n            return 0;\n        }\n        case SPEED_RESULT: /* insert before first size result, then return */\n        {\n            winner_ll_node* newnode = malloc(sizeof(winner_ll_node));\n            if(newnode == NULL) {\n                return 1;\n            }\n            newnode->res = cur_node->res;\n            cur_node->res = w;\n            newnode->next = cur_node->next;\n            cur_node->next = newnode;\n            return 0;\n        }\n        default:\n            return 1;\n    }\n}\n\nstatic void\nBMK_displayOneResult(FILE* f, winnerInfo_t res, const size_t srcSize)\n{\n    varInds_t v;\n    int first = 1;\n    res.params = cParamUnsetMin(res.params);\n    fprintf(f, \"    {\");\n    for (v = 0; v < NUM_PARAMS; v++) {\n        if (g_silenceParams[v]) { continue; }\n        if (!first) { fprintf(f, \",\"); }\n        displayParamVal(f, v, res.params.vals[v], 3);\n        first = 0;\n    }\n\n    {   double const ratio = res.result.cSize ?\n                            (double)srcSize / (double)res.result.cSize : 0;\n        double const cSpeedMBps = (double)res.result.cSpeed / MB_UNIT;\n        double const dSpeedMBps = (double)res.result.dSpeed / MB_UNIT;\n\n        fprintf(f, \" },     /* R:%5.3f at %5.1f MB/s - %5.1f MB/s */\\n\",\n                            ratio, cSpeedMBps, dSpeedMBps);\n    }\n}\n\n/* Writes to f the results of a parameter benchmark */\n/* when used with --optimize, will only print results better than previously discovered */\nstatic void\nBMK_printWinner(FILE* f, const int cLevel, const BMK_benchResult_t result, const paramValues_t params, const size_t srcSize)\n{\n    char lvlstr[15] = \"Custom Level\";\n    winnerInfo_t w;\n    w.params = params;\n    w.result = result;\n\n    fprintf(f, \"\\r%79s\\r\", \"\");\n\n    if(cLevel != CUSTOM_LEVEL) {\n        snprintf(lvlstr, 15, \"  Level %2d  \", cLevel);\n    }\n\n    if(TIMED) {\n        const U64 mn_in_ns = 60ULL * TIMELOOP_NANOSEC;\n        const U64 time_ns = UTIL_clockSpanNano(g_time);\n        const U64 minutes = time_ns / mn_in_ns;\n        fprintf(f, \"%1lu:%2lu:%05.2f - \",\n                (unsigned long) minutes / 60,\n                (unsigned long) minutes % 60,\n                (double)(time_ns - (minutes * mn_in_ns)) / TIMELOOP_NANOSEC );\n    }\n\n    fprintf(f, \"/* %s */   \", lvlstr);\n    BMK_displayOneResult(f, w, srcSize);\n}\n\nstatic void\nBMK_printWinnerOpt(FILE* f, const U32 cLevel, const BMK_benchResult_t result, const paramValues_t params, const constraint_t targetConstraints, const size_t srcSize)\n{\n    /* global winner used for constraints */\n                                    /* cSize, cSpeed, dSpeed, cMem */\n    static winnerInfo_t g_winner = { { (size_t)-1LL, 0, 0, (size_t)-1LL },\n                                     { { PARAM_UNSET, PARAM_UNSET, PARAM_UNSET, PARAM_UNSET, PARAM_UNSET, PARAM_UNSET, PARAM_UNSET, PARAM_UNSET } }\n                                   };\n    if ( DEBUG\n      || compareResultLT(g_winner.result, result, targetConstraints, srcSize)\n      || g_displayLevel >= 4) {\n        if ( DEBUG\n          && compareResultLT(g_winner.result, result, targetConstraints, srcSize)) {\n            DISPLAY(\"New Winner: \\n\");\n        }\n\n        if(g_displayLevel >= 2) {\n            BMK_printWinner(f, cLevel, result, params, srcSize);\n        }\n\n        if(compareResultLT(g_winner.result, result, targetConstraints, srcSize)) {\n            if(g_displayLevel >= 1) { BMK_paramValues_into_commandLine(f, params); }\n            g_winner.result = result;\n            g_winner.params = params;\n        }\n    }\n\n    if(g_optmode && g_optimizer && (DEBUG || g_displayLevel == 3)) {\n        winnerInfo_t w;\n        winner_ll_node* n;\n        w.result = result;\n        w.params = params;\n        insertWinner(w, targetConstraints);\n\n        if(!DEBUG) { fprintf(f, \"\\033c\"); }\n        fprintf(f, \"\\n\");\n\n        /* the table */\n        fprintf(f, \"================================\\n\");\n        for(n = g_winners; n != NULL; n = n->next) {\n            BMK_displayOneResult(f, n->res, srcSize);\n        }\n        fprintf(f, \"================================\\n\");\n        fprintf(f, \"Level Bounds: R: > %.3f AND C: < %.1f MB/s \\n\\n\",\n            (double)srcSize / (double)g_lvltarget.cSize, (double)g_lvltarget.cSpeed / MB_UNIT);\n\n\n        fprintf(f, \"Overall Winner: \\n\");\n        BMK_displayOneResult(f, g_winner, srcSize);\n        BMK_paramValues_into_commandLine(f, g_winner.params);\n\n        fprintf(f, \"Latest BMK: \\n\");\\\n        BMK_displayOneResult(f, w, srcSize);\n    }\n}\n\n\n/* BMK_print_cLevelEntry() :\n * Writes one cLevelTable entry, for one level.\n * f must exist, be already opened, and be seekable.\n * this function cannot error.\n */\nstatic void\nBMK_print_cLevelEntry(FILE* f, const int cLevel,\n                      paramValues_t params,\n                      const BMK_benchResult_t result, const size_t srcSize)\n{\n    varInds_t v;\n    int first = 1;\n\n    assert(cLevel >= 0);\n    assert(cLevel <= NB_LEVELS_TRACKED);\n    params = cParamUnsetMin(params);\n\n    fprintf(f, \"   {\");\n    /* print cParams.\n     * assumption : all cParams are present and in order in the following range */\n    for (v = 0; v <= strt_ind; v++) {\n        if (!first) { fprintf(f, \",\"); }\n        displayParamVal(f, v, params.vals[v], 3);\n        first = 0;\n    }\n    /* print comment */\n    {   double const ratio = result.cSize ?\n                            (double)srcSize / (double)result.cSize : 0;\n        double const cSpeedMBps = (double)result.cSpeed / MB_UNIT;\n        double const dSpeedMBps = (double)result.dSpeed / MB_UNIT;\n\n        fprintf(f, \" },   /* level %2i:  R=%5.3f at %5.1f MB/s - %5.1f MB/s */\\n\",\n                             cLevel, ratio, cSpeedMBps, dSpeedMBps);\n    }\n}\n\n\n/* BMK_print_cLevelTable() :\n * print candidate compression table into proposed FILE* f.\n * f must exist, be already opened, and be seekable.\n * winners must be a table of NB_LEVELS_TRACKED+1 elements winnerInfo_t, all entries presumed initialized\n * this function cannot error.\n */\nstatic void\nBMK_print_cLevelTable(FILE* f, const winnerInfo_t* winners, const size_t srcSize)\n{\n    int cLevel;\n\n    fprintf(f, \"\\n /* Proposed configurations : */ \\n\");\n    fprintf(f, \"   /* W,  C,  H,  S,  L,  T, strat */ \\n\");\n\n    for (cLevel=0; cLevel <= NB_LEVELS_TRACKED; cLevel++)\n        BMK_print_cLevelEntry(f,\n                              cLevel, winners[cLevel].params,\n                              winners[cLevel].result, srcSize);\n}\n\n\n/* BMK_saveAndPrint_cLevelTable() :\n * save candidate compression table into FILE* f,\n * and then to stdout.\n * f must exist, be already opened, and be seekable.\n * winners must be a table of NB_LEVELS_TRACKED+1 elements winnerInfo_t, all entries presumed initialized\n * this function cannot error.\n */\nstatic void\nBMK_saveAndPrint_cLevelTable(FILE* const f,\n                       const winnerInfo_t* winners,\n                       const size_t srcSize)\n{\n    fseek(f, 0, SEEK_SET);\n    BMK_print_cLevelTable(f, winners, srcSize);\n    fflush(f);\n    BMK_print_cLevelTable(stdout, winners, srcSize);\n}\n\n\n/*-*******************************************************\n*  Functions to Benchmark\n*********************************************************/\n\ntypedef struct {\n    ZSTD_CCtx* cctx;\n    const void* dictBuffer;\n    size_t dictBufferSize;\n    int cLevel;\n    const paramValues_t* comprParams;\n} BMK_initCCtxArgs;\n\nstatic size_t local_initCCtx(void* payload) {\n    const BMK_initCCtxArgs* ag = (const BMK_initCCtxArgs*)payload;\n    varInds_t i;\n    ZSTD_CCtx_reset(ag->cctx, ZSTD_reset_session_and_parameters);\n    ZSTD_CCtx_setParameter(ag->cctx, ZSTD_c_compressionLevel, ag->cLevel);\n\n    for(i = 0; i < NUM_PARAMS; i++) {\n        if(ag->comprParams->vals[i] != PARAM_UNSET)\n        ZSTD_CCtx_setParameter(ag->cctx, cctxSetParamTable[i], ag->comprParams->vals[i]);\n    }\n    ZSTD_CCtx_loadDictionary(ag->cctx, ag->dictBuffer, ag->dictBufferSize);\n\n    return 0;\n}\n\ntypedef struct {\n    ZSTD_DCtx* dctx;\n    const void* dictBuffer;\n    size_t dictBufferSize;\n} BMK_initDCtxArgs;\n\nstatic size_t local_initDCtx(void* payload) {\n    const BMK_initDCtxArgs* ag = (const BMK_initDCtxArgs*)payload;\n    ZSTD_DCtx_reset(ag->dctx, ZSTD_reset_session_and_parameters);\n    ZSTD_DCtx_loadDictionary(ag->dctx, ag->dictBuffer, ag->dictBufferSize);\n    return 0;\n}\n\n/* additional argument is just the context */\nstatic size_t local_defaultCompress(\n                            const void* srcBuffer, size_t srcSize,\n                            void* dstBuffer, size_t dstSize,\n                            void* addArgs)\n{\n    ZSTD_CCtx* cctx = (ZSTD_CCtx*)addArgs;\n    assert(dstSize == ZSTD_compressBound(srcSize)); /* specific to this version, which is only used in paramgrill */\n    return ZSTD_compress2(cctx, dstBuffer, dstSize, srcBuffer, srcSize);\n}\n\n/* additional argument is just the context */\nstatic size_t local_defaultDecompress(\n    const void* srcBuffer, size_t srcSize,\n    void* dstBuffer, size_t dstSize,\n    void* addArgs) {\n    size_t moreToFlush = 1;\n    ZSTD_DCtx* dctx = (ZSTD_DCtx*)addArgs;\n    ZSTD_inBuffer in;\n    ZSTD_outBuffer out;\n    in.src = srcBuffer;\n    in.size = srcSize;\n    in.pos = 0;\n    out.dst = dstBuffer;\n    out.size = dstSize;\n    out.pos = 0;\n    while (moreToFlush) {\n        if(out.pos == out.size) {\n            return (size_t)-ZSTD_error_dstSize_tooSmall;\n        }\n        moreToFlush = ZSTD_decompressStream(dctx,\n                            &out, &in);\n        if (ZSTD_isError(moreToFlush)) {\n            return moreToFlush;\n        }\n    }\n    return out.pos;\n\n}\n\n/*-************************************\n*  Data Initialization Functions\n**************************************/\n\ntypedef struct {\n    void* srcBuffer;\n    size_t srcSize;\n    const void** srcPtrs;\n    size_t* srcSizes;\n    void** dstPtrs;\n    size_t* dstCapacities;\n    size_t* dstSizes;\n    void** resPtrs;\n    size_t* resSizes;\n    size_t nbBlocks;\n    size_t maxBlockSize;\n} buffers_t;\n\ntypedef struct {\n    size_t dictSize;\n    void* dictBuffer;\n    ZSTD_CCtx* cctx;\n    ZSTD_DCtx* dctx;\n} contexts_t;\n\nstatic void freeNonSrcBuffers(const buffers_t b) {\n    free((void*)b.srcPtrs);\n    free(b.srcSizes);\n\n    if(b.dstPtrs != NULL) {\n        free(b.dstPtrs[0]);\n    }\n    free(b.dstPtrs);\n    free(b.dstCapacities);\n    free(b.dstSizes);\n\n    if(b.resPtrs != NULL) {\n        free(b.resPtrs[0]);\n    }\n    free(b.resPtrs);\n    free(b.resSizes);\n}\n\nstatic void freeBuffers(const buffers_t b) {\n    if(b.srcPtrs != NULL) {\n        free(b.srcBuffer);\n    }\n    freeNonSrcBuffers(b);\n}\n\n/* srcBuffer will be freed by freeBuffers now */\nstatic int createBuffersFromMemory(buffers_t* buff, void * srcBuffer, const size_t nbFiles,\n    const size_t* fileSizes)\n{\n    size_t pos = 0, n, blockSize;\n    U32 maxNbBlocks, blockNb = 0;\n    buff->srcSize = 0;\n    for(n = 0; n < nbFiles; n++) {\n        buff->srcSize += fileSizes[n];\n    }\n\n    if(buff->srcSize == 0) {\n        DISPLAY(\"No data to bench\\n\");\n        return 1;\n    }\n\n    blockSize = g_blockSize ? g_blockSize : buff->srcSize;\n    maxNbBlocks = (U32) ((buff->srcSize + (blockSize-1)) / blockSize) + (U32)nbFiles;\n\n    buff->srcPtrs = (const void**)calloc(maxNbBlocks, sizeof(void*));\n    buff->srcSizes = (size_t*)malloc(maxNbBlocks * sizeof(size_t));\n\n    buff->dstPtrs = (void**)calloc(maxNbBlocks, sizeof(void*));\n    buff->dstCapacities = (size_t*)malloc(maxNbBlocks * sizeof(size_t));\n    buff->dstSizes = (size_t*)malloc(maxNbBlocks * sizeof(size_t));\n\n    buff->resPtrs = (void**)calloc(maxNbBlocks, sizeof(void*));\n    buff->resSizes = (size_t*)malloc(maxNbBlocks * sizeof(size_t));\n\n    if(!buff->srcPtrs || !buff->srcSizes || !buff->dstPtrs || !buff->dstCapacities || !buff->dstSizes || !buff->resPtrs || !buff->resSizes) {\n        DISPLAY(\"alloc error\\n\");\n        freeNonSrcBuffers(*buff);\n        return 1;\n    }\n\n    buff->srcBuffer = srcBuffer;\n    buff->srcPtrs[0] = (const void*)buff->srcBuffer;\n    buff->dstPtrs[0] = malloc(ZSTD_compressBound(buff->srcSize) + (maxNbBlocks * 1024));\n    buff->resPtrs[0] = malloc(buff->srcSize);\n\n    if(!buff->dstPtrs[0] || !buff->resPtrs[0]) {\n        DISPLAY(\"alloc error\\n\");\n        freeNonSrcBuffers(*buff);\n        return 1;\n    }\n\n    for(n = 0; n < nbFiles; n++) {\n        size_t pos_end = pos + fileSizes[n];\n        for(; pos < pos_end; blockNb++) {\n            buff->srcPtrs[blockNb] = (const void*)((char*)srcBuffer + pos);\n            buff->srcSizes[blockNb] = blockSize;\n            pos += blockSize;\n        }\n\n        if(fileSizes[n] > 0) { buff->srcSizes[blockNb - 1] = ((fileSizes[n] - 1) % blockSize) + 1; }\n        pos = pos_end;\n    }\n\n    buff->dstCapacities[0] = ZSTD_compressBound(buff->srcSizes[0]);\n    buff->dstSizes[0] = buff->dstCapacities[0];\n    buff->resSizes[0] = buff->srcSizes[0];\n    buff->maxBlockSize = buff->srcSizes[0];\n\n    for(n = 1; n < blockNb; n++) {\n        buff->dstPtrs[n] = ((char*)buff->dstPtrs[n-1]) + buff->dstCapacities[n-1];\n        buff->resPtrs[n] = ((char*)buff->resPtrs[n-1]) + buff->resSizes[n-1];\n        buff->dstCapacities[n] = ZSTD_compressBound(buff->srcSizes[n]);\n        buff->dstSizes[n] = buff->dstCapacities[n];\n        buff->resSizes[n] = buff->srcSizes[n];\n\n        buff->maxBlockSize = MAX(buff->maxBlockSize, buff->srcSizes[n]);\n    }\n\n    buff->nbBlocks = blockNb;\n\n    return 0;\n}\n\n/* allocates buffer's arguments. returns success / failure */\nstatic int createBuffers(buffers_t* buff, const char* const * const fileNamesTable,\n                          size_t nbFiles) {\n    size_t pos = 0;\n    size_t n;\n    size_t totalSizeToLoad = (size_t)UTIL_getTotalFileSize(fileNamesTable, (U32)nbFiles);\n    size_t benchedSize = MIN(BMK_findMaxMem(totalSizeToLoad * 3) / 3, totalSizeToLoad);\n    size_t* fileSizes = calloc(nbFiles, sizeof(size_t));\n    void* srcBuffer = NULL;\n    int ret = 0;\n\n    if(!totalSizeToLoad || !benchedSize) {\n        ret = 1;\n        DISPLAY(\"Nothing to Bench\\n\");\n        goto _cleanUp;\n    }\n\n    srcBuffer = malloc(benchedSize);\n\n    if(!fileSizes || !srcBuffer) {\n        ret = 1;\n        goto _cleanUp;\n    }\n\n    for(n = 0; n < nbFiles; n++) {\n        FILE* f;\n        U64 fileSize = UTIL_getFileSize(fileNamesTable[n]);\n        if (UTIL_isDirectory(fileNamesTable[n])) {\n            DISPLAY(\"Ignoring %s directory...       \\n\", fileNamesTable[n]);\n            continue;\n        }\n        if (fileSize == UTIL_FILESIZE_UNKNOWN) {\n            DISPLAY(\"Cannot evaluate size of %s, ignoring ... \\n\", fileNamesTable[n]);\n            continue;\n        }\n        f = fopen(fileNamesTable[n], \"rb\");\n        if (f==NULL) {\n            DISPLAY(\"impossible to open file %s\\n\", fileNamesTable[n]);\n            ret = 10;\n            goto _cleanUp;\n        }\n\n        DISPLAYLEVEL(2, \"Loading %s...       \\r\", fileNamesTable[n]);\n\n        if (fileSize + pos > benchedSize) fileSize = benchedSize - pos, nbFiles=n;   /* buffer too small - stop after this file */\n        {\n            char* buffer = (char*)(srcBuffer);\n            size_t const readSize = fread((buffer)+pos, 1, (size_t)fileSize, f);\n            fclose(f);\n            if (readSize != (size_t)fileSize) {\n                DISPLAY(\"could not read %s\", fileNamesTable[n]);\n                ret = 1;\n                goto _cleanUp;\n            }\n\n            fileSizes[n] = readSize;\n            pos += readSize;\n        }\n    }\n\n    ret = createBuffersFromMemory(buff, srcBuffer, nbFiles, fileSizes);\n\n_cleanUp:\n    if(ret) { free(srcBuffer); }\n    free(fileSizes);\n    return ret;\n}\n\nstatic void freeContexts(const contexts_t ctx) {\n    free(ctx.dictBuffer);\n    ZSTD_freeCCtx(ctx.cctx);\n    ZSTD_freeDCtx(ctx.dctx);\n}\n\nstatic int createContexts(contexts_t* ctx, const char* dictFileName) {\n    FILE* f;\n    size_t readSize;\n    ctx->cctx = ZSTD_createCCtx();\n    ctx->dctx = ZSTD_createDCtx();\n    assert(ctx->cctx != NULL);\n    assert(ctx->dctx != NULL);\n\n    if(dictFileName == NULL) {\n        ctx->dictSize = 0;\n        ctx->dictBuffer = NULL;\n        return 0;\n    }\n    {   U64 const dictFileSize = UTIL_getFileSize(dictFileName);\n        assert(dictFileSize != UTIL_FILESIZE_UNKNOWN);\n        ctx->dictSize = (size_t)dictFileSize;\n        assert((U64)ctx->dictSize == dictFileSize); /* check overflow */\n    }\n    ctx->dictBuffer = malloc(ctx->dictSize);\n\n    f = fopen(dictFileName, \"rb\");\n\n    if (f==NULL) {\n        DISPLAY(\"unable to open file\\n\");\n        freeContexts(*ctx);\n        return 1;\n    }\n\n    if (ctx->dictSize > 64 MB || !(ctx->dictBuffer)) {\n        DISPLAY(\"dictionary too large\\n\");\n        fclose(f);\n        freeContexts(*ctx);\n        return 1;\n    }\n    readSize = fread(ctx->dictBuffer, 1, ctx->dictSize, f);\n    fclose(f);\n    if (readSize != ctx->dictSize) {\n        DISPLAY(\"unable to read file\\n\");\n        freeContexts(*ctx);\n        return 1;\n    }\n    return 0;\n}\n\n/*-************************************\n*  Optimizer Memoization Functions\n**************************************/\n\n/* return: new length */\n/* keep old array, will need if iter over strategy. */\n/* prunes useless params */\nstatic size_t sanitizeVarArray(varInds_t* varNew, const size_t varLength, const varInds_t* varArray, const ZSTD_strategy strat) {\n    size_t i, j = 0;\n    for(i = 0; i < varLength; i++) {\n        if( !((varArray[i] == clog_ind && strat == ZSTD_fast)\n            || (varArray[i] == slog_ind && strat == ZSTD_fast)\n            || (varArray[i] == slog_ind && strat == ZSTD_dfast)\n            || (varArray[i] == tlen_ind && strat < ZSTD_btopt && strat != ZSTD_fast))) {\n            varNew[j] = varArray[i];\n            j++;\n        }\n    }\n    return j;\n}\n\n/* res should be NUM_PARAMS size */\n/* constructs varArray from paramValues_t style parameter */\n/* pass in using dict. */\nstatic size_t variableParams(const paramValues_t paramConstraints, varInds_t* res, const int usingDictionary) {\n    varInds_t i;\n    size_t j = 0;\n    for(i = 0; i < NUM_PARAMS; i++) {\n        if(paramConstraints.vals[i] == PARAM_UNSET) {\n            if(i == fadt_ind && !usingDictionary) continue; /* don't use fadt if no dictionary */\n            res[j] = i; j++;\n        }\n    }\n    return j;\n}\n\n/* length of memo table given free variables */\nstatic size_t memoTableLen(const varInds_t* varyParams, const size_t varyLen) {\n    size_t arrayLen = 1;\n    size_t i;\n    for(i = 0; i < varyLen; i++) {\n        if(varyParams[i] == strt_ind) continue; /* strategy separated by table */\n        arrayLen *= rangetable[varyParams[i]];\n    }\n    return arrayLen;\n}\n\n/* returns unique index in memotable of compression parameters */\nstatic unsigned memoTableIndDirect(const paramValues_t* ptr, const varInds_t* varyParams, const size_t varyLen) {\n    size_t i;\n    unsigned ind = 0;\n    for(i = 0; i < varyLen; i++) {\n        varInds_t v = varyParams[i];\n        if(v == strt_ind) continue; /* exclude strategy from memotable */\n        ind *= rangetable[v]; ind += (unsigned)invRangeMap(v, ptr->vals[v]);\n    }\n    return ind;\n}\n\nstatic size_t memoTableGet(const memoTable_t* memoTableArray, const paramValues_t p) {\n    const memoTable_t mt = memoTableArray[p.vals[strt_ind]];\n    switch(mt.tableType) {\n        case directMap:\n            return mt.table[memoTableIndDirect(&p, mt.varArray, mt.varLen)];\n        case xxhashMap:\n            return mt.table[(XXH64(&p.vals, sizeof(U32) * NUM_PARAMS, 0) >> 3) % mt.tableLen];\n        case noMemo:\n            return 0;\n    }\n    return 0; /* should never happen, stop compiler warnings */\n}\n\nstatic void memoTableSet(const memoTable_t* memoTableArray, const paramValues_t p, const BYTE value) {\n    const memoTable_t mt = memoTableArray[p.vals[strt_ind]];\n    switch(mt.tableType) {\n        case directMap:\n            mt.table[memoTableIndDirect(&p, mt.varArray, mt.varLen)] = value; break;\n        case xxhashMap:\n            mt.table[(XXH64(&p.vals, sizeof(U32) * NUM_PARAMS, 0) >> 3) % mt.tableLen] = value; break;\n        case noMemo:\n            break;\n    }\n}\n\n/* frees all allocated memotables */\n/* secret contract :\n * mtAll is a table of (ZSTD_STRATEGY_MAX+1) memoTable_t */\nstatic void freeMemoTableArray(memoTable_t* const mtAll) {\n    int i;\n    if(mtAll == NULL) { return; }\n    for(i = 1; i <= (int)ZSTD_STRATEGY_MAX; i++) {\n        free(mtAll[i].table);\n    }\n    free(mtAll);\n}\n\n/* inits memotables for all (including mallocs), all strategies */\n/* takes unsanitized varyParams */\nstatic memoTable_t*\ncreateMemoTableArray(const paramValues_t p,\n                     const varInds_t* const varyParams,\n                     const size_t varyLen,\n                     const U32 memoTableLog)\n{\n    memoTable_t* const mtAll = (memoTable_t*)calloc((ZSTD_STRATEGY_MAX + 1), sizeof(memoTable_t));\n    ZSTD_strategy i, stratMin = ZSTD_STRATEGY_MIN, stratMax = ZSTD_STRATEGY_MAX;\n\n    if(mtAll == NULL) {\n        return NULL;\n    }\n\n    for(i = 1; i <= (int)ZSTD_STRATEGY_MAX; i++) {\n        mtAll[i].varLen = sanitizeVarArray(mtAll[i].varArray, varyLen, varyParams, i);\n    }\n\n    /* no memoization */\n    if(memoTableLog == 0) {\n        for(i = 1; i <= (int)ZSTD_STRATEGY_MAX; i++) {\n            mtAll[i].tableType = noMemo;\n            mtAll[i].table = NULL;\n            mtAll[i].tableLen = 0;\n        }\n        return mtAll;\n    }\n\n\n    if(p.vals[strt_ind] != PARAM_UNSET) {\n        stratMin = p.vals[strt_ind];\n        stratMax = p.vals[strt_ind];\n    }\n\n\n    for(i = stratMin; i <= stratMax; i++) {\n        size_t mtl = memoTableLen(mtAll[i].varArray, mtAll[i].varLen);\n        mtAll[i].tableType = directMap;\n\n        if(memoTableLog != PARAM_UNSET && mtl > (1ULL << memoTableLog)) { /* use hash table */ /* provide some option to only use hash tables? */\n            mtAll[i].tableType = xxhashMap;\n            mtl = ((size_t)1 << memoTableLog);\n        }\n\n        mtAll[i].table = (BYTE*)calloc(mtl, sizeof(BYTE));\n        mtAll[i].tableLen = mtl;\n\n        if(mtAll[i].table == NULL) {\n            freeMemoTableArray(mtAll);\n            return NULL;\n        }\n    }\n\n    return mtAll;\n}\n\n/* Sets pc to random unmeasured set of parameters */\n/* specify strategy */\nstatic void randomConstrainedParams(paramValues_t* pc, const memoTable_t* memoTableArray, const ZSTD_strategy st)\n{\n    size_t j;\n    const memoTable_t mt = memoTableArray[st];\n    pc->vals[strt_ind] = st;\n    for(j = 0; j < mt.tableLen; j++) {\n        int i;\n        for(i = 0; i < NUM_PARAMS; i++) {\n            varInds_t v = mt.varArray[i];\n            if(v == strt_ind) continue;\n            pc->vals[v] = rangeMap(v, FUZ_rand(&g_rand) % rangetable[v]);\n        }\n\n        if(!(memoTableGet(memoTableArray, *pc))) break; /* only pick unpicked params. */\n    }\n}\n\n/*-************************************\n*  Benchmarking Functions\n**************************************/\n\nstatic void display_params_tested(paramValues_t cParams)\n{\n    varInds_t vi;\n    DISPLAYLEVEL(3, \"\\r testing :\");\n    for (vi=0; vi < NUM_PARAMS; vi++) {\n        DISPLAYLEVEL(3, \"%3u,\", (unsigned)cParams.vals[vi]);\n    }\n    DISPLAYLEVEL(3, \"\\b    \\r\");\n}\n\n/* Replicate functionality of benchMemAdvanced, but with pre-split src / dst buffers */\n/* The purpose is so that sufficient information is returned so that a decompression call to benchMemInvertible is possible */\n/* BMK_benchMemAdvanced(srcBuffer,srcSize, dstBuffer, dstSize, fileSizes, nbFiles, 0, &cParams, dictBuffer, dictSize, ctx, dctx, 0, \"File\", &adv); */\n/* nbSeconds used in same way as in BMK_advancedParams_t */\n/* if in decodeOnly, then srcPtr's will be compressed blocks, and uncompressedBlocks will be written to dstPtrs */\n/* dictionary nullable, nothing else though. */\n/* note : it would be a lot better if this function was present in benchzstd.c,\n * sharing code with benchMemAdvanced(), since it's technically a part of it */\nstatic BMK_benchOutcome_t\nBMK_benchMemInvertible( buffers_t buf, contexts_t ctx,\n                        int cLevel, const paramValues_t* comprParams,\n                        BMK_mode_t mode, unsigned nbSeconds)\n{\n    U32 i;\n    BMK_benchResult_t bResult;\n    const void *const *const srcPtrs = (const void *const *const)buf.srcPtrs;\n    size_t const *const srcSizes = buf.srcSizes;\n    void** const dstPtrs = buf.dstPtrs;\n    size_t const *const dstCapacities = buf.dstCapacities;\n    size_t* const dstSizes = buf.dstSizes;\n    void** const resPtrs = buf.resPtrs;\n    size_t const *const resSizes = buf.resSizes;\n    const void* dictBuffer = ctx.dictBuffer;\n    const size_t dictBufferSize = ctx.dictSize;\n    const size_t nbBlocks = buf.nbBlocks;\n    const size_t srcSize = buf.srcSize;\n    ZSTD_CCtx* cctx = ctx.cctx;\n    ZSTD_DCtx* dctx = ctx.dctx;\n\n    /* init */\n    display_params_tested(*comprParams);\n    memset(&bResult, 0, sizeof(bResult));\n\n    /* warming up memory */\n    for (i = 0; i < buf.nbBlocks; i++) {\n        if (mode != BMK_decodeOnly) {\n            RDG_genBuffer(dstPtrs[i], dstCapacities[i], 0.10, 0.50, 1);\n        } else {\n            RDG_genBuffer(resPtrs[i], resSizes[i], 0.10, 0.50, 1);\n        }\n    }\n\n    /* Bench */\n    {\n        /* init args */\n        int compressionCompleted = (mode == BMK_decodeOnly);\n        int decompressionCompleted = (mode == BMK_compressOnly);\n        BMK_timedFnState_t* timeStateCompress = BMK_createTimedFnState(nbSeconds * 1000, 1000);\n        BMK_timedFnState_t* timeStateDecompress = BMK_createTimedFnState(nbSeconds * 1000, 1000);\n        BMK_benchParams_t cbp, dbp;\n        BMK_initCCtxArgs cctxprep;\n        BMK_initDCtxArgs dctxprep;\n\n        cbp.benchFn = local_defaultCompress;\n        cbp.benchPayload = cctx;\n        cbp.initFn = local_initCCtx;\n        cbp.initPayload = &cctxprep;\n        cbp.errorFn = ZSTD_isError;\n        cbp.blockCount = nbBlocks;\n        cbp.srcBuffers = srcPtrs;\n        cbp.srcSizes = srcSizes;\n        cbp.dstBuffers = dstPtrs;\n        cbp.dstCapacities = dstCapacities;\n        cbp.blockResults = dstSizes;\n\n        cctxprep.cctx = cctx;\n        cctxprep.dictBuffer = dictBuffer;\n        cctxprep.dictBufferSize = dictBufferSize;\n        cctxprep.cLevel = cLevel;\n        cctxprep.comprParams = comprParams;\n\n        dbp.benchFn = local_defaultDecompress;\n        dbp.benchPayload = dctx;\n        dbp.initFn = local_initDCtx;\n        dbp.initPayload = &dctxprep;\n        dbp.errorFn = ZSTD_isError;\n        dbp.blockCount = nbBlocks;\n        dbp.srcBuffers = (const void* const *) dstPtrs;\n        dbp.srcSizes = dstCapacities;\n        dbp.dstBuffers = resPtrs;\n        dbp.dstCapacities = resSizes;\n        dbp.blockResults = NULL;\n\n        dctxprep.dctx = dctx;\n        dctxprep.dictBuffer = dictBuffer;\n        dctxprep.dictBufferSize = dictBufferSize;\n\n        assert(timeStateCompress != NULL);\n        assert(timeStateDecompress != NULL);\n        while(!compressionCompleted) {\n            BMK_runOutcome_t const cOutcome = BMK_benchTimedFn(timeStateCompress, cbp);\n\n            if (!BMK_isSuccessful_runOutcome(cOutcome)) {\n                BMK_benchOutcome_t bOut;\n                memset(&bOut, 0, sizeof(bOut));\n                bOut.tag = 1;   /* should rather be a function or a constant */\n                BMK_freeTimedFnState(timeStateCompress);\n                BMK_freeTimedFnState(timeStateDecompress);\n                return bOut;\n            }\n            {   BMK_runTime_t const rResult = BMK_extract_runTime(cOutcome);\n                bResult.cSpeed = (unsigned long long)((double)srcSize * TIMELOOP_NANOSEC / rResult.nanoSecPerRun);\n                bResult.cSize = rResult.sumOfReturn;\n            }\n            compressionCompleted = BMK_isCompleted_TimedFn(timeStateCompress);\n        }\n\n        while (!decompressionCompleted) {\n            BMK_runOutcome_t const dOutcome = BMK_benchTimedFn(timeStateDecompress, dbp);\n\n            if (!BMK_isSuccessful_runOutcome(dOutcome)) {\n                BMK_benchOutcome_t bOut;\n                memset(&bOut, 0, sizeof(bOut));\n                bOut.tag = 1;   /* should rather be a function or a constant */\n                BMK_freeTimedFnState(timeStateCompress);\n                BMK_freeTimedFnState(timeStateDecompress);\n                return bOut;\n            }\n            {   BMK_runTime_t const rResult = BMK_extract_runTime(dOutcome);\n                bResult.dSpeed = (unsigned long long)((double)srcSize * TIMELOOP_NANOSEC / rResult.nanoSecPerRun);\n            }\n            decompressionCompleted = BMK_isCompleted_TimedFn(timeStateDecompress);\n        }\n\n        BMK_freeTimedFnState(timeStateCompress);\n        BMK_freeTimedFnState(timeStateDecompress);\n    }\n\n   /* Bench */\n    bResult.cMem = ((size_t)1 << (comprParams->vals[wlog_ind])) + ZSTD_sizeof_CCtx(cctx);\n\n    {   BMK_benchOutcome_t bOut;\n        bOut.tag = 0;\n        bOut.internal_never_use_directly = bResult;  /* should be a function */\n        return bOut;\n    }\n}\n\n/* BMK_benchParam() :\n * benchmark a set of `cParams` over sample `buf`,\n * store the result in `resultPtr`.\n * @return : 0 if success, 1 if error */\nstatic int BMK_benchParam ( BMK_benchResult_t* resultPtr,\n                            buffers_t buf, contexts_t ctx,\n                            paramValues_t cParams)\n{\n    BMK_benchOutcome_t const outcome = BMK_benchMemInvertible(buf, ctx,\n                                                        BASE_CLEVEL, &cParams,\n                                                        BMK_both, 3);\n    if (!BMK_isSuccessful_benchOutcome(outcome)) return 1;\n    *resultPtr = BMK_extract_benchResult(outcome);\n    return 0;\n}\n\n\n/* Benchmarking which stops when we are sufficiently sure the solution is infeasible / worse than the winner */\n#define VARIANCE 1.2\nstatic int allBench(BMK_benchResult_t* resultPtr,\n                const buffers_t buf, const contexts_t ctx,\n                const paramValues_t cParams,\n                const constraint_t target,\n                BMK_benchResult_t* winnerResult, int feas)\n{\n    BMK_benchResult_t benchres;\n    double uncertaintyConstantC = 3., uncertaintyConstantD = 3.;\n    double winnerRS;\n\n    BMK_benchOutcome_t const outcome = BMK_benchMemInvertible(buf, ctx, BASE_CLEVEL, &cParams, BMK_both, 2);\n    if (!BMK_isSuccessful_benchOutcome(outcome)) {\n        DEBUGOUTPUT(\"Benchmarking failed \\n\");\n        return ERROR_RESULT;\n    }\n    benchres = BMK_extract_benchResult(outcome);\n\n    winnerRS = resultScore(*winnerResult, buf.srcSize, target);\n    DEBUGOUTPUT(\"WinnerScore: %f \\n \", winnerRS);\n\n    *resultPtr = benchres;\n\n    /* anything with worse ratio in feas is definitely worse, discard */\n    if(feas && benchres.cSize < winnerResult->cSize && !g_optmode) {\n        return WORSE_RESULT;\n    }\n\n    /* calculate uncertainty in compression / decompression runs */\n    if (benchres.cSpeed) {\n        double const loopDurationC = (double)(((U64)buf.srcSize * TIMELOOP_NANOSEC) / benchres.cSpeed);\n        uncertaintyConstantC = ((loopDurationC + (double)(2 * g_clockGranularity))/loopDurationC);\n    }\n\n    if (benchres.dSpeed) {\n        double const loopDurationD = (double)(((U64)buf.srcSize * TIMELOOP_NANOSEC) / benchres.dSpeed);\n        uncertaintyConstantD = ((loopDurationD + (double)(2 * g_clockGranularity))/loopDurationD);\n    }\n\n    /* optimistic assumption of benchres */\n    {   BMK_benchResult_t resultMax = benchres;\n        resultMax.cSpeed = (unsigned long long)((double)resultMax.cSpeed * uncertaintyConstantC * VARIANCE);\n        resultMax.dSpeed = (unsigned long long)((double)resultMax.dSpeed * uncertaintyConstantD * VARIANCE);\n\n        /* disregard infeasible results in feas mode */\n        /* disregard if resultMax < winner in infeas mode */\n        if((feas && !feasible(resultMax, target)) ||\n          (!feas && (winnerRS > resultScore(resultMax, buf.srcSize, target)))) {\n            return WORSE_RESULT;\n        }\n    }\n\n    /* compare by resultScore when in infeas */\n    /* compare by compareResultLT when in feas */\n    if((!feas && (resultScore(benchres, buf.srcSize, target) > resultScore(*winnerResult, buf.srcSize, target))) ||\n       (feas && (compareResultLT(*winnerResult, benchres, target, buf.srcSize))) )  {\n        return BETTER_RESULT;\n    } else {\n        return WORSE_RESULT;\n    }\n}\n\n\n#define INFEASIBLE_THRESHOLD 200\n/* Memoized benchmarking, won't benchmark anything which has already been benchmarked before. */\nstatic int benchMemo(BMK_benchResult_t* resultPtr,\n                const buffers_t buf, const contexts_t ctx,\n                const paramValues_t cParams,\n                const constraint_t target,\n                BMK_benchResult_t* winnerResult, memoTable_t* const memoTableArray,\n                const int feas) {\n    static int bmcount = 0;\n    int res;\n\n    if ( memoTableGet(memoTableArray, cParams) >= INFEASIBLE_THRESHOLD\n      || redundantParams(cParams, target, buf.maxBlockSize) ) {\n        return WORSE_RESULT;\n    }\n\n    res = allBench(resultPtr, buf, ctx, cParams, target, winnerResult, feas);\n\n    if(DEBUG && !(bmcount % 250)) {\n        DISPLAY(\"Count: %d\\n\", bmcount);\n        bmcount++;\n    }\n    BMK_printWinnerOpt(stdout, CUSTOM_LEVEL, *resultPtr, cParams, target, buf.srcSize);\n\n    if(res == BETTER_RESULT || feas) {\n        memoTableSet(memoTableArray, cParams, 255); /* what happens if collisions are frequent */\n    }\n    return res;\n}\n\n\ntypedef struct {\n    U64 cSpeed_min;\n    U64 dSpeed_min;\n    U32 windowLog_max;\n    ZSTD_strategy strategy_max;\n} level_constraints_t;\n\nstatic level_constraints_t g_level_constraint[NB_LEVELS_TRACKED+1];\n\nstatic void BMK_init_level_constraints(int bytePerSec_level1)\n{\n    assert(NB_LEVELS_TRACKED >= ZSTD_maxCLevel());\n    memset(g_level_constraint, 0, sizeof(g_level_constraint));\n    g_level_constraint[1].cSpeed_min = bytePerSec_level1;\n    g_level_constraint[1].dSpeed_min = 0;\n    g_level_constraint[1].windowLog_max = 19;\n    g_level_constraint[1].strategy_max = ZSTD_fast;\n\n    /* establish speed objectives (relative to level 1) */\n    {   int l;\n        for (l=2; l<=NB_LEVELS_TRACKED; l++) {\n            g_level_constraint[l].cSpeed_min = (g_level_constraint[l-1].cSpeed_min * 49) / 64;\n            g_level_constraint[l].dSpeed_min = 0;\n            g_level_constraint[l].windowLog_max = (l<20) ? 23 : l+5;   /* only --ultra levels >= 20 can use windowlog > 23 */\n            g_level_constraint[l].strategy_max = ZSTD_STRATEGY_MAX;\n    }   }\n}\n\nstatic int BMK_seed(winnerInfo_t* winners,\n                    const paramValues_t params,\n                    const buffers_t buf,\n                    const contexts_t ctx)\n{\n    BMK_benchResult_t testResult;\n    int better = 0;\n    int cLevel;\n\n    BMK_benchParam(&testResult, buf, ctx, params);\n\n    for (cLevel = 1; cLevel <= NB_LEVELS_TRACKED; cLevel++) {\n\n        if (testResult.cSpeed < g_level_constraint[cLevel].cSpeed_min)\n            continue;   /* not fast enough for this level */\n        if (testResult.dSpeed < g_level_constraint[cLevel].dSpeed_min)\n            continue;   /* not fast enough for this level */\n        if (params.vals[wlog_ind] > g_level_constraint[cLevel].windowLog_max)\n            continue;   /* too much memory for this level */\n        if (params.vals[strt_ind] > (U32)g_level_constraint[cLevel].strategy_max)\n            continue;   /* forbidden strategy for this level */\n        if (winners[cLevel].result.cSize==0) {\n            /* first solution for this cLevel */\n            winners[cLevel].result = testResult;\n            winners[cLevel].params = params;\n            BMK_print_cLevelEntry(stdout, cLevel, params, testResult, buf.srcSize);\n            better = 1;\n            continue;\n        }\n\n        if ((double)testResult.cSize <= ((double)winners[cLevel].result.cSize * (1. + (0.02 / cLevel))) ) {\n            /* Validate solution is \"good enough\" */\n            double W_ratio = (double)buf.srcSize / (double)testResult.cSize;\n            double O_ratio = (double)buf.srcSize / (double)winners[cLevel].result.cSize;\n            double W_ratioNote = log (W_ratio);\n            double O_ratioNote = log (O_ratio);\n            size_t W_DMemUsed = (1 << params.vals[wlog_ind]) + (16 KB);\n            size_t O_DMemUsed = (1 << winners[cLevel].params.vals[wlog_ind]) + (16 KB);\n            double W_DMemUsed_note = W_ratioNote * ( 40 + 9*cLevel) - log((double)W_DMemUsed);\n            double O_DMemUsed_note = O_ratioNote * ( 40 + 9*cLevel) - log((double)O_DMemUsed);\n\n            size_t W_CMemUsed = ((size_t)1 << params.vals[wlog_ind]) + ZSTD_estimateCCtxSize_usingCParams(pvalsToCParams(params));\n            size_t O_CMemUsed = ((size_t)1 << winners[cLevel].params.vals[wlog_ind]) + ZSTD_estimateCCtxSize_usingCParams(pvalsToCParams(winners[cLevel].params));\n            double W_CMemUsed_note = W_ratioNote * ( 50 + 13*cLevel) - log((double)W_CMemUsed);\n            double O_CMemUsed_note = O_ratioNote * ( 50 + 13*cLevel) - log((double)O_CMemUsed);\n\n            double W_CSpeed_note = W_ratioNote * (double)( 30 + 10*cLevel) + log((double)testResult.cSpeed);\n            double O_CSpeed_note = O_ratioNote * (double)( 30 + 10*cLevel) + log((double)winners[cLevel].result.cSpeed);\n\n            double W_DSpeed_note = W_ratioNote * (double)( 20 + 2*cLevel) + log((double)testResult.dSpeed);\n            double O_DSpeed_note = O_ratioNote * (double)( 20 + 2*cLevel) + log((double)winners[cLevel].result.dSpeed);\n\n            if (W_DMemUsed_note < O_DMemUsed_note) {\n                /* uses too much Decompression memory for too little benefit */\n                if (W_ratio > O_ratio)\n                DISPLAYLEVEL(3, \"Decompression Memory : %5.3f @ %4.1f MB  vs  %5.3f @ %4.1f MB   : not enough for level %i\\n\",\n                         W_ratio, (double)(W_DMemUsed) / 1024 / 1024,\n                         O_ratio, (double)(O_DMemUsed) / 1024 / 1024,   cLevel);\n                continue;\n            }\n            if (W_CMemUsed_note < O_CMemUsed_note) {\n                /* uses too much memory for compression for too little benefit */\n                if (W_ratio > O_ratio)\n                DISPLAYLEVEL(3, \"Compression Memory : %5.3f @ %4.1f MB  vs  %5.3f @ %4.1f MB   : not enough for level %i\\n\",\n                         W_ratio, (double)(W_CMemUsed) / 1024 / 1024,\n                         O_ratio, (double)(O_CMemUsed) / 1024 / 1024,\n                         cLevel);\n                continue;\n            }\n            if (W_CSpeed_note   < O_CSpeed_note  ) {\n                /* too large compression speed difference for the compression benefit */\n                if (W_ratio > O_ratio)\n                DISPLAYLEVEL(3, \"Compression Speed : %5.3f @ %4.1f MB/s  vs  %5.3f @ %4.1f MB/s   : not enough for level %i\\n\",\n                         W_ratio, (double)testResult.cSpeed / MB_UNIT,\n                         O_ratio, (double)winners[cLevel].result.cSpeed / MB_UNIT,\n                         cLevel);\n                continue;\n            }\n            if (W_DSpeed_note   < O_DSpeed_note  ) {\n                /* too large decompression speed difference for the compression benefit */\n                if (W_ratio > O_ratio)\n                DISPLAYLEVEL(3, \"Decompression Speed : %5.3f @ %4.1f MB/s  vs  %5.3f @ %4.1f MB/s   : not enough for level %i\\n\",\n                         W_ratio, (double)testResult.dSpeed / MB_UNIT,\n                         O_ratio, (double)winners[cLevel].result.dSpeed / MB_UNIT,\n                         cLevel);\n                continue;\n            }\n\n            if (W_ratio < O_ratio)\n                DISPLAYLEVEL(3, \"Solution %4.3f selected over %4.3f at level %i, due to better secondary statistics \\n\",\n                                W_ratio, O_ratio, cLevel);\n\n            winners[cLevel].result = testResult;\n            winners[cLevel].params = params;\n            BMK_print_cLevelEntry(stdout, cLevel, params, testResult, buf.srcSize);\n\n            better = 1;\n    }   }\n\n    return better;\n}\n\n/*-************************************\n*  Compression Level Table Generation Functions\n**************************************/\n\n#define PARAMTABLELOG   25\n#define PARAMTABLESIZE (1<<PARAMTABLELOG)\n#define PARAMTABLEMASK (PARAMTABLESIZE-1)\nstatic BYTE g_alreadyTested[PARAMTABLESIZE] = {0};   /* init to zero */\n\nstatic BYTE* NB_TESTS_PLAYED(paramValues_t p)\n{\n    ZSTD_compressionParameters const cParams = pvalsToCParams(sanitizeParams(p));\n    unsigned long long const h64 = XXH64(&cParams, sizeof(cParams), 0);\n    return &g_alreadyTested[(h64 >> 3) & PARAMTABLEMASK];\n}\n\nstatic void playAround(FILE* f,\n                       winnerInfo_t* winners,\n                       paramValues_t p,\n                       const buffers_t buf, const contexts_t ctx)\n{\n    int nbVariations = 0;\n    UTIL_time_t const clockStart = UTIL_getTime();\n\n    while (UTIL_clockSpanMicro(clockStart) < g_maxVariationTime) {\n        if (nbVariations++ > g_maxNbVariations) break;\n\n        do {\n            int i;\n            for(i = 0; i < 4; i++) {\n                paramVaryOnce(FUZ_rand(&g_rand) % (strt_ind + 1),\n                              ((FUZ_rand(&g_rand) & 1) << 1) - 1,\n                              &p);\n            }\n        } while (!paramValid(p));\n\n        /* exclude faster if already played params */\n        if (FUZ_rand(&g_rand) & ((1 << *NB_TESTS_PLAYED(p))-1))\n            continue;\n\n        /* test */\n        {   BYTE* const b = NB_TESTS_PLAYED(p);\n            (*b)++;\n        }\n        if (!BMK_seed(winners, p, buf, ctx)) continue;\n\n        /* improvement found => search more */\n        BMK_saveAndPrint_cLevelTable(f, winners, buf.srcSize);\n        playAround(f, winners, p, buf, ctx);\n    }\n\n}\n\nstatic void\nBMK_selectRandomStart( FILE* f,\n                       winnerInfo_t* winners,\n                       const buffers_t buf, const contexts_t ctx)\n{\n    U32 const id = FUZ_rand(&g_rand) % (NB_LEVELS_TRACKED+1);\n    if ((id==0) || (winners[id].params.vals[wlog_ind]==0)) {\n        /* use some random entry */\n        paramValues_t const p = adjustParams(cParamsToPVals(pvalsToCParams(randomParams())), /* defaults nonCompression parameters */\n                                             buf.srcSize, 0);\n        playAround(f, winners, p, buf, ctx);\n    } else {\n        playAround(f, winners, winners[id].params, buf, ctx);\n    }\n}\n\n\n/* BMK_generate_cLevelTable() :\n * test a large number of configurations\n * and distribute them across compression levels according to speed conditions.\n * display and save all intermediate results into rfName = \"grillResults.txt\".\n * the function automatically stops after g_timeLimit_s.\n * this function cannot error, it directly exit() in case of problem.\n */\nstatic void BMK_generate_cLevelTable(const buffers_t buf, const contexts_t ctx)\n{\n    paramValues_t params;\n    winnerInfo_t winners[NB_LEVELS_TRACKED+1];\n    const char* const rfName = \"grillResults.txt\";\n    FILE* const f = fopen(rfName, \"w\");\n\n    /* init */\n    assert(g_singleRun==0);\n    memset(winners, 0, sizeof(winners));\n    if (f==NULL) { DISPLAY(\"error opening %s \\n\", rfName); exit(1); }\n\n    if (g_target) {\n        BMK_init_level_constraints(g_target * MB_UNIT);\n    } else {\n        /* baseline config for level 1 */\n        paramValues_t const l1params = cParamsToPVals(ZSTD_getCParams(1, buf.maxBlockSize, ctx.dictSize));\n        BMK_benchResult_t testResult;\n        BMK_benchParam(&testResult, buf, ctx, l1params);\n        BMK_init_level_constraints((int)((testResult.cSpeed * 31) / 32));\n    }\n\n    /* populate initial solution */\n    {   const int maxSeeds = g_noSeed ? 1 : ZSTD_maxCLevel();\n        int i;\n        for (i=0; i<=maxSeeds; i++) {\n            params = cParamsToPVals(ZSTD_getCParams(i, buf.maxBlockSize, 0));\n            BMK_seed(winners, params, buf, ctx);\n    }   }\n    BMK_saveAndPrint_cLevelTable(f, winners, buf.srcSize);\n\n    /* start tests */\n    {   const UTIL_time_t grillStart = UTIL_getTime();\n        do {\n            BMK_selectRandomStart(f, winners, buf, ctx);\n        } while (BMK_timeSpan_s(grillStart) < g_timeLimit_s);\n    }\n\n    /* end summary */\n    BMK_saveAndPrint_cLevelTable(f, winners, buf.srcSize);\n    DISPLAY(\"grillParams operations completed \\n\");\n\n    /* clean up*/\n    fclose(f);\n}\n\n\n/*-************************************\n*  Single Benchmark Functions\n**************************************/\n\nstatic int\nbenchOnce(const buffers_t buf, const contexts_t ctx, const int cLevel)\n{\n    BMK_benchResult_t testResult;\n    g_params = adjustParams(overwriteParams(cParamsToPVals(ZSTD_getCParams(cLevel, buf.maxBlockSize, ctx.dictSize)), g_params), buf.maxBlockSize, ctx.dictSize);\n\n    if (BMK_benchParam(&testResult, buf, ctx, g_params)) {\n        DISPLAY(\"Error during benchmarking\\n\");\n        return 1;\n    }\n\n    BMK_printWinner(stdout, CUSTOM_LEVEL, testResult, g_params, buf.srcSize);\n\n    return 0;\n}\n\nstatic int benchSample(double compressibility, int cLevel)\n{\n    const char* const name = \"Sample 10MB\";\n    size_t const benchedSize = 10 MB;\n    void* const srcBuffer = malloc(benchedSize);\n    int ret = 0;\n\n    buffers_t buf;\n    contexts_t ctx;\n\n    if(srcBuffer == NULL) {\n        DISPLAY(\"Out of Memory\\n\");\n        return 2;\n    }\n\n    RDG_genBuffer(srcBuffer, benchedSize, compressibility, 0.0, 0);\n\n    if(createBuffersFromMemory(&buf, srcBuffer, 1, &benchedSize)) {\n        DISPLAY(\"Buffer Creation Error\\n\");\n        free(srcBuffer);\n        return 3;\n    }\n\n    if(createContexts(&ctx, NULL)) {\n        DISPLAY(\"Context Creation Error\\n\");\n        freeBuffers(buf);\n        return 1;\n    }\n\n    /* bench */\n    DISPLAY(\"\\r%79s\\r\", \"\");\n    DISPLAY(\"using %s %i%%: \\n\", name, (int)(compressibility*100));\n\n    if(g_singleRun) {\n        ret = benchOnce(buf, ctx, cLevel);\n    } else {\n        BMK_generate_cLevelTable(buf, ctx);\n    }\n\n    freeBuffers(buf);\n    freeContexts(ctx);\n\n    return ret;\n}\n\n/* benchFiles() :\n * note: while this function takes a table of filenames,\n * in practice, only the first filename will be used */\nstatic int benchFiles(const char** fileNamesTable, int nbFiles,\n                      const char* dictFileName, int cLevel)\n{\n    buffers_t buf;\n    contexts_t ctx;\n    int ret = 0;\n\n    if (createBuffers(&buf, fileNamesTable, nbFiles)) {\n        DISPLAY(\"unable to load files\\n\");\n        return 1;\n    }\n\n    if (createContexts(&ctx, dictFileName)) {\n        DISPLAY(\"unable to load dictionary\\n\");\n        freeBuffers(buf);\n        return 2;\n    }\n\n    DISPLAY(\"\\r%79s\\r\", \"\");\n    if (nbFiles == 1) {\n        DISPLAY(\"using %s : \\n\", fileNamesTable[0]);\n    } else {\n        DISPLAY(\"using %d Files : \\n\", nbFiles);\n    }\n\n    if (g_singleRun) {\n        ret = benchOnce(buf, ctx, cLevel);\n    } else {\n        BMK_generate_cLevelTable(buf, ctx);\n    }\n\n    freeBuffers(buf);\n    freeContexts(ctx);\n    return ret;\n}\n\n\n/*-************************************\n*  Local Optimization Functions\n**************************************/\n\n/* One iteration of hill climbing. Specifically, it first tries all\n * valid parameter configurations w/ manhattan distance 1 and picks the best one\n * failing that, it progressively tries candidates further and further away (up to #dim + 2)\n * if it finds a candidate exceeding winnerInfo, it will repeat. Otherwise, it will stop the\n * current stage of hill climbing.\n * Each iteration of hill climbing proceeds in 2 'phases'. Phase 1 climbs according to\n * the resultScore function, which is effectively a linear increase in reward until it reaches\n * the constraint-satisfying value, it which point any excess results in only logarithmic reward.\n * This aims to find some constraint-satisfying point.\n * Phase 2 optimizes in accordance with what the original function sets out to maximize, with\n * all feasible solutions valued over all infeasible solutions.\n */\n\n/* sanitize all params here.\n * all generation after random should be sanitized. (maybe sanitize random)\n */\nstatic winnerInfo_t climbOnce(const constraint_t target,\n                memoTable_t* mtAll,\n                const buffers_t buf, const contexts_t ctx,\n                const paramValues_t init)\n{\n    /*\n     * cparam - currently considered 'center'\n     * candidate - params to benchmark/results\n     * winner - best option found so far.\n     */\n    paramValues_t cparam = init;\n    winnerInfo_t candidateInfo, winnerInfo;\n    int better = 1;\n    int feas = 0;\n\n    winnerInfo = initWinnerInfo(init);\n    candidateInfo = winnerInfo;\n\n    {   winnerInfo_t bestFeasible1 = initWinnerInfo(cparam);\n        DEBUGOUTPUT(\"Climb Part 1\\n\");\n        while(better) {\n            int offset;\n            size_t i, dist;\n            const size_t varLen = mtAll[cparam.vals[strt_ind]].varLen;\n            better = 0;\n            DEBUGOUTPUT(\"Start\\n\");\n            cparam = winnerInfo.params;\n            candidateInfo.params = cparam;\n             /* all dist-1 candidates */\n            for (i = 0; i < varLen; i++) {\n                for (offset = -1; offset <= 1; offset += 2) {\n                    CHECKTIME(winnerInfo);\n                    candidateInfo.params = cparam;\n                    paramVaryOnce(mtAll[cparam.vals[strt_ind]].varArray[i],\n                                  offset,\n                                  &candidateInfo.params);\n\n                    if(paramValid(candidateInfo.params)) {\n                        int res;\n                        res = benchMemo(&candidateInfo.result, buf, ctx,\n                            sanitizeParams(candidateInfo.params), target, &winnerInfo.result, mtAll, feas);\n                        DEBUGOUTPUT(\"Res: %d\\n\", res);\n                        if(res == BETTER_RESULT) { /* synonymous with better when called w/ infeasibleBM */\n                            winnerInfo = candidateInfo;\n                            better = 1;\n                            if(compareResultLT(bestFeasible1.result, winnerInfo.result, target, buf.srcSize)) {\n                                bestFeasible1 = winnerInfo;\n                            }\n                        }\n                    }\n                }  /* for (offset = -1; offset <= 1; offset += 2) */\n            }   /* for (i = 0; i < varLen; i++) */\n\n            if(better) {\n                continue;\n            }\n\n            for (dist = 2; dist < varLen + 2; dist++) { /* varLen is # dimensions */\n                for (i = 0; i < (1ULL << varLen) / varLen + 2; i++) {\n                    int res;\n                    CHECKTIME(winnerInfo);\n                    candidateInfo.params = cparam;\n                    /* param error checking already done here */\n                    paramVariation(&candidateInfo.params, mtAll, (U32)dist);\n\n                    res = benchMemo(&candidateInfo.result,\n                                buf, ctx,\n                                sanitizeParams(candidateInfo.params), target,\n                                &winnerInfo.result, mtAll, feas);\n                    DEBUGOUTPUT(\"Res: %d\\n\", res);\n                    if (res == BETTER_RESULT) { /* synonymous with better in this case*/\n                        winnerInfo = candidateInfo;\n                        better = 1;\n                        if (compareResultLT(bestFeasible1.result, winnerInfo.result, target, buf.srcSize)) {\n                            bestFeasible1 = winnerInfo;\n                        }\n                        break;\n                    }\n                }\n\n                if (better) {\n                    break;\n                }\n            }   /* for(dist = 2; dist < varLen + 2; dist++) */\n\n            if (!better) { /* infeas -> feas -> stop */\n                if (feas) return winnerInfo;\n                feas = 1;\n                better = 1;\n                winnerInfo = bestFeasible1; /* note with change, bestFeasible may not necessarily be feasible, but if one has been benchmarked, it will be. */\n                DEBUGOUTPUT(\"Climb Part 2\\n\");\n            }\n        }\n        winnerInfo = bestFeasible1;\n    }\n\n    return winnerInfo;\n}\n\n/* Optimizes for a fixed strategy */\n\n/* flexible parameters: iterations of failed climbing (or if we do non-random, maybe this is when everything is close to visited)\n   weight more on visit for bad results, less on good results/more on later results / ones with more failures.\n   allocate memoTable here.\n */\nstatic winnerInfo_t\noptimizeFixedStrategy(const buffers_t buf, const contexts_t ctx,\n                      const constraint_t target, paramValues_t paramTarget,\n                      const ZSTD_strategy strat,\n                      memoTable_t* memoTableArray, const int tries)\n{\n    int i = 0;\n\n    paramValues_t init;\n    winnerInfo_t winnerInfo, candidateInfo;\n    winnerInfo = initWinnerInfo(emptyParams());\n    /* so climb is given the right fixed strategy */\n    paramTarget.vals[strt_ind] = strat;\n    /* to pass ZSTD_checkCParams */\n    paramTarget = cParamUnsetMin(paramTarget);\n\n    init = paramTarget;\n\n    for(i = 0; i < tries; i++) {\n        DEBUGOUTPUT(\"Restart\\n\");\n        do {\n            randomConstrainedParams(&init, memoTableArray, strat);\n        } while(redundantParams(init, target, buf.maxBlockSize));\n        candidateInfo = climbOnce(target, memoTableArray, buf, ctx, init);\n        if (compareResultLT(winnerInfo.result, candidateInfo.result, target, buf.srcSize)) {\n            winnerInfo = candidateInfo;\n            BMK_printWinnerOpt(stdout, CUSTOM_LEVEL, winnerInfo.result, winnerInfo.params, target, buf.srcSize);\n            i = 0;\n            continue;\n        }\n        CHECKTIME(winnerInfo);\n        i++;\n    }\n    return winnerInfo;\n}\n\n/* goes best, best-1, best+1, best-2, ... */\n/* return 0 if nothing remaining */\nstatic int nextStrategy(const int currentStrategy, const int bestStrategy)\n{\n    if(bestStrategy <= currentStrategy) {\n        int candidate = 2 * bestStrategy - currentStrategy - 1;\n        if(candidate < 1) {\n            candidate = currentStrategy + 1;\n            if(candidate > (int)ZSTD_STRATEGY_MAX) {\n                return 0;\n            } else {\n                return candidate;\n            }\n        } else {\n            return candidate;\n        }\n    } else { /* bestStrategy >= currentStrategy */\n        int candidate = 2 * bestStrategy - currentStrategy;\n        if(candidate > (int)ZSTD_STRATEGY_MAX) {\n            candidate = currentStrategy - 1;\n            if(candidate < 1) {\n                return 0;\n            } else {\n                return candidate;\n            }\n        } else {\n            return candidate;\n        }\n    }\n}\n\n/* experiment with playing with this and decay value */\n\n/* main fn called when using --optimize */\n/* Does strategy selection by benchmarking default compression levels\n * then optimizes by strategy, starting with the best one and moving\n * progressively moving further away by number\n * args:\n * fileNamesTable - list of files to benchmark\n * nbFiles - length of fileNamesTable\n * dictFileName - name of dictionary file if one, else NULL\n * target - performance constraints (cSpeed, dSpeed, cMem)\n * paramTarget - parameter constraints (i.e. restriction search space to where strategy = ZSTD_fast)\n * cLevel - compression level to exceed (all solutions must be > lvl in cSpeed + ratio)\n */\n\nstatic unsigned g_maxTries = 5;\n#define TRY_DECAY 1\n\nstatic int\noptimizeForSize(const char* const * const fileNamesTable, const size_t nbFiles,\n                const char* dictFileName,\n                constraint_t target, paramValues_t paramTarget,\n                const int cLevelOpt, const int cLevelRun,\n                const U32 memoTableLog)\n{\n    varInds_t varArray [NUM_PARAMS];\n    int ret = 0;\n    const size_t varLen = variableParams(paramTarget, varArray, dictFileName != NULL);\n    winnerInfo_t winner = initWinnerInfo(emptyParams());\n    memoTable_t* allMT = NULL;\n    paramValues_t paramBase;\n    contexts_t ctx;\n    buffers_t buf;\n    g_time = UTIL_getTime();\n\n    if (createBuffers(&buf, fileNamesTable, nbFiles)) {\n        DISPLAY(\"unable to load files\\n\");\n        return 1;\n    }\n\n    if (createContexts(&ctx, dictFileName)) {\n        DISPLAY(\"unable to load dictionary\\n\");\n        freeBuffers(buf);\n        return 2;\n    }\n\n    if (nbFiles == 1) {\n        DISPLAYLEVEL(2, \"Loading %s...       \\r\", fileNamesTable[0]);\n    } else {\n        DISPLAYLEVEL(2, \"Loading %lu Files...       \\r\", (unsigned long)nbFiles);\n    }\n\n    /* sanitize paramTarget */\n    optimizerAdjustInput(&paramTarget, buf.maxBlockSize);\n    paramBase = cParamUnsetMin(paramTarget);\n\n    allMT = createMemoTableArray(paramTarget, varArray, varLen, memoTableLog);\n\n    if (!allMT) {\n        DISPLAY(\"MemoTable Init Error\\n\");\n        ret = 2;\n        goto _cleanUp;\n    }\n\n    /* default strictnesses */\n    if (g_strictness == PARAM_UNSET) {\n        if(g_optmode) {\n            g_strictness = 100;\n        } else {\n            g_strictness = 90;\n        }\n    } else {\n        if(0 >= g_strictness || g_strictness > 100) {\n            DISPLAY(\"Strictness Outside of Bounds\\n\");\n            ret = 4;\n            goto _cleanUp;\n        }\n    }\n\n    /* use level'ing mode instead of normal target mode */\n    if (g_optmode) {\n        winner.params = cParamsToPVals(ZSTD_getCParams(cLevelOpt, buf.maxBlockSize, ctx.dictSize));\n        if(BMK_benchParam(&winner.result, buf, ctx, winner.params)) {\n            ret = 3;\n            goto _cleanUp;\n        }\n\n        g_lvltarget = winner.result;\n        g_lvltarget.cSpeed = (g_lvltarget.cSpeed * g_strictness) / 100;\n        g_lvltarget.dSpeed = (g_lvltarget.dSpeed * g_strictness) / 100;\n        g_lvltarget.cSize = (g_lvltarget.cSize * 100) / g_strictness;\n\n        target.cSpeed = (U32)g_lvltarget.cSpeed;\n        target.dSpeed = (U32)g_lvltarget.dSpeed;\n\n        BMK_printWinnerOpt(stdout, cLevelOpt, winner.result, winner.params, target, buf.srcSize);\n    }\n\n    /* Don't want it to return anything worse than the best known result */\n    if (g_singleRun) {\n        BMK_benchResult_t res;\n        g_params = adjustParams(overwriteParams(cParamsToPVals(ZSTD_getCParams(cLevelRun, buf.maxBlockSize, ctx.dictSize)), g_params), buf.maxBlockSize, ctx.dictSize);\n        if (BMK_benchParam(&res, buf, ctx, g_params)) {\n            ret = 45;\n            goto _cleanUp;\n        }\n        if(compareResultLT(winner.result, res, relaxTarget(target), buf.srcSize)) {\n            winner.result = res;\n            winner.params = g_params;\n        }\n    }\n\n    /* bench */\n    DISPLAYLEVEL(2, \"\\r%79s\\r\", \"\");\n    if(nbFiles == 1) {\n        DISPLAYLEVEL(2, \"optimizing for %s\", fileNamesTable[0]);\n    } else {\n        DISPLAYLEVEL(2, \"optimizing for %lu Files\", (unsigned long)nbFiles);\n    }\n\n    if(target.cSpeed != 0) { DISPLAYLEVEL(2,\" - limit compression speed %u MB/s\", (unsigned)(target.cSpeed >> 20)); }\n    if(target.dSpeed != 0) { DISPLAYLEVEL(2, \" - limit decompression speed %u MB/s\", (unsigned)(target.dSpeed >> 20)); }\n    if(target.cMem != (U32)-1) { DISPLAYLEVEL(2, \" - limit memory %u MB\", (unsigned)(target.cMem >> 20)); }\n\n    DISPLAYLEVEL(2, \"\\n\");\n    init_clockGranularity();\n\n    {   paramValues_t CParams;\n\n        /* find best solution from default params */\n        {   const int maxSeeds = g_noSeed ? 1 : ZSTD_maxCLevel();\n            DEBUGOUTPUT(\"Strategy Selection\\n\");\n            if (paramTarget.vals[strt_ind] == PARAM_UNSET) {\n                BMK_benchResult_t candidate;\n                int i;\n                for (i=1; i<=maxSeeds; i++) {\n                    int ec;\n                    CParams = overwriteParams(cParamsToPVals(ZSTD_getCParams(i, buf.maxBlockSize, ctx.dictSize)), paramTarget);\n                    ec = BMK_benchParam(&candidate, buf, ctx, CParams);\n                    BMK_printWinnerOpt(stdout, i, candidate, CParams, target, buf.srcSize);\n\n                    if(!ec && compareResultLT(winner.result, candidate, relaxTarget(target), buf.srcSize)) {\n                        winner.result = candidate;\n                        winner.params = CParams;\n                    }\n\n                    CHECKTIMEGT(ret, 0, _displayCleanUp); /* if pass time limit, stop */\n                    /* if the current params are too slow, just stop. */\n                    if(target.cSpeed > candidate.cSpeed * 3 / 2) { break; }\n                }\n\n                BMK_printWinnerOpt(stdout, CUSTOM_LEVEL, winner.result, winner.params, target, buf.srcSize);\n            }\n        }\n\n        DEBUGOUTPUT(\"Real Opt\\n\");\n        /* start 'real' optimization */\n        {   int bestStrategy = (int)winner.params.vals[strt_ind];\n            if (paramTarget.vals[strt_ind] == PARAM_UNSET) {\n                int st = bestStrategy;\n                int tries = g_maxTries;\n\n                /* one iterations of hill climbing with the level-defined parameters. */\n                {   winnerInfo_t const w1 = climbOnce(target, allMT, buf, ctx, winner.params);\n                    if (compareResultLT(winner.result, w1.result, target, buf.srcSize)) {\n                        winner = w1;\n                    }\n                    CHECKTIMEGT(ret, 0, _displayCleanUp);\n                }\n\n                while(st && tries > 0) {\n                    winnerInfo_t wc;\n                    DEBUGOUTPUT(\"StrategySwitch: %s\\n\", g_stratName[st]);\n\n                    wc = optimizeFixedStrategy(buf, ctx, target, paramBase, st, allMT, tries);\n\n                    if(compareResultLT(winner.result, wc.result, target, buf.srcSize)) {\n                        winner = wc;\n                        tries = g_maxTries;\n                        bestStrategy = st;\n                    } else {\n                        st = nextStrategy(st, bestStrategy);\n                        tries -= TRY_DECAY;\n                    }\n                    CHECKTIMEGT(ret, 0, _displayCleanUp);\n                }\n            } else {\n                winner = optimizeFixedStrategy(buf, ctx, target, paramBase, paramTarget.vals[strt_ind], allMT, g_maxTries);\n            }\n\n        }\n\n        /* no solution found */\n        if(winner.result.cSize == (size_t)-1) {\n            ret = 1;\n            DISPLAY(\"No feasible solution found\\n\");\n            goto _cleanUp;\n        }\n\n        /* end summary */\n_displayCleanUp:\n        if (g_displayLevel >= 0) {\n            BMK_displayOneResult(stdout, winner, buf.srcSize);\n        }\n        BMK_paramValues_into_commandLine(stdout, winner.params);\n        DISPLAYLEVEL(1, \"grillParams size - optimizer completed \\n\");\n    }\n\n_cleanUp:\n    freeContexts(ctx);\n    freeBuffers(buf);\n    freeMemoTableArray(allMT);\n    return ret;\n}\n\n/*-************************************\n*  CLI parsing functions\n**************************************/\n\n/** longCommandWArg() :\n *  check if *stringPtr is the same as longCommand.\n *  If yes, @return 1 and advances *stringPtr to the position which immediately follows longCommand.\n * @return 0 and doesn't modify *stringPtr otherwise.\n * from zstdcli.c\n */\nstatic int longCommandWArg(const char** stringPtr, const char* longCommand)\n{\n    size_t const comSize = strlen(longCommand);\n    int const result = !strncmp(*stringPtr, longCommand, comSize);\n    if (result) *stringPtr += comSize;\n    return result;\n}\n\nstatic void errorOut(const char* msg)\n{\n    DISPLAY(\"%s \\n\", msg); exit(1);\n}\n\n/*! readU32FromChar() :\n * @return : unsigned integer value read from input in `char` format.\n *  allows and interprets K, KB, KiB, M, MB and MiB suffix.\n *  Will also modify `*stringPtr`, advancing it to position where it stopped reading.\n *  Note : function will exit() program if digit sequence overflows */\nstatic unsigned readU32FromChar(const char** stringPtr)\n{\n    const char errorMsg[] = \"error: numeric value too large\";\n    unsigned sign = 1;\n    unsigned result = 0;\n    if(**stringPtr == '-') { sign = (unsigned)-1; (*stringPtr)++; }\n    while ((**stringPtr >='0') && (**stringPtr <='9')) {\n        unsigned const max = (((unsigned)(-1)) / 10) - 1;\n        if (result > max) errorOut(errorMsg);\n        result *= 10;\n        assert(**stringPtr >= '0');\n        result += (unsigned)(**stringPtr - '0');\n        (*stringPtr)++ ;\n    }\n    if ((**stringPtr=='K') || (**stringPtr=='M')) {\n        unsigned const maxK = ((unsigned)(-1)) >> 10;\n        if (result > maxK) errorOut(errorMsg);\n        result <<= 10;\n        if (**stringPtr=='M') {\n            if (result > maxK) errorOut(errorMsg);\n            result <<= 10;\n        }\n        (*stringPtr)++;  /* skip `K` or `M` */\n        if (**stringPtr=='i') (*stringPtr)++;\n        if (**stringPtr=='B') (*stringPtr)++;\n    }\n    return result * sign;\n}\n\nstatic double readDoubleFromChar(const char** stringPtr)\n{\n    double result = 0, divide = 10;\n    while ((**stringPtr >='0') && (**stringPtr <='9')) {\n        result *= 10, result += **stringPtr - '0', (*stringPtr)++ ;\n    }\n    if(**stringPtr!='.') {\n        return result;\n    }\n    (*stringPtr)++;\n    while ((**stringPtr >='0') && (**stringPtr <='9')) {\n        result += (double)(**stringPtr - '0') / divide, divide *= 10, (*stringPtr)++ ;\n    }\n    return result;\n}\n\nstatic int usage(const char* exename)\n{\n    DISPLAY( \"Usage :\\n\");\n    DISPLAY( \"      %s [arg] file\\n\", exename);\n    DISPLAY( \"Arguments :\\n\");\n    DISPLAY( \" file : path to the file used as reference (if none, generates a compressible sample)\\n\");\n    DISPLAY( \" -H/-h  : Help (this text + advanced options)\\n\");\n    return 0;\n}\n\nstatic int usage_advanced(void)\n{\n    DISPLAY( \"\\nAdvanced options :\\n\");\n    DISPLAY( \" -T#          : set level 1 speed objective \\n\");\n    DISPLAY( \" -B#          : cut input into blocks of size # (default : single block) \\n\");\n    DISPLAY( \" --optimize=  : same as -O with more verbose syntax (see README.md)\\n\");\n    DISPLAY( \" -S           : Single run \\n\");\n    DISPLAY( \" --zstd       : Single run, parameter selection same as zstdcli \\n\");\n    DISPLAY( \" -P#          : generated sample compressibility (default : %.1f%%) \\n\", COMPRESSIBILITY_DEFAULT * 100);\n    DISPLAY( \" -t#          : Caps runtime of operation in seconds (default : %u seconds (%.1f hours)) \\n\",\n                                (unsigned)g_timeLimit_s, (double)g_timeLimit_s / 3600);\n    DISPLAY( \" -v           : Prints Benchmarking output\\n\");\n    DISPLAY( \" -D           : Next argument dictionary file\\n\");\n    DISPLAY( \" -s           : Separate Files\\n\");\n    return 0;\n}\n\nstatic int badusage(const char* exename)\n{\n    DISPLAY(\"Wrong parameters\\n\");\n    usage(exename);\n    return 1;\n}\n\n#define PARSE_SUB_ARGS(stringLong, stringShort, variable) { \\\n    if ( longCommandWArg(&argument, stringLong)             \\\n      || longCommandWArg(&argument, stringShort) ) {        \\\n          variable = readU32FromChar(&argument);            \\\n          if (argument[0]==',') {                           \\\n              argument++; continue;                         \\\n          } else break;                                     \\\n}   }\n\n/* 1 if successful parse, 0 otherwise */\nstatic int parse_params(const char** argptr, paramValues_t* pv) {\n    int matched = 0;\n    const char* argOrig = *argptr;\n    varInds_t v;\n    for(v = 0; v < NUM_PARAMS; v++) {\n        if ( longCommandWArg(argptr,g_shortParamNames[v])\n          || longCommandWArg(argptr, g_paramNames[v]) ) {\n            if(**argptr == '=') {\n                (*argptr)++;\n                pv->vals[v] = readU32FromChar(argptr);\n                matched = 1;\n                break;\n            }\n        }\n        /* reset and try again */\n        *argptr = argOrig;\n    }\n    return matched;\n}\n\n/*-************************************\n*  Main\n**************************************/\n\nint main(int argc, const char** argv)\n{\n    int i,\n        filenamesStart=0,\n        result;\n    const char* exename=argv[0];\n    const char* input_filename = NULL;\n    const char* dictFileName = NULL;\n    U32 main_pause = 0;\n    int cLevelOpt = 0, cLevelRun = 0;\n    int separateFiles = 0;\n    double compressibility = COMPRESSIBILITY_DEFAULT;\n    U32 memoTableLog = PARAM_UNSET;\n    constraint_t target = { 0, 0, (U32)-1 };\n\n    paramValues_t paramTarget = emptyParams();\n    g_params = emptyParams();\n\n    assert(argc>=1);   /* for exename */\n\n    for(i=1; i<argc; i++) {\n        const char* argument = argv[i];\n        DEBUGOUTPUT(\"%d: %s\\n\", i, argument);\n        assert(argument != NULL);\n\n        if(!strcmp(argument,\"--no-seed\")) { g_noSeed = 1; continue; }\n\n        if (longCommandWArg(&argument, \"--optimize=\")) {\n            g_optimizer = 1;\n            for ( ; ;) {\n                if(parse_params(&argument, &paramTarget)) { if(argument[0] == ',') { argument++; continue; } else break; }\n                PARSE_SUB_ARGS(\"compressionSpeed=\" ,  \"cSpeed=\", target.cSpeed);\n                PARSE_SUB_ARGS(\"decompressionSpeed=\", \"dSpeed=\", target.dSpeed);\n                PARSE_SUB_ARGS(\"compressionMemory=\" , \"cMem=\", target.cMem);\n                PARSE_SUB_ARGS(\"strict=\", \"stc=\", g_strictness);\n                PARSE_SUB_ARGS(\"maxTries=\", \"tries=\", g_maxTries);\n                PARSE_SUB_ARGS(\"memoLimitLog=\", \"memLog=\", memoTableLog);\n                if (longCommandWArg(&argument, \"level=\") || longCommandWArg(&argument, \"lvl=\")) { cLevelOpt = (int)readU32FromChar(&argument); g_optmode = 1; if (argument[0]==',') { argument++; continue; } else break; }\n                if (longCommandWArg(&argument, \"speedForRatio=\") || longCommandWArg(&argument, \"speedRatio=\")) { g_ratioMultiplier = readDoubleFromChar(&argument); if (argument[0]==',') { argument++; continue; } else break; }\n\n                DISPLAY(\"invalid optimization parameter \\n\");\n                return 1;\n            }\n\n            if (argument[0] != 0) {\n                DISPLAY(\"invalid --optimize= format\\n\");\n                return 1; /* check the end of string */\n            }\n            continue;\n        } else if (longCommandWArg(&argument, \"--zstd=\")) {\n        /* Decode command (note : aggregated commands are allowed) */\n            g_singleRun = 1;\n            for ( ; ;) {\n                if(parse_params(&argument, &g_params)) { if(argument[0] == ',') { argument++; continue; } else break; }\n                if (longCommandWArg(&argument, \"level=\") || longCommandWArg(&argument, \"lvl=\")) { cLevelRun = (int)readU32FromChar(&argument); g_params = emptyParams(); if (argument[0]==',') { argument++; continue; } else break; }\n\n                DISPLAY(\"invalid compression parameter \\n\");\n                return 1;\n            }\n\n            if (argument[0] != 0) {\n                DISPLAY(\"invalid --zstd= format\\n\");\n                return 1; /* check the end of string */\n            }\n            continue;\n            /* if not return, success */\n\n        } else if (longCommandWArg(&argument, \"--display=\")) {\n            /* Decode command (note : aggregated commands are allowed) */\n            memset(g_silenceParams, 1, sizeof(g_silenceParams));\n            for ( ; ;) {\n                int found = 0;\n                varInds_t v;\n                for(v = 0; v < NUM_PARAMS; v++) {\n                    if(longCommandWArg(&argument, g_shortParamNames[v]) || longCommandWArg(&argument, g_paramNames[v])) {\n                        g_silenceParams[v] = 0;\n                        found = 1;\n                    }\n                }\n                if(longCommandWArg(&argument, \"compressionParameters\") || longCommandWArg(&argument, \"cParams\")) {\n                    for(v = 0; v <= strt_ind; v++) {\n                        g_silenceParams[v] = 0;\n                    }\n                    found = 1;\n                }\n\n\n                if(found) {\n                    if(argument[0]==',') {\n                        continue;\n                    } else {\n                        break;\n                    }\n                }\n                DISPLAY(\"invalid parameter name parameter \\n\");\n                return 1;\n            }\n\n            if (argument[0] != 0) {\n                DISPLAY(\"invalid --display format\\n\");\n                return 1; /* check the end of string */\n            }\n            continue;\n        } else if (argument[0]=='-') {\n            argument++;\n\n            while (argument[0]!=0) {\n\n                switch(argument[0])\n                {\n                    /* Display help on usage */\n                case 'h' :\n                case 'H': usage(exename); usage_advanced(); return 0;\n\n                    /* Pause at the end (hidden option) */\n                case 'p': main_pause = 1; argument++; break;\n\n                    /* Sample compressibility (when no file provided) */\n                case 'P':\n                    argument++;\n                    {   U32 const proba32 = readU32FromChar(&argument);\n                        compressibility = (double)proba32 / 100.;\n                    }\n                    break;\n\n                    /* Run Single conf */\n                case 'S':\n                    g_singleRun = 1;\n                    argument++;\n                    for ( ; ; ) {\n                        switch(*argument)\n                        {\n                        case 'w':\n                            argument++;\n                            g_params.vals[wlog_ind] = readU32FromChar(&argument);\n                            continue;\n                        case 'c':\n                            argument++;\n                            g_params.vals[clog_ind] = readU32FromChar(&argument);\n                            continue;\n                        case 'h':\n                            argument++;\n                            g_params.vals[hlog_ind] = readU32FromChar(&argument);\n                            continue;\n                        case 's':\n                            argument++;\n                            g_params.vals[slog_ind] = readU32FromChar(&argument);\n                            continue;\n                        case 'l':  /* search length */\n                            argument++;\n                            g_params.vals[mml_ind] = readU32FromChar(&argument);\n                            continue;\n                        case 't':  /* target length */\n                            argument++;\n                            g_params.vals[tlen_ind] = readU32FromChar(&argument);\n                            continue;\n                        case 'S':  /* strategy */\n                            argument++;\n                            g_params.vals[strt_ind] = readU32FromChar(&argument);\n                            continue;\n                        case 'f':  /* forceAttachDict */\n                            argument++;\n                            g_params.vals[fadt_ind] = readU32FromChar(&argument);\n                            continue;\n                        case 'L':\n                            {   argument++;\n                                cLevelRun = (int)readU32FromChar(&argument);\n                                g_params = emptyParams();\n                                continue;\n                            }\n                        default : ;\n                        }\n                        break;\n                    }\n\n                    break;\n\n                    /* target level1 speed objective, in MB/s */\n                case 'T':\n                    argument++;\n                    g_target = readU32FromChar(&argument);\n                    break;\n\n                    /* cut input into blocks */\n                case 'B':\n                    argument++;\n                    g_blockSize = readU32FromChar(&argument);\n                    DISPLAY(\"using %u KB block size \\n\", (unsigned)(g_blockSize>>10));\n                    break;\n\n                    /* caps runtime (in seconds) */\n                case 't':\n                    argument++;\n                    g_timeLimit_s = readU32FromChar(&argument);\n                    break;\n\n                case 's':\n                    argument++;\n                    separateFiles = 1;\n                    break;\n\n                case 'q':\n                    while (argument[0] == 'q') { argument++; g_displayLevel--; }\n                    break;\n\n                case 'v':\n                    while (argument[0] == 'v') { argument++; g_displayLevel++; }\n                    break;\n\n                /* load dictionary file (only applicable for optimizer rn) */\n                case 'D':\n                    if(i == argc - 1) { /* last argument, return error. */\n                        DISPLAY(\"Dictionary file expected but not given : %d\\n\", i);\n                        return 1;\n                    } else {\n                        i++;\n                        dictFileName = argv[i];\n                        argument += strlen(argument);\n                    }\n                    break;\n\n                    /* Unknown command */\n                default : return badusage(exename);\n                }\n            }\n            continue;\n        }   /* if (argument[0]=='-') */\n\n        /* first provided filename is input */\n        if (!input_filename) { input_filename=argument; filenamesStart=i; continue; }\n    }\n\n    /* Welcome message */\n    DISPLAYLEVEL(2, WELCOME_MESSAGE);\n\n    if (filenamesStart==0) {\n        if (g_optimizer) {\n            DISPLAY(\"Optimizer Expects File\\n\");\n            return 1;\n        } else {\n            result = benchSample(compressibility, cLevelRun);\n        }\n    } else {\n        if(separateFiles) {\n            for(i = 0; i < argc - filenamesStart; i++) {\n                if (g_optimizer) {\n                    result = optimizeForSize(argv+filenamesStart + i, 1, dictFileName, target, paramTarget, cLevelOpt, cLevelRun, memoTableLog);\n                    if(result) { DISPLAY(\"Error on File %d\", i); return result; }\n                } else {\n                    result = benchFiles(argv+filenamesStart + i, 1, dictFileName, cLevelRun);\n                    if(result) { DISPLAY(\"Error on File %d\", i); return result; }\n                }\n            }\n        } else {\n            if (g_optimizer) {\n                assert(filenamesStart < argc);\n                result = optimizeForSize(argv+filenamesStart, (size_t)(argc-filenamesStart), dictFileName, target, paramTarget, cLevelOpt, cLevelRun, memoTableLog);\n            } else {\n                result = benchFiles(argv+filenamesStart, argc-filenamesStart, dictFileName, cLevelRun);\n            }\n        }\n    }\n\n    if (main_pause) { int unused; printf(\"press enter...\\n\"); unused = getchar(); (void)unused; }\n\n    return result;\n}\n"
  },
  {
    "path": "tests/playTests.sh",
    "content": "#!/bin/sh\n\nset -e # exit immediately on error\nset -x # print commands before execution (debug)\n\nunset ZSTD_CLEVEL\nunset ZSTD_NBTHREADS\n\n\ndie() {\n    println \"$@\" 1>&2\n    exit 1\n}\n\ndatagen() {\n    \"$DATAGEN_BIN\" \"$@\"\n}\n\nalias zstd='$EXE_PREFIX $ZSTD_BIN'\n\nsudoZstd() {\n    if [ -z \"$EXE_PREFIX\" ]; then\n        sudo \"$ZSTD_BIN\" \"$@\"\n    else\n        sudo \"$EXE_PREFIX\" \"$ZSTD_BIN\" \"$@\"\n    fi\n}\n\nroundTripTest() {\n    if [ -n \"$3\" ]; then\n        cLevel=\"$3\"\n        proba=\"$2\"\n    else\n        cLevel=\"$2\"\n        proba=\"\"\n    fi\n    if [ -n \"$4\" ]; then\n        dLevel=\"$4\"\n    else\n        dLevel=\"$cLevel\"\n    fi\n\n    rm -f tmp1 tmp2\n    println \"roundTripTest: datagen $1 $proba | zstd -v$cLevel | zstd -d$dLevel\"\n    datagen $1 $proba | $MD5SUM > tmp1\n    datagen $1 $proba | zstd -T0 --ultra -v$cLevel | zstd -d$dLevel  | $MD5SUM > tmp2\n    $DIFF -q tmp1 tmp2\n}\n\nfileRoundTripTest() {\n    if [ -n \"$3\" ]; then\n        local_c=\"$3\"\n        local_p=\"$2\"\n    else\n        local_c=\"$2\"\n        local_p=\"\"\n    fi\n    if [ -n \"$4\" ]; then\n        local_d=\"$4\"\n    else\n        local_d=\"$local_c\"\n    fi\n\n    rm -f tmp.zst tmp.md5.1 tmp.md5.2\n    println \"fileRoundTripTest: datagen $1 $local_p > tmp && zstd -v$local_c -c tmp | zstd -d$local_d\"\n    datagen $1 $local_p > tmp\n    < tmp $MD5SUM > tmp.md5.1\n    zstd -T0 --ultra -v$local_c -c tmp | zstd -d$local_d | $MD5SUM > tmp.md5.2\n    $DIFF -q tmp.md5.1 tmp.md5.2\n}\n\ntruncateLastByte() {\n    dd bs=1 count=$(($(wc -c < \"$1\") - 1)) if=\"$1\"\n}\n\nprintln() {\n    printf '%b\\n' \"${*}\"\n}\n\nif [ -z \"${size}\" ]; then\n    size=\nelse\n    size=${size}\nfi\n\nSCRIPT_DIR=$(cd \"$(dirname \"$0\")\" && pwd)\nPRGDIR=\"$SCRIPT_DIR/../programs\"\nTESTDIR=\"$SCRIPT_DIR/../tests\"\nUNAME=${UNAME:-$(uname)}\nGREP=${GREP:-grep}\n\ncase \"$UNAME\" in\n  SunOS) DIFF=${DIFF:-gdiff} ;;\n  *) DIFF=${DIFF:-diff} ;;\nesac\n\ndetectedTerminal=false\nif [ -t 0 ] && [ -t 1 ]\nthen\n    detectedTerminal=true\nfi\nisTerminal=${isTerminal:-$detectedTerminal}\n\nisWindows=false\nINTOVOID=\"/dev/null\"\nDEVDEVICE=\"/dev/zero\"\ncase \"$OS\" in\n  Windows*)\n    isWindows=true\n    INTOVOID=\"NUL\"\n    DEVDEVICE=\"NUL\"\n    ;;\nesac\n\ncase \"$UNAME\" in\n  Darwin) MD5SUM=\"md5 -r\" ;;\n  NetBSD) MD5SUM=\"md5 -n\" ;;\n  OpenBSD) MD5SUM=\"md5\" ;;\n  *) MD5SUM=\"md5sum\" ;;\nesac\n\nMTIME=\"stat -c %Y\"\ncase \"$UNAME\" in\n    Darwin | FreeBSD | OpenBSD | NetBSD) MTIME=\"stat -f %m\" ;;\nesac\n\nassertSameMTime() {\n    MT1=$($MTIME \"$1\")\n    MT2=$($MTIME \"$2\")\n    echo MTIME $MT1 $MT2\n    [ \"$MT1\" = \"$MT2\" ] || die \"mtime on $1 doesn't match mtime on $2 ($MT1 != $MT2)\"\n}\n\nGET_PERMS=\"stat -c %a\"\ncase \"$UNAME\" in\n    Darwin | FreeBSD | OpenBSD | NetBSD) GET_PERMS=\"stat -f %Lp\" ;;\nesac\n\nassertFilePermissions() {\n    STAT1=$($GET_PERMS \"$1\")\n    STAT2=$2\n    [ \"$STAT1\" = \"$STAT2\" ] || die \"permissions on $1 don't match expected ($STAT1 != $STAT2)\"\n}\n\nassertSamePermissions() {\n    STAT1=$($GET_PERMS \"$1\")\n    STAT2=$($GET_PERMS \"$2\")\n    [ \"$STAT1\" = \"$STAT2\" ] || die \"permissions on $1 don't match those on $2 ($STAT1 != $STAT2)\"\n}\n\n\n# check if ZSTD_BIN is defined. if not, use the default value\nif [ -z \"${ZSTD_BIN}\" ]; then\n  println \"\\nZSTD_BIN is not set. Using the default value...\"\n  ZSTD_BIN=\"$PRGDIR/zstd\"\nfi\n\n# check if DATAGEN_BIN is defined. if not, use the default value\nif [ -z \"${DATAGEN_BIN}\" ]; then\n  println \"\\nDATAGEN_BIN is not set. Using the default value...\"\n  DATAGEN_BIN=\"$TESTDIR/datagen\"\nfi\n\n# Why was this line here ? Generates a strange ZSTD_BIN when EXE_PREFIX is non empty\n# ZSTD_BIN=\"$EXE_PREFIX$ZSTD_BIN\"\n\n# assertions\n[ -n \"$ZSTD_BIN\" ] || die \"zstd not found at $ZSTD_BIN! \\n Please define ZSTD_BIN pointing to the zstd binary. You might also consider rebuilding zstd following the instructions in README.md\"\n[ -n \"$DATAGEN_BIN\" ] || die \"datagen not found at $DATAGEN_BIN! \\n Please define DATAGEN_BIN pointing to the datagen binary. You might also consider rebuilding zstd tests following the instructions in README.md. \"\nprintln \"\\nStarting playTests.sh isWindows=$isWindows EXE_PREFIX='$EXE_PREFIX' ZSTD_BIN='$ZSTD_BIN' DATAGEN_BIN='$DATAGEN_BIN'\"\n\nif echo hello | zstd -v -T2 2>&1 > $INTOVOID | $GREP -q 'multi-threading is disabled'\nthen\n    hasMT=\"\"\nelse\n    hasMT=\"true\"\nfi\n\n\nzstd -vvV\n\nprintln \"\\n===>  simple tests \"\n\ndatagen > tmp\nzstd -h\nzstd -H\nzstd -V\nprintln \"test : basic compression \"\nzstd -f tmp                      # trivial compression case, creates tmp.zst\nzstd -f -z tmp\nzstd -f -k tmp\nzstd -f -C tmp\nprintln \"test : basic decompression\"\nzstd -df tmp.zst                 # trivial decompression case (overwrites tmp)\nprintln \"test : too large compression level => auto-fix\"\nzstd -99 -f tmp  # too large compression level, automatic sized down\nzstd -5000000000 -f tmp && die \"too large numeric value : must fail\"\nprintln \"test : --fast aka negative compression levels\"\nzstd --fast -f tmp  # == -1\nzstd --fast=3 -f tmp  # == -3\nzstd --fast=200000 -f tmp  # too low compression level, automatic fixed\nzstd --fast=5000000000 -f tmp && die \"too large numeric value : must fail\"\nzstd -c --fast=0 tmp > $INTOVOID && die \"--fast must not accept value 0\"\nprintln \"test : too large numeric argument\"\nzstd --fast=9999999999 -f tmp  && die \"should have refused numeric value\"\nprintln \"test : set compression level with environment variable ZSTD_CLEVEL\"\n\nZSTD_CLEVEL=12  zstd -f tmp # positive compression level\nZSTD_CLEVEL=-12 zstd -f tmp # negative compression level\nZSTD_CLEVEL=+12 zstd -f tmp # valid: verbose '+' sign\nZSTD_CLEVEL=''  zstd -f tmp # empty env var, warn and revert to default setting\nZSTD_CLEVEL=-   zstd -f tmp # malformed env var, warn and revert to default setting\nZSTD_CLEVEL=a   zstd -f tmp # malformed env var, warn and revert to default setting\nZSTD_CLEVEL=+a  zstd -f tmp # malformed env var, warn and revert to default setting\nZSTD_CLEVEL=3a7 zstd -f tmp # malformed env var, warn and revert to default setting\nZSTD_CLEVEL=50000000000 zstd -f tmp # numeric value too large, warn and revert to default setting\nprintln \"test : override ZSTD_CLEVEL with command line option\"\nZSTD_CLEVEL=12  zstd --fast=3 -f tmp # overridden by command line option\n\n# temporary envvar changes in the above tests would actually persist in macos /bin/sh\nunset ZSTD_CLEVEL\n\n\nprintln \"test : compress to stdout\"\nzstd tmp -c > tmpCompressed\nzstd tmp --stdout > tmpCompressed       # long command format\n\nprintln \"test : compress to named file (-o)\"\nrm -f tmpCompressed\nzstd tmp -o tmpCompressed\ntest -f tmpCompressed   # file must be created\n\nprintln \"test : force write, correct order\"\nzstd tmp -fo tmpCompressed\n\nprintln \"test : -c + -o : last one wins\"\nrm -f tmpOut\nzstd tmp -c > tmpCompressed -o tmpOut\ntest -f tmpOut   # file must be created\nrm -f tmpCompressed\nzstd tmp -o tmpOut -c > tmpCompressed\ntest -f tmpCompressed   # file must be created\n\nprintln \"test : forgotten argument\"\ncp tmp tmp2\nzstd tmp2 -fo && die \"-o must be followed by filename \"\nprintln \"test : implied stdout when input is stdin\"\nprintln bob | zstd | zstd -d\nif [ \"$isTerminal\" = true ]; then\nprintln \"test : compressed data to terminal\"\nprintln bob | zstd && die \"should have refused : compressed data to terminal\"\nprintln \"test : compressed data from terminal (a hang here is a test fail, zstd is wrongly waiting on data from terminal)\"\nzstd -d > $INTOVOID && die \"should have refused : compressed data from terminal\"\nfi\nprintln \"test : null-length file roundtrip\"\nprintln -n '' | zstd - --stdout | zstd -d --stdout\nprintln \"test : ensure small file doesn't add 3-bytes null block\"\ndatagen -g1 > tmp1\nzstd tmp1 -c | wc -c | $GREP \"14\"\nzstd < tmp1  | wc -c | $GREP \"14\"\nprintln \"test : decompress file with wrong suffix (must fail)\"\nzstd -d tmpCompressed && die \"wrong suffix error not detected!\"\nzstd -df tmp && die \"should have refused : wrong extension\"\nprintln \"test : decompress into stdout\"\nzstd -d tmpCompressed -c > tmpResult    # decompression using stdout\nzstd --decompress tmpCompressed -c > tmpResult\nzstd --decompress tmpCompressed --stdout > tmpResult\nprintln \"test : decompress from stdin into stdout\"\nzstd -dc   < tmp.zst > $INTOVOID   # combine decompression, stdin & stdout\nzstd -dc - < tmp.zst > $INTOVOID\nzstd -d    < tmp.zst > $INTOVOID   # implicit stdout when stdin is used\nzstd -d  - < tmp.zst > $INTOVOID\nprintln \"test : impose memory limitation (must fail)\"\ndatagen -g500K > tmplimit\nzstd -f tmplimit\nzstd -d -f tmplimit.zst -M2K -c > $INTOVOID && die \"decompression needs more memory than allowed\"\nzstd -d -f tmplimit.zst --memlimit=2K -c > $INTOVOID && die \"decompression needs more memory than allowed\"  # long command\nzstd -d -f tmplimit.zst --memory=2K -c > $INTOVOID && die \"decompression needs more memory than allowed\"  # long command\nzstd -d -f tmplimit.zst --memlimit-decompress=2K -c > $INTOVOID && die \"decompression needs more memory than allowed\"  # long command\nrm -f tmplimit tmplimit.zst\nprintln \"test : overwrite protection\"\nzstd -q tmp && die \"overwrite check failed!\"\nprintln \"test : force overwrite\"\nzstd -q -f tmp\nzstd -q --force tmp\nprintln \"test : overwrite readonly file\"\nrm -f tmpro tmpro.zst\nprintln foo > tmpro.zst\nprintln foo > tmpro\nchmod 400 tmpro.zst\nzstd -q tmpro && die \"should have refused to overwrite read-only file\"\nzstd -q -f tmpro\nprintln \"test: --no-progress flag\"\nzstd tmpro -c --no-progress | zstd -d -f -o \"$INTOVOID\" --no-progress\nzstd tmpro -cv --no-progress | zstd -dv -f -o \"$INTOVOID\" --no-progress\nprintln \"test: --progress flag\"\nzstd tmpro -c | zstd -d -f -o \"$INTOVOID\" --progress 2>&1 | $GREP '[A-Za-z0-9._ ]*: [0-9]* bytes'\nzstd tmpro -c | zstd -d -f -q -o \"$INTOVOID\" --progress 2>&1 | $GREP '[A-Za-z0-9._ ]*: [0-9]* bytes'\nzstd tmpro -c | zstd -d -f -v -o \"$INTOVOID\" 2>&1 | $GREP '[A-Za-z0-9._ ]*: [0-9]* bytes'\nrm -f tmpro tmpro.zst\nprintln \"test: overwrite input file (must fail)\"\nzstd tmp -fo tmp && die \"zstd compression overwrote the input file\"\nzstd tmp.zst -dfo tmp.zst && die \"zstd decompression overwrote the input file\"\nprintln \"test: detect that input file does not exist\"\nzstd nothere && die \"zstd hasn't detected that input file does not exist\"\nprintln \"test: --[no-]compress-literals\"\nzstd tmp -c --no-compress-literals -1       | zstd -t\nzstd tmp -c --no-compress-literals --fast=1 | zstd -t\nzstd tmp -c --no-compress-literals -19      | zstd -t\nzstd tmp -c --compress-literals    -1       | zstd -t\nzstd tmp -c --compress-literals    --fast=1 | zstd -t\nzstd tmp -c --compress-literals    -19      | zstd -t\nzstd -b --fast=1 -i0e1 tmp --compress-literals\nzstd -b --fast=1 -i0e1 tmp --no-compress-literals\nprintln \"test: --no-check for decompression\"\nzstd -f tmp -o tmp_corrupt.zst --check\nzstd -f tmp -o tmp.zst --no-check\nprintf '\\xDE\\xAD\\xBE\\xEF' | dd of=tmp_corrupt.zst bs=1 seek=$(($(wc -c < \"tmp_corrupt.zst\") - 4)) count=4 conv=notrunc # corrupt checksum in tmp\nzstd -d -f tmp_corrupt.zst --no-check\nzstd -d -f tmp_corrupt.zst --check --no-check # final flag overrides\nzstd -d -f tmp.zst --no-check\n\nif [ \"$isWindows\" = false ] && [ \"$UNAME\" != \"AIX\" ]; then\n  if [ -n \"$(which readelf)\" ]; then\n    println \"test: check if binary has executable stack (#2963)\"\n    readelf -lW \"$ZSTD_BIN\" | $GREP 'GNU_STACK .* RW ' || die \"zstd binary has executable stack!\"\n  fi\nfi\n\nprintln \"\\n===>  multiple_thread test \"\n\ndatagen > tmp\nprintln \"test : single-thread \"\nzstd --fast --single-thread tmp -o tmpMT0\nprintln \"test : one worker thread (default)\"\nzstd --fast -T1 tmp -o tmpMT1\nprintln \"test : two worker threads \"\nzstd --fast -T2 tmp -o tmpMT2\nprintln \"test : 16-thread \"\nzstd --fast -T16 tmp -o tmpMT3\nprintln \"test : 127-thread \"\nzstd --fast -T127 tmp -o tmpMT4\nprintln \"test : 128-thread \"\nzstd --fast -T128 tmp -o tmpMT5\nprintln \"test : max allowed numeric value is 4294967295 \"\nzstd --fast -4294967295 tmp -o tmpMT6\nprintln \"test : numeric value overflows 32-bit unsigned int \"\nzstd --fast -4294967296 tmp -o tmptest9 && die \"max allowed numeric value is 4294967295\"\n\ndatagen > tmp\nprintln \"test : basic compression \"\nzstd -f tmp  # trivial compression case, creates tmp.zst\nprintln \"test : basic decompression\"\nzstd -d -f -T1 tmp.zst\nprintln \"note : decompression does not support -T mode, but execution support\"\nrm -rf tmpMT*\n\nprintln \"\\n===>  --fast_argument test \"\ndatagen > tmp\nprintln \"test : basic compression \"\nzstd -f tmp  # trivial compression case, creates tmp.zst\nprintln \"test: --fast=1\"\nzstd --fast=1 -f tmp\nprintln \"test: --fast=99\"\nzstd --fast=99 -f tmp\nprintln \"test: Invalid value -- negative number\"\nzstd --fast=-1 -f tmp && die \"error: Invalid value -- negative number\"\nprintln \"test: Invalid value -- zero\"\nzstd --fast=0 -f tmp && die \"error: Invalid value -- 0 number\"\nprintln \"test: max allowed numeric argument of --fast is 4294967295\"\nzstd --fast=4294967295 -f tmp\nprintln \"test: numeric value overflows 32-bit unsigned int \"\nzstd --fast=4294967296 -f tmp && die \"max allowed argument of --fast is 4294967295\"\n\nprintln \"\\n===>  --exclude-compressed flag\"\nrm -rf precompressedFilterTestDir\nmkdir -p precompressedFilterTestDir\ndatagen $size > precompressedFilterTestDir/input.5\ndatagen $size > precompressedFilterTestDir/input.6\nzstd --exclude-compressed --long --rm -r precompressedFilterTestDir\ndatagen $size > precompressedFilterTestDir/input.7\ndatagen $size > precompressedFilterTestDir/input.8\nzstd --exclude-compressed --long --rm -r precompressedFilterTestDir\ntest ! -f precompressedFilterTestDir/input.5.zst.zst\ntest ! -f precompressedFilterTestDir/input.6.zst.zst\nfile1timestamp=`$MTIME precompressedFilterTestDir/input.5.zst`\nfile2timestamp=`$MTIME precompressedFilterTestDir/input.7.zst`\nif [ $file2timestamp -ge $file1timestamp ]; then\n  println \"Test is successful. input.5.zst is precompressed and therefore not compressed/modified again.\"\nelse\n  println \"Test is not successful\"\nfi\n# File Extension check.\ndatagen $size > precompressedFilterTestDir/input.zstbar\nzstd --exclude-compressed --long --rm -r precompressedFilterTestDir\n# zstd should compress input.zstbar\ntest -f precompressedFilterTestDir/input.zstbar.zst\n# Check without the --exclude-compressed flag\nzstd --long --rm -r precompressedFilterTestDir\n# Files should get compressed again without the --exclude-compressed flag.\ntest -f precompressedFilterTestDir/input.5.zst.zst\ntest -f precompressedFilterTestDir/input.6.zst.zst\n\n# Test some other compressed file extensions\ndatagen $size > precompressedFilterTestDir/input.flac\ndatagen $size > precompressedFilterTestDir/input.mov\ndatagen $size > precompressedFilterTestDir/input.mp3\nzstd --exclude-compressed --long --rm -r precompressedFilterTestDir\ntest ! -f precompressedFilterTestDir/input.flac.zst\ntest ! -f precompressedFilterTestDir/input.mov.zst\ntest ! -f precompressedFilterTestDir/input.mp3.zst\nzstd --long --rm -r precompressedFilterTestDir\ntest -f precompressedFilterTestDir/input.flac.zst\ntest -f precompressedFilterTestDir/input.mov.zst\ntest -f precompressedFilterTestDir/input.mp3.zst\nrm -rf precompressedFilterTestDir\nprintln \"Test completed\"\n\n\n\nprintln \"\\n===>  warning prompts should not occur if stdin is an input\"\nprintln \"y\" > tmpPrompt\nprintln \"hello world\" >> tmpPrompt\nzstd tmpPrompt -f\nzstd < tmpPrompt -o tmpPrompt.zst && die \"should have aborted immediately and failed to overwrite\"\nzstd < tmpPrompt -o tmpPrompt.zst -f    # should successfully overwrite with -f\nzstd -q -d -f tmpPrompt.zst -o tmpPromptRegenerated\n$DIFF tmpPromptRegenerated tmpPrompt    # the first 'y' character should not be swallowed\n\necho 'yes' | zstd tmpPrompt -v -o tmpPrompt.zst  # accept piped \"y\" input to force overwrite when using files\necho 'yes' | zstd < tmpPrompt -v -o tmpPrompt.zst && die \"should have aborted immediately and failed to overwrite\"\nzstd tmpPrompt - < tmpPrompt -o tmpPromp.zst --rm && die \"should have aborted immediately and failed to remove\"\n\nprintln \"Test completed\"\n\n\nprintln \"\\n===>  recursive mode test \"\n# combination of -r with empty list of input file\nzstd -c -r < tmp > tmp.zst\n\n# combination of -r with empty folder\nmkdir -p tmpEmptyDir\nzstd -r tmpEmptyDir\nrm -rf tmpEmptyDir\n\n\nprintln \"\\n===>  file removal\"\nzstd -f --rm tmp\ntest ! -f tmp  # tmp should no longer be present\nzstd -f -d --rm tmp.zst\ntest ! -f tmp.zst  # tmp.zst should no longer be present\nprintln \"test: --rm is disabled when output is stdout\"\ntest -f tmp\nzstd --rm tmp -c > $INTOVOID\ntest -f tmp # tmp shall still be there\nzstd --rm tmp --stdout > $INTOVOID\ntest -f tmp # tmp shall still be there\nzstd -f --rm tmp -c > $INTOVOID\ntest -f tmp # tmp shall still be there\nzstd -f tmp -c > $INTOVOID --rm\ntest -f tmp # tmp shall still be there\nprintln \"test: --rm is disabled when multiple inputs are concatenated into a single output\"\ncp tmp tmp2\nzstd --rm tmp tmp2 -c > $INTOVOID\ntest -f tmp\ntest -f tmp2\nrm -f tmp3.zst\necho 'y' | zstd -v tmp tmp2 -o tmp3.zst --rm # prompt for confirmation\ntest -f tmp\ntest -f tmp2\nzstd -f tmp tmp2 -o tmp3.zst --rm # just warns, no prompt\ntest -f tmp\ntest -f tmp2\nzstd -q tmp tmp2 -o tmp3.zst --rm && die \"should refuse to concatenate\"\nprintln \"test: --rm is active with -o when single input\"\nrm -f tmp2.zst\nzstd --rm tmp2 -o tmp2.zst\ntest -f tmp2.zst\ntest ! -f tmp2\nprintln \"test: -c followed by -o => -o wins, so --rm remains active\" # (#3719)\nrm tmp2.zst\ncp tmp tmp2\nzstd --rm tmp2 -c > $INTOVOID -o tmp2.zst\ntest ! -f tmp2\nprintln \"test: -o followed by -c => -c wins, so --rm is disabled\" # (#3719)\nrm tmp3.zst\ncp tmp tmp2\nzstd -v --rm tmp2 -o tmp2.zst -c > tmp3.zst\ntest -f tmp2\ntest -f tmp3.zst\nprintln \"test : should quietly not remove non-regular file\"\nprintln hello > tmp\nzstd tmp -f -o \"$DEVDEVICE\" 2>tmplog > \"$INTOVOID\"\n$GREP \"Refusing to remove non-regular file\" tmplog && die\nrm -f tmplog\nzstd tmp -f -o \"$INTOVOID\" 2>&1 | $GREP \"Refusing to remove non-regular file\" && die\nprintln \"test : --rm on stdin\"\nprintln a | zstd --rm > $INTOVOID   # --rm should remain silent\nrm -f tmp\nzstd -f tmp && die \"tmp not present : should have failed\"\ntest ! -f tmp.zst  # tmp.zst should not be created\nprintln \"test : -d -f do not delete destination when source is not present\"\ntouch tmp    # create destination file\nzstd -d -f tmp.zst && die \"attempt to decompress a non existing file\"\ntest -f tmp  # destination file should still be present\nprintln \"test : -f do not delete destination when source is not present\"\nrm -f tmp         # erase source file\ntouch tmp.zst  # create destination file\nzstd -f tmp && die \"attempt to compress a non existing file\"\ntest -f tmp.zst  # destination file should still be present\nrm -rf tmp*  # may also erase tmp* directory from previous failed run\n\n\nprintln \"\\n===>  decompression only tests \"\n# the following test verifies that the decoder is compatible with RLE as first block\n# older versions of zstd cli are not able to decode such corner case.\n# As a consequence, the zstd cli do not generate them, to maintain compatibility with older versions.\ndd bs=1048576 count=1 if=/dev/zero of=tmp\nzstd -d -o tmp1 \"$TESTDIR/golden-decompression/rle-first-block.zst\"\n$DIFF -s tmp1 tmp\n\ntouch tmp_empty\nzstd -d -o tmp2 \"$TESTDIR/golden-decompression/empty-block.zst\"\n$DIFF -s tmp2 tmp_empty\n\nzstd -t \"$TESTDIR/golden-decompression/zeroSeq_2B.zst\"\n\nzstd -t \"$TESTDIR/golden-decompression-errors/zeroSeq_extraneous.zst\" && die \"invalid Sequences section should have been detected\"\n\nrm -f tmp*\n\nprintln \"\\n===>  compress multiple files\"\nprintln hello > tmp1\nprintln world > tmp2\nzstd tmp1 tmp2 -o \"$INTOVOID\" -f\nzstd tmp1 tmp2 -c | zstd -t\necho 'y' | zstd -v tmp1 tmp2 -o tmp.zst\ntest ! -f tmp1.zst\ntest ! -f tmp2.zst\nzstd tmp1 tmp2\nzstd -t tmp1.zst tmp2.zst\nzstd -dc tmp1.zst tmp2.zst\nzstd tmp1.zst tmp2.zst -o \"$INTOVOID\" -f\necho 'y' | zstd -v -d tmp1.zst tmp2.zst -o tmp\ntouch tmpexists\nzstd tmp1 tmp2 -f -o tmpexists\nzstd tmp1 tmp2 -q -o tmpexists && die \"should have refused to overwrite\"\nprintln gooder > tmp_rm1\nprintln boi > tmp_rm2\nprintln worldly > tmp_rm3\necho 'y' | zstd -v tmp_rm1 tmp_rm2 -v -o tmp_rm3.zst\ntest -f tmp_rm1\ntest -f tmp_rm2\ncp tmp_rm3.zst tmp_rm4.zst\necho 'Y' | zstd -v -d tmp_rm3.zst tmp_rm4.zst -v -o tmp_rm_out --rm\ntest -f tmp_rm3.zst\ntest -f tmp_rm4.zst\nprintln gooder > tmpexists1\nzstd tmpexists1 tmpexists -c --rm -f > $INTOVOID\n# Bug: PR #972\nif [ \"$?\" -eq 139 ]; then\n  die \"should not have segfaulted\"\nfi\ntest -f tmpexists1\ntest -f tmpexists\nprintln \"\\n===>  multiple files and shell completion \"\ndatagen -s1        > tmp1 2> $INTOVOID\ndatagen -s2 -g100K > tmp2 2> $INTOVOID\ndatagen -s3 -g1M   > tmp3 2> $INTOVOID\nprintln \"compress tmp* : \"\nzstd -f tmp*\ntest -f tmp1.zst\ntest -f tmp2.zst\ntest -f tmp3.zst\nrm -f tmp1 tmp2 tmp3\nprintln \"decompress tmp* : \"\nzstd -df ./*.zst\ntest -f tmp1\ntest -f tmp2\ntest -f tmp3\nprintln \"compress tmp* into stdout > tmpall : \"\nzstd -c tmp1 tmp2 tmp3 > tmpall\ntest -f tmpall  # should check size of tmpall (should be tmp1.zst + tmp2.zst + tmp3.zst)\nprintln \"decompress tmpall* into stdout > tmpdec : \"\ncp tmpall tmpall2\nzstd -dc tmpall* > tmpdec\ntest -f tmpdec  # should check size of tmpdec (should be 2*(tmp1 + tmp2 + tmp3))\nprintln \"compress multiple files including a missing one (notHere) : \"\nzstd -f tmp1 notHere tmp2 && die \"missing file not detected!\"\nrm -f tmp*\n\n\nif [ \"$isWindows\" = false ] ; then\n    println \"\\n===>  zstd fifo named pipe test \"\n    echo \"Hello World!\" > tmp_original\n    mkfifo tmp_named_pipe\n    # note : fifo test doesn't work in combination with `dd` or `cat`\n    echo \"Hello World!\" > tmp_named_pipe &\n    zstd tmp_named_pipe -o tmp_compressed\n    zstd -d -o tmp_decompressed tmp_compressed\n    $DIFF -s tmp_original tmp_decompressed\n    rm -rf tmp*\nfi\n\nprintln \"\\n===>  zstd created file permissions tests\"\nif [ \"$isWindows\" = false ] ; then\n    rm -f tmp1 tmp2 tmp1.zst tmp2.zst tmp1.out tmp2.out # todo: remove\n\n    ORIGINAL_UMASK=$(umask)\n    umask 0000\n\n    datagen > tmp1\n    datagen > tmp2\n    assertFilePermissions tmp1 666\n    assertFilePermissions tmp2 666\n\n    println \"test : copy 666 permissions in file -> file compression \"\n    zstd -f tmp1 -o tmp1.zst\n    assertSamePermissions tmp1 tmp1.zst\n    println \"test : copy 666 permissions in file -> file decompression \"\n    zstd -f -d tmp1.zst -o tmp1.out\n    assertSamePermissions tmp1.zst tmp1.out\n\n    rm -f tmp1.zst tmp1.out\n\n    println \"test : copy 400 permissions in file -> file compression (write to a read-only file) \"\n    chmod 0400 tmp1\n    assertFilePermissions tmp1 400\n    zstd -f tmp1 -o tmp1.zst\n    assertSamePermissions tmp1 tmp1.zst\n    println \"test : copy 400 permissions in file -> file decompression (write to a read-only file) \"\n    zstd -f -d tmp1.zst -o tmp1\n    assertSamePermissions tmp1.zst tmp1\n\n    rm -f tmp1.zst tmp1.out\n\n    println \"test : check created permissions from stdin input in compression \"\n    zstd -f -o tmp1.zst < tmp1\n    assertFilePermissions tmp1.zst 666\n    println \"test : check created permissions from stdin input in decompression \"\n    zstd -f -d -o tmp1.out < tmp1.zst\n    assertFilePermissions tmp1.out 666\n\n    rm -f tmp1.zst tmp1.out\n\n    println \"test : check created permissions from multiple inputs in compression \"\n    zstd -f tmp1 tmp2 -o tmp1.zst\n    assertFilePermissions tmp1.zst 666\n    println \"test : check created permissions from multiple inputs in decompression \"\n    cp tmp1.zst tmp2.zst\n    zstd -f -d tmp1.zst tmp2.zst -o tmp1.out\n    assertFilePermissions tmp1.out 666\n\n    rm -f tmp1.zst tmp2.zst tmp1.out tmp2.out\n\n    println \"test : check permissions on pre-existing output file in compression \"\n    chmod 0600 tmp1\n    touch tmp1.zst\n    chmod 0400 tmp1.zst\n    zstd -f tmp1 -o tmp1.zst\n    assertFilePermissions tmp1.zst 600\n    println \"test : check permissions on pre-existing output file in decompression \"\n    chmod 0400 tmp1.zst\n    touch tmp1.out\n    chmod 0200 tmp1.out\n    zstd -f -d tmp1.zst -o tmp1.out\n    assertFilePermissions tmp1.out 400\n\n    umask 0666\n    chmod 0666 tmp1 tmp2\n\n    rm -f tmp1.zst tmp1.out\n\n    println \"test : respect umask when compressing from stdin input \"\n    zstd -f -o tmp1.zst < tmp1\n    assertFilePermissions tmp1.zst 0\n    println \"test : respect umask when decompressing from stdin input \"\n    chmod 0666 tmp1.zst\n    zstd -f -d -o tmp1.out < tmp1.zst\n    assertFilePermissions tmp1.out 0\n\n    rm -f tmp1 tmp2 tmp1.zst tmp2.zst tmp1.out tmp2.out\n    umask $ORIGINAL_UMASK\nfi\n\nif [ -n \"$DEVNULLRIGHTS\" ] ; then\n    # these tests requires sudo rights, which is uncommon.\n    # they are only triggered if DEVNULLRIGHTS macro is defined.\n    println \"\\n===> checking /dev/null permissions are unaltered \"\n    datagen > tmp\n    sudoZstd tmp -o $INTOVOID   # sudo rights could modify /dev/null permissions\n    sudoZstd tmp -c > $INTOVOID\n    zstd tmp -f -o tmp.zst\n    sudoZstd -d tmp.zst -c > $INTOVOID\n    sudoZstd -d tmp.zst -o $INTOVOID\n    ls -las $INTOVOID | $GREP \"rw-rw-rw-\"\nfi\n\nif [ -n \"$READFROMBLOCKDEVICE\" ] ; then\n    # This creates a temporary block device, which is only possible on unix-y\n    # systems, is somewhat invasive, and requires sudo. For these reasons, you\n    # have to specifically ask for this test.\n    println \"\\n===> checking that zstd can read from a block device\"\n    datagen -g65536 > tmp.img\n    sudo losetup -fP tmp.img\n    LOOP_DEV=$(losetup -a | $GREP 'tmp\\.img' | cut -f1 -d:)\n    [ -z \"$LOOP_DEV\" ] && die \"failed to get loopback device\"\n    sudoZstd $LOOP_DEV -c > tmp.img.zst && die \"should fail without -f\"\n    sudoZstd -f $LOOP_DEV -c > tmp.img.zst\n    zstd -d tmp.img.zst -o tmp.img.copy\n    sudo losetup -d $LOOP_DEV\n    $DIFF -s tmp.img tmp.img.copy || die \"round trip failed\"\n    rm -f tmp.img tmp.img.zst tmp.img.copy\nfi\n\nprintln \"\\n===>  zstd created file timestamp tests\"\ndatagen > tmp\ntouch -m -t 200001010000.00 tmp\nprintln \"test : copy mtime in file -> file compression \"\nzstd -f tmp -o tmp.zst\nassertSameMTime tmp tmp.zst\nprintln \"test : copy mtime in file -> file decompression \"\nzstd -f -d tmp.zst -o tmp.out\nassertSameMTime tmp.zst tmp.out\nrm -f tmp\n\nprintln \"\\n===>  compress multiple files into an output directory, --output-dir-flat\"\nprintln henlo > tmp1\nmkdir tmpInputTestDir\nmkdir tmpInputTestDir/we\nmkdir tmpInputTestDir/we/must\nmkdir tmpInputTestDir/we/must/go\nmkdir tmpInputTestDir/we/must/go/deeper\nprintln cool > tmpInputTestDir/we/must/go/deeper/tmp2\nmkdir tmpOutDir\nzstd tmp1 tmpInputTestDir/we/must/go/deeper/tmp2 --output-dir-flat tmpOutDir\ntest -f tmpOutDir/tmp1.zst\ntest -f tmpOutDir/tmp2.zst\nprintln \"test : decompress multiple files into an output directory, --output-dir-flat\"\nmkdir tmpOutDirDecomp\nzstd tmpOutDir -r -d --output-dir-flat tmpOutDirDecomp\ntest -f tmpOutDirDecomp/tmp2\ntest -f tmpOutDirDecomp/tmp1\nrm -f tmpOutDirDecomp/*\nzstd tmpOutDir -r -d --output-dir-flat=tmpOutDirDecomp\ntest -f tmpOutDirDecomp/tmp2\ntest -f tmpOutDirDecomp/tmp1\nrm -rf tmp*\n\nif [ \"$isWindows\" = false ] ; then\n    println \"\\n===>  compress multiple files into an output directory and mirror input folder, --output-dir-mirror\"\n    println \"test --output-dir-mirror\" > tmp1\n    mkdir -p tmpInputTestDir/we/.../..must/go/deeper..\n    println cool > tmpInputTestDir/we/.../..must/go/deeper../tmp2\n    zstd tmp1 -r tmpInputTestDir --output-dir-mirror tmpOutDir\n    test -f tmpOutDir/tmp1.zst\n    test -f tmpOutDir/tmpInputTestDir/we/.../..must/go/deeper../tmp2.zst\n\n    println \"test: compress input dir will be ignored if it has '..'\"\n    zstd  -r tmpInputTestDir/we/.../..must/../..mustgo/deeper.. --output-dir-mirror non-exist && die \"input cannot contain '..'\"\n    zstd  -r tmpInputTestDir/we/.../..must/deeper../.. --output-dir-mirror non-exist && die \"input cannot contain '..'\"\n    zstd  -r ../tests/tmpInputTestDir/we/.../..must/deeper.. --output-dir-mirror non-exist && die \"input cannot contain '..'\"\n    test ! -d non-exist\n\n    println \"test: compress input dir should succeed with benign uses of '..'\"\n    zstd  -r tmpInputTestDir/we/.../..must/go/deeper.. --output-dir-mirror tmpout\n    test -d tmpout\n\n    println \"test : decompress multiple files into an output directory, --output-dir-mirror\"\n    zstd tmpOutDir -r -d --output-dir-mirror tmpOutDirDecomp\n    test -f tmpOutDirDecomp/tmpOutDir/tmp1\n    test -f tmpOutDirDecomp/tmpOutDir/tmpInputTestDir/we/.../..must/go/deeper../tmp2\n\n    println \"test: decompress input dir will be ignored if it has '..'\"\n    zstd  -r tmpOutDir/tmpInputTestDir/we/.../..must/../..must --output-dir-mirror non-exist && die \"input cannot contain '..'\"\n    test ! -d non-exist\n\n    rm -rf tmp*\nfi\n\n\nprintln \"test : compress multiple files reading them from a file, --filelist=FILE\"\nprintln \"Hello world!, file1\" > tmp1\nprintln \"Hello world!, file2\" > tmp2\nprintln tmp1 > tmp_fileList\nprintln tmp2 >> tmp_fileList\nzstd -f --filelist=tmp_fileList\ntest -f tmp2.zst\ntest -f tmp1.zst\n\nprintln \"test : alternate syntax: --filelist FILE\"\nzstd -f --filelist tmp_fileList\ntest -f tmp2.zst\ntest -f tmp1.zst\n\nprintln \"test : reading file list from a symlink, --filelist=FILE\"\nrm -f *.zst\nln -s tmp_fileList tmp_symLink\nzstd -f --filelist=tmp_symLink\ntest -f tmp2.zst\ntest -f tmp1.zst\n\nprintln \"test : compress multiple files reading them from multiple files, --filelist=FILE\"\nrm -f *.zst\nprintln \"Hello world!, file3\" > tmp3\nprintln \"Hello world!, file4\" > tmp4\nprintln tmp3 > tmp_fileList2\nprintln tmp4 >> tmp_fileList2\nzstd -f --filelist=tmp_fileList --filelist=tmp_fileList2\ntest -f tmp1.zst\ntest -f tmp2.zst\ntest -f tmp3.zst\ntest -f tmp4.zst\n\nprintln \"test : decompress multiple files reading them from a file, --filelist=FILE\"\nrm -f tmp1 tmp2\nprintln tmp1.zst > tmpZst\nprintln tmp2.zst >> tmpZst\nzstd -d -f --filelist=tmpZst\ntest -f tmp1\ntest -f tmp2\n\nprintln \"test : decompress multiple files reading them from multiple files, --filelist=FILE\"\nrm -f tmp1 tmp2 tmp3 tmp4\nprintln tmp3.zst > tmpZst2\nprintln tmp4.zst >> tmpZst2\nzstd -d -f --filelist=tmpZst --filelist=tmpZst2\ntest -f tmp1\ntest -f tmp2\ntest -f tmp3\ntest -f tmp4\n\nprintln \"test : survive the list of files with too long filenames (--filelist=FILE)\"\ndatagen -g5M > tmp_badList\nzstd -qq -f --filelist=tmp_badList && die \"should have failed : file name length is too long\"  # printing very long text garbage on console will cause CI failure\n\nprintln \"test : survive a list of files which is text garbage (--filelist=FILE)\"\ndatagen > tmp_badList\nzstd -qq -f --filelist=tmp_badList && die \"should have failed : list is text garbage\"  # printing very long text garbage on console will cause CI failure\n\nprintln \"test : survive a list of files which is binary garbage (--filelist=FILE)\"\ndatagen -P0 -g1M > tmp_badList\nzstd -qq -f --filelist=tmp_badList && die \"should have failed : list is binary garbage\"  # let's avoid printing binary garbage on console\n\nprintln \"test : try to overflow internal list of files (--filelist=FILE)\"\ntouch tmp1 tmp2 tmp3 tmp4 tmp5 tmp6\nls tmp* > tmpList\nzstd -f tmp1 --filelist=tmpList --filelist=tmpList tmp2 tmp3  # can trigger an overflow of internal file list\nrm -rf tmp*\n\n\nprintln \"\\n===> --[no-]content-size tests\"\n\ndatagen > tmp_contentsize\nzstd -f tmp_contentsize\nzstd -lv tmp_contentsize.zst | $GREP \"Decompressed Size:\"\nzstd -f --no-content-size tmp_contentsize\nzstd -lv tmp_contentsize.zst | $GREP \"Decompressed Size:\" && die\nzstd -f --content-size tmp_contentsize\nzstd -lv tmp_contentsize.zst | $GREP \"Decompressed Size:\"\nzstd -f --content-size --no-content-size tmp_contentsize\nzstd -lv tmp_contentsize.zst | $GREP \"Decompressed Size:\" && die\nrm -rf tmp*\n\nprintln \"test : show-default-cparams regular\"\ndatagen > tmp\nzstd --show-default-cparams -f tmp\nzstd --show-default-cparams -d tmp.zst && die \"error: can't use --show-default-cparams in decompression mode\"\nrm -rf tmp*\n\nprintln \"test : show-default-cparams recursive\"\nmkdir tmp_files\ndatagen -g15000 > tmp_files/tmp1\ndatagen -g129000 > tmp_files/tmp2\ndatagen -g257000 > tmp_files/tmp3\nzstd --show-default-cparams -f -r tmp_files\nrm -rf tmp*\n\nprintln \"test : show compression parameters in verbose mode\"\ndatagen > tmp\nzstd -vv tmp 2>&1 | \\\n$GREP -q -- \"--zstd=wlog=[0-9]*,clog=[0-9]*,hlog=[0-9]*,slog=[0-9]*,mml=[0-9]*,tlen=[0-9]*,strat=[0-9]*\"\nrm -rf tmp*\n\nprintln \"\\n===>  Advanced compression parameters \"\nprintln \"Hello world!\" | zstd --zstd=windowLog=21,      - -o tmp.zst && die \"wrong parameters not detected!\"\nprintln \"Hello world!\" | zstd --zstd=windowLo=21        - -o tmp.zst && die \"wrong parameters not detected!\"\nprintln \"Hello world!\" | zstd --zstd=windowLog=21,slog  - -o tmp.zst && die \"wrong parameters not detected!\"\nprintln \"Hello world!\" | zstd --zstd=strategy=10        - -o tmp.zst && die \"parameter out of bound not detected!\"  # > btultra2 : does not exist\ntest ! -f tmp.zst  # tmp.zst should not be created\nroundTripTest -g512K\nroundTripTest -g512K \" --zstd=mml=3,tlen=48,strat=6\"\nroundTripTest -g512K \" --zstd=strat=6,wlog=23,clog=23,hlog=22,slog=6\"\nroundTripTest -g512K \" --zstd=windowLog=23,chainLog=23,hashLog=22,searchLog=6,minMatch=3,targetLength=48,strategy=6\"\nroundTripTest -g512K \" --single-thread --long --zstd=ldmHashLog=20,ldmMinMatch=64,ldmBucketSizeLog=1,ldmHashRateLog=7\"\nroundTripTest -g512K \" --single-thread --long --zstd=lhlog=20,lmml=64,lblog=1,lhrlog=7\"\nroundTripTest -g64K  \"19 --zstd=strat=9\"   # btultra2\n\n\nprintln \"\\n===>  Pass-Through mode \"\nprintln \"Hello world 1!\" | zstd -df\nprintln \"Hello world 2!\" | zstd -dcf\nprintln \"Hello world 3!\" > tmp1\nzstd -dcf tmp1\nprintln \"\" | zstd -df > tmp1\nprintln \"\" > tmp2\n$DIFF -q tmp1 tmp2\nprintln \"1\" | zstd -df > tmp1\nprintln \"1\" > tmp2\n$DIFF -q tmp1 tmp2\nprintln \"12\" | zstd -df > tmp1\nprintln \"12\" > tmp2\n$DIFF -q tmp1 tmp2\nrm -rf tmp*\n\n\nprintln \"\\n===>  frame concatenation \"\nprintln \"hello \" > hello.tmp\nprintln \"world!\" > world.tmp\ncat hello.tmp world.tmp > helloworld.tmp\nzstd -c hello.tmp > hello.zst\nzstd -c world.tmp > world.zst\nzstd -c hello.tmp world.tmp > helloworld.zst\nzstd -dc helloworld.zst > result.tmp\n$DIFF helloworld.tmp result.tmp\ncat hello.zst world.zst > helloworld.zst\nzstd -dc helloworld.zst > result.tmp\ncat result.tmp\n$DIFF helloworld.tmp result.tmp\nprintln \"frame concatenation without checksum\"\nzstd -c hello.tmp > hello.zst --no-check\nzstd -c world.tmp > world.zst --no-check\ncat hello.zst world.zst > helloworld.zstd\nzstd -dc helloworld.zst > result.tmp\n$DIFF helloworld.tmp result.tmp\nprintln \"testing zstdcat symlink\"\nln -sf \"$ZSTD_BIN\" zstdcat\n$EXE_PREFIX ./zstdcat helloworld.zst > result.tmp\n$DIFF helloworld.tmp result.tmp\nln -s helloworld.zst helloworld.link.zst\n$EXE_PREFIX ./zstdcat helloworld.link.zst > result.tmp\n$DIFF helloworld.tmp result.tmp\nrm -f zstdcat\nrm -f result.tmp\nprintln \"testing zcat symlink\"\nln -sf \"$ZSTD_BIN\" zcat\n$EXE_PREFIX ./zcat helloworld.zst > result.tmp\n$DIFF helloworld.tmp result.tmp\n$EXE_PREFIX ./zcat helloworld.link.zst > result.tmp\n$DIFF helloworld.tmp result.tmp\nrm -f zcat\nrm -f ./*.tmp ./*.zstd\nprintln \"frame concatenation tests completed\"\n\n\nif [ \"$isWindows\" = false ] && [ \"$UNAME\" != 'SunOS' ] && [ \"$UNAME\" != \"OpenBSD\" ] && [ \"$UNAME\" != \"AIX\" ]; then\nprintln \"\\n**** flush write error test **** \"\n\nprintln \"println foo | zstd > /dev/full\"\nprintln foo | zstd > /dev/full && die \"write error not detected!\"\nprintln \"println foo | zstd | zstd -d > /dev/full\"\nprintln foo | zstd | zstd -d > /dev/full && die \"write error not detected!\"\n\nfi\n\n\nif [ \"$isWindows\" = false ] && [ \"$UNAME\" != 'SunOS' ] ; then\n\nprintln \"\\n===>  symbolic link test \"\n\nrm -f hello.tmp world.tmp world2.tmp hello.tmp.zst world.tmp.zst\nprintln \"hello world\" > hello.tmp\nln -s hello.tmp world.tmp\nln -s hello.tmp world2.tmp\nzstd world.tmp hello.tmp || true\ntest -f hello.tmp.zst  # regular file should have been compressed!\ntest ! -f world.tmp.zst  # symbolic link should not have been compressed!\nzstd world.tmp || true\ntest ! -f world.tmp.zst  # symbolic link should not have been compressed!\nzstd world.tmp world2.tmp || true\ntest ! -f world.tmp.zst  # symbolic link should not have been compressed!\ntest ! -f world2.tmp.zst  # symbolic link should not have been compressed!\nzstd world.tmp hello.tmp -f\ntest -f world.tmp.zst  # symbolic link should have been compressed with --force\nrm -f hello.tmp world.tmp world2.tmp hello.tmp.zst world.tmp.zst\n\nfi\n\n\nprintln \"\\n===>  test sparse file support \"\n\ndatagen -g5M  -P100 > tmpSparse\nzstd tmpSparse -c | zstd -dv -o tmpSparseRegen\n$DIFF -s tmpSparse tmpSparseRegen\nzstd tmpSparse -c | zstd -dv --sparse -c > tmpOutSparse\n$DIFF -s tmpSparse tmpOutSparse\nzstd tmpSparse -c | zstd -dv --no-sparse -c > tmpOutNoSparse\n$DIFF -s tmpSparse tmpOutNoSparse\nls -ls tmpSparse*  # look at file size and block size on disk\ndatagen -s1 -g1200007 -P100 | zstd | zstd -dv --sparse -c > tmpSparseOdd   # Odd size file (to not finish on an exact nb of blocks)\ndatagen -s1 -g1200007 -P100 | $DIFF -s - tmpSparseOdd\nls -ls tmpSparseOdd  # look at file size and block size on disk\nprintln \"\\n Sparse Compatibility with Console :\"\nprintln \"Hello World 1 !\" | zstd | zstd -d -c\nprintln \"Hello World 2 !\" | zstd | zstd -d | cat\nprintln \"\\n Sparse Compatibility with Append :\"\ndatagen -P100 -g1M > tmpSparse1M\ncat tmpSparse1M tmpSparse1M > tmpSparse2M\nzstd -v -f tmpSparse1M -o tmpSparseCompressed\nzstd -d -v -f tmpSparseCompressed -o tmpSparseRegenerated\nzstd -d -v -f tmpSparseCompressed -c >> tmpSparseRegenerated\nls -ls tmpSparse*  # look at file size and block size on disk\n$DIFF tmpSparse2M tmpSparseRegenerated\nrm -f tmpSparse*\n\n\nprintln \"\\n===>  stream-size mode\"\n\ndatagen -g11000 > tmp\nprintln \"test : basic file compression vs sized streaming compression\"\nfile_size=$(zstd -14 -f tmp -o tmp.zst && wc -c < tmp.zst)\nstream_size=$(cat tmp | zstd -14 --stream-size=11000 | wc -c)\nif [ \"$stream_size\" -gt \"$file_size\" ]; then\n  die \"hinted compression larger than expected\"\nfi\nprintln \"test : sized streaming compression and decompression\"\ncat tmp | zstd -14 -f tmp -o tmp.zst --stream-size=11000\nzstd -df tmp.zst -o tmp_decompress\ncmp tmp tmp_decompress || die \"difference between original and decompressed file\"\nprintln \"test : incorrect stream size\"\ncat tmp | zstd -14 -f -o tmp.zst --stream-size=11001 && die \"should fail with incorrect stream size\"\n\nprintln \"\\n===>  zstd zero weight dict test \"\nrm -f tmp*\ncp \"$TESTDIR/dict-files/zero-weight-dict\" tmp_input\nzstd -D \"$TESTDIR/dict-files/zero-weight-dict\" tmp_input\nzstd -D \"$TESTDIR/dict-files/zero-weight-dict\" -d tmp_input.zst -o tmp_decomp\n$DIFF tmp_decomp tmp_input\nrm -rf tmp*\n\nprintln \"\\n===>  zstd (valid) zero weight dict test \"\nrm -f tmp*\n# 0 has a non-zero weight in the dictionary\necho \"0000000000000000000000000\" > tmp_input\nzstd -D \"$TESTDIR/dict-files/zero-weight-dict\" tmp_input\nzstd -D \"$TESTDIR/dict-files/zero-weight-dict\" -d tmp_input.zst -o tmp_decomp\n$DIFF tmp_decomp tmp_input\nrm -rf tmp*\n\nprintln \"\\n===>  size-hint mode\"\n\ndatagen -g11000 > tmp\ndatagen -g11000 > tmp2\ndatagen > tmpDict\nprintln \"test : basic file compression vs hinted streaming compression\"\nfile_size=$(zstd -14 -f tmp -o tmp.zst && wc -c < tmp.zst)\nstream_size=$(cat tmp | zstd -14 --size-hint=11000 | wc -c)\nif [ \"$stream_size\" -ge \"$file_size\" ]; then\n  die \"hinted compression larger than expected\"\nfi\nprintln \"test : hinted streaming compression and decompression\"\ncat tmp | zstd -14 -f -o tmp.zst --size-hint=11000\nzstd -df tmp.zst -o tmp_decompress\ncmp tmp tmp_decompress || die \"difference between original and decompressed file\"\nprintln \"test : hinted streaming compression with dictionary\"\ncat tmp | zstd -14 -f -D tmpDict --size-hint=11000 | zstd -t -D tmpDict\nprintln \"test : multiple file compression with hints and dictionary\"\nzstd -14 -f -D tmpDict --size-hint=11000 tmp tmp2\nzstd -14 -f -o tmp1_.zst -D tmpDict --size-hint=11000 tmp\nzstd -14 -f -o tmp2_.zst -D tmpDict --size-hint=11000 tmp2\ncmp tmp.zst tmp1_.zst || die \"first file's output differs\"\ncmp tmp2.zst tmp2_.zst || die \"second file's output differs\"\nprintln \"test : incorrect hinted stream sizes\"\ncat tmp | zstd -14 -f --size-hint=11050 | zstd -t  # slightly too high\ncat tmp | zstd -14 -f --size-hint=10950 | zstd -t  # slightly too low\ncat tmp | zstd -14 -f --size-hint=22000 | zstd -t  # considerably too high\ncat tmp | zstd -14 -f --size-hint=5500  | zstd -t  # considerably too low\nprintln \"test : allows and interprets K,KB,KiB,M,MB,MiB,G,GB and GiB suffix\"\ncat tmp | zstd -14 -f --size-hint=11K | zstd -t\ncat tmp | zstd -14 -f --size-hint=11KB | zstd -t\ncat tmp | zstd -14 -f --size-hint=11KiB | zstd -t\ncat tmp | zstd -14 -f --size-hint=1M  | zstd -t\ncat tmp | zstd -14 -f --size-hint=1MB  | zstd -t\ncat tmp | zstd -14 -f --size-hint=1MiB  | zstd -t\ncat tmp | zstd -14 -f --size-hint=1G  | zstd -t\ncat tmp | zstd -14 -f --size-hint=1GB  | zstd -t\ncat tmp | zstd -14 -f --size-hint=1GiB  | zstd -t\ncat tmp | zstd -14 -f --size-hint=3G  | zstd -t\ncat tmp | zstd -14 -f --size-hint=3GB  | zstd -t\ncat tmp | zstd -14 -f --size-hint=3GiB  | zstd -t\n\n\nprintln \"\\n===>  dictionary tests \"\nprintln \"- Test high/low compressibility corpus training\"\ndatagen -g12M -P90 > tmpCorpusHighCompress\ndatagen -g12M -P5 > tmpCorpusLowCompress\nzstd --train --split=2K tmpCorpusHighCompress -o tmpDictHighCompress\nzstd --train --split=2K tmpCorpusLowCompress -o tmpDictLowCompress\nrm -f tmpCorpusHighCompress tmpCorpusLowCompress tmpDictHighCompress tmpDictLowCompress\nprintln \"- Test with raw dict (content only) \"\ndatagen > tmpDict\ndatagen -g1M | $MD5SUM > tmp1\ndatagen -g1M | zstd -D tmpDict | zstd -D tmpDict -dvq | $MD5SUM > tmp2\n$DIFF -q tmp1 tmp2\nprintln \"- Create first dictionary \"\nTESTFILE=\"$PRGDIR\"/zstdcli.c\nzstd --train \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c -o tmpDict\ncp \"$TESTFILE\" tmp\nprintln \"- Test dictionary compression with tmpDict as an input file and dictionary\"\nzstd -f tmpDict -D tmpDict && die \"compression error not detected!\"\nprintln \"- Dictionary compression roundtrip\"\nzstd -f tmp -D tmpDict\nzstd -d tmp.zst -D tmpDict -fo result\n$DIFF \"$TESTFILE\" result\nprintln \"- Dictionary compression with hlog < clog\"\nzstd -6f tmp -D tmpDict --zstd=clog=25,hlog=23\nprintln \"- Dictionary compression with btlazy2 strategy\"\nzstd -f tmp -D tmpDict --zstd=strategy=6\nzstd -d tmp.zst -D tmpDict -fo result\n$DIFF \"$TESTFILE\" result\nif [ -e /proc/self/fd/0 ]; then\n    println \"- Test rejecting irregular dictionary file\"\n    cat tmpDict | zstd -f tmp -D /proc/self/fd/0 && die \"Piped dictionary should fail!\"\n    cat tmpDict | zstd -d tmp.zst -D /proc/self/fd/0 -f && die \"Piped dictionary should fail!\"\nfi\nif [ -n \"$hasMT\" ]\nthen\n    println \"- Test dictionary compression with multithreading \"\n    datagen -g5M | zstd -T2 -D tmpDict | zstd -t -D tmpDict   # fails with v1.3.2\nfi\nprintln \"- Create second (different) dictionary \"\nzstd --train \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c \"$PRGDIR\"/*.h -o tmpDictC\nzstd -d tmp.zst -D tmpDictC -fo result && die \"wrong dictionary not detected!\"\nprintln \"- Create dictionary with short dictID\"\nzstd --train \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c --dictID=1 -o tmpDict1\ncmp tmpDict tmpDict1 && die \"dictionaries should have different ID !\"\nprintln \"- Create dictionary with wrong dictID parameter order (must fail)\"\nzstd --train \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c --dictID -o 1 tmpDict1 && die \"wrong order : --dictID must be followed by argument \"\nprintln \"- Create dictionary with size limit\"\nzstd --train \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c -o tmpDict2 --maxdict=4K -v\nprintln \"- Create dictionary with small size limit\"\nzstd --train \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c -o tmpDict3 --maxdict=1K -v\nprintln \"- Create dictionary with wrong parameter order (must fail)\"\nzstd --train \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c -o tmpDict3 --maxdict -v 4K && die \"wrong order : --maxdict must be followed by argument \"\nprintln \"- Compress without dictID\"\nzstd -f tmp -D tmpDict1 --no-dictID\nzstd -d tmp.zst -D tmpDict -fo result\n$DIFF \"$TESTFILE\" result\nprintln \"- Compress multiple files with dictionary\"\nrm -rf dirTestDict\nmkdir dirTestDict\ncp \"$TESTDIR\"/*.c dirTestDict\ncp \"$PRGDIR\"/*.c dirTestDict\ncp \"$PRGDIR\"/*.h dirTestDict\n$MD5SUM dirTestDict/* > tmph1\nzstd -f --rm dirTestDict/* -D tmpDictC\nzstd -d --rm dirTestDict/*.zst -D tmpDictC  # note : use internal checksum by default\ncase \"$UNAME\" in\n  Darwin) println \"md5sum -c not supported on OS-X : test skipped\" ;;  # not compatible with OS-X's md5\n  *) $MD5SUM -c tmph1 ;;\nesac\nrm -rf dirTestDict\nprintln \"- dictionary builder on bogus input\"\nprintln \"Hello World\" > tmp\nzstd --train-legacy -q tmp && die \"Dictionary training should fail : not enough input source\"\ndatagen -P0 -g10M > tmp\nzstd --train-legacy -q tmp && die \"Dictionary training should fail : source is pure noise\"\nprintln \"- Test -o before --train\"\nrm -f tmpDict dictionary\nzstd -o tmpDict --train \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c\ntest -f tmpDict\nzstd --train \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c\ntest -f dictionary\nif [ -n \"$hasMT\" ]\nthen\n  println \"- Create dictionary with multithreading enabled\"\n  zstd --train -T0 \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c -o tmpDict\nfi\nrm -f tmp* dictionary\n\nprintln \"- Test --memory for dictionary compression\"\ndatagen -g12M -P90 > tmpCorpusHighCompress\nzstd --train --split=2K tmpCorpusHighCompress -o tmpDictHighCompress --memory=10K && die \"Dictionary training should fail : --memory too low (10K)\"\nzstd --train --split=2K tmpCorpusHighCompress -o tmpDictHighCompress --memory=5MB 2> zstTrainWithMemLimitStdErr\ncat zstTrainWithMemLimitStdErr | $GREP \"setting manual memory limit for dictionary training data at 5 MB\"\ncat zstTrainWithMemLimitStdErr | $GREP \"Training samples set too large (12 MB); training on 5 MB only...\"\nrm zstTrainWithMemLimitStdErr\n\nprintln \"\\n===>  fastCover dictionary builder : advanced options \"\nTESTFILE=\"$PRGDIR\"/zstdcli.c\ndatagen > tmpDict\nprintln \"- Create first dictionary\"\nzstd --train-fastcover=k=46,d=8,f=15,split=80 \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c -o tmpDict\ncp \"$TESTFILE\" tmp\nzstd -f tmp -D tmpDict\nzstd -d tmp.zst -D tmpDict -fo result\n$DIFF \"$TESTFILE\" result\nprintln \"- Create second (different) dictionary\"\nzstd --train-fastcover=k=56,d=8 \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c \"$PRGDIR\"/*.h -o tmpDictC\nzstd -d tmp.zst -D tmpDictC -fo result && die \"wrong dictionary not detected!\"\nzstd --train-fastcover=k=56,d=8 && die \"Create dictionary without input file\"\nprintln \"- Create dictionary with short dictID\"\nzstd --train-fastcover=k=46,d=8,f=15,split=80 \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c --dictID=1 -o tmpDict1\ncmp tmpDict tmpDict1 && die \"dictionaries should have different ID !\"\nprintln \"- Create dictionaries with shrink-dict flag enabled\"\nzstd --train-fastcover=steps=1,shrink \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c -o tmpShrinkDict\nzstd --train-fastcover=steps=1,shrink=1 \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c -o tmpShrinkDict1\nzstd --train-fastcover=steps=1,shrink=5 \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c -o tmpShrinkDict2\nzstd --train-fastcover=shrink=5,steps=1 \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c -o tmpShrinkDict3\nprintln \"- Create dictionary with size limit\"\nzstd --train-fastcover=steps=1 \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c -o tmpDict2 --maxdict=4K\nprintln \"- Create dictionary using all samples for both training and testing\"\nzstd --train-fastcover=k=56,d=8,split=100 -r \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c\nprintln \"- Create dictionary using f=16\"\nzstd --train-fastcover=k=56,d=8,f=16 -r \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c\nzstd --train-fastcover=k=56,d=8,accel=15 -r \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c && die \"Created dictionary using accel=15\"\nprintln \"- Create dictionary using accel=2\"\nzstd --train-fastcover=k=56,d=8,accel=2 -r \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c\nprintln \"- Create dictionary using accel=10\"\nzstd --train-fastcover=k=56,d=8,accel=10 -r \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c\nprintln \"- Create dictionary with multithreading\"\nzstd --train-fastcover -T4 -r \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c\nprintln \"- Test -o before --train-fastcover\"\nrm -f tmpDict dictionary\nzstd -o tmpDict --train-fastcover=k=56,d=8 \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c\ntest -f tmpDict\nzstd --train-fastcover=k=56,d=8 \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c\ntest -f dictionary\nrm -f tmp* dictionary\n\n\nprintln \"\\n===>  legacy dictionary builder \"\n\nTESTFILE=\"$PRGDIR\"/zstdcli.c\ndatagen > tmpDict\nprintln \"- Create first dictionary\"\nzstd --train-legacy=selectivity=8 \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c -o tmpDict\ncp \"$TESTFILE\" tmp\nzstd -f tmp -D tmpDict\nzstd -d tmp.zst -D tmpDict -fo result\n$DIFF \"$TESTFILE\" result\nzstd --train-legacy=s=8 && die \"Create dictionary without input files (should error)\"\nprintln \"- Create second (different) dictionary\"\nzstd --train-legacy=s=5 \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c \"$PRGDIR\"/*.h -o tmpDictC\nzstd -d tmp.zst -D tmpDictC -fo result && die \"wrong dictionary not detected!\"\nprintln \"- Create dictionary with short dictID\"\nzstd --train-legacy -s5 \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c --dictID=1 -o tmpDict1\ncmp tmpDict tmpDict1 && die \"dictionaries should have different ID !\"\nprintln \"- Create dictionary with size limit\"\nzstd --train-legacy -s9 \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c -o tmpDict2 --maxdict=4K\nprintln \"- Test -o before --train-legacy\"\nrm -f tmpDict dictionary\nzstd -o tmpDict --train-legacy \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c\ntest -f tmpDict\nzstd --train-legacy \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c\ntest -f dictionary\nrm -f tmp* dictionary\n\n\nprintln \"\\n===>  integrity tests \"\n\nprintln \"test one file (tmp1.zst) \"\ndatagen > tmp1\nzstd tmp1\nzstd -t tmp1.zst\nzstd --test tmp1.zst\nprintln \"test multiple files (*.zst) \"\nzstd -t ./*.zst\nprintln \"test bad files (*) \"\nzstd -t ./* && die \"bad files not detected !\"\nzstd -t tmp1 && die \"bad file not detected !\"\ncp tmp1 tmp2.zst\nzstd -t tmp2.zst && die \"bad file not detected !\"\ndatagen -g0 > tmp3\nzstd -t tmp3 && die \"bad file not detected !\"   # detects 0-sized files as bad\nprintln \"test --rm and --test combined \"\nzstd -t --rm tmp1.zst\ntest -f tmp1.zst   # check file is still present\ncp tmp1.zst tmp2.zst\nzstd -t tmp1.zst tmp2.zst --rm\ntest -f tmp1.zst   # check file is still present\ntest -f tmp2.zst   # check file is still present\nsplit -b16384 tmp1.zst tmpSplit.\nzstd -t tmpSplit.* && die \"bad file not detected !\"\ndatagen | zstd -c | zstd -t\n\n\nprintln \"\\n===>  golden files tests \"\n\nzstd -t -r \"$TESTDIR/golden-decompression\"\nzstd -c -r \"$TESTDIR/golden-compression\" | zstd -t\nzstd -D \"$TESTDIR/golden-dictionaries/http-dict-missing-symbols\" \"$TESTDIR/golden-compression/http\" -c | zstd -D \"$TESTDIR/golden-dictionaries/http-dict-missing-symbols\" -t\n\n\nprintln \"\\n===>  benchmark mode tests \"\n\nprintln \"bench one file\"\ndatagen > tmp1\nzstd -bi0 tmp1\nprintln \"bench multiple levels\"\nzstd -i0b0e3 tmp1\nprintln \"bench negative level\"\nzstd -bi0 --fast tmp1\nprintln \"with recursive and quiet modes\"\nzstd -rqi0b1e2 tmp1\nprintln \"benchmark decompression only\"\nzstd -f tmp1\nzstd -b -d -i0 tmp1.zst\nprintln \"benchmark can fail - decompression on invalid data\"\nzstd -b -d -i0 tmp1 && die \"invalid .zst data => benchmark should have failed\"\n\nGZIPMODE=1\nzstd --format=gzip -V || GZIPMODE=0\nif [ $GZIPMODE -eq 1 ]; then\n    println \"benchmark mode is only compatible with zstd\"\n    zstd --format=gzip -b tmp1 && die \"-b should be incompatible with gzip format!\"\nfi\n\nprintln \"\\n===>  zstd compatibility tests \"\n\ndatagen > tmp\nrm -f tmp.zst\nzstd --format=zstd -f tmp\ntest -f tmp.zst\n\n\nprintln \"\\n===>  gzip compatibility tests \"\n\nGZIPMODE=1\nzstd --format=gzip -V || GZIPMODE=0\nif [ $GZIPMODE -eq 1 ]; then\n    println \"gzip support detected\"\n    GZIPEXE=1\n    gzip -V || GZIPEXE=0\n    if [ $GZIPEXE -eq 1 ]; then\n        datagen > tmp\n        zstd --format=gzip -f tmp\n        gzip -t -v tmp.gz\n        gzip -f tmp\n        zstd -d -f -v tmp.gz\n        rm -f tmp*\n    else\n        println \"gzip binary not detected\"\n    fi\nelse\n    println \"gzip mode not supported\"\nfi\n\n\nprintln \"\\n===>  gzip frame tests \"\n\nif [ $GZIPMODE -eq 1 ]; then\n    datagen > tmp\n    zstd -f --format=gzip tmp\n    zstd -f tmp\n    cat tmp.gz tmp.zst tmp.gz tmp.zst | zstd -d -f -o tmp\n    truncateLastByte tmp.gz | zstd -t > $INTOVOID && die \"incomplete frame not detected !\"\n    rm -f tmp*\nelse\n    println \"gzip mode not supported\"\nfi\n\nif [ $GZIPMODE -eq 1 ]; then\n    datagen > tmp\n    rm -f tmp.zst\n    zstd --format=gzip --format=zstd -f tmp\n    test -f tmp.zst\nfi\n\nprintln \"\\n===>  xz compatibility tests \"\n\nLZMAMODE=1\nzstd --format=xz -V || LZMAMODE=0\nif [ $LZMAMODE -eq 1 ]; then\n    println \"xz support detected\"\n    XZEXE=1\n    xz -Q -V && lzma -Q -V || XZEXE=0\n    if [ $XZEXE -eq 1 ]; then\n        println \"Testing zstd xz and lzma support\"\n        datagen > tmp\n        zstd --format=lzma -f tmp\n        zstd --format=xz -f tmp\n        xz -Q -t -v tmp.xz\n        xz -Q -t -v tmp.lzma\n        xz -Q -f -k tmp\n        lzma -Q -f -k --lzma1 tmp\n        zstd -d -f -v tmp.xz\n        zstd -d -f -v tmp.lzma\n        rm -f tmp*\n        println \"Creating symlinks\"\n        ln -s \"$ZSTD_BIN\" ./xz\n        ln -s \"$ZSTD_BIN\" ./unxz\n        ln -s \"$ZSTD_BIN\" ./lzma\n        ln -s \"$ZSTD_BIN\" ./unlzma\n        println \"Testing xz and lzma symlinks\"\n        datagen > tmp\n        ./xz tmp\n        xz -Q -d tmp.xz\n        ./lzma tmp\n        lzma -Q -d tmp.lzma\n        println \"Testing unxz and unlzma symlinks\"\n        xz -Q tmp\n        ./xz -d tmp.xz\n        lzma -Q tmp\n        ./lzma -d tmp.lzma\n        rm -f xz unxz lzma unlzma\n        rm -f tmp*\n    else\n        println \"xz binary not detected\"\n    fi\nelse\n    println \"xz mode not supported\"\nfi\n\n\nprintln \"\\n===>  xz frame tests \"\n\nif [ $LZMAMODE -eq 1 ]; then\n    datagen > tmp\n    zstd -f --format=xz tmp\n    zstd -f --format=lzma tmp\n    zstd -f tmp\n    cat tmp.xz tmp.lzma tmp.zst tmp.lzma tmp.xz tmp.zst | zstd -d -f -o tmp\n    truncateLastByte tmp.xz | zstd -t > $INTOVOID && die \"incomplete frame not detected !\"\n    truncateLastByte tmp.lzma | zstd -t > $INTOVOID && die \"incomplete frame not detected !\"\n    rm -f tmp*\nelse\n    println \"xz mode not supported\"\nfi\n\nprintln \"\\n===>  lz4 compatibility tests \"\n\nLZ4MODE=1\nzstd --format=lz4 -V || LZ4MODE=0\nif [ $LZ4MODE -eq 1 ]; then\n    println \"lz4 support detected\"\n    LZ4EXE=1\n    lz4 -V || LZ4EXE=0\n    if [ $LZ4EXE -eq 1 ]; then\n        datagen > tmp\n        zstd --format=lz4 -f tmp\n        lz4 -t -v tmp.lz4\n        lz4 -f -m tmp   # ensure result is sent into tmp.lz4, not stdout\n        zstd -d -f -v tmp.lz4\n        rm -f tmp*\n    else\n        println \"lz4 binary not detected\"\n    fi\nelse\n    println \"lz4 mode not supported\"\nfi\n\n\nif [ $LZ4MODE -eq 1 ]; then\n    println \"\\n===>  lz4 frame tests \"\n    datagen > tmp\n    zstd -f --format=lz4 tmp\n    zstd -f tmp\n    cat tmp.lz4 tmp.zst tmp.lz4 tmp.zst | zstd -d -f -o tmp\n    truncateLastByte tmp.lz4 | zstd -t > $INTOVOID && die \"incomplete frame not detected !\"\n    rm -f tmp*\nelse\n    println \"\\nlz4 mode not supported\"\nfi\n\n\nprintln \"\\n===> suffix list test\"\n\n! zstd -d tmp.abc 2> tmplg\n\nif [ $GZIPMODE -ne 1 ]; then\n    $GREP \".gz\" tmplg > $INTOVOID && die \"Unsupported suffix listed\"\nfi\n\nif [ $LZMAMODE -ne 1 ]; then\n    $GREP \".lzma\" tmplg > $INTOVOID && die \"Unsupported suffix listed\"\n    $GREP \".xz\" tmplg > $INTOVOID && die \"Unsupported suffix listed\"\nfi\n\nif [ $LZ4MODE -ne 1 ]; then\n    $GREP \".lz4\" tmplg > $INTOVOID && die \"Unsupported suffix listed\"\nfi\n\ntouch tmp1\nzstd tmp1 -o tmp1.zstd\nzstd -d -f tmp1.zstd   # support .zstd suffix even though it's not the default suffix\n\nprintln \"\\n===>  tar extension tests \"\n\nrm -f tmp tmp.tar tmp.tzst tmp.tgz tmp.txz tmp.tlz4 tmp1.zstd\n\ndatagen > tmp\ntar -cf tmp.tar tmp\nzstd tmp.tar -o tmp.tzst\nrm -f tmp.tar\nzstd -d tmp.tzst\n[ -e tmp.tar ] || die \".tzst failed to decompress to .tar!\"\nrm -f tmp.tar tmp.tzst\n\nif [ $GZIPMODE -eq 1 ]; then\n    tar -f - -c tmp | gzip > tmp.tgz\n    zstd -d tmp.tgz\n    [ -e tmp.tar ] || die \".tgz failed to decompress to .tar!\"\n    rm -f tmp.tar tmp.tgz\nfi\n\nif [ $LZMAMODE -eq 1 ]; then\n    tar -f - -c tmp | zstd --format=xz > tmp.txz\n    zstd -d tmp.txz\n    [ -e tmp.tar ] || die \".txz failed to decompress to .tar!\"\n    rm -f tmp.tar tmp.txz\nfi\n\nif [ $LZ4MODE -eq 1 ]; then\n    tar -f - -c tmp | zstd --format=lz4 > tmp.tlz4\n    zstd -d tmp.tlz4\n    [ -e tmp.tar ] || die \".tlz4 failed to decompress to .tar!\"\n    rm -f tmp.tar tmp.tlz4\nfi\n\ntouch tmp.t tmp.tz tmp.tzs\n! zstd -d tmp.t\n! zstd -d tmp.tz\n! zstd -d tmp.tzs\n\n\nprintln \"\\n===>  zstd round-trip tests \"\n\nroundTripTest\nroundTripTest -g15K       # TableID==3\nroundTripTest -g127K      # TableID==2\nroundTripTest -g255K      # TableID==1\nroundTripTest -g522K      # TableID==0\nroundTripTest -g519K 6    # greedy, hash chain\nroundTripTest -g517K 16   # btlazy2\nroundTripTest -g516K 19   # btopt\n\nfileRoundTripTest -g500K\n\nprintln \"\\n===>  zstd long distance matching round-trip tests \"\nroundTripTest -g0 \"2 --single-thread --long\"\nroundTripTest -g1000K \"1 --single-thread --long\"\nroundTripTest -g517K \"6 --single-thread --long\"\nroundTripTest -g516K \"16 --single-thread --long\"\nroundTripTest -g518K \"19 --single-thread --long\"\nroundTripTest -g2M \"22 --single-thread --ultra --long\"\nfileRoundTripTest -g5M \"3 --single-thread --long\"\n\n\nroundTripTest -g96K \"5 --single-thread\"\nif [ -n \"$hasMT\" ]\nthen\n    println \"\\n===>  zstdmt round-trip tests \"\n    roundTripTest -g4M \"1 -T0\"\n    roundTripTest -g4M \"1 -T0 --auto-threads=physical\"\n    roundTripTest -g4M \"1 -T0 --auto-threads=logical\"\n    roundTripTest -g8M \"3 -T2\"\n    roundTripTest -g8000K \"2 --threads=2\"\n    fileRoundTripTest -g4M \"19 -T2 --split=1M\"\n\n    println \"\\n===>  zstdmt long distance matching round-trip tests \"\n    roundTripTest -g8M \"3 --long=24 -T2\"\n\n    println \"\\n===>  zstdmt environment variable tests \"\n    echo \"multifoo\" >> mt_tmp\n    ZSTD_NBTHREADS=-3 zstd -f mt_tmp # negative value, warn and revert to default setting\n    ZSTD_NBTHREADS='' zstd -f mt_tmp # empty env var, warn and revert to default setting\n    ZSTD_NBTHREADS=-  zstd -f mt_tmp # malformed env var, warn and revert to default setting\n    ZSTD_NBTHREADS=a  zstd -f mt_tmp # malformed env var, warn and revert to default setting\n    ZSTD_NBTHREADS=+a zstd -f mt_tmp # malformed env var, warn and revert to default setting\n    ZSTD_NBTHREADS=3a7 zstd -f mt_tmp # malformed env var, warn and revert to default setting\n    ZSTD_NBTHREADS=50000000000 zstd -f mt_tmp # numeric value too large, warn and revert to default setting=\n    ZSTD_NBTHREADS=2  zstd -f mt_tmp # correct usage\n    ZSTD_NBTHREADS=1  zstd -f mt_tmp # correct usage: single worker\n    ZSTD_NBTHREADS=4  zstd -f mt_tmp -vv 2>&1 | $GREP \"4 worker threads\" # check message\n    ZSTD_NBTHREADS=0  zstd -f mt_tmp -vv 2>&1 | $GREP \"core(s) detected\" # check core count autodetection is triggered\n    # temporary envvar changes in the above tests would actually persist in macos /bin/sh\n    unset ZSTD_NBTHREADS\n    rm -f mt_tmp*\n\n    println \"\\n===>  ovLog tests \"\n    datagen -g2MB > tmp\n    refSize=$(zstd tmp -6 -c --zstd=wlog=18         | wc -c)\n    ov9Size=$(zstd tmp -6 -c --zstd=wlog=18,ovlog=9 | wc -c)\n    ov1Size=$(zstd tmp -6 -c --zstd=wlog=18,ovlog=1 | wc -c)\n    if [ \"$refSize\" -eq \"$ov9Size\" ]; then\n        echo ov9Size should be different from refSize\n        exit 1\n    fi\n    if [ \"$refSize\" -eq \"$ov1Size\" ]; then\n        echo ov1Size should be different from refSize\n        exit 1\n    fi\n    if [ \"$ov9Size\" -ge \"$ov1Size\" ]; then\n        echo ov9Size=\"$ov9Size\" should be smaller than ov1Size=\"$ov1Size\"\n        exit 1\n    fi\n\nelse\n    println \"\\n===>  no multithreading, skipping zstdmt tests \"\nfi\n\nrm -f tmp*\n\nprintln \"\\n===>  zstd --list/-l single frame tests \"\ndatagen > tmp1\ndatagen > tmp2\ndatagen > tmp3\nzstd tmp*\nzstd -l ./*.zst\nzstd -lv ./*.zst | $GREP \"Decompressed Size:\"  # check that decompressed size is present in header\nzstd --list ./*.zst\nzstd --list -v ./*.zst\n\nprintln \"\\n===>  zstd --list/-l multiple frame tests \"\ncat tmp1.zst tmp2.zst > tmp12.zst\ncat tmp12.zst tmp3.zst > tmp123.zst\nzstd -l ./*.zst\nzstd -lv ./*.zst\n\nprintln \"\\n===>  zstd --list/-l error detection tests \"\nzstd -l tmp1 tmp1.zst && die \"-l must fail on non-zstd file\"\nzstd --list tmp* && die \"-l must fail on non-zstd file\"\nzstd -lv tmp1* && die \"-l must fail on non-zstd file\"\nzstd --list -v tmp2 tmp12.zst && die \"-l must fail on non-zstd file\"\n\nprintln \"test : detect truncated compressed file \"\nTEST_DATA_FILE=truncatable-input.txt\nFULL_COMPRESSED_FILE=${TEST_DATA_FILE}.zst\nTRUNCATED_COMPRESSED_FILE=truncated-input.txt.zst\ndatagen -g50000 > $TEST_DATA_FILE\nzstd -f $TEST_DATA_FILE -o $FULL_COMPRESSED_FILE\ndd bs=1 count=100 if=$FULL_COMPRESSED_FILE of=$TRUNCATED_COMPRESSED_FILE\nzstd --list $TRUNCATED_COMPRESSED_FILE && die \"-l must fail on truncated file\"\n\nrm -f $TEST_DATA_FILE\nrm -f $FULL_COMPRESSED_FILE\nrm -f $TRUNCATED_COMPRESSED_FILE\n\nprintln \"\\n===>  zstd --list/-l errors when presented with stdin / no files\"\nzstd -l && die \"-l must fail on empty list of files\"\nzstd -l - && die \"-l does not work on stdin\"\nzstd -l < tmp1.zst && die \"-l does not work on stdin\"\nzstd -l - < tmp1.zst && die \"-l does not work on stdin\"\nzstd -l - tmp1.zst && die \"-l does not work on stdin\"\nzstd -l - tmp1.zst < tmp1.zst && die \"-l does not work on stdin\"\nzstd -l tmp1.zst < tmp2.zst # this will check tmp1.zst, but not tmp2.zst, which is not an error : zstd simply doesn't read stdin in this case. It must not error just because stdin is not a tty\n\nprintln \"\\n===>  zstd --list/-l test with null files \"\ndatagen -g0 > tmp5\nzstd tmp5\nzstd -l tmp5.zst\nzstd -l tmp5* && die \"-l must fail on non-zstd file\"\nzstd -lv tmp5.zst | $GREP \"Decompressed Size: 0 B (0 B)\"  # check that 0 size is present in header\nzstd -lv tmp5* && die \"-l must fail on non-zstd file\"\n\nprintln \"\\n===>  zstd --list/-l test with no content size field \"\ndatagen -g513K | zstd > tmp6.zst\nzstd -l tmp6.zst\nzstd -lv tmp6.zst | $GREP \"Decompressed Size:\"  && die \"Field :Decompressed Size: should not be available in this compressed file\"\n\nprintln \"\\n===>   zstd --list/-l test with no checksum \"\nzstd -f --no-check tmp1\nzstd -l tmp1.zst\nzstd -lv tmp1.zst\n\nprintln \"\\n===>  zstd trace tests \"\nzstd -f --trace tmp.trace tmp1\nzstd -f --trace tmp.trace tmp1 tmp2 tmp3\nzstd -f --trace tmp.trace tmp1 tmp2 tmp3 -o /dev/null\nzstd -f --trace tmp.trace tmp1 tmp2 tmp3 --single-thread\nzstd -f --trace tmp.trace -D tmp1 tmp2 tmp3 -o /dev/null\nzstd -f --trace tmp.trace -D tmp1 tmp2 tmp3 -o /dev/null --single-thread\nzstd --trace tmp.trace -t tmp1.zst\nzstd --trace tmp.trace -t tmp1.zst tmp2.zst\nzstd -f --trace tmp.trace -d tmp1.zst\nzstd -f --trace tmp.trace -d tmp1.zst tmp2.zst tmp3.zst\nzstd -D tmp1 tmp2 -c | zstd --trace tmp.trace -t -D tmp1\nzstd -b1e10i0 --trace tmp.trace tmp1\nzstd -b1e10i0 --trace tmp.trace tmp1 tmp2 tmp3\n\nrm -f tmp*\n\n\nprintln \"\\n===>   zstd long distance matching tests \"\nroundTripTest -g0 \" --single-thread --long\"\nroundTripTest -g9M \"2 --single-thread --long\"\n# Test parameter parsing\nroundTripTest -g1M -P50 \"1 --single-thread --long=29\" \" --memory=512MB\"\nroundTripTest -g1M -P50 \"1 --single-thread --long=29 --zstd=wlog=28\" \" --memory=256MB\"\nroundTripTest -g1M -P50 \"1 --single-thread --long=29\" \" --long=28 --memory=512MB\"\nroundTripTest -g1M -P50 \"1 --single-thread --long=29\" \" --zstd=wlog=28 --memory=512MB\"\nroundTripTest -g1M -P50 \"1 --single-thread --long=30\" \" --memory=1GB\"\nroundTripTest -g1M -P50 \"1 --single-thread --long=30\" \" --zstd=wlog=29 --memory=1GB\"\n\n\nif [ \"$ZSTD_LIB_EXCLUDE_COMPRESSORS_DFAST_AND_UP\" -ne \"1\" ]; then\n    println \"\\n===>  zstd long distance matching with optimal parser compressed size tests \"\n    optCSize16=$(datagen -g511K | zstd -16 -c | wc -c)\n    longCSize16=$(datagen -g511K | zstd -16 --long -c | wc -c)\n    optCSize19=$(datagen -g2M | zstd -19 -c | wc -c)\n    longCSize19=$(datagen -g2M | zstd -19 --long -c | wc -c)\n    optCSize19wlog23=$(datagen -g2M | zstd -19 -c  --zstd=wlog=23 | wc -c)\n    longCSize19wlog23=$(datagen -g2M | zstd -19 -c --long=23 | wc -c)\n    if [ \"$longCSize16\" -gt \"$optCSize16\" ]; then\n        echo using --long on compression level 16 should not cause compressed size regression\n        exit 1\n    elif [ \"$longCSize19\" -gt \"$optCSize19\" ]; then\n        echo using --long on compression level 19 should not cause compressed size regression\n        exit 1\n    elif [ \"$longCSize19wlog23\" -gt \"$optCSize19wlog23\" ]; then\n        echo using --long on compression level 19 with wLog=23 should not cause compressed size regression\n        exit 1\n    fi\nfi\n\nprintln \"\\n===>  zstd asyncio tests \"\n\naddFrame() {\n    datagen -g2M -s$2 >> tmp_uncompressed\n    datagen -g2M -s$2 | zstd -1 --format=$1 >> tmp_compressed.zst\n}\n\naddTwoFrames() {\n  addFrame $1 1\n  addFrame $1 2\n}\n\ntestAsyncIO() {\n  roundTripTest -g2M \"3 --asyncio --format=$1\"\n  roundTripTest -g2M \"3 --no-asyncio --format=$1\"\n}\n\nrm -f tmp_compressed tmp_uncompressed\ntestAsyncIO zstd\naddTwoFrames zstd\nif [ $GZIPMODE -eq 1 ]; then\n  testAsyncIO gzip\n  addTwoFrames gzip\nfi\nif [ $LZMAMODE -eq 1 ]; then\n  testAsyncIO lzma\n  addTwoFrames lzma\nfi\nif [ $LZ4MODE -eq 1 ]; then\n  testAsyncIO lz4\n  addTwoFrames lz4\nfi\ncat tmp_uncompressed | $MD5SUM > tmp2\nzstd -d tmp_compressed.zst --asyncio -c | $MD5SUM > tmp1\n$DIFF -q tmp1 tmp2\nrm tmp1\nzstd -d tmp_compressed.zst --no-asyncio -c | $MD5SUM > tmp1\n$DIFF -q tmp1 tmp2\n\nif [ \"$1\" != \"--test-large-data\" ]; then\n    println \"Skipping large data tests\"\n    exit 0\nfi\n\n\n#############################################################################\n\n\nif [ -n \"$hasMT\" ]\nthen\n    println \"\\n===>   adaptive mode \"\n    roundTripTest -g270000000 \" --adapt\"\n    roundTripTest -g27000000 \" --adapt=min=1,max=4\"\n    roundTripTest -g27000000 \" --adapt=min=-2,max=-1\"\n    println \"===>   test: --adapt must fail on incoherent bounds \"\n    datagen > tmp\n    zstd --adapt= tmp && die \"invalid compression parameter\"\n    zstd -f -vv --adapt=min=10,max=9 tmp && die \"--adapt must fail on incoherent bounds\"\n\n    println \"\\n===>   rsyncable mode \"\n    roundTripTest -g10M \" --rsyncable\"\n    roundTripTest -g10M \" --rsyncable --split=100K\"\n    println \"===>   test: --rsyncable must fail with --single-thread\"\n    zstd -f -vv --rsyncable --single-thread tmp && die \"--rsyncable must fail with --single-thread\"\nfi\n\nprintln \"\\n===> patch-from=origin tests\"\ndatagen -g1000 -P50 > tmp_dict\ndatagen -g1000 -P10 > tmp_patch\nzstd --patch-from=tmp_dict tmp_patch -o tmp_patch_diff\nzstd -d --patch-from=tmp_dict tmp_patch_diff -o tmp_patch_recon\n$DIFF -s tmp_patch_recon tmp_patch\nzstd -f --patch-apply=tmp_dict tmp_patch_diff -o tmp_patch_recon\n$DIFF -s tmp_patch_recon tmp_patch\n\nprintln \"\\n===> alternate syntax: patch-from origin\"\nzstd -f --patch-from tmp_dict tmp_patch -o tmp_patch_diff\nzstd -df --patch-from tmp_dict tmp_patch_diff -o tmp_patch_recon\n$DIFF -s tmp_patch_recon tmp_patch\nzstd -f --patch-apply tmp_dict tmp_patch_diff -o tmp_patch_recon\n$DIFF -s tmp_patch_recon tmp_patch\nrm -rf tmp_*\n\nprintln \"\\n===> patch-from recursive tests\"\nmkdir tmp_dir\ndatagen > tmp_dir/tmp1\ndatagen > tmp_dir/tmp2\ndatagen > tmp_dict\nzstd --patch-from=tmp_dict -r tmp_dir && die\nrm -rf tmp*\n\nprintln \"\\n===> patch-from long mode trigger larger file test\"\nif [ \"$ZSTD_LIB_EXCLUDE_COMPRESSORS_DFAST_AND_UP\" -eq \"1\" ]; then\n    # if binary tree strategies are excluded, the threshold is different\n    datagen -g10000000 > tmp_dict\n    datagen -g10000000 > tmp_patch\nelse\n    datagen -g5000000 > tmp_dict\n    datagen -g5000000 > tmp_patch\nfi\nzstd -15 --patch-from=tmp_dict tmp_patch 2>&1 | $GREP \"long mode automatically triggered\"\nrm -rf tmp*\n\nprintln \"\\n===> patch-from very large dictionary and file test\"\ndatagen -g550000000 -P0 > tmp_dict\ndatagen -g100000000 -P1 > tmp_patch\nzstd --long=30 -1f --patch-from tmp_dict tmp_patch\nzstd --long=30 -df --patch-from tmp_dict tmp_patch.zst -o tmp_patch_recon\n$DIFF -s tmp_patch_recon tmp_patch\nrm -rf tmp*\n\nprintln \"\\n===> patch-from --stream-size test\"\ndatagen -g1000 -P50 > tmp_dict\ndatagen -g1000 -P10 > tmp_patch\ncat tmp_patch | zstd -f --patch-from=tmp_dict -c -o tmp_patch_diff && die\ncat tmp_patch | zstd -f --patch-from=tmp_dict --stream-size=1000 -c -o tmp_patch_diff\nrm -rf tmp*\n\nprintln \"\\n===>   large files tests \"\n\nroundTripTest -g270000000 1\nroundTripTest -g250000000 2\nroundTripTest -g230000000 3\n\nroundTripTest -g140000000 -P60 4\nroundTripTest -g130000000 -P62 5\nroundTripTest -g120000000 -P65 6\n\nroundTripTest -g70000000 -P70 7\nroundTripTest -g60000000 -P71 8\nroundTripTest -g50000000 -P73 9\n\nroundTripTest -g35000000 -P75 10\nroundTripTest -g30000000 -P76 11\nroundTripTest -g25000000 -P78 12\n\nroundTripTest -g18000013 -P80 13\nroundTripTest -g18000014 -P80 14\nroundTripTest -g18000015 -P81 15\nroundTripTest -g18000016 -P84 16\nroundTripTest -g18000017 -P88 17\nroundTripTest -g18000018 -P94 18\nroundTripTest -g18000019 -P96 19\n\nroundTripTest -g8M \"19 --long\"\n\nroundTripTest -g5000000000 -P99 \"1 --zstd=wlog=25\"\nroundTripTest -g3700000000 -P0 \"1 --zstd=strategy=6,wlog=25\"   # ensure btlazy2 can survive an overflow rescale\n\nfileRoundTripTest -g4193M -P99 1\n\n\nprintln \"\\n===>   zstd long, long distance matching round-trip tests \"\nroundTripTest -g270000000 \"1 --single-thread --long\"\nroundTripTest -g130000000 -P60 \"5 --single-thread --long\"\nroundTripTest -g35000000 -P70 \"8 --single-thread --long\"\nroundTripTest -g18000001 -P80  \"18 --single-thread --long\"\n# Test large window logs\nroundTripTest -g700M -P50 \"1 --single-thread --long=29\"\nroundTripTest -g600M -P50 \"1 --single-thread --long --zstd=wlog=29,clog=28\"\n\n\nif [ -n \"$hasMT\" ]\nthen\n    println \"\\n===>   zstdmt long round-trip tests \"\n    roundTripTest -g80000000 -P99 \"19 -T2\" \" \"\n    roundTripTest -g5000000000 -P99 \"1 -T2\" \" \"\n    roundTripTest -g500000000 -P97 \"1 -T999\" \" \"\n    fileRoundTripTest -g4103M -P98 \" -T0\" \" \"\n    roundTripTest -g400000000 -P97 \"1 --long=24 -T2\" \" \"\n    # Exposes the bug in https://github.com/facebook/zstd/pull/1678\n    # This test fails on 4 different travis builds at the time of writing\n    # because it needs to allocate 8 GB of memory.\n    # roundTripTest -g10G -P99 \"1 -T1 --long=31 --zstd=clog=27 --fast=1000\"\nelse\n    println \"\\n**** no multithreading, skipping zstdmt tests **** \"\nfi\n\n\nprintln \"\\n===>  cover dictionary builder : advanced options \"\n\nTESTFILE=\"$PRGDIR\"/zstdcli.c\ndatagen > tmpDict\nprintln \"- Create first dictionary\"\nzstd -T0 --train-cover=k=46,d=8,split=80 \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c -o tmpDict\ncp \"$TESTFILE\" tmp\nzstd -f tmp -D tmpDict\nzstd -f tmp -D tmpDict --patch-from=tmpDict && die \"error: can't use -D and --patch-from=#at the same time\"\nzstd -d tmp.zst -D tmpDict -fo result\n$DIFF \"$TESTFILE\" result\nzstd -T0 --train-cover=k=56,d=8 && die \"Create dictionary without input file (should error)\"\nprintln \"- Create second (different) dictionary\"\nzstd -T0 --train-cover=k=56,d=8 \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c \"$PRGDIR\"/*.h -o tmpDictC\nzstd -d tmp.zst -D tmpDictC -fo result && die \"wrong dictionary not detected!\"\nprintln \"- Create dictionary using shrink-dict flag\"\nzstd -T0 --train-cover=steps=256,shrink \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c --dictID=1 -o tmpShrinkDict\nzstd -T0 --train-cover=steps=256,shrink=1 \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c --dictID=1 -o tmpShrinkDict1\nzstd -T0 --train-cover=steps=256,shrink=5 \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c --dictID=1 -o tmpShrinkDict2\nzstd -T0 --train-cover=shrink=5,steps=256 \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c --dictID=1 -o tmpShrinkDict3\nprintln \"- Create dictionary with short dictID\"\nzstd -T0 --train-cover=k=46,d=8,split=80 \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c --dictID=1 -o tmpDict1\ncmp tmpDict tmpDict1 && die \"dictionaries should have different ID !\"\nprintln \"- Create dictionary with size limit\"\nzstd -T0 --train-cover=steps=8 \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c -o tmpDict2 --maxdict=4K\nprintln \"- Compare size of dictionary from 90% training samples with 80% training samples\"\nzstd -T0 --train-cover=split=90 -r \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c\nzstd -T0 --train-cover=split=80 -r \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c\nprintln \"- Create dictionary using all samples for both training and testing\"\nzstd -T0 --train-cover=split=100 -r \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c\nprintln \"- Test -o before --train-cover\"\nrm -f tmpDict dictionary\nzstd -o tmpDict --train-cover \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c\ntest -f tmpDict\nzstd -T0 --train-cover \"$TESTDIR\"/*.c \"$PRGDIR\"/*.c\ntest -f dictionary\nrm -f tmp* dictionary\n\nrm -f tmp*\n"
  },
  {
    "path": "tests/poolTests.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n#include \"pool.h\"\n#include \"threading.h\"\n#include \"util.h\"\n#include \"timefn.h\"\n#include <stddef.h>\n#include <stdio.h>\n\n#define ASSERT_TRUE(p)                                                       \\\n  do {                                                                       \\\n    if (!(p)) {                                                              \\\n      return 1;                                                              \\\n    }                                                                        \\\n  } while (0)\n#define ASSERT_FALSE(p) ASSERT_TRUE(!(p))\n#define ASSERT_EQ(lhs, rhs) ASSERT_TRUE((lhs) == (rhs))\n\nstruct data {\n  ZSTD_pthread_mutex_t mutex;\n  unsigned data[16];\n  size_t i;\n};\n\nstatic void fn(void *opaque)\n{\n  struct data *data = (struct data *)opaque;\n  ZSTD_pthread_mutex_lock(&data->mutex);\n  data->data[data->i] = (unsigned)(data->i);\n  ++data->i;\n  ZSTD_pthread_mutex_unlock(&data->mutex);\n}\n\nstatic int testOrder(size_t numThreads, size_t queueSize)\n{\n  struct data data;\n  POOL_ctx* const ctx = POOL_create(numThreads, queueSize);\n  ASSERT_TRUE(ctx);\n  data.i = 0;\n  ASSERT_FALSE(ZSTD_pthread_mutex_init(&data.mutex, NULL));\n  { size_t i;\n    for (i = 0; i < 16; ++i) {\n      POOL_add(ctx, &fn, &data);\n    }\n  }\n  POOL_free(ctx);\n  ASSERT_EQ(16, data.i);\n  { size_t i;\n    for (i = 0; i < data.i; ++i) {\n      ASSERT_EQ(i, data.data[i]);\n    }\n  }\n  ZSTD_pthread_mutex_destroy(&data.mutex);\n  return 0;\n}\n\n\n/* --- test deadlocks --- */\n\nstatic void waitFn(void *opaque) {\n  (void)opaque;\n  UTIL_sleepMilli(1);\n}\n\n/* Tests for deadlock */\nstatic int testWait(size_t numThreads, size_t queueSize) {\n  struct data data;\n  POOL_ctx* const ctx = POOL_create(numThreads, queueSize);\n  ASSERT_TRUE(ctx);\n  { size_t i;\n    for (i = 0; i < 16; ++i) {\n        POOL_add(ctx, &waitFn, &data);\n    }\n  }\n  POOL_free(ctx);\n  return 0;\n}\n\n\n/* --- test POOL_resize() --- */\n\ntypedef struct {\n    ZSTD_pthread_mutex_t mut;\n    int countdown;\n    int val;\n    int max;\n    ZSTD_pthread_cond_t cond;\n} poolTest_t;\n\nstatic void waitLongFn(void *opaque) {\n  poolTest_t* const test = (poolTest_t*) opaque;\n  ZSTD_pthread_mutex_lock(&test->mut);\n  test->val++;\n  if (test->val > test->max)\n      test->max = test->val;\n  ZSTD_pthread_mutex_unlock(&test->mut);\n\n  UTIL_sleepMilli(10);\n\n  ZSTD_pthread_mutex_lock(&test->mut);\n  test->val--;\n  test->countdown--;\n  if (test->countdown == 0)\n      ZSTD_pthread_cond_signal(&test->cond);\n  ZSTD_pthread_mutex_unlock(&test->mut);\n}\n\nstatic int testThreadReduction_internal(POOL_ctx* ctx, poolTest_t test)\n{\n    int const nbWaits = 16;\n\n    test.countdown = nbWaits;\n    test.val = 0;\n    test.max = 0;\n\n    {   int i;\n        for (i=0; i<nbWaits; i++)\n            POOL_add(ctx, &waitLongFn, &test);\n    }\n    ZSTD_pthread_mutex_lock(&test.mut);\n    while (test.countdown > 0)\n        ZSTD_pthread_cond_wait(&test.cond, &test.mut);\n    ASSERT_EQ(test.val, 0);\n    ASSERT_EQ(test.max, 4);\n    ZSTD_pthread_mutex_unlock(&test.mut);\n\n    ASSERT_EQ( POOL_resize(ctx, 2/*nbThreads*/) , 0 );\n    test.countdown = nbWaits;\n    test.val = 0;\n    test.max = 0;\n    {   int i;\n        for (i=0; i<nbWaits; i++)\n            POOL_add(ctx, &waitLongFn, &test);\n    }\n    ZSTD_pthread_mutex_lock(&test.mut);\n    while (test.countdown > 0)\n        ZSTD_pthread_cond_wait(&test.cond, &test.mut);\n    ASSERT_EQ(test.val, 0);\n    ASSERT_EQ(test.max, 2);\n    ZSTD_pthread_mutex_unlock(&test.mut);\n\n    return 0;\n}\n\nstatic int testThreadReduction(void) {\n    int result;\n    poolTest_t test;\n    POOL_ctx* const ctx = POOL_create(4 /*nbThreads*/, 2 /*queueSize*/);\n\n    ASSERT_TRUE(ctx);\n\n    memset(&test, 0, sizeof(test));\n    ASSERT_FALSE( ZSTD_pthread_mutex_init(&test.mut, NULL) );\n    ASSERT_FALSE( ZSTD_pthread_cond_init(&test.cond, NULL) );\n\n    result = testThreadReduction_internal(ctx, test);\n\n    ZSTD_pthread_mutex_destroy(&test.mut);\n    ZSTD_pthread_cond_destroy(&test.cond);\n    POOL_free(ctx);\n\n    return result;\n}\n\n\n/* --- test abrupt ending --- */\n\ntypedef struct {\n    ZSTD_pthread_mutex_t mut;\n    int val;\n} abruptEndCanary_t;\n\nstatic void waitIncFn(void *opaque) {\n  abruptEndCanary_t* test = (abruptEndCanary_t*) opaque;\n  UTIL_sleepMilli(10);\n  ZSTD_pthread_mutex_lock(&test->mut);\n  test->val = test->val + 1;\n  ZSTD_pthread_mutex_unlock(&test->mut);\n}\n\nstatic int testAbruptEnding_internal(abruptEndCanary_t test)\n{\n    int const nbWaits = 16;\n\n    POOL_ctx* const ctx = POOL_create(3 /*numThreads*/, nbWaits /*queueSize*/);\n    ASSERT_TRUE(ctx);\n    test.val = 0;\n\n    {   int i;\n        for (i=0; i<nbWaits; i++)\n            POOL_add(ctx, &waitIncFn, &test);  /* all jobs pushed into queue */\n    }\n    ASSERT_EQ( POOL_resize(ctx, 1 /*numThreads*/) , 0 );   /* downsize numThreads, to try to break end condition */\n\n    POOL_free(ctx);  /* must finish all jobs in queue before giving back control */\n    ASSERT_EQ(test.val, nbWaits);\n    return 0;\n}\n\nstatic int testAbruptEnding(void) {\n    int result;\n    abruptEndCanary_t test;\n\n    memset(&test, 0, sizeof(test));\n    ASSERT_FALSE( ZSTD_pthread_mutex_init(&test.mut, NULL) );\n\n    result = testAbruptEnding_internal(test);\n\n    ZSTD_pthread_mutex_destroy(&test.mut);\n    return result;\n}\n\n\n\n/* --- test launcher --- */\n\nint main(int argc, const char **argv) {\n  size_t numThreads;\n  (void)argc;\n  (void)argv;\n\n  if (POOL_create(0, 1)) {   /* should not be possible */\n    printf(\"FAIL: should not create POOL with 0 threads\\n\");\n    return 1;\n  }\n\n  for (numThreads = 1; numThreads <= 4; ++numThreads) {\n    size_t queueSize;\n    for (queueSize = 0; queueSize <= 2; ++queueSize) {\n      printf(\"queueSize==%u, numThreads=%u \\n\",\n            (unsigned)queueSize, (unsigned)numThreads);\n      if (testOrder(numThreads, queueSize)) {\n        printf(\"FAIL: testOrder\\n\");\n        return 1;\n      }\n      printf(\"SUCCESS: testOrder\\n\");\n      if (testWait(numThreads, queueSize)) {\n        printf(\"FAIL: testWait\\n\");\n        return 1;\n      }\n      printf(\"SUCCESS: testWait\\n\");\n    }\n  }\n\n  if (testThreadReduction()) {\n      printf(\"FAIL: thread reduction not effective \\n\");\n      return 1;\n  } else {\n      printf(\"SUCCESS: thread reduction effective \\n\");\n  }\n\n  if (testAbruptEnding()) {\n      printf(\"FAIL: jobs in queue not completed on early end \\n\");\n      return 1;\n  } else {\n      printf(\"SUCCESS: all jobs in queue completed on early end \\n\");\n  }\n\n  printf(\"PASS: all POOL tests\\n\");\n\n  return 0;\n}\n"
  },
  {
    "path": "tests/rateLimiter.py",
    "content": "#!/usr/bin/env python3\n\n# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ##########################################################################\n\n# Rate limiter, replacement for pv\n# this rate limiter does not \"catch up\" after a blocking period\n# Limitations:\n# - only accepts limit speed in MB/s\n\nimport sys\nimport time\n\nMB = 1024 * 1024\nrate = float(sys.argv[1]) * MB\nstart = time.time()\ntotal_read = 0\n\n# sys.stderr.close()  # remove error message, for Ctrl+C\n\ntry:\n  buf = \" \"\n  while len(buf):\n    now = time.time()\n    to_read = max(int(rate * (now - start)), 1)\n    max_buf_size = 1 * MB\n    to_read = min(to_read, max_buf_size)\n    start = now\n\n    buf = sys.stdin.buffer.read(to_read)\n    sys.stdout.buffer.write(buf)\n\nexcept (KeyboardInterrupt, BrokenPipeError) as e:\n    pass\n"
  },
  {
    "path": "tests/regression/.gitignore",
    "content": "# regression test artifacts\ndata-cache\ncache\ntest\n"
  },
  {
    "path": "tests/regression/Makefile",
    "content": "# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ################################################################\n\nCFLAGS ?= -O3\n\nCURL_CFLAGS := $(shell curl-config --cflags)\nCURL_LDFLAGS := $(shell curl-config --libs) -pthread\n\nPROGDIR := ../../programs\nLIBDIR := ../../lib\nZSTD_CPPFLAGS := -I$(PROGDIR) -I$(LIBDIR) -I$(LIBDIR)/common -Wno-deprecated-declarations\n\nREGRESSION_CFLAGS = $(CFLAGS) $(CURL_CFLAGS)\nREGRESSION_CPPFLAGS = $(CPPFLAGS) $(ZSTD_CPPFLAGS)\nREGRESSION_LDFLAGS = $(LDFLAGS) $(CURL_LDFLAGS)\n\nall: test\n\nxxhash.o: $(LIBDIR)/common/xxhash.c $(LIBDIR)/common/xxhash.h\n\t$(CC) $(REGRESSION_CFLAGS) $(REGRESSION_CPPFLAGS) $< -c -o $@\n\nutil.o: $(PROGDIR)/util.c $(PROGDIR)/util.h\n\t$(CC) $(REGRESSION_CFLAGS) $(REGRESSION_CPPFLAGS) $< -c -o $@\n\ndata.o: data.c data.h $(PROGDIR)/util.h $(LIBDIR)/common/xxhash.h\n\t$(CC) $(REGRESSION_CFLAGS) $(REGRESSION_CPPFLAGS) $< -c -o $@\n\nconfig.o: config.c config.h levels.h\n\t$(CC) $(REGRESSION_CFLAGS) $(REGRESSION_CPPFLAGS) $< -c -o $@\n\nmethod.h: data.h config.h result.h\n\nmethod.o: method.c method.h\n\t$(CC) $(REGRESSION_CFLAGS) $(REGRESSION_CPPFLAGS) $< -c -o $@\n\nresult.o: result.c result.h\n\t$(CC) $(REGRESSION_CFLAGS) $(REGRESSION_CPPFLAGS) $< -c -o $@\n\ntest.o: test.c data.h config.h method.h\n\t$(CC) $(REGRESSION_CFLAGS) $(REGRESSION_CPPFLAGS) $< -c -o $@\n\n.PHONY: libzstd.a\nlibzstd.a:\n\t$(MAKE) -C $(LIBDIR) libzstd.a-mt\n\tcp $(LIBDIR)/libzstd.a .\n\ntest: test.o data.o config.o util.o method.o result.o xxhash.o libzstd.a\n\t$(CC) $^ $(REGRESSION_LDFLAGS) -o $@\n\n.PHONY: clean\nclean:\n\t$(MAKE) -C $(LIBDIR) clean\n\t$(RM) *.o *.a test\n"
  },
  {
    "path": "tests/regression/README.md",
    "content": "# Regression tests\n\nThe regression tests run zstd in many scenarios and ensures that the size of the compressed results doesn't change. This helps us ensure that we don't accidentally regress zstd's compression ratio.\n\nThese tests get run every night by CircleCI. If the job fails you can read the diff printed by the job to ensure the change isn't a regression. If all is well you can download the `results.csv` artifact and commit the new results. Or you can rebuild it yourself following the instructions below.\n\n## Rebuilding results.csv\n\nFrom the root of the zstd repo run:\n\n```\n# Build the zstd binary\nmake clean\nmake -j zstd\n\n# Build the regression test binary\ncd tests/regression\nmake clean\nmake -j test\n\n# Run the regression test\n./test --cache data-cache --zstd ../../zstd --output results.csv\n\n# Check results.csv to ensure the new results are okay\ngit diff\n\n# Then submit the PR\n```\n"
  },
  {
    "path": "tests/regression/config.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"config.h\"\n\n/* Define a config for each fast level we want to test with. */\n#define FAST_LEVEL(x)                                               \\\n    param_value_t const level_fast##x##_param_values[] = {          \\\n        {.param = ZSTD_c_compressionLevel, .value = -x},            \\\n    };                                                              \\\n    config_t const level_fast##x = {                                \\\n        .name = \"level -\" #x,                                       \\\n        .cli_args = \"--fast=\" #x,                                   \\\n        .param_values = PARAM_VALUES(level_fast##x##_param_values), \\\n    };                                                              \\\n    config_t const level_fast##x##_dict = {                         \\\n        .name = \"level -\" #x \" with dict\",                          \\\n        .cli_args = \"--fast=\" #x,                                   \\\n        .param_values = PARAM_VALUES(level_fast##x##_param_values), \\\n        .use_dictionary = 1,                                        \\\n    };\n\n/* Define a config for each level we want to test with. */\n#define LEVEL(x)                                                                  \\\n    param_value_t const level_##x##_param_values[] = {                            \\\n        {.param = ZSTD_c_compressionLevel, .value = x},                           \\\n    };                                                                            \\\n    param_value_t const level_##x##_param_values_dms[] = {                        \\\n        {.param = ZSTD_c_compressionLevel, .value = x},                           \\\n        {.param = ZSTD_c_enableDedicatedDictSearch, .value = 0},                  \\\n        {.param = ZSTD_c_forceAttachDict, .value = ZSTD_dictForceAttach},         \\\n    };                                                                            \\\n    param_value_t const level_##x##_param_values_dds[] = {                        \\\n        {.param = ZSTD_c_compressionLevel, .value = x},                           \\\n        {.param = ZSTD_c_enableDedicatedDictSearch, .value = 1},                  \\\n        {.param = ZSTD_c_forceAttachDict, .value = ZSTD_dictForceAttach},         \\\n    };                                                                            \\\n    param_value_t const level_##x##_param_values_dictcopy[] = {                   \\\n        {.param = ZSTD_c_compressionLevel, .value = x},                           \\\n        {.param = ZSTD_c_enableDedicatedDictSearch, .value = 0},                  \\\n        {.param = ZSTD_c_forceAttachDict, .value = ZSTD_dictForceCopy},           \\\n    };                                                                            \\\n    param_value_t const level_##x##_param_values_dictload[] = {                   \\\n        {.param = ZSTD_c_compressionLevel, .value = x},                           \\\n        {.param = ZSTD_c_enableDedicatedDictSearch, .value = 0},                  \\\n        {.param = ZSTD_c_forceAttachDict, .value = ZSTD_dictForceLoad},           \\\n    };                                                                            \\\n    config_t const level_##x = {                                                  \\\n        .name = \"level \" #x,                                                      \\\n        .cli_args = \"-\" #x,                                                       \\\n        .param_values = PARAM_VALUES(level_##x##_param_values),                   \\\n    };                                                                            \\\n    config_t const level_##x##_dict = {                                           \\\n        .name = \"level \" #x \" with dict\",                                         \\\n        .cli_args = \"-\" #x,                                                       \\\n        .param_values = PARAM_VALUES(level_##x##_param_values),                   \\\n        .use_dictionary = 1,                                                      \\\n    };                                                                            \\\n    config_t const level_##x##_dict_dms = {                                       \\\n        .name = \"level \" #x \" with dict dms\",                                     \\\n        .cli_args = \"-\" #x,                                                       \\\n        .param_values = PARAM_VALUES(level_##x##_param_values_dms),               \\\n        .use_dictionary = 1,                                                      \\\n        .advanced_api_only = 1,                                                   \\\n    };                                                                            \\\n    config_t const level_##x##_dict_dds = {                                       \\\n        .name = \"level \" #x \" with dict dds\",                                     \\\n        .cli_args = \"-\" #x,                                                       \\\n        .param_values = PARAM_VALUES(level_##x##_param_values_dds),               \\\n        .use_dictionary = 1,                                                      \\\n        .advanced_api_only = 1,                                                   \\\n    };                                                                            \\\n    config_t const level_##x##_dict_copy = {                                      \\\n        .name = \"level \" #x \" with dict copy\",                                    \\\n        .cli_args = \"-\" #x,                                                       \\\n        .param_values = PARAM_VALUES(level_##x##_param_values_dictcopy),          \\\n        .use_dictionary = 1,                                                      \\\n        .advanced_api_only = 1,                                                   \\\n    };                                                                            \\\n    config_t const level_##x##_dict_load = {                                      \\\n        .name = \"level \" #x \" with dict load\",                                    \\\n        .cli_args = \"-\" #x,                                                       \\\n        .param_values = PARAM_VALUES(level_##x##_param_values_dictload),          \\\n        .use_dictionary = 1,                                                      \\\n        .advanced_api_only = 1,                                                   \\\n    };\n\n/* Define a config specifically to test row hash based levels and settings.\n */\n#define ROW_LEVEL(x, y)                                                            \\\n    param_value_t const row_##y##_level_##x##_param_values[] = {                   \\\n        {.param = ZSTD_c_useRowMatchFinder, .value = y},                           \\\n        {.param = ZSTD_c_compressionLevel, .value = x},                            \\\n    };                                                                             \\\n    param_value_t const row_##y##_level_##x##_param_values_dms[] = {               \\\n        {.param = ZSTD_c_useRowMatchFinder, .value = y},                           \\\n        {.param = ZSTD_c_compressionLevel, .value = x},                            \\\n        {.param = ZSTD_c_enableDedicatedDictSearch, .value = 0},                   \\\n        {.param = ZSTD_c_forceAttachDict, .value = ZSTD_dictForceAttach},          \\\n    };                                                                             \\\n    param_value_t const row_##y##_level_##x##_param_values_dds[] = {               \\\n        {.param = ZSTD_c_useRowMatchFinder, .value = y},                           \\\n        {.param = ZSTD_c_compressionLevel, .value = x},                            \\\n        {.param = ZSTD_c_enableDedicatedDictSearch, .value = 1},                   \\\n        {.param = ZSTD_c_forceAttachDict, .value = ZSTD_dictForceAttach},          \\\n    };                                                                             \\\n    param_value_t const row_##y##_level_##x##_param_values_dictcopy[] = {          \\\n        {.param = ZSTD_c_useRowMatchFinder, .value = y},                           \\\n        {.param = ZSTD_c_compressionLevel, .value = x},                            \\\n        {.param = ZSTD_c_enableDedicatedDictSearch, .value = 0},                   \\\n        {.param = ZSTD_c_forceAttachDict, .value = ZSTD_dictForceCopy},            \\\n    };                                                                             \\\n    param_value_t const row_##y##_level_##x##_param_values_dictload[] = {          \\\n        {.param = ZSTD_c_useRowMatchFinder, .value = y},                           \\\n        {.param = ZSTD_c_compressionLevel, .value = x},                            \\\n        {.param = ZSTD_c_enableDedicatedDictSearch, .value = 0},                   \\\n        {.param = ZSTD_c_forceAttachDict, .value = ZSTD_dictForceLoad},            \\\n    };                                                                             \\\n    config_t const row_##y##_level_##x = {                                         \\\n        .name = \"level \" #x \" row \" #y,                                            \\\n        .cli_args = \"-\" #x,                                                        \\\n        .param_values = PARAM_VALUES(row_##y##_level_##x##_param_values),          \\\n        .advanced_api_only = 1,                                                    \\\n    };                                                                             \\\n    config_t const row_##y##_level_##x##_dict_dms = {                              \\\n        .name = \"level \" #x \" row \" #y \" with dict dms\",                           \\\n        .cli_args = \"-\" #x,                                                        \\\n        .param_values = PARAM_VALUES(row_##y##_level_##x##_param_values_dms),      \\\n        .use_dictionary = 1,                                                       \\\n        .advanced_api_only = 1,                                                    \\\n    };                                                                             \\\n    config_t const row_##y##_level_##x##_dict_dds = {                              \\\n        .name = \"level \" #x \" row \" #y \" with dict dds\",                           \\\n        .cli_args = \"-\" #x,                                                        \\\n        .param_values = PARAM_VALUES(row_##y##_level_##x##_param_values_dds),      \\\n        .use_dictionary = 1,                                                       \\\n        .advanced_api_only = 1,                                                    \\\n    };                                                                             \\\n    config_t const row_##y##_level_##x##_dict_copy = {                             \\\n        .name = \"level \" #x \" row \" #y\" with dict copy\",                          \\\n        .cli_args = \"-\" #x,                                                        \\\n        .param_values = PARAM_VALUES(row_##y##_level_##x##_param_values_dictcopy), \\\n        .use_dictionary = 1,                                                       \\\n        .advanced_api_only = 1,                                                    \\\n    };                                                                             \\\n    config_t const row_##y##_level_##x##_dict_load = {                             \\\n        .name = \"level \" #x \" row \" #y \" with dict load\",                          \\\n        .cli_args = \"-\" #x,                                                        \\\n        .param_values = PARAM_VALUES(row_##y##_level_##x##_param_values_dictload), \\\n        .use_dictionary = 1,                                                       \\\n        .advanced_api_only = 1,                                                    \\\n    };\n\n#define PARAM_VALUES(pv) \\\n    { .data = pv, .size = sizeof(pv) / sizeof((pv)[0]) }\n\n#include \"levels.h\"\n\n#undef LEVEL\n#undef FAST_LEVEL\n#undef ROW_LEVEL\n\nstatic config_t no_pledged_src_size = {\n    .name = \"no source size\",\n    .cli_args = \"\",\n    .param_values = PARAM_VALUES(level_0_param_values),\n    .no_pledged_src_size = 1,\n};\n\nstatic config_t no_pledged_src_size_with_dict = {\n    .name = \"no source size with dict\",\n    .cli_args = \"\",\n    .param_values = PARAM_VALUES(level_0_param_values),\n    .no_pledged_src_size = 1,\n    .use_dictionary = 1,\n};\n\nstatic param_value_t const ldm_param_values[] = {\n    {.param = ZSTD_c_enableLongDistanceMatching, .value = ZSTD_ps_enable},\n};\n\nstatic config_t ldm = {\n    .name = \"long distance mode\",\n    .cli_args = \"--long\",\n    .param_values = PARAM_VALUES(ldm_param_values),\n};\n\nstatic param_value_t const mt_param_values[] = {\n    {.param = ZSTD_c_nbWorkers, .value = 2},\n};\n\nstatic config_t mt = {\n    .name = \"multithreaded\",\n    .cli_args = \"-T2\",\n    .param_values = PARAM_VALUES(mt_param_values),\n};\n\nstatic param_value_t const mt_ldm_param_values[] = {\n    {.param = ZSTD_c_nbWorkers, .value = 2},\n    {.param = ZSTD_c_enableLongDistanceMatching, .value = ZSTD_ps_enable},\n};\n\nstatic config_t mt_ldm = {\n    .name = \"multithreaded long distance mode\",\n    .cli_args = \"-T2 --long\",\n    .param_values = PARAM_VALUES(mt_ldm_param_values),\n};\n\nstatic param_value_t mt_advanced_param_values[] = {\n    {.param = ZSTD_c_nbWorkers, .value = 2},\n    {.param = ZSTD_c_literalCompressionMode, .value = ZSTD_ps_disable},\n};\n\nstatic config_t mt_advanced = {\n    .name = \"multithreaded with advanced params\",\n    .cli_args = \"-T2 --no-compress-literals\",\n    .param_values = PARAM_VALUES(mt_advanced_param_values),\n};\n\nstatic param_value_t const small_wlog_param_values[] = {\n    {.param = ZSTD_c_windowLog, .value = 10},\n};\n\nstatic config_t small_wlog = {\n    .name = \"small window log\",\n    .cli_args = \"--zstd=wlog=10\",\n    .param_values = PARAM_VALUES(small_wlog_param_values),\n};\n\nstatic param_value_t const small_hlog_param_values[] = {\n    {.param = ZSTD_c_hashLog, .value = 6},\n    {.param = ZSTD_c_strategy, .value = (int)ZSTD_btopt},\n};\n\nstatic config_t small_hlog = {\n    .name = \"small hash log\",\n    .cli_args = \"--zstd=hlog=6,strat=7\",\n    .param_values = PARAM_VALUES(small_hlog_param_values),\n};\n\nstatic param_value_t const small_clog_param_values[] = {\n    {.param = ZSTD_c_chainLog, .value = 6},\n    {.param = ZSTD_c_strategy, .value = (int)ZSTD_btopt},\n};\n\nstatic config_t small_clog = {\n    .name = \"small chain log\",\n    .cli_args = \"--zstd=clog=6,strat=7\",\n    .param_values = PARAM_VALUES(small_clog_param_values),\n};\n\nstatic param_value_t const uncompressed_literals_param_values[] = {\n    {.param = ZSTD_c_compressionLevel, .value = 3},\n    {.param = ZSTD_c_literalCompressionMode, .value = ZSTD_ps_disable},\n};\n\nstatic config_t uncompressed_literals = {\n    .name = \"uncompressed literals\",\n    .cli_args = \"-3 --no-compress-literals\",\n    .param_values = PARAM_VALUES(uncompressed_literals_param_values),\n};\n\nstatic param_value_t const uncompressed_literals_opt_param_values[] = {\n    {.param = ZSTD_c_compressionLevel, .value = 19},\n    {.param = ZSTD_c_literalCompressionMode, .value = ZSTD_ps_disable},\n};\n\nstatic config_t uncompressed_literals_opt = {\n    .name = \"uncompressed literals optimal\",\n    .cli_args = \"-19 --no-compress-literals\",\n    .param_values = PARAM_VALUES(uncompressed_literals_opt_param_values),\n};\n\nstatic param_value_t const huffman_literals_param_values[] = {\n    {.param = ZSTD_c_compressionLevel, .value = -1},\n    {.param = ZSTD_c_literalCompressionMode, .value = ZSTD_ps_enable},\n};\n\nstatic config_t huffman_literals = {\n    .name = \"huffman literals\",\n    .cli_args = \"--fast=1 --compress-literals\",\n    .param_values = PARAM_VALUES(huffman_literals_param_values),\n};\n\nstatic param_value_t const explicit_params_param_values[] = {\n    {.param = ZSTD_c_checksumFlag, .value = 1},\n    {.param = ZSTD_c_contentSizeFlag, .value = 0},\n    {.param = ZSTD_c_dictIDFlag, .value = 0},\n    {.param = ZSTD_c_strategy, .value = (int)ZSTD_greedy},\n    {.param = ZSTD_c_windowLog, .value = 18},\n    {.param = ZSTD_c_hashLog, .value = 21},\n    {.param = ZSTD_c_chainLog, .value = 21},\n    {.param = ZSTD_c_targetLength, .value = 100},\n};\n\nstatic config_t explicit_params = {\n    .name = \"explicit params\",\n    .cli_args = \"--no-check --no-dictID --zstd=strategy=3,wlog=18,hlog=21,clog=21,tlen=100\",\n    .param_values = PARAM_VALUES(explicit_params_param_values),\n};\n\nstatic config_t const* g_configs[] = {\n\n#define FAST_LEVEL(x) &level_fast##x, &level_fast##x##_dict,\n#define LEVEL(x) &level_##x, &level_##x##_dict, &level_##x##_dict_dms, &level_##x##_dict_dds, &level_##x##_dict_copy, &level_##x##_dict_load,\n#define ROW_LEVEL(x, y) &row_##y##_level_##x, &row_##y##_level_##x##_dict_dms, &row_##y##_level_##x##_dict_dds, &row_##y##_level_##x##_dict_copy, &row_##y##_level_##x##_dict_load,\n#include \"levels.h\"\n#undef ROW_LEVEL\n#undef LEVEL\n#undef FAST_LEVEL\n\n    &no_pledged_src_size,\n    &no_pledged_src_size_with_dict,\n    &ldm,\n    &mt,\n    &mt_ldm,\n    &small_wlog,\n    &small_hlog,\n    &small_clog,\n    &explicit_params,\n    &uncompressed_literals,\n    &uncompressed_literals_opt,\n    &huffman_literals,\n    &mt_advanced,\n    NULL,\n};\n\nconfig_t const* const* configs = g_configs;\n\nint config_skip_data(config_t const* config, data_t const* data) {\n    return config->use_dictionary && !data_has_dict(data);\n}\n\nint config_get_level(config_t const* config)\n{\n    param_values_t const params = config->param_values;\n    size_t i;\n    for (i = 0; i < params.size; ++i) {\n        if (params.data[i].param == ZSTD_c_compressionLevel)\n            return (int)params.data[i].value;\n    }\n    return CONFIG_NO_LEVEL;\n}\n\nZSTD_parameters config_get_zstd_params(\n    config_t const* config,\n    uint64_t srcSize,\n    size_t dictSize)\n{\n    ZSTD_parameters zparams = {};\n    param_values_t const params = config->param_values;\n    int level = config_get_level(config);\n    if (level == CONFIG_NO_LEVEL)\n        level = 3;\n    zparams = ZSTD_getParams(\n        level,\n        config->no_pledged_src_size ? ZSTD_CONTENTSIZE_UNKNOWN : srcSize,\n        dictSize);\n    for (size_t i = 0; i < params.size; ++i) {\n        unsigned const value = params.data[i].value;\n        switch (params.data[i].param) {\n            case ZSTD_c_contentSizeFlag:\n                zparams.fParams.contentSizeFlag = value;\n                break;\n            case ZSTD_c_checksumFlag:\n                zparams.fParams.checksumFlag = value;\n                break;\n            case ZSTD_c_dictIDFlag:\n                zparams.fParams.noDictIDFlag = !value;\n                break;\n            case ZSTD_c_windowLog:\n                zparams.cParams.windowLog = value;\n                break;\n            case ZSTD_c_chainLog:\n                zparams.cParams.chainLog = value;\n                break;\n            case ZSTD_c_hashLog:\n                zparams.cParams.hashLog = value;\n                break;\n            case ZSTD_c_searchLog:\n                zparams.cParams.searchLog = value;\n                break;\n            case ZSTD_c_minMatch:\n                zparams.cParams.minMatch = value;\n                break;\n            case ZSTD_c_targetLength:\n                zparams.cParams.targetLength = value;\n                break;\n            case ZSTD_c_strategy:\n                zparams.cParams.strategy = (ZSTD_strategy)value;\n                break;\n            default:\n                break;\n        }\n    }\n    return zparams;\n}\n"
  },
  {
    "path": "tests/regression/config.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef CONFIG_H\n#define CONFIG_H\n\n#include <stddef.h>\n\n#define ZSTD_STATIC_LINKING_ONLY\n#include <zstd.h>\n\n#include \"data.h\"\n\ntypedef struct {\n    ZSTD_cParameter param;\n    int value;\n} param_value_t;\n\ntypedef struct {\n    size_t size;\n    param_value_t const* data;\n} param_values_t;\n\n/**\n * The config tells the compression method what options to use.\n */\ntypedef struct {\n    const char* name;  /**< Identifies the config in the results table */\n    /**\n     * Optional arguments to pass to the CLI. If not set, CLI-based methods\n     * will skip this config.\n     */\n    char const* cli_args;\n    /**\n     * Parameters to pass to the advanced API. If the advanced API isn't used,\n     * the parameters will be derived from these.\n     */\n    param_values_t param_values;\n    /**\n     * Boolean parameter that says if we should use a dictionary. If the data\n     * doesn't have a dictionary, this config is skipped. Defaults to no.\n     */\n    int use_dictionary;\n    /**\n     * Boolean parameter that says if we should pass the pledged source size\n     * when the method allows it. Defaults to yes.\n     */\n    int no_pledged_src_size;\n    /**\n     * Boolean parameter that says that this config should only be used\n     * for methods that use the advanced compression API\n     */\n    int advanced_api_only;\n} config_t;\n\n/**\n * Returns true if the config should skip this data.\n * For instance, if the config requires a dictionary but the data doesn't have\n * one.\n */\nint config_skip_data(config_t const* config, data_t const* data);\n\n#define CONFIG_NO_LEVEL (-ZSTD_TARGETLENGTH_MAX - 1)\n/**\n * Returns the compression level specified by the config, or CONFIG_NO_LEVEL if\n * no level is specified. Note that 0 is a valid compression level, meaning\n * default.\n */\nint config_get_level(config_t const* config);\n\n/**\n * Returns the compression parameters specified by the config.\n */\nZSTD_parameters config_get_zstd_params(\n    config_t const* config,\n    uint64_t srcSize,\n    size_t dictSize);\n\n/**\n * The NULL-terminated list of configs.\n */\nextern config_t const* const* configs;\n\n#endif\n"
  },
  {
    "path": "tests/regression/data.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"data.h\"\n\n#include <assert.h>\n#include <errno.h>\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>   /* free() */\n\n#include <sys/stat.h>\n\n#include <curl/curl.h>\n\n#include \"mem.h\"\n#include \"util.h\"\n#define XXH_STATIC_LINKING_ONLY\n#include \"xxhash.h\"\n\n/**\n * Data objects\n */\n\n#define REGRESSION_RELEASE(x) \\\n    \"https://github.com/facebook/zstd/releases/download/regression-data/\" x\n\ndata_t silesia = {\n    .name = \"silesia\",\n    .type = data_type_dir,\n    .data =\n        {\n            .url = REGRESSION_RELEASE(\"silesia.tar.zst\"),\n            .xxhash64 = 0x48a199f92f93e977LL,\n        },\n};\n\ndata_t silesia_tar = {\n    .name = \"silesia.tar\",\n    .type = data_type_file,\n    .data =\n        {\n            .url = REGRESSION_RELEASE(\"silesia.tar.zst\"),\n            .xxhash64 = 0x48a199f92f93e977LL,\n        },\n};\n\ndata_t github = {\n    .name = \"github\",\n    .type = data_type_dir,\n    .data =\n        {\n            .url = REGRESSION_RELEASE(\"github.tar.zst\"),\n            .xxhash64 = 0xa9b1b44b020df292LL,\n        },\n    .dict =\n        {\n            .url = REGRESSION_RELEASE(\"github.dict.zst\"),\n            .xxhash64 = 0x1eddc6f737d3cb53LL,\n\n        },\n};\n\ndata_t github_tar = {\n    .name = \"github.tar\",\n    .type = data_type_file,\n    .data =\n        {\n            .url = REGRESSION_RELEASE(\"github.tar.zst\"),\n            .xxhash64 = 0xa9b1b44b020df292LL,\n        },\n    .dict =\n        {\n            .url = REGRESSION_RELEASE(\"github.dict.zst\"),\n            .xxhash64 = 0x1eddc6f737d3cb53LL,\n\n        },\n};\n\nstatic data_t* g_data[] = {\n    &silesia,\n    &silesia_tar,\n    &github,\n    &github_tar,\n    NULL,\n};\n\ndata_t const* const* data = (data_t const* const*)g_data;\n\n/**\n * data helpers.\n */\n\nint data_has_dict(data_t const* data) {\n    return data->dict.url != NULL;\n}\n\n/**\n * data buffer helper functions (documented in header).\n */\n\ndata_buffer_t data_buffer_create(size_t const capacity) {\n    data_buffer_t buffer = {};\n\n    buffer.data = (uint8_t*)malloc(capacity);\n    if (buffer.data == NULL)\n        return buffer;\n    buffer.capacity = capacity;\n    return buffer;\n}\n\ndata_buffer_t data_buffer_read(char const* filename) {\n    data_buffer_t buffer = {};\n\n    uint64_t const size = UTIL_getFileSize(filename);\n    if (size == UTIL_FILESIZE_UNKNOWN) {\n        fprintf(stderr, \"unknown size for %s\\n\", filename);\n        return buffer;\n    }\n\n    buffer.data = (uint8_t*)malloc(size);\n    if (buffer.data == NULL) {\n        fprintf(stderr, \"malloc failed\\n\");\n        return buffer;\n    }\n    buffer.capacity = size;\n\n    FILE* file = fopen(filename, \"rb\");\n    if (file == NULL) {\n        fprintf(stderr, \"file null\\n\");\n        goto err;\n    }\n    buffer.size = fread(buffer.data, 1, buffer.capacity, file);\n    fclose(file);\n    if (buffer.size != buffer.capacity) {\n        fprintf(stderr, \"read %zu != %zu\\n\", buffer.size, buffer.capacity);\n        goto err;\n    }\n\n    return buffer;\nerr:\n    free(buffer.data);\n    memset(&buffer, 0, sizeof(buffer));\n    return buffer;\n}\n\ndata_buffer_t data_buffer_get_data(data_t const* data) {\n    data_buffer_t const kEmptyBuffer = {};\n\n    if (data->type != data_type_file)\n        return kEmptyBuffer;\n\n    return data_buffer_read(data->data.path);\n}\n\ndata_buffer_t data_buffer_get_dict(data_t const* data) {\n    data_buffer_t const kEmptyBuffer = {};\n\n    if (!data_has_dict(data))\n        return kEmptyBuffer;\n\n    return data_buffer_read(data->dict.path);\n}\n\nint data_buffer_compare(data_buffer_t buffer1, data_buffer_t buffer2) {\n    size_t const size =\n        buffer1.size < buffer2.size ? buffer1.size : buffer2.size;\n    int const cmp = memcmp(buffer1.data, buffer2.data, size);\n    if (cmp != 0)\n        return cmp;\n    if (buffer1.size < buffer2.size)\n        return -1;\n    if (buffer1.size == buffer2.size)\n        return 0;\n    assert(buffer1.size > buffer2.size);\n    return 1;\n}\n\nvoid data_buffer_free(data_buffer_t buffer) {\n    free(buffer.data);\n}\n\n/**\n * data filenames helpers.\n */\n\nFileNamesTable* data_filenames_get(data_t const* data)\n{\n    char const* const path = data->data.path;\n    return UTIL_createExpandedFNT(&path, 1, 0 /* followLinks */ );\n}\n\n/**\n * data buffers helpers.\n */\n\ndata_buffers_t data_buffers_get(data_t const* data) {\n    data_buffers_t buffers = {.size = 0};\n    FileNamesTable* const filenames = data_filenames_get(data);\n    if (filenames == NULL) return buffers;\n    if (filenames->tableSize == 0) {\n        UTIL_freeFileNamesTable(filenames);\n        return buffers;\n    }\n\n    data_buffer_t* buffersPtr =\n        (data_buffer_t*)malloc(filenames->tableSize * sizeof(*buffersPtr));\n    if (buffersPtr == NULL) {\n        UTIL_freeFileNamesTable(filenames);\n        return buffers;\n    }\n    buffers.buffers = (data_buffer_t const*)buffersPtr;\n    buffers.size = filenames->tableSize;\n\n    for (size_t i = 0; i < filenames->tableSize; ++i) {\n        buffersPtr[i] = data_buffer_read(filenames->fileNames[i]);\n        if (buffersPtr[i].data == NULL) {\n            data_buffers_t const kEmptyBuffer = {};\n            data_buffers_free(buffers);\n            UTIL_freeFileNamesTable(filenames);\n            return kEmptyBuffer;\n        }\n    }\n\n    UTIL_freeFileNamesTable(filenames);\n    return buffers;\n}\n\n/**\n * Frees the data buffers.\n */\nvoid data_buffers_free(data_buffers_t buffers) {\n    free((data_buffer_t*)buffers.buffers);\n}\n\n/**\n * Initialization and download functions.\n */\n\nstatic char* g_data_dir = NULL;\n\n/* mkdir -p */\nstatic int ensure_directory_exists(char const* indir) {\n    char* const dir = strdup(indir);\n    char* end = dir;\n    int ret = 0;\n    if (dir == NULL) {\n        ret = EINVAL;\n        goto out;\n    }\n    do {\n        /* Find the next directory level. */\n        for (++end; *end != '\\0' && *end != '/'; ++end)\n            ;\n        /* End the string there, make the directory, and restore the string. */\n        char const save = *end;\n        *end = '\\0';\n        int const isdir = UTIL_isDirectory(dir);\n        ret = mkdir(dir, S_IRWXU);\n        *end = save;\n        /* Its okay if the directory already exists. */\n        if (ret == 0 || (errno == EEXIST && isdir))\n            continue;\n        ret = errno;\n        fprintf(stderr, \"mkdir() failed\\n\");\n        goto out;\n    } while (*end != '\\0');\n\n    ret = 0;\nout:\n    free(dir);\n    return ret;\n}\n\n/** Concatenate 3 strings into a new buffer. */\nstatic char* cat3(char const* str1, char const* str2, char const* str3) {\n    size_t const size1 = strlen(str1);\n    size_t const size2 = strlen(str2);\n    size_t const size3 = str3 == NULL ? 0 : strlen(str3);\n    size_t const size = size1 + size2 + size3 + 1;\n    char* const dst = (char*)malloc(size);\n    if (dst == NULL)\n        return NULL;\n    strcpy(dst, str1);\n    strcpy(dst + size1, str2);\n    if (str3 != NULL)\n        strcpy(dst + size1 + size2, str3);\n    assert(strlen(dst) == size1 + size2 + size3);\n    return dst;\n}\n\nstatic char* cat2(char const* str1, char const* str2) {\n    return cat3(str1, str2, NULL);\n}\n\n/**\n * State needed by the curl callback.\n * It takes data from curl, hashes it, and writes it to the file.\n */\ntypedef struct {\n    FILE* file;\n    XXH64_state_t xxhash64;\n    int error;\n} curl_data_t;\n\n/** Create the curl state. */\nstatic curl_data_t curl_data_create(\n    data_resource_t const* resource,\n    data_type_t type) {\n    curl_data_t cdata = {};\n\n    XXH64_reset(&cdata.xxhash64, 0);\n\n    assert(UTIL_isDirectory(g_data_dir));\n\n    if (type == data_type_file) {\n        /* Decompress the resource and store to the path. */\n        char* cmd = cat3(\"zstd -dqfo '\", resource->path, \"'\");\n        if (cmd == NULL) {\n            cdata.error = ENOMEM;\n            return cdata;\n        }\n        cdata.file = popen(cmd, \"w\");\n        free(cmd);\n    } else {\n        /* Decompress and extract the resource to the cache directory. */\n        char* cmd = cat3(\"zstd -dc | tar -x -C '\", g_data_dir, \"'\");\n        if (cmd == NULL) {\n            cdata.error = ENOMEM;\n            return cdata;\n        }\n        cdata.file = popen(cmd, \"w\");\n        free(cmd);\n    }\n    if (cdata.file == NULL) {\n        cdata.error = errno;\n    }\n\n    return cdata;\n}\n\n/** Free the curl state. */\nstatic int curl_data_free(curl_data_t cdata) {\n    return pclose(cdata.file);\n}\n\n/** curl callback. Updates the hash, and writes to the file. */\nstatic size_t curl_write(void* data, size_t size, size_t count, void* ptr) {\n    curl_data_t* cdata = (curl_data_t*)ptr;\n    size_t const written = fwrite(data, size, count, cdata->file);\n    XXH64_update(&cdata->xxhash64, data, written * size);\n    return written;\n}\n\nstatic int curl_download_resource(\n    CURL* curl,\n    data_resource_t const* resource,\n    data_type_t type) {\n    curl_data_t cdata;\n    /* Download the data. */\n    if (curl_easy_setopt(curl, CURLOPT_URL, resource->url) != 0)\n        return EINVAL;\n    if (curl_easy_setopt(curl, CURLOPT_WRITEDATA, &cdata) != 0)\n        return EINVAL;\n    cdata = curl_data_create(resource, type);\n    if (cdata.error != 0)\n        return cdata.error;\n    int const curl_err = curl_easy_perform(curl);\n    int const close_err = curl_data_free(cdata);\n    if (curl_err) {\n        fprintf(\n            stderr,\n            \"downloading '%s' for '%s' failed\\n\",\n            resource->url,\n            resource->path);\n        return EIO;\n    }\n    if (close_err) {\n        fprintf(stderr, \"writing data to '%s' failed\\n\", resource->path);\n        return EIO;\n    }\n    /* check that the file exists. */\n    if (type == data_type_file && !UTIL_isRegularFile(resource->path)) {\n        fprintf(stderr, \"output file '%s' does not exist\\n\", resource->path);\n        return EIO;\n    }\n    if (type == data_type_dir && !UTIL_isDirectory(resource->path)) {\n        fprintf(\n            stderr, \"output directory '%s' does not exist\\n\", resource->path);\n        return EIO;\n    }\n    /* Check that the hash matches. */\n    if (XXH64_digest(&cdata.xxhash64) != resource->xxhash64) {\n        fprintf(\n            stderr,\n            \"checksum does not match: 0x%llxLL != 0x%llxLL\\n\",\n            (unsigned long long)XXH64_digest(&cdata.xxhash64),\n            (unsigned long long)resource->xxhash64);\n        return EINVAL;\n    }\n\n    return 0;\n}\n\n/** Download a single data object. */\nstatic int curl_download_datum(CURL* curl, data_t const* data) {\n    int ret;\n    ret = curl_download_resource(curl, &data->data, data->type);\n    if (ret != 0)\n        return ret;\n    if (data_has_dict(data)) {\n        ret = curl_download_resource(curl, &data->dict, data_type_file);\n        if (ret != 0)\n            return ret;\n    }\n    return ret;\n}\n\n/** Download all the data. */\nstatic int curl_download_data(data_t const* const* data) {\n    if (curl_global_init(CURL_GLOBAL_ALL) != 0)\n        return EFAULT;\n\n    curl_data_t cdata = {};\n    CURL* curl = curl_easy_init();\n    int err = EFAULT;\n\n    if (curl == NULL)\n        return EFAULT;\n\n    if (curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L) != 0)\n        goto out;\n    if (curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L) != 0)\n        goto out;\n    if (curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write) != 0)\n        goto out;\n\n    assert(data != NULL);\n    for (; *data != NULL; ++data) {\n        if (curl_download_datum(curl, *data) != 0)\n            goto out;\n    }\n\n    err = 0;\nout:\n    curl_easy_cleanup(curl);\n    curl_global_cleanup();\n    return err;\n}\n\n/** Fill the path member variable of the data objects. */\nstatic int data_create_paths(data_t* const* data, char const* dir) {\n    size_t const dirlen = strlen(dir);\n    assert(data != NULL);\n    for (; *data != NULL; ++data) {\n        data_t* const datum = *data;\n        datum->data.path = cat3(dir, \"/\", datum->name);\n        if (datum->data.path == NULL)\n            return ENOMEM;\n        if (data_has_dict(datum)) {\n            datum->dict.path = cat2(datum->data.path, \".dict\");\n            if (datum->dict.path == NULL)\n                return ENOMEM;\n        }\n    }\n    return 0;\n}\n\n/** Free the path member variable of the data objects. */\nstatic void data_free_paths(data_t* const* data) {\n    assert(data != NULL);\n    for (; *data != NULL; ++data) {\n        data_t* datum = *data;\n        free((void*)datum->data.path);\n        free((void*)datum->dict.path);\n        datum->data.path = NULL;\n        datum->dict.path = NULL;\n    }\n}\n\nstatic char const kStampName[] = \"STAMP\";\n\nstatic void xxh_update_le(XXH64_state_t* state, uint64_t data) {\n    if (!MEM_isLittleEndian())\n        data = MEM_swap64(data);\n    XXH64_update(state, &data, sizeof(data));\n}\n\n/** Hash the data to create the stamp. */\nstatic uint64_t stamp_hash(data_t const* const* data) {\n    XXH64_state_t state;\n\n    XXH64_reset(&state, 0);\n    assert(data != NULL);\n    for (; *data != NULL; ++data) {\n        data_t const* datum = *data;\n        /* We don't care about the URL that we fetch from. */\n        /* The path is derived from the name. */\n        XXH64_update(&state, datum->name, strlen(datum->name));\n        xxh_update_le(&state, datum->data.xxhash64);\n        xxh_update_le(&state, datum->dict.xxhash64);\n        xxh_update_le(&state, datum->type);\n    }\n    return XXH64_digest(&state);\n}\n\n/** Check if the stamp matches the stamp in the cache directory. */\nstatic int stamp_check(char const* dir, data_t const* const* data) {\n    char* stamp = cat3(dir, \"/\", kStampName);\n    uint64_t const expected = stamp_hash(data);\n    XXH64_canonical_t actual;\n    FILE* stampfile = NULL;\n    int matches = 0;\n\n    if (stamp == NULL)\n        goto out;\n    if (!UTIL_isRegularFile(stamp)) {\n        fprintf(stderr, \"stamp does not exist: recreating the data cache\\n\");\n        goto out;\n    }\n\n    stampfile = fopen(stamp, \"rb\");\n    if (stampfile == NULL) {\n        fprintf(stderr, \"could not open stamp: recreating the data cache\\n\");\n        goto out;\n    }\n\n    size_t b;\n    if ((b = fread(&actual, sizeof(actual), 1, stampfile)) != 1) {\n        fprintf(stderr, \"invalid stamp: recreating the data cache\\n\");\n        goto out;\n    }\n\n    matches = (expected == XXH64_hashFromCanonical(&actual));\n    if (matches)\n        fprintf(stderr, \"stamp matches: reusing the cached data\\n\");\n    else\n        fprintf(stderr, \"stamp does not match: recreating the data cache\\n\");\n\nout:\n    free(stamp);\n    if (stampfile != NULL)\n        fclose(stampfile);\n    return matches;\n}\n\n/** On success write a new stamp, on failure delete the old stamp. */\nstatic int\nstamp_write(char const* dir, data_t const* const* data, int const data_err) {\n    char* stamp = cat3(dir, \"/\", kStampName);\n    FILE* stampfile = NULL;\n    int err = EIO;\n\n    if (stamp == NULL)\n        return ENOMEM;\n\n    if (data_err != 0) {\n        err = data_err;\n        goto out;\n    }\n    XXH64_canonical_t hash;\n\n    XXH64_canonicalFromHash(&hash, stamp_hash(data));\n\n    stampfile = fopen(stamp, \"wb\");\n    if (stampfile == NULL)\n        goto out;\n    if (fwrite(&hash, sizeof(hash), 1, stampfile) != 1)\n        goto out;\n    err = 0;\n    fprintf(stderr, \"stamped new data cache\\n\");\nout:\n    if (err != 0)\n        /* Ignore errors. */\n        unlink(stamp);\n    free(stamp);\n    if (stampfile != NULL)\n        fclose(stampfile);\n    return err;\n}\n\nint data_init(char const* dir) {\n    int err;\n\n    if (dir == NULL)\n        return EINVAL;\n\n    /* This must be first to simplify logic. */\n    err = ensure_directory_exists(dir);\n    if (err != 0)\n        return err;\n\n    /* Save the cache directory. */\n    g_data_dir = strdup(dir);\n    if (g_data_dir == NULL)\n        return ENOMEM;\n\n    err = data_create_paths(g_data, dir);\n    if (err != 0)\n        return err;\n\n    /* If the stamp matches then we are good to go.\n     * This must be called before any modifications to the data cache.\n     * After this point, we MUST call stamp_write() to update the STAMP,\n     * since we've updated the data cache.\n     */\n    if (stamp_check(dir, data))\n        return 0;\n\n    err = curl_download_data(data);\n    if (err != 0)\n        goto out;\n\nout:\n    /* This must be last, since it must know if data_init() succeeded. */\n    stamp_write(dir, data, err);\n    return err;\n}\n\nvoid data_finish(void) {\n    data_free_paths(g_data);\n    free(g_data_dir);\n    g_data_dir = NULL;\n}\n"
  },
  {
    "path": "tests/regression/data.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef DATA_H\n#define DATA_H\n\n#include <stddef.h>\n#include <stdint.h>\n\ntypedef enum {\n    data_type_file = 1,  /**< This data is a file. *.zst */\n    data_type_dir = 2,   /**< This data is a directory. *.tar.zst */\n} data_type_t;\n\ntypedef struct {\n    char const* url;   /**< Where to get this resource. */\n    uint64_t xxhash64; /**< Hash of the url contents. */\n    char const* path;  /**< The path of the unpacked resource (derived). */\n} data_resource_t;\n\ntypedef struct {\n    data_resource_t data;\n    data_resource_t dict;\n    data_type_t type;  /**< The type of the data. */\n    char const* name;  /**< The logical name of the data (no extension). */\n} data_t;\n\n/**\n * The NULL-terminated list of data objects.\n */\nextern data_t const* const* data;\n\n\nint data_has_dict(data_t const* data);\n\n/**\n * Initializes the data module and downloads the data necessary.\n * Caches the downloads in dir. We add a stamp file in the directory after\n * a successful download. If a stamp file already exists, and matches our\n * current data stamp, we will use the cached data without downloading.\n *\n * @param dir The directory to cache the downloaded data into.\n *\n * @returns 0 on success.\n */\nint data_init(char const* dir);\n\n/**\n * Must be called at exit to free resources allocated by data_init().\n */\nvoid data_finish(void);\n\ntypedef struct {\n    uint8_t* data;\n    size_t size;\n    size_t capacity;\n} data_buffer_t;\n\n/**\n * Read the file that data points to into a buffer.\n * NOTE: data must be a file, not a directory.\n *\n * @returns The buffer, which is NULL on failure.\n */\ndata_buffer_t data_buffer_get_data(data_t const* data);\n\n/**\n * Read the dictionary that the data points to into a buffer.\n *\n * @returns The buffer, which is NULL on failure.\n */\ndata_buffer_t data_buffer_get_dict(data_t const* data);\n\n/**\n * Read the contents of filename into a buffer.\n *\n * @returns The buffer, which is NULL on failure.\n */\ndata_buffer_t data_buffer_read(char const* filename);\n\n/**\n * Create a buffer with the specified capacity.\n *\n * @returns The buffer, which is NULL on failure.\n */\ndata_buffer_t data_buffer_create(size_t capacity);\n\n/**\n * Calls memcmp() on the contents [0, size) of both buffers.\n */\nint data_buffer_compare(data_buffer_t buffer1, data_buffer_t buffer2);\n\n/**\n * Frees an allocated buffer.\n */\nvoid data_buffer_free(data_buffer_t buffer);\n\n\ntypedef struct {\n    data_buffer_t const* buffers;\n    size_t size;\n} data_buffers_t;\n\n/**\n * @returns a list of buffers for every file in data. It is zero sized on error.\n */\ndata_buffers_t data_buffers_get(data_t const* data);\n\n/**\n * Frees the data buffers.\n */\nvoid data_buffers_free(data_buffers_t buffers);\n\n#endif\n"
  },
  {
    "path": "tests/regression/levels.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef LEVEL\n# error LEVEL(x) must be defined\n#endif\n#ifndef FAST_LEVEL\n# error FAST_LEVEL(x) must be defined\n#endif\n#ifndef ROW_LEVEL\n# error ROW_LEVEL(x, y) must be defined\n#endif\n\n/**\n * The levels are chosen to trigger every strategy in every source size,\n * as well as some fast levels and the default level.\n * If you change the compression levels, you should probably update these.\n */\n\nFAST_LEVEL(5)\n\nFAST_LEVEL(3)\n\nFAST_LEVEL(1)\nLEVEL(0)\nLEVEL(1)\n\nLEVEL(3)\nLEVEL(4)\n/* ROW_LEVEL triggers the row hash (force enabled and disabled) with different\n * dictionary strategies, and 16/32/64 row entries based on the level/searchLog.\n * 1 == enabled, 2 == disabled.\n */\nROW_LEVEL(5, 1)\nROW_LEVEL(5, 2) /* 16-entry rows */\nLEVEL(5)\nLEVEL(6)\nROW_LEVEL(7, 1)\nROW_LEVEL(7, 2) /* 16-entry rows */\nLEVEL(7)\n\nLEVEL(9)\n\nROW_LEVEL(11, 1)\nROW_LEVEL(11, 2) /* 32-entry rows */\nROW_LEVEL(12, 1)\nROW_LEVEL(12, 2) /* 64-entry rows */\nLEVEL(13)\n\nLEVEL(16)\n\nLEVEL(19)\n"
  },
  {
    "path": "tests/regression/method.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"method.h\"\n\n#include <stdio.h>\n#include <stdlib.h>\n\n#define ZSTD_STATIC_LINKING_ONLY\n#include <zstd.h>\n\n#define MIN(x, y) ((x) < (y) ? (x) : (y))\n\nstatic char const* g_zstdcli = NULL;\n\nvoid method_set_zstdcli(char const* zstdcli) {\n    g_zstdcli = zstdcli;\n}\n\n/**\n * Macro to get a pointer of type, given ptr, which is a member variable with\n * the given name, member.\n *\n *     method_state_t* base = ...;\n *     buffer_state_t* state = container_of(base, buffer_state_t, base);\n */\n#define container_of(ptr, type, member) \\\n    ((type*)(ptr == NULL ? NULL : (char*)(ptr)-offsetof(type, member)))\n\n/** State to reuse the same buffers between compression calls. */\ntypedef struct {\n    method_state_t base;\n    data_buffers_t inputs; /**< The input buffer for each file. */\n    data_buffer_t dictionary; /**< The dictionary. */\n    data_buffer_t compressed; /**< The compressed data buffer. */\n    data_buffer_t decompressed; /**< The decompressed data buffer. */\n} buffer_state_t;\n\nstatic size_t buffers_max_size(data_buffers_t buffers) {\n    size_t max = 0;\n    for (size_t i = 0; i < buffers.size; ++i) {\n        if (buffers.buffers[i].size > max)\n            max = buffers.buffers[i].size;\n    }\n    return max;\n}\n\nstatic method_state_t* buffer_state_create(data_t const* data) {\n    buffer_state_t* state = (buffer_state_t*)calloc(1, sizeof(buffer_state_t));\n    if (state == NULL)\n        return NULL;\n    state->base.data = data;\n    state->inputs = data_buffers_get(data);\n    state->dictionary = data_buffer_get_dict(data);\n    size_t const max_size = buffers_max_size(state->inputs);\n    state->compressed = data_buffer_create(ZSTD_compressBound(max_size));\n    state->decompressed = data_buffer_create(max_size);\n    return &state->base;\n}\n\nstatic void buffer_state_destroy(method_state_t* base) {\n    if (base == NULL)\n        return;\n    buffer_state_t* state = container_of(base, buffer_state_t, base);\n    free(state);\n}\n\nstatic int buffer_state_bad(\n    buffer_state_t const* state,\n    config_t const* config) {\n    if (state == NULL) {\n        fprintf(stderr, \"buffer_state_t is NULL\\n\");\n        return 1;\n    }\n    if (state->inputs.size == 0 || state->compressed.data == NULL ||\n        state->decompressed.data == NULL) {\n        fprintf(stderr, \"buffer state allocation failure\\n\");\n        return 1;\n    }\n    if (config->use_dictionary && state->dictionary.data == NULL) {\n        fprintf(stderr, \"dictionary loading failed\\n\");\n        return 1;\n    }\n    return 0;\n}\n\nstatic result_t simple_compress(method_state_t* base, config_t const* config) {\n    buffer_state_t* state = container_of(base, buffer_state_t, base);\n\n    if (buffer_state_bad(state, config))\n        return result_error(result_error_system_error);\n\n    /* Keep the tests short by skipping directories, since behavior shouldn't\n     * change.\n     */\n    if (base->data->type != data_type_file)\n        return result_error(result_error_skip);\n    \n    if (config->advanced_api_only)\n        return result_error(result_error_skip);\n\n    if (config->use_dictionary || config->no_pledged_src_size)\n        return result_error(result_error_skip);\n\n    /* If the config doesn't specify a level, skip. */\n    int const level = config_get_level(config);\n    if (level == CONFIG_NO_LEVEL)\n        return result_error(result_error_skip);\n\n    data_buffer_t const input = state->inputs.buffers[0];\n\n    /* Compress, decompress, and check the result. */\n    state->compressed.size = ZSTD_compress(\n        state->compressed.data,\n        state->compressed.capacity,\n        input.data,\n        input.size,\n        level);\n    if (ZSTD_isError(state->compressed.size))\n        return result_error(result_error_compression_error);\n\n    state->decompressed.size = ZSTD_decompress(\n        state->decompressed.data,\n        state->decompressed.capacity,\n        state->compressed.data,\n        state->compressed.size);\n    if (ZSTD_isError(state->decompressed.size))\n        return result_error(result_error_decompression_error);\n    if (data_buffer_compare(input, state->decompressed))\n        return result_error(result_error_round_trip_error);\n\n    result_data_t data;\n    data.total_size = state->compressed.size;\n    return result_data(data);\n}\n\nstatic result_t compress_cctx_compress(\n    method_state_t* base,\n    config_t const* config) {\n    buffer_state_t* state = container_of(base, buffer_state_t, base);\n\n    if (buffer_state_bad(state, config))\n        return result_error(result_error_system_error);\n\n    if (config->no_pledged_src_size)\n        return result_error(result_error_skip);\n\n    if (base->data->type != data_type_dir)\n        return result_error(result_error_skip);\n    \n    if (config->advanced_api_only)\n        return result_error(result_error_skip);\n\n    int const level = config_get_level(config);\n    result_t result;\n    ZSTD_CCtx* cctx = ZSTD_createCCtx();\n    ZSTD_DCtx* dctx = ZSTD_createDCtx();\n    if (cctx == NULL || dctx == NULL) {\n        fprintf(stderr, \"context creation failed\\n\");\n        result = result_error(result_error_system_error);\n        goto out;\n    }\n\n    result_data_t data = {.total_size = 0};\n    for (size_t i = 0; i < state->inputs.size; ++i) {\n        data_buffer_t const input = state->inputs.buffers[i];\n        ZSTD_parameters const params =\n            config_get_zstd_params(config, input.size, state->dictionary.size);\n\n        if (level == CONFIG_NO_LEVEL)\n            state->compressed.size = ZSTD_compress_advanced(\n                cctx,\n                state->compressed.data,\n                state->compressed.capacity,\n                input.data,\n                input.size,\n                config->use_dictionary ? state->dictionary.data : NULL,\n                config->use_dictionary ? state->dictionary.size : 0,\n                params);\n        else if (config->use_dictionary)\n            state->compressed.size = ZSTD_compress_usingDict(\n                cctx,\n                state->compressed.data,\n                state->compressed.capacity,\n                input.data,\n                input.size,\n                state->dictionary.data,\n                state->dictionary.size,\n                level);\n        else\n            state->compressed.size = ZSTD_compressCCtx(\n                cctx,\n                state->compressed.data,\n                state->compressed.capacity,\n                input.data,\n                input.size,\n                level);\n\n        if (ZSTD_isError(state->compressed.size)) {\n            result = result_error(result_error_compression_error);\n            goto out;\n        }\n\n        if (config->use_dictionary)\n            state->decompressed.size = ZSTD_decompress_usingDict(\n                dctx,\n                state->decompressed.data,\n                state->decompressed.capacity,\n                state->compressed.data,\n                state->compressed.size,\n                state->dictionary.data,\n                state->dictionary.size);\n        else\n            state->decompressed.size = ZSTD_decompressDCtx(\n                dctx,\n                state->decompressed.data,\n                state->decompressed.capacity,\n                state->compressed.data,\n                state->compressed.size);\n        if (ZSTD_isError(state->decompressed.size)) {\n            result = result_error(result_error_decompression_error);\n            goto out;\n        }\n        if (data_buffer_compare(input, state->decompressed)) {\n            result = result_error(result_error_round_trip_error);\n            goto out;\n        }\n\n        data.total_size += state->compressed.size;\n    }\n\n    result = result_data(data);\nout:\n    ZSTD_freeCCtx(cctx);\n    ZSTD_freeDCtx(dctx);\n    return result;\n}\n\n/** Generic state creation function. */\nstatic method_state_t* method_state_create(data_t const* data) {\n    method_state_t* state = (method_state_t*)malloc(sizeof(method_state_t));\n    if (state == NULL)\n        return NULL;\n    state->data = data;\n    return state;\n}\n\nstatic void method_state_destroy(method_state_t* state) {\n    free(state);\n}\n\nstatic result_t cli_compress(method_state_t* state, config_t const* config) {\n    if (config->cli_args == NULL)\n        return result_error(result_error_skip);\n\n    if (config->advanced_api_only)\n        return result_error(result_error_skip);\n\n    /* We don't support no pledged source size with directories. Too slow. */\n    if (state->data->type == data_type_dir && config->no_pledged_src_size)\n        return result_error(result_error_skip);\n\n    if (g_zstdcli == NULL)\n        return result_error(result_error_system_error);\n\n    /* '<zstd>' -cqr <args> [-D '<dict>'] '<file/dir>' */\n    char cmd[1024];\n    size_t const cmd_size = snprintf(\n        cmd,\n        sizeof(cmd),\n        \"'%s' -cqr %s %s%s%s %s '%s'\",\n        g_zstdcli,\n        config->cli_args,\n        config->use_dictionary ? \"-D '\" : \"\",\n        config->use_dictionary ? state->data->dict.path : \"\",\n        config->use_dictionary ? \"'\" : \"\",\n        config->no_pledged_src_size ? \"<\" : \"\",\n        state->data->data.path);\n    if (cmd_size >= sizeof(cmd)) {\n        fprintf(stderr, \"command too large: %s\\n\", cmd);\n        return result_error(result_error_system_error);\n    }\n    FILE* zstd = popen(cmd, \"r\");\n    if (zstd == NULL) {\n        fprintf(stderr, \"failed to popen command: %s\\n\", cmd);\n        return result_error(result_error_system_error);\n    }\n\n    char out[4096];\n    size_t total_size = 0;\n    while (1) {\n        size_t const size = fread(out, 1, sizeof(out), zstd);\n        total_size += size;\n        if (size != sizeof(out))\n            break;\n    }\n    if (ferror(zstd) || pclose(zstd) != 0) {\n        fprintf(stderr, \"zstd failed with command: %s\\n\", cmd);\n        return result_error(result_error_compression_error);\n    }\n\n    result_data_t const data = {.total_size = total_size};\n    return result_data(data);\n}\n\nstatic int advanced_config(\n    ZSTD_CCtx* cctx,\n    buffer_state_t* state,\n    config_t const* config) {\n    ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n    for (size_t p = 0; p < config->param_values.size; ++p) {\n        param_value_t const pv = config->param_values.data[p];\n        if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, pv.param, pv.value))) {\n            return 1;\n        }\n    }\n    if (config->use_dictionary) {\n        if (ZSTD_isError(ZSTD_CCtx_loadDictionary(\n                cctx, state->dictionary.data, state->dictionary.size))) {\n            return 1;\n        }\n    }\n    return 0;\n}\n\nstatic result_t advanced_one_pass_compress_output_adjustment(\n    method_state_t* base,\n    config_t const* config,\n    size_t const subtract) {\n    buffer_state_t* state = container_of(base, buffer_state_t, base);\n\n    if (buffer_state_bad(state, config))\n        return result_error(result_error_system_error);\n\n    ZSTD_CCtx* cctx = ZSTD_createCCtx();\n    result_t result;\n\n    if (!cctx || advanced_config(cctx, state, config)) {\n        result = result_error(result_error_compression_error);\n        goto out;\n    }\n\n    result_data_t data = {.total_size = 0};\n    for (size_t i = 0; i < state->inputs.size; ++i) {\n        data_buffer_t const input = state->inputs.buffers[i];\n\n        if (!config->no_pledged_src_size) {\n            if (ZSTD_isError(ZSTD_CCtx_setPledgedSrcSize(cctx, input.size))) {\n                result = result_error(result_error_compression_error);\n                goto out;\n            }\n        }\n        size_t const size = ZSTD_compress2(\n            cctx,\n            state->compressed.data,\n            ZSTD_compressBound(input.size) - subtract,\n            input.data,\n            input.size);\n        if (ZSTD_isError(size)) {\n            result = result_error(result_error_compression_error);\n            goto out;\n        }\n        data.total_size += size;\n    }\n\n    result = result_data(data);\nout:\n    ZSTD_freeCCtx(cctx);\n    return result;\n}\n\nstatic result_t advanced_one_pass_compress(\n    method_state_t* base,\n    config_t const* config) {\n  return advanced_one_pass_compress_output_adjustment(base, config, 0);\n}\n\nstatic result_t advanced_one_pass_compress_small_output(\n    method_state_t* base,\n    config_t const* config) {\n  return advanced_one_pass_compress_output_adjustment(base, config, 1);\n}\n\nstatic result_t advanced_streaming_compress(\n    method_state_t* base,\n    config_t const* config) {\n    buffer_state_t* state = container_of(base, buffer_state_t, base);\n\n    if (buffer_state_bad(state, config))\n        return result_error(result_error_system_error);\n\n    ZSTD_CCtx* cctx = ZSTD_createCCtx();\n    result_t result;\n\n    if (!cctx || advanced_config(cctx, state, config)) {\n        result = result_error(result_error_compression_error);\n        goto out;\n    }\n\n    result_data_t data = {.total_size = 0};\n    for (size_t i = 0; i < state->inputs.size; ++i) {\n        data_buffer_t input = state->inputs.buffers[i];\n\n        if (!config->no_pledged_src_size) {\n            if (ZSTD_isError(ZSTD_CCtx_setPledgedSrcSize(cctx, input.size))) {\n                result = result_error(result_error_compression_error);\n                goto out;\n            }\n        }\n\n        while (input.size > 0) {\n            ZSTD_inBuffer in = {input.data, MIN(input.size, 4096)};\n            input.data += in.size;\n            input.size -= in.size;\n            ZSTD_EndDirective const op =\n                input.size > 0 ? ZSTD_e_continue : ZSTD_e_end;\n            size_t ret = 0;\n            while (in.pos < in.size || (op == ZSTD_e_end && ret != 0)) {\n                ZSTD_outBuffer out = {state->compressed.data,\n                                      MIN(state->compressed.capacity, 1024)};\n                ret = ZSTD_compressStream2(cctx, &out, &in, op);\n                if (ZSTD_isError(ret)) {\n                    result = result_error(result_error_compression_error);\n                    goto out;\n                }\n                data.total_size += out.pos;\n            }\n        }\n    }\n\n    result = result_data(data);\nout:\n    ZSTD_freeCCtx(cctx);\n    return result;\n}\n\nstatic int init_cstream(\n    buffer_state_t* state,\n    ZSTD_CStream* zcs,\n    config_t const* config,\n    int const advanced,\n    ZSTD_CDict** cdict)\n{\n    size_t zret;\n    if (advanced) {\n        ZSTD_parameters const params = config_get_zstd_params(config, 0, 0);\n        ZSTD_CDict* dict = NULL;\n        if (cdict) {\n            if (!config->use_dictionary)\n              return 1;\n            *cdict = ZSTD_createCDict_advanced(\n                state->dictionary.data,\n                state->dictionary.size,\n                ZSTD_dlm_byRef,\n                ZSTD_dct_auto,\n                params.cParams,\n                ZSTD_defaultCMem);\n            if (!*cdict) {\n                return 1;\n            }\n            zret = ZSTD_initCStream_usingCDict_advanced(\n                zcs, *cdict, params.fParams, ZSTD_CONTENTSIZE_UNKNOWN);\n        } else {\n            zret = ZSTD_initCStream_advanced(\n                zcs,\n                config->use_dictionary ? state->dictionary.data : NULL,\n                config->use_dictionary ? state->dictionary.size : 0,\n                params,\n                ZSTD_CONTENTSIZE_UNKNOWN);\n        }\n    } else {\n        int const level = config_get_level(config);\n        if (level == CONFIG_NO_LEVEL)\n            return 1;\n        if (cdict) {\n            if (!config->use_dictionary)\n              return 1;\n            *cdict = ZSTD_createCDict(\n                state->dictionary.data,\n                state->dictionary.size,\n                level);\n            if (!*cdict) {\n                return 1;\n            }\n            zret = ZSTD_initCStream_usingCDict(zcs, *cdict);\n        } else if (config->use_dictionary) {\n            zret = ZSTD_initCStream_usingDict(\n                zcs,\n                state->dictionary.data,\n                state->dictionary.size,\n                level);\n        } else {\n            zret = ZSTD_initCStream(zcs, level);\n        }\n    }\n    if (ZSTD_isError(zret)) {\n        return 1;\n    }\n    return 0;\n}\n\nstatic result_t old_streaming_compress_internal(\n    method_state_t* base,\n    config_t const* config,\n    int const advanced,\n    int const cdict) {\n  buffer_state_t* state = container_of(base, buffer_state_t, base);\n\n  if (buffer_state_bad(state, config))\n    return result_error(result_error_system_error);\n\n\n  ZSTD_CStream* zcs = ZSTD_createCStream();\n  ZSTD_CDict* cd = NULL;\n  result_t result;\n  if (zcs == NULL) {\n    result = result_error(result_error_compression_error);\n    goto out;\n  }\n  if (!advanced && config_get_level(config) == CONFIG_NO_LEVEL) {\n    result = result_error(result_error_skip);\n    goto out;\n  }\n  if (cdict && !config->use_dictionary) {\n    result = result_error(result_error_skip);\n    goto out;\n  }\n  if (config->advanced_api_only) {\n    result = result_error(result_error_skip);\n    goto out;\n  }\n  if (init_cstream(state, zcs, config, advanced, cdict ? &cd : NULL)) {\n    result = result_error(result_error_compression_error);\n    goto out;\n  }\n\n  result_data_t data = {.total_size = 0};\n  for (size_t i = 0; i < state->inputs.size; ++i) {\n    data_buffer_t input = state->inputs.buffers[i];\n    size_t zret = ZSTD_resetCStream(\n        zcs,\n        config->no_pledged_src_size ? ZSTD_CONTENTSIZE_UNKNOWN : input.size);\n    if (ZSTD_isError(zret)) {\n      result = result_error(result_error_compression_error);\n      goto out;\n    }\n\n    while (input.size > 0) {\n      ZSTD_inBuffer in = {input.data, MIN(input.size, 4096)};\n      input.data += in.size;\n      input.size -= in.size;\n      ZSTD_EndDirective const op =\n          input.size > 0 ? ZSTD_e_continue : ZSTD_e_end;\n      zret = 0;\n      while (in.pos < in.size || (op == ZSTD_e_end && zret != 0)) {\n        ZSTD_outBuffer out = {state->compressed.data,\n                              MIN(state->compressed.capacity, 1024)};\n        if (op == ZSTD_e_continue || in.pos < in.size)\n          zret = ZSTD_compressStream(zcs, &out, &in);\n        else\n          zret = ZSTD_endStream(zcs, &out);\n        if (ZSTD_isError(zret)) {\n          result = result_error(result_error_compression_error);\n          goto out;\n        }\n        data.total_size += out.pos;\n      }\n    }\n  }\n\n  result = result_data(data);\nout:\n    ZSTD_freeCStream(zcs);\n    ZSTD_freeCDict(cd);\n    return result;\n}\n\nstatic result_t old_streaming_compress(\n    method_state_t* base,\n    config_t const* config)\n{\n    return old_streaming_compress_internal(\n        base, config, /* advanced */ 0, /* cdict */ 0);\n}\n\nstatic result_t old_streaming_compress_advanced(\n    method_state_t* base,\n    config_t const* config)\n{\n    return old_streaming_compress_internal(\n        base, config, /* advanced */ 1, /* cdict */ 0);\n}\n\nstatic result_t old_streaming_compress_cdict(\n    method_state_t* base,\n    config_t const* config)\n{\n    return old_streaming_compress_internal(\n        base, config, /* advanced */ 0, /* cdict */ 1);\n}\n\nstatic result_t old_streaming_compress_cdict_advanced(\n    method_state_t* base,\n    config_t const* config)\n{\n    return old_streaming_compress_internal(\n        base, config, /* advanced */ 1, /* cdict */ 1);\n}\n\nmethod_t const simple = {\n    .name = \"compress simple\",\n    .create = buffer_state_create,\n    .compress = simple_compress,\n    .destroy = buffer_state_destroy,\n};\n\nmethod_t const compress_cctx = {\n    .name = \"compress cctx\",\n    .create = buffer_state_create,\n    .compress = compress_cctx_compress,\n    .destroy = buffer_state_destroy,\n};\n\nmethod_t const advanced_one_pass = {\n    .name = \"advanced one pass\",\n    .create = buffer_state_create,\n    .compress = advanced_one_pass_compress,\n    .destroy = buffer_state_destroy,\n};\n\nmethod_t const advanced_one_pass_small_out = {\n    .name = \"advanced one pass small out\",\n    .create = buffer_state_create,\n    .compress = advanced_one_pass_compress,\n    .destroy = buffer_state_destroy,\n};\n\nmethod_t const advanced_streaming = {\n    .name = \"advanced streaming\",\n    .create = buffer_state_create,\n    .compress = advanced_streaming_compress,\n    .destroy = buffer_state_destroy,\n};\n\nmethod_t const old_streaming = {\n    .name = \"old streaming\",\n    .create = buffer_state_create,\n    .compress = old_streaming_compress,\n    .destroy = buffer_state_destroy,\n};\n\nmethod_t const old_streaming_advanced = {\n    .name = \"old streaming advanced\",\n    .create = buffer_state_create,\n    .compress = old_streaming_compress_advanced,\n    .destroy = buffer_state_destroy,\n};\n\nmethod_t const old_streaming_cdict = {\n    .name = \"old streaming cdict\",\n    .create = buffer_state_create,\n    .compress = old_streaming_compress_cdict,\n    .destroy = buffer_state_destroy,\n};\n\nmethod_t const old_streaming_advanced_cdict = {\n    .name = \"old streaming advanced cdict\",\n    .create = buffer_state_create,\n    .compress = old_streaming_compress_cdict_advanced,\n    .destroy = buffer_state_destroy,\n};\n\nmethod_t const cli = {\n    .name = \"zstdcli\",\n    .create = method_state_create,\n    .compress = cli_compress,\n    .destroy = method_state_destroy,\n};\n\nstatic method_t const* g_methods[] = {\n    &simple,\n    &compress_cctx,\n    &cli,\n    &advanced_one_pass,\n    &advanced_one_pass_small_out,\n    &advanced_streaming,\n    &old_streaming,\n    &old_streaming_advanced,\n    &old_streaming_cdict,\n    &old_streaming_advanced_cdict,\n    NULL,\n};\n\nmethod_t const* const* methods = g_methods;\n"
  },
  {
    "path": "tests/regression/method.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef METHOD_H\n#define METHOD_H\n\n#include <stddef.h>\n\n#include \"data.h\"\n#include \"config.h\"\n#include \"result.h\"\n\n/**\n * The base class for state that methods keep.\n * All derived method state classes must have a member of this type.\n */\ntypedef struct {\n    data_t const* data;\n} method_state_t;\n\n/**\n * A method that compresses the data using config.\n */\ntypedef struct {\n    char const* name;  /**< The identifier for this method in the results. */\n    /**\n     * Creates a state that must contain a member variable of method_state_t,\n     * and returns a pointer to that member variable.\n     *\n     * This method can be used to do expensive work that only depends on the\n     * data, like loading the data file into a buffer.\n     */\n    method_state_t* (*create)(data_t const* data);\n    /**\n     * Compresses the data in the state using the given config.\n     *\n     * @param state A pointer to the state returned by create().\n     *\n     * @returns The total compressed size on success, or an error code.\n     */\n    result_t (*compress)(method_state_t* state, config_t const* config);\n    /**\n     * Frees the state.\n     */\n    void (*destroy)(method_state_t* state);\n} method_t;\n\n/**\n * Set the zstd cli path. Must be called before any methods are used.\n */\nvoid method_set_zstdcli(char const* zstdcli);\n\n/**\n * A NULL-terminated list of methods.\n */\nextern method_t const* const* methods;\n\n#endif\n"
  },
  {
    "path": "tests/regression/result.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"result.h\"\n\nconst char* result_get_error_string(result_t result) {\n    switch (result_get_error(result)) {\n        case result_error_ok:\n            return \"okay\";\n        case result_error_skip:\n            return \"skip\";\n        case result_error_system_error:\n            return \"system error\";\n        case result_error_compression_error:\n            return \"compression error\";\n        case result_error_decompression_error:\n            return \"decompression error\";\n        case result_error_round_trip_error:\n            return \"round trip error\";\n        default:\n            return \"unknown error\";\n    }\n}\n"
  },
  {
    "path": "tests/regression/result.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef RESULT_H\n#define RESULT_H\n\n#include <stddef.h>\n\n/**\n * The error type enum.\n */\ntypedef enum {\n    result_error_ok,                   /**< No error. */\n    result_error_skip,                 /**< This method was skipped. */\n    result_error_system_error,         /**< Some internal error happened. */\n    result_error_compression_error,    /**< Compression failed. */\n    result_error_decompression_error,  /**< Decompression failed. */\n    result_error_round_trip_error,     /**< Data failed to round trip. */\n} result_error_t;\n\n/**\n * The success type.\n */\ntypedef struct {\n    size_t total_size;  /**< The total compressed size. */\n} result_data_t;\n\n/**\n * The result type.\n * Do not access the member variables directory, use the helper functions.\n */\ntypedef struct {\n    result_error_t internal_error;\n    result_data_t internal_data;\n} result_t;\n\n/**\n * Create a result of the error type.\n */\nstatic result_t result_error(result_error_t error);\n/**\n * Create a result of the success type.\n */\nstatic result_t result_data(result_data_t data);\n\n/**\n * Check if the result is an error or skip.\n */\nstatic int result_is_error(result_t result);\n/**\n * Check if the result error is skip.\n */\nstatic int result_is_skip(result_t result);\n/**\n * Get the result error or okay.\n */\nstatic result_error_t result_get_error(result_t result);\n/**\n * Get the result data. The result MUST be checked with result_is_error() first.\n */\nstatic result_data_t result_get_data(result_t result);\n\nstatic result_t result_error(result_error_t error) {\n    result_t result = {\n        .internal_error = error,\n    };\n    return result;\n}\n\nstatic result_t result_data(result_data_t data) {\n    result_t result = {\n        .internal_error = result_error_ok,\n        .internal_data = data,\n    };\n    return result;\n}\n\nstatic int result_is_error(result_t result) {\n    return result_get_error(result) != result_error_ok;\n}\n\nstatic int result_is_skip(result_t result) {\n    return result_get_error(result) == result_error_skip;\n}\n\nstatic result_error_t result_get_error(result_t result) {\n    return result.internal_error;\n}\n\nconst char* result_get_error_string(result_t result);\n\nstatic result_data_t result_get_data(result_t result) {\n    return result.internal_data;\n}\n\n#endif\n"
  },
  {
    "path": "tests/regression/results.csv",
    "content": "Data,                               Config,                             Method,                             Total compressed size\nsilesia.tar,                        level -5,                           compress simple,                    6858730\nsilesia.tar,                        level -3,                           compress simple,                    6502944\nsilesia.tar,                        level -1,                           compress simple,                    6175652\nsilesia.tar,                        level 0,                            compress simple,                    4829268\nsilesia.tar,                        level 1,                            compress simple,                    5307443\nsilesia.tar,                        level 3,                            compress simple,                    4829268\nsilesia.tar,                        level 4,                            compress simple,                    4767074\nsilesia.tar,                        level 5,                            compress simple,                    4662847\nsilesia.tar,                        level 6,                            compress simple,                    4597877\nsilesia.tar,                        level 7,                            compress simple,                    4563998\nsilesia.tar,                        level 9,                            compress simple,                    4537558\nsilesia.tar,                        level 13,                           compress simple,                    4484732\nsilesia.tar,                        level 16,                           compress simple,                    4355572\nsilesia.tar,                        level 19,                           compress simple,                    4257629\nsilesia.tar,                        uncompressed literals,              compress simple,                    4829268\nsilesia.tar,                        uncompressed literals optimal,      compress simple,                    4257629\nsilesia.tar,                        huffman literals,                   compress simple,                    6175652\ngithub.tar,                         level -5,                           compress simple,                    52173\ngithub.tar,                         level -3,                           compress simple,                    45783\ngithub.tar,                         level -1,                           compress simple,                    42606\ngithub.tar,                         level 0,                            compress simple,                    38884\ngithub.tar,                         level 1,                            compress simple,                    39200\ngithub.tar,                         level 3,                            compress simple,                    38884\ngithub.tar,                         level 4,                            compress simple,                    38880\ngithub.tar,                         level 5,                            compress simple,                    39651\ngithub.tar,                         level 6,                            compress simple,                    39282\ngithub.tar,                         level 7,                            compress simple,                    38005\ngithub.tar,                         level 9,                            compress simple,                    36723\ngithub.tar,                         level 13,                           compress simple,                    35501\ngithub.tar,                         level 16,                           compress simple,                    40466\ngithub.tar,                         level 19,                           compress simple,                    32262\ngithub.tar,                         uncompressed literals,              compress simple,                    38884\ngithub.tar,                         uncompressed literals optimal,      compress simple,                    32262\ngithub.tar,                         huffman literals,                   compress simple,                    42606\nsilesia,                            level -5,                           compress cctx,                      6854688\nsilesia,                            level -3,                           compress cctx,                      6502839\nsilesia,                            level -1,                           compress cctx,                      6173625\nsilesia,                            level 0,                            compress cctx,                      4832054\nsilesia,                            level 1,                            compress cctx,                      5304296\nsilesia,                            level 3,                            compress cctx,                      4832054\nsilesia,                            level 4,                            compress cctx,                      4768799\nsilesia,                            level 5,                            compress cctx,                      4663718\nsilesia,                            level 6,                            compress cctx,                      4600034\nsilesia,                            level 7,                            compress cctx,                      4566069\nsilesia,                            level 9,                            compress cctx,                      4540520\nsilesia,                            level 13,                           compress cctx,                      4488969\nsilesia,                            level 16,                           compress cctx,                      4356799\nsilesia,                            level 19,                           compress cctx,                      4265851\nsilesia,                            long distance mode,                 compress cctx,                      4832054\nsilesia,                            multithreaded,                      compress cctx,                      4832054\nsilesia,                            multithreaded long distance mode,   compress cctx,                      4832054\nsilesia,                            small window log,                   compress cctx,                      7082907\nsilesia,                            small hash log,                     compress cctx,                      6525510\nsilesia,                            small chain log,                    compress cctx,                      4912248\nsilesia,                            explicit params,                    compress cctx,                      4789676\nsilesia,                            uncompressed literals,              compress cctx,                      4832054\nsilesia,                            uncompressed literals optimal,      compress cctx,                      4265851\nsilesia,                            huffman literals,                   compress cctx,                      6173625\nsilesia,                            multithreaded with advanced params, compress cctx,                      4832054\ngithub,                             level -5,                           compress cctx,                      204407\ngithub,                             level -5 with dict,                 compress cctx,                      47581\ngithub,                             level -3,                           compress cctx,                      193253\ngithub,                             level -3 with dict,                 compress cctx,                      43043\ngithub,                             level -1,                           compress cctx,                      175468\ngithub,                             level -1 with dict,                 compress cctx,                      42044\ngithub,                             level 0,                            compress cctx,                      136331\ngithub,                             level 0 with dict,                  compress cctx,                      41534\ngithub,                             level 1,                            compress cctx,                      142365\ngithub,                             level 1 with dict,                  compress cctx,                      41715\ngithub,                             level 3,                            compress cctx,                      136331\ngithub,                             level 3 with dict,                  compress cctx,                      41534\ngithub,                             level 4,                            compress cctx,                      136199\ngithub,                             level 4 with dict,                  compress cctx,                      41725\ngithub,                             level 5,                            compress cctx,                      135121\ngithub,                             level 5 with dict,                  compress cctx,                      38755\ngithub,                             level 6,                            compress cctx,                      135122\ngithub,                             level 6 with dict,                  compress cctx,                      38665\ngithub,                             level 7,                            compress cctx,                      135122\ngithub,                             level 7 with dict,                  compress cctx,                      38759\ngithub,                             level 9,                            compress cctx,                      135122\ngithub,                             level 9 with dict,                  compress cctx,                      39362\ngithub,                             level 13,                           compress cctx,                      132878\ngithub,                             level 13 with dict,                 compress cctx,                      39948\ngithub,                             level 16,                           compress cctx,                      133209\ngithub,                             level 16 with dict,                 compress cctx,                      37892\ngithub,                             level 19,                           compress cctx,                      132879\ngithub,                             level 19 with dict,                 compress cctx,                      37906\ngithub,                             long distance mode,                 compress cctx,                      141069\ngithub,                             multithreaded,                      compress cctx,                      141069\ngithub,                             multithreaded long distance mode,   compress cctx,                      141069\ngithub,                             small window log,                   compress cctx,                      141069\ngithub,                             small hash log,                     compress cctx,                      138949\ngithub,                             small chain log,                    compress cctx,                      139242\ngithub,                             explicit params,                    compress cctx,                      140932\ngithub,                             uncompressed literals,              compress cctx,                      136331\ngithub,                             uncompressed literals optimal,      compress cctx,                      132879\ngithub,                             huffman literals,                   compress cctx,                      175468\ngithub,                             multithreaded with advanced params, compress cctx,                      141069\nsilesia,                            level -5,                           zstdcli,                            6854509\nsilesia,                            level -3,                           zstdcli,                            6502336\nsilesia,                            level -1,                           zstdcli,                            6171366\nsilesia,                            level 0,                            zstdcli,                            4833113\nsilesia,                            level 1,                            zstdcli,                            5302161\nsilesia,                            level 3,                            zstdcli,                            4833113\nsilesia,                            level 4,                            zstdcli,                            4770061\nsilesia,                            level 5,                            zstdcli,                            4663332\nsilesia,                            level 6,                            zstdcli,                            4599601\nsilesia,                            level 7,                            zstdcli,                            4565601\nsilesia,                            level 9,                            zstdcli,                            4540082\nsilesia,                            level 13,                           zstdcli,                            4488438\nsilesia,                            level 16,                           zstdcli,                            4358150\nsilesia,                            level 19,                           zstdcli,                            4265929\nsilesia,                            long distance mode,                 zstdcli,                            4824341\nsilesia,                            multithreaded,                      zstdcli,                            4833113\nsilesia,                            multithreaded long distance mode,   zstdcli,                            4824341\nsilesia,                            small window log,                   zstdcli,                            7094528\nsilesia,                            small hash log,                     zstdcli,                            6527214\nsilesia,                            small chain log,                    zstdcli,                            4911647\nsilesia,                            explicit params,                    zstdcli,                            4790803\nsilesia,                            uncompressed literals,              zstdcli,                            5118235\nsilesia,                            uncompressed literals optimal,      zstdcli,                            4316761\nsilesia,                            huffman literals,                   zstdcli,                            5316827\nsilesia,                            multithreaded with advanced params, zstdcli,                            5118235\nsilesia.tar,                        level -5,                           zstdcli,                            6859945\nsilesia.tar,                        level -3,                           zstdcli,                            6504296\nsilesia.tar,                        level -1,                           zstdcli,                            6176520\nsilesia.tar,                        level 0,                            zstdcli,                            4836004\nsilesia.tar,                        level 1,                            zstdcli,                            5309074\nsilesia.tar,                        level 3,                            zstdcli,                            4836004\nsilesia.tar,                        level 4,                            zstdcli,                            4774061\nsilesia.tar,                        level 5,                            zstdcli,                            4667310\nsilesia.tar,                        level 6,                            zstdcli,                            4602398\nsilesia.tar,                        level 7,                            zstdcli,                            4568891\nsilesia.tar,                        level 9,                            zstdcli,                            4541098\nsilesia.tar,                        level 13,                           zstdcli,                            4488484\nsilesia.tar,                        level 16,                           zstdcli,                            4357018\nsilesia.tar,                        level 19,                           zstdcli,                            4259593\nsilesia.tar,                        no source size,                     zstdcli,                            4836000\nsilesia.tar,                        long distance mode,                 zstdcli,                            4827830\nsilesia.tar,                        multithreaded,                      zstdcli,                            4836004\nsilesia.tar,                        multithreaded long distance mode,   zstdcli,                            4827830\nsilesia.tar,                        small window log,                   zstdcli,                            7100110\nsilesia.tar,                        small hash log,                     zstdcli,                            6530127\nsilesia.tar,                        small chain log,                    zstdcli,                            4915865\nsilesia.tar,                        explicit params,                    zstdcli,                            4808370\nsilesia.tar,                        uncompressed literals,              zstdcli,                            5116583\nsilesia.tar,                        uncompressed literals optimal,      zstdcli,                            4306520\nsilesia.tar,                        huffman literals,                   zstdcli,                            5324019\nsilesia.tar,                        multithreaded with advanced params, zstdcli,                            5116583\ngithub,                             level -5,                           zstdcli,                            206407\ngithub,                             level -5 with dict,                 zstdcli,                            47832\ngithub,                             level -3,                           zstdcli,                            195253\ngithub,                             level -3 with dict,                 zstdcli,                            46671\ngithub,                             level -1,                           zstdcli,                            177468\ngithub,                             level -1 with dict,                 zstdcli,                            43825\ngithub,                             level 0,                            zstdcli,                            138331\ngithub,                             level 0 with dict,                  zstdcli,                            43118\ngithub,                             level 1,                            zstdcli,                            144365\ngithub,                             level 1 with dict,                  zstdcli,                            43266\ngithub,                             level 3,                            zstdcli,                            138331\ngithub,                             level 3 with dict,                  zstdcli,                            43118\ngithub,                             level 4,                            zstdcli,                            138199\ngithub,                             level 4 with dict,                  zstdcli,                            43229\ngithub,                             level 5,                            zstdcli,                            137121\ngithub,                             level 5 with dict,                  zstdcli,                            40728\ngithub,                             level 6,                            zstdcli,                            137122\ngithub,                             level 6 with dict,                  zstdcli,                            40638\ngithub,                             level 7,                            zstdcli,                            137122\ngithub,                             level 7 with dict,                  zstdcli,                            40749\ngithub,                             level 9,                            zstdcli,                            137122\ngithub,                             level 9 with dict,                  zstdcli,                            41393\ngithub,                             level 13,                           zstdcli,                            134878\ngithub,                             level 13 with dict,                 zstdcli,                            41900\ngithub,                             level 16,                           zstdcli,                            135209\ngithub,                             level 16 with dict,                 zstdcli,                            39902\ngithub,                             level 19,                           zstdcli,                            134879\ngithub,                             level 19 with dict,                 zstdcli,                            39916\ngithub,                             long distance mode,                 zstdcli,                            138331\ngithub,                             multithreaded,                      zstdcli,                            138331\ngithub,                             multithreaded long distance mode,   zstdcli,                            138331\ngithub,                             small window log,                   zstdcli,                            138331\ngithub,                             small hash log,                     zstdcli,                            137590\ngithub,                             small chain log,                    zstdcli,                            138341\ngithub,                             explicit params,                    zstdcli,                            136197\ngithub,                             uncompressed literals,              zstdcli,                            167909\ngithub,                             uncompressed literals optimal,      zstdcli,                            154667\ngithub,                             huffman literals,                   zstdcli,                            144365\ngithub,                             multithreaded with advanced params, zstdcli,                            167909\ngithub.tar,                         level -5,                           zstdcli,                            52231\ngithub.tar,                         level -5 with dict,                 zstdcli,                            51249\ngithub.tar,                         level -3,                           zstdcli,                            45778\ngithub.tar,                         level -3 with dict,                 zstdcli,                            44847\ngithub.tar,                         level -1,                           zstdcli,                            42680\ngithub.tar,                         level -1 with dict,                 zstdcli,                            41486\ngithub.tar,                         level 0,                            zstdcli,                            38888\ngithub.tar,                         level 0 with dict,                  zstdcli,                            37999\ngithub.tar,                         level 1,                            zstdcli,                            39340\ngithub.tar,                         level 1 with dict,                  zstdcli,                            38230\ngithub.tar,                         level 3,                            zstdcli,                            38888\ngithub.tar,                         level 3 with dict,                  zstdcli,                            37999\ngithub.tar,                         level 4,                            zstdcli,                            38884\ngithub.tar,                         level 4 with dict,                  zstdcli,                            37952\ngithub.tar,                         level 5,                            zstdcli,                            39655\ngithub.tar,                         level 5 with dict,                  zstdcli,                            39073\ngithub.tar,                         level 6,                            zstdcli,                            39286\ngithub.tar,                         level 6 with dict,                  zstdcli,                            38647\ngithub.tar,                         level 7,                            zstdcli,                            38009\ngithub.tar,                         level 7 with dict,                  zstdcli,                            37861\ngithub.tar,                         level 9,                            zstdcli,                            36727\ngithub.tar,                         level 9 with dict,                  zstdcli,                            36686\ngithub.tar,                         level 13,                           zstdcli,                            35505\ngithub.tar,                         level 13 with dict,                 zstdcli,                            37134\ngithub.tar,                         level 16,                           zstdcli,                            40470\ngithub.tar,                         level 16 with dict,                 zstdcli,                            33379\ngithub.tar,                         level 19,                           zstdcli,                            32266\ngithub.tar,                         level 19 with dict,                 zstdcli,                            32705\ngithub.tar,                         no source size,                     zstdcli,                            38885\ngithub.tar,                         no source size with dict,           zstdcli,                            38115\ngithub.tar,                         long distance mode,                 zstdcli,                            40143\ngithub.tar,                         multithreaded,                      zstdcli,                            38888\ngithub.tar,                         multithreaded long distance mode,   zstdcli,                            40143\ngithub.tar,                         small window log,                   zstdcli,                            198539\ngithub.tar,                         small hash log,                     zstdcli,                            129874\ngithub.tar,                         small chain log,                    zstdcli,                            41673\ngithub.tar,                         explicit params,                    zstdcli,                            41385\ngithub.tar,                         uncompressed literals,              zstdcli,                            41566\ngithub.tar,                         uncompressed literals optimal,      zstdcli,                            35360\ngithub.tar,                         huffman literals,                   zstdcli,                            38989\ngithub.tar,                         multithreaded with advanced params, zstdcli,                            41566\nsilesia,                            level -5,                           advanced one pass,                  6854688\nsilesia,                            level -3,                           advanced one pass,                  6502839\nsilesia,                            level -1,                           advanced one pass,                  6173625\nsilesia,                            level 0,                            advanced one pass,                  4832054\nsilesia,                            level 1,                            advanced one pass,                  5304296\nsilesia,                            level 3,                            advanced one pass,                  4832054\nsilesia,                            level 4,                            advanced one pass,                  4768799\nsilesia,                            level 5 row 1,                      advanced one pass,                  4663718\nsilesia,                            level 5 row 2,                      advanced one pass,                  4666272\nsilesia,                            level 5,                            advanced one pass,                  4663718\nsilesia,                            level 6,                            advanced one pass,                  4600034\nsilesia,                            level 7 row 1,                      advanced one pass,                  4566069\nsilesia,                            level 7 row 2,                      advanced one pass,                  4560893\nsilesia,                            level 7,                            advanced one pass,                  4566069\nsilesia,                            level 9,                            advanced one pass,                  4540520\nsilesia,                            level 11 row 1,                     advanced one pass,                  4500472\nsilesia,                            level 11 row 2,                     advanced one pass,                  4498174\nsilesia,                            level 12 row 1,                     advanced one pass,                  4500472\nsilesia,                            level 12 row 2,                     advanced one pass,                  4498174\nsilesia,                            level 13,                           advanced one pass,                  4488969\nsilesia,                            level 16,                           advanced one pass,                  4356799\nsilesia,                            level 19,                           advanced one pass,                  4265851\nsilesia,                            no source size,                     advanced one pass,                  4832054\nsilesia,                            long distance mode,                 advanced one pass,                  4823264\nsilesia,                            multithreaded,                      advanced one pass,                  4833065\nsilesia,                            multithreaded long distance mode,   advanced one pass,                  4824293\nsilesia,                            small window log,                   advanced one pass,                  7094480\nsilesia,                            small hash log,                     advanced one pass,                  6525510\nsilesia,                            small chain log,                    advanced one pass,                  4912248\nsilesia,                            explicit params,                    advanced one pass,                  4791219\nsilesia,                            uncompressed literals,              advanced one pass,                  5117526\nsilesia,                            uncompressed literals optimal,      advanced one pass,                  4316644\nsilesia,                            huffman literals,                   advanced one pass,                  5319104\nsilesia,                            multithreaded with advanced params, advanced one pass,                  5118187\nsilesia.tar,                        level -5,                           advanced one pass,                  6858730\nsilesia.tar,                        level -3,                           advanced one pass,                  6502944\nsilesia.tar,                        level -1,                           advanced one pass,                  6175652\nsilesia.tar,                        level 0,                            advanced one pass,                  4829268\nsilesia.tar,                        level 1,                            advanced one pass,                  5307443\nsilesia.tar,                        level 3,                            advanced one pass,                  4829268\nsilesia.tar,                        level 4,                            advanced one pass,                  4767074\nsilesia.tar,                        level 5 row 1,                      advanced one pass,                  4662847\nsilesia.tar,                        level 5 row 2,                      advanced one pass,                  4666825\nsilesia.tar,                        level 5,                            advanced one pass,                  4662847\nsilesia.tar,                        level 6,                            advanced one pass,                  4597877\nsilesia.tar,                        level 7 row 1,                      advanced one pass,                  4563998\nsilesia.tar,                        level 7 row 2,                      advanced one pass,                  4559520\nsilesia.tar,                        level 7,                            advanced one pass,                  4563998\nsilesia.tar,                        level 9,                            advanced one pass,                  4537558\nsilesia.tar,                        level 11 row 1,                     advanced one pass,                  4496590\nsilesia.tar,                        level 11 row 2,                     advanced one pass,                  4495225\nsilesia.tar,                        level 12 row 1,                     advanced one pass,                  4496084\nsilesia.tar,                        level 12 row 2,                     advanced one pass,                  4495434\nsilesia.tar,                        level 13,                           advanced one pass,                  4484732\nsilesia.tar,                        level 16,                           advanced one pass,                  4355572\nsilesia.tar,                        level 19,                           advanced one pass,                  4257629\nsilesia.tar,                        no source size,                     advanced one pass,                  4829268\nsilesia.tar,                        long distance mode,                 advanced one pass,                  4815868\nsilesia.tar,                        multithreaded,                      advanced one pass,                  4836000\nsilesia.tar,                        multithreaded long distance mode,   advanced one pass,                  4827826\nsilesia.tar,                        small window log,                   advanced one pass,                  7100064\nsilesia.tar,                        small hash log,                     advanced one pass,                  6530222\nsilesia.tar,                        small chain log,                    advanced one pass,                  4915689\nsilesia.tar,                        explicit params,                    advanced one pass,                  4790421\nsilesia.tar,                        uncompressed literals,              advanced one pass,                  5114702\nsilesia.tar,                        uncompressed literals optimal,      advanced one pass,                  4306289\nsilesia.tar,                        huffman literals,                   advanced one pass,                  5323421\nsilesia.tar,                        multithreaded with advanced params, advanced one pass,                  5116579\ngithub,                             level -5,                           advanced one pass,                  204407\ngithub,                             level -5 with dict,                 advanced one pass,                  45832\ngithub,                             level -3,                           advanced one pass,                  193253\ngithub,                             level -3 with dict,                 advanced one pass,                  44671\ngithub,                             level -1,                           advanced one pass,                  175468\ngithub,                             level -1 with dict,                 advanced one pass,                  41825\ngithub,                             level 0,                            advanced one pass,                  136331\ngithub,                             level 0 with dict,                  advanced one pass,                  41118\ngithub,                             level 0 with dict dms,              advanced one pass,                  41118\ngithub,                             level 0 with dict dds,              advanced one pass,                  41118\ngithub,                             level 0 with dict copy,             advanced one pass,                  41124\ngithub,                             level 0 with dict load,             advanced one pass,                  41847\ngithub,                             level 1,                            advanced one pass,                  142365\ngithub,                             level 1 with dict,                  advanced one pass,                  41266\ngithub,                             level 1 with dict dms,              advanced one pass,                  41266\ngithub,                             level 1 with dict dds,              advanced one pass,                  41266\ngithub,                             level 1 with dict copy,             advanced one pass,                  41279\ngithub,                             level 1 with dict load,             advanced one pass,                  43331\ngithub,                             level 3,                            advanced one pass,                  136331\ngithub,                             level 3 with dict,                  advanced one pass,                  41118\ngithub,                             level 3 with dict dms,              advanced one pass,                  41118\ngithub,                             level 3 with dict dds,              advanced one pass,                  41118\ngithub,                             level 3 with dict copy,             advanced one pass,                  41124\ngithub,                             level 3 with dict load,             advanced one pass,                  41847\ngithub,                             level 4,                            advanced one pass,                  136199\ngithub,                             level 4 with dict,                  advanced one pass,                  41229\ngithub,                             level 4 with dict dms,              advanced one pass,                  41229\ngithub,                             level 4 with dict dds,              advanced one pass,                  41229\ngithub,                             level 4 with dict copy,             advanced one pass,                  41216\ngithub,                             level 4 with dict load,             advanced one pass,                  41548\ngithub,                             level 5 row 1,                      advanced one pass,                  134584\ngithub,                             level 5 row 1 with dict dms,        advanced one pass,                  38754\ngithub,                             level 5 row 1 with dict dds,        advanced one pass,                  38728\ngithub,                             level 5 row 1 with dict copy,       advanced one pass,                  38755\ngithub,                             level 5 row 1 with dict load,       advanced one pass,                  41899\ngithub,                             level 5 row 2,                      advanced one pass,                  135121\ngithub,                             level 5 row 2 with dict dms,        advanced one pass,                  38938\ngithub,                             level 5 row 2 with dict dds,        advanced one pass,                  38732\ngithub,                             level 5 row 2 with dict copy,       advanced one pass,                  38934\ngithub,                             level 5 row 2 with dict load,       advanced one pass,                  41248\ngithub,                             level 5,                            advanced one pass,                  135121\ngithub,                             level 5 with dict,                  advanced one pass,                  38754\ngithub,                             level 5 with dict dms,              advanced one pass,                  38754\ngithub,                             level 5 with dict dds,              advanced one pass,                  38728\ngithub,                             level 5 with dict copy,             advanced one pass,                  38755\ngithub,                             level 5 with dict load,             advanced one pass,                  41248\ngithub,                             level 6,                            advanced one pass,                  135122\ngithub,                             level 6 with dict,                  advanced one pass,                  38669\ngithub,                             level 6 with dict dms,              advanced one pass,                  38669\ngithub,                             level 6 with dict dds,              advanced one pass,                  38638\ngithub,                             level 6 with dict copy,             advanced one pass,                  38665\ngithub,                             level 6 with dict load,             advanced one pass,                  41153\ngithub,                             level 7 row 1,                      advanced one pass,                  134584\ngithub,                             level 7 row 1 with dict dms,        advanced one pass,                  38765\ngithub,                             level 7 row 1 with dict dds,        advanced one pass,                  38749\ngithub,                             level 7 row 1 with dict copy,       advanced one pass,                  38759\ngithub,                             level 7 row 1 with dict load,       advanced one pass,                  43227\ngithub,                             level 7 row 2,                      advanced one pass,                  135122\ngithub,                             level 7 row 2 with dict dms,        advanced one pass,                  38860\ngithub,                             level 7 row 2 with dict dds,        advanced one pass,                  38766\ngithub,                             level 7 row 2 with dict copy,       advanced one pass,                  38834\ngithub,                             level 7 row 2 with dict load,       advanced one pass,                  41153\ngithub,                             level 7,                            advanced one pass,                  135122\ngithub,                             level 7 with dict,                  advanced one pass,                  38765\ngithub,                             level 7 with dict dms,              advanced one pass,                  38765\ngithub,                             level 7 with dict dds,              advanced one pass,                  38749\ngithub,                             level 7 with dict copy,             advanced one pass,                  38759\ngithub,                             level 7 with dict load,             advanced one pass,                  41153\ngithub,                             level 9,                            advanced one pass,                  135122\ngithub,                             level 9 with dict,                  advanced one pass,                  39439\ngithub,                             level 9 with dict dms,              advanced one pass,                  39439\ngithub,                             level 9 with dict dds,              advanced one pass,                  39393\ngithub,                             level 9 with dict copy,             advanced one pass,                  39362\ngithub,                             level 9 with dict load,             advanced one pass,                  42148\ngithub,                             level 11 row 1,                     advanced one pass,                  135367\ngithub,                             level 11 row 1 with dict dms,       advanced one pass,                  39671\ngithub,                             level 11 row 1 with dict dds,       advanced one pass,                  39671\ngithub,                             level 11 row 1 with dict copy,      advanced one pass,                  39651\ngithub,                             level 11 row 1 with dict load,      advanced one pass,                  41744\ngithub,                             level 11 row 2,                     advanced one pass,                  135367\ngithub,                             level 11 row 2 with dict dms,       advanced one pass,                  39671\ngithub,                             level 11 row 2 with dict dds,       advanced one pass,                  39671\ngithub,                             level 11 row 2 with dict copy,      advanced one pass,                  39651\ngithub,                             level 11 row 2 with dict load,      advanced one pass,                  41744\ngithub,                             level 12 row 1,                     advanced one pass,                  134402\ngithub,                             level 12 row 1 with dict dms,       advanced one pass,                  39677\ngithub,                             level 12 row 1 with dict dds,       advanced one pass,                  39677\ngithub,                             level 12 row 1 with dict copy,      advanced one pass,                  39677\ngithub,                             level 12 row 1 with dict load,      advanced one pass,                  41553\ngithub,                             level 12 row 2,                     advanced one pass,                  134402\ngithub,                             level 12 row 2 with dict dms,       advanced one pass,                  39677\ngithub,                             level 12 row 2 with dict dds,       advanced one pass,                  39677\ngithub,                             level 12 row 2 with dict copy,      advanced one pass,                  39677\ngithub,                             level 12 row 2 with dict load,      advanced one pass,                  41553\ngithub,                             level 13,                           advanced one pass,                  132878\ngithub,                             level 13 with dict,                 advanced one pass,                  39900\ngithub,                             level 13 with dict dms,             advanced one pass,                  39900\ngithub,                             level 13 with dict dds,             advanced one pass,                  39900\ngithub,                             level 13 with dict copy,            advanced one pass,                  39948\ngithub,                             level 13 with dict load,            advanced one pass,                  42643\ngithub,                             level 16,                           advanced one pass,                  133209\ngithub,                             level 16 with dict,                 advanced one pass,                  37902\ngithub,                             level 16 with dict dms,             advanced one pass,                  37902\ngithub,                             level 16 with dict dds,             advanced one pass,                  37902\ngithub,                             level 16 with dict copy,            advanced one pass,                  37892\ngithub,                             level 16 with dict load,            advanced one pass,                  42434\ngithub,                             level 19,                           advanced one pass,                  132879\ngithub,                             level 19 with dict,                 advanced one pass,                  37916\ngithub,                             level 19 with dict dms,             advanced one pass,                  37916\ngithub,                             level 19 with dict dds,             advanced one pass,                  37916\ngithub,                             level 19 with dict copy,            advanced one pass,                  37906\ngithub,                             level 19 with dict load,            advanced one pass,                  40405\ngithub,                             no source size,                     advanced one pass,                  136331\ngithub,                             no source size with dict,           advanced one pass,                  41118\ngithub,                             long distance mode,                 advanced one pass,                  136331\ngithub,                             multithreaded,                      advanced one pass,                  136331\ngithub,                             multithreaded long distance mode,   advanced one pass,                  136331\ngithub,                             small window log,                   advanced one pass,                  136331\ngithub,                             small hash log,                     advanced one pass,                  135590\ngithub,                             small chain log,                    advanced one pass,                  136341\ngithub,                             explicit params,                    advanced one pass,                  137727\ngithub,                             uncompressed literals,              advanced one pass,                  165909\ngithub,                             uncompressed literals optimal,      advanced one pass,                  152667\ngithub,                             huffman literals,                   advanced one pass,                  142365\ngithub,                             multithreaded with advanced params, advanced one pass,                  165909\ngithub.tar,                         level -5,                           advanced one pass,                  52173\ngithub.tar,                         level -5 with dict,                 advanced one pass,                  51161\ngithub.tar,                         level -3,                           advanced one pass,                  45783\ngithub.tar,                         level -3 with dict,                 advanced one pass,                  44768\ngithub.tar,                         level -1,                           advanced one pass,                  42606\ngithub.tar,                         level -1 with dict,                 advanced one pass,                  41397\ngithub.tar,                         level 0,                            advanced one pass,                  38884\ngithub.tar,                         level 0 with dict,                  advanced one pass,                  37995\ngithub.tar,                         level 0 with dict dms,              advanced one pass,                  38114\ngithub.tar,                         level 0 with dict dds,              advanced one pass,                  38114\ngithub.tar,                         level 0 with dict copy,             advanced one pass,                  37995\ngithub.tar,                         level 0 with dict load,             advanced one pass,                  37956\ngithub.tar,                         level 1,                            advanced one pass,                  39200\ngithub.tar,                         level 1 with dict,                  advanced one pass,                  38189\ngithub.tar,                         level 1 with dict dms,              advanced one pass,                  38398\ngithub.tar,                         level 1 with dict dds,              advanced one pass,                  38398\ngithub.tar,                         level 1 with dict copy,             advanced one pass,                  38189\ngithub.tar,                         level 1 with dict load,             advanced one pass,                  38393\ngithub.tar,                         level 3,                            advanced one pass,                  38884\ngithub.tar,                         level 3 with dict,                  advanced one pass,                  37995\ngithub.tar,                         level 3 with dict dms,              advanced one pass,                  38114\ngithub.tar,                         level 3 with dict dds,              advanced one pass,                  38114\ngithub.tar,                         level 3 with dict copy,             advanced one pass,                  37995\ngithub.tar,                         level 3 with dict load,             advanced one pass,                  37956\ngithub.tar,                         level 4,                            advanced one pass,                  38880\ngithub.tar,                         level 4 with dict,                  advanced one pass,                  37948\ngithub.tar,                         level 4 with dict dms,              advanced one pass,                  37995\ngithub.tar,                         level 4 with dict dds,              advanced one pass,                  37995\ngithub.tar,                         level 4 with dict copy,             advanced one pass,                  37948\ngithub.tar,                         level 4 with dict load,             advanced one pass,                  37927\ngithub.tar,                         level 5 row 1,                      advanced one pass,                  39651\ngithub.tar,                         level 5 row 1 with dict dms,        advanced one pass,                  39043\ngithub.tar,                         level 5 row 1 with dict dds,        advanced one pass,                  39069\ngithub.tar,                         level 5 row 1 with dict copy,       advanced one pass,                  39145\ngithub.tar,                         level 5 row 1 with dict load,       advanced one pass,                  39000\ngithub.tar,                         level 5 row 2,                      advanced one pass,                  39701\ngithub.tar,                         level 5 row 2 with dict dms,        advanced one pass,                  39365\ngithub.tar,                         level 5 row 2 with dict dds,        advanced one pass,                  39233\ngithub.tar,                         level 5 row 2 with dict copy,       advanced one pass,                  39715\ngithub.tar,                         level 5 row 2 with dict load,       advanced one pass,                  39158\ngithub.tar,                         level 5,                            advanced one pass,                  39651\ngithub.tar,                         level 5 with dict,                  advanced one pass,                  39145\ngithub.tar,                         level 5 with dict dms,              advanced one pass,                  39043\ngithub.tar,                         level 5 with dict dds,              advanced one pass,                  39069\ngithub.tar,                         level 5 with dict copy,             advanced one pass,                  39145\ngithub.tar,                         level 5 with dict load,             advanced one pass,                  39000\ngithub.tar,                         level 6,                            advanced one pass,                  39282\ngithub.tar,                         level 6 with dict,                  advanced one pass,                  38656\ngithub.tar,                         level 6 with dict dms,              advanced one pass,                  38640\ngithub.tar,                         level 6 with dict dds,              advanced one pass,                  38643\ngithub.tar,                         level 6 with dict copy,             advanced one pass,                  38656\ngithub.tar,                         level 6 with dict load,             advanced one pass,                  38647\ngithub.tar,                         level 7 row 1,                      advanced one pass,                  38005\ngithub.tar,                         level 7 row 1 with dict dms,        advanced one pass,                  37832\ngithub.tar,                         level 7 row 1 with dict dds,        advanced one pass,                  37857\ngithub.tar,                         level 7 row 1 with dict copy,       advanced one pass,                  37839\ngithub.tar,                         level 7 row 1 with dict load,       advanced one pass,                  37286\ngithub.tar,                         level 7 row 2,                      advanced one pass,                  38077\ngithub.tar,                         level 7 row 2 with dict dms,        advanced one pass,                  38012\ngithub.tar,                         level 7 row 2 with dict dds,        advanced one pass,                  38014\ngithub.tar,                         level 7 row 2 with dict copy,       advanced one pass,                  38101\ngithub.tar,                         level 7 row 2 with dict load,       advanced one pass,                  37402\ngithub.tar,                         level 7,                            advanced one pass,                  38005\ngithub.tar,                         level 7 with dict,                  advanced one pass,                  37839\ngithub.tar,                         level 7 with dict dms,              advanced one pass,                  37832\ngithub.tar,                         level 7 with dict dds,              advanced one pass,                  37857\ngithub.tar,                         level 7 with dict copy,             advanced one pass,                  37839\ngithub.tar,                         level 7 with dict load,             advanced one pass,                  37286\ngithub.tar,                         level 9,                            advanced one pass,                  36723\ngithub.tar,                         level 9 with dict,                  advanced one pass,                  36531\ngithub.tar,                         level 9 with dict dms,              advanced one pass,                  36615\ngithub.tar,                         level 9 with dict dds,              advanced one pass,                  36682\ngithub.tar,                         level 9 with dict copy,             advanced one pass,                  36531\ngithub.tar,                         level 9 with dict load,             advanced one pass,                  36322\ngithub.tar,                         level 11 row 1,                     advanced one pass,                  36085\ngithub.tar,                         level 11 row 1 with dict dms,       advanced one pass,                  36963\ngithub.tar,                         level 11 row 1 with dict dds,       advanced one pass,                  36963\ngithub.tar,                         level 11 row 1 with dict copy,      advanced one pass,                  36557\ngithub.tar,                         level 11 row 1 with dict load,      advanced one pass,                  36423\ngithub.tar,                         level 11 row 2,                     advanced one pass,                  36110\ngithub.tar,                         level 11 row 2 with dict dms,       advanced one pass,                  36963\ngithub.tar,                         level 11 row 2 with dict dds,       advanced one pass,                  36963\ngithub.tar,                         level 11 row 2 with dict copy,      advanced one pass,                  36557\ngithub.tar,                         level 11 row 2 with dict load,      advanced one pass,                  36459\ngithub.tar,                         level 12 row 1,                     advanced one pass,                  36085\ngithub.tar,                         level 12 row 1 with dict dms,       advanced one pass,                  36986\ngithub.tar,                         level 12 row 1 with dict dds,       advanced one pass,                  36986\ngithub.tar,                         level 12 row 1 with dict copy,      advanced one pass,                  36609\ngithub.tar,                         level 12 row 1 with dict load,      advanced one pass,                  36423\ngithub.tar,                         level 12 row 2,                     advanced one pass,                  36110\ngithub.tar,                         level 12 row 2 with dict dms,       advanced one pass,                  36986\ngithub.tar,                         level 12 row 2 with dict dds,       advanced one pass,                  36986\ngithub.tar,                         level 12 row 2 with dict copy,      advanced one pass,                  36609\ngithub.tar,                         level 12 row 2 with dict load,      advanced one pass,                  36459\ngithub.tar,                         level 13,                           advanced one pass,                  35501\ngithub.tar,                         level 13 with dict,                 advanced one pass,                  37130\ngithub.tar,                         level 13 with dict dms,             advanced one pass,                  37220\ngithub.tar,                         level 13 with dict dds,             advanced one pass,                  37220\ngithub.tar,                         level 13 with dict copy,            advanced one pass,                  37130\ngithub.tar,                         level 13 with dict load,            advanced one pass,                  36010\ngithub.tar,                         level 16,                           advanced one pass,                  40466\ngithub.tar,                         level 16 with dict,                 advanced one pass,                  33375\ngithub.tar,                         level 16 with dict dms,             advanced one pass,                  33207\ngithub.tar,                         level 16 with dict dds,             advanced one pass,                  33207\ngithub.tar,                         level 16 with dict copy,            advanced one pass,                  33375\ngithub.tar,                         level 16 with dict load,            advanced one pass,                  39081\ngithub.tar,                         level 19,                           advanced one pass,                  32262\ngithub.tar,                         level 19 with dict,                 advanced one pass,                  32701\ngithub.tar,                         level 19 with dict dms,             advanced one pass,                  32565\ngithub.tar,                         level 19 with dict dds,             advanced one pass,                  32565\ngithub.tar,                         level 19 with dict copy,            advanced one pass,                  32701\ngithub.tar,                         level 19 with dict load,            advanced one pass,                  32428\ngithub.tar,                         no source size,                     advanced one pass,                  38884\ngithub.tar,                         no source size with dict,           advanced one pass,                  37995\ngithub.tar,                         long distance mode,                 advanced one pass,                  40156\ngithub.tar,                         multithreaded,                      advanced one pass,                  38884\ngithub.tar,                         multithreaded long distance mode,   advanced one pass,                  40139\ngithub.tar,                         small window log,                   advanced one pass,                  198535\ngithub.tar,                         small hash log,                     advanced one pass,                  129870\ngithub.tar,                         small chain log,                    advanced one pass,                  41669\ngithub.tar,                         explicit params,                    advanced one pass,                  41385\ngithub.tar,                         uncompressed literals,              advanced one pass,                  41562\ngithub.tar,                         uncompressed literals optimal,      advanced one pass,                  35356\ngithub.tar,                         huffman literals,                   advanced one pass,                  38921\ngithub.tar,                         multithreaded with advanced params, advanced one pass,                  41562\nsilesia,                            level -5,                           advanced one pass small out,        6854688\nsilesia,                            level -3,                           advanced one pass small out,        6502839\nsilesia,                            level -1,                           advanced one pass small out,        6173625\nsilesia,                            level 0,                            advanced one pass small out,        4832054\nsilesia,                            level 1,                            advanced one pass small out,        5304296\nsilesia,                            level 3,                            advanced one pass small out,        4832054\nsilesia,                            level 4,                            advanced one pass small out,        4768799\nsilesia,                            level 5 row 1,                      advanced one pass small out,        4663718\nsilesia,                            level 5 row 2,                      advanced one pass small out,        4666272\nsilesia,                            level 5,                            advanced one pass small out,        4663718\nsilesia,                            level 6,                            advanced one pass small out,        4600034\nsilesia,                            level 7 row 1,                      advanced one pass small out,        4566069\nsilesia,                            level 7 row 2,                      advanced one pass small out,        4560893\nsilesia,                            level 7,                            advanced one pass small out,        4566069\nsilesia,                            level 9,                            advanced one pass small out,        4540520\nsilesia,                            level 11 row 1,                     advanced one pass small out,        4500472\nsilesia,                            level 11 row 2,                     advanced one pass small out,        4498174\nsilesia,                            level 12 row 1,                     advanced one pass small out,        4500472\nsilesia,                            level 12 row 2,                     advanced one pass small out,        4498174\nsilesia,                            level 13,                           advanced one pass small out,        4488969\nsilesia,                            level 16,                           advanced one pass small out,        4356799\nsilesia,                            level 19,                           advanced one pass small out,        4265851\nsilesia,                            no source size,                     advanced one pass small out,        4832054\nsilesia,                            long distance mode,                 advanced one pass small out,        4823264\nsilesia,                            multithreaded,                      advanced one pass small out,        4833065\nsilesia,                            multithreaded long distance mode,   advanced one pass small out,        4824293\nsilesia,                            small window log,                   advanced one pass small out,        7094480\nsilesia,                            small hash log,                     advanced one pass small out,        6525510\nsilesia,                            small chain log,                    advanced one pass small out,        4912248\nsilesia,                            explicit params,                    advanced one pass small out,        4791219\nsilesia,                            uncompressed literals,              advanced one pass small out,        5117526\nsilesia,                            uncompressed literals optimal,      advanced one pass small out,        4316644\nsilesia,                            huffman literals,                   advanced one pass small out,        5319104\nsilesia,                            multithreaded with advanced params, advanced one pass small out,        5118187\nsilesia.tar,                        level -5,                           advanced one pass small out,        6858730\nsilesia.tar,                        level -3,                           advanced one pass small out,        6502944\nsilesia.tar,                        level -1,                           advanced one pass small out,        6175652\nsilesia.tar,                        level 0,                            advanced one pass small out,        4829268\nsilesia.tar,                        level 1,                            advanced one pass small out,        5307443\nsilesia.tar,                        level 3,                            advanced one pass small out,        4829268\nsilesia.tar,                        level 4,                            advanced one pass small out,        4767074\nsilesia.tar,                        level 5 row 1,                      advanced one pass small out,        4662847\nsilesia.tar,                        level 5 row 2,                      advanced one pass small out,        4666825\nsilesia.tar,                        level 5,                            advanced one pass small out,        4662847\nsilesia.tar,                        level 6,                            advanced one pass small out,        4597877\nsilesia.tar,                        level 7 row 1,                      advanced one pass small out,        4563998\nsilesia.tar,                        level 7 row 2,                      advanced one pass small out,        4559520\nsilesia.tar,                        level 7,                            advanced one pass small out,        4563998\nsilesia.tar,                        level 9,                            advanced one pass small out,        4537558\nsilesia.tar,                        level 11 row 1,                     advanced one pass small out,        4496590\nsilesia.tar,                        level 11 row 2,                     advanced one pass small out,        4495225\nsilesia.tar,                        level 12 row 1,                     advanced one pass small out,        4496084\nsilesia.tar,                        level 12 row 2,                     advanced one pass small out,        4495434\nsilesia.tar,                        level 13,                           advanced one pass small out,        4484732\nsilesia.tar,                        level 16,                           advanced one pass small out,        4355572\nsilesia.tar,                        level 19,                           advanced one pass small out,        4257629\nsilesia.tar,                        no source size,                     advanced one pass small out,        4829268\nsilesia.tar,                        long distance mode,                 advanced one pass small out,        4815868\nsilesia.tar,                        multithreaded,                      advanced one pass small out,        4836000\nsilesia.tar,                        multithreaded long distance mode,   advanced one pass small out,        4827826\nsilesia.tar,                        small window log,                   advanced one pass small out,        7100064\nsilesia.tar,                        small hash log,                     advanced one pass small out,        6530222\nsilesia.tar,                        small chain log,                    advanced one pass small out,        4915689\nsilesia.tar,                        explicit params,                    advanced one pass small out,        4790421\nsilesia.tar,                        uncompressed literals,              advanced one pass small out,        5114702\nsilesia.tar,                        uncompressed literals optimal,      advanced one pass small out,        4306289\nsilesia.tar,                        huffman literals,                   advanced one pass small out,        5323421\nsilesia.tar,                        multithreaded with advanced params, advanced one pass small out,        5116579\ngithub,                             level -5,                           advanced one pass small out,        204407\ngithub,                             level -5 with dict,                 advanced one pass small out,        45832\ngithub,                             level -3,                           advanced one pass small out,        193253\ngithub,                             level -3 with dict,                 advanced one pass small out,        44671\ngithub,                             level -1,                           advanced one pass small out,        175468\ngithub,                             level -1 with dict,                 advanced one pass small out,        41825\ngithub,                             level 0,                            advanced one pass small out,        136331\ngithub,                             level 0 with dict,                  advanced one pass small out,        41118\ngithub,                             level 0 with dict dms,              advanced one pass small out,        41118\ngithub,                             level 0 with dict dds,              advanced one pass small out,        41118\ngithub,                             level 0 with dict copy,             advanced one pass small out,        41124\ngithub,                             level 0 with dict load,             advanced one pass small out,        41847\ngithub,                             level 1,                            advanced one pass small out,        142365\ngithub,                             level 1 with dict,                  advanced one pass small out,        41266\ngithub,                             level 1 with dict dms,              advanced one pass small out,        41266\ngithub,                             level 1 with dict dds,              advanced one pass small out,        41266\ngithub,                             level 1 with dict copy,             advanced one pass small out,        41279\ngithub,                             level 1 with dict load,             advanced one pass small out,        43331\ngithub,                             level 3,                            advanced one pass small out,        136331\ngithub,                             level 3 with dict,                  advanced one pass small out,        41118\ngithub,                             level 3 with dict dms,              advanced one pass small out,        41118\ngithub,                             level 3 with dict dds,              advanced one pass small out,        41118\ngithub,                             level 3 with dict copy,             advanced one pass small out,        41124\ngithub,                             level 3 with dict load,             advanced one pass small out,        41847\ngithub,                             level 4,                            advanced one pass small out,        136199\ngithub,                             level 4 with dict,                  advanced one pass small out,        41229\ngithub,                             level 4 with dict dms,              advanced one pass small out,        41229\ngithub,                             level 4 with dict dds,              advanced one pass small out,        41229\ngithub,                             level 4 with dict copy,             advanced one pass small out,        41216\ngithub,                             level 4 with dict load,             advanced one pass small out,        41548\ngithub,                             level 5 row 1,                      advanced one pass small out,        134584\ngithub,                             level 5 row 1 with dict dms,        advanced one pass small out,        38754\ngithub,                             level 5 row 1 with dict dds,        advanced one pass small out,        38728\ngithub,                             level 5 row 1 with dict copy,       advanced one pass small out,        38755\ngithub,                             level 5 row 1 with dict load,       advanced one pass small out,        41899\ngithub,                             level 5 row 2,                      advanced one pass small out,        135121\ngithub,                             level 5 row 2 with dict dms,        advanced one pass small out,        38938\ngithub,                             level 5 row 2 with dict dds,        advanced one pass small out,        38732\ngithub,                             level 5 row 2 with dict copy,       advanced one pass small out,        38934\ngithub,                             level 5 row 2 with dict load,       advanced one pass small out,        41248\ngithub,                             level 5,                            advanced one pass small out,        135121\ngithub,                             level 5 with dict,                  advanced one pass small out,        38754\ngithub,                             level 5 with dict dms,              advanced one pass small out,        38754\ngithub,                             level 5 with dict dds,              advanced one pass small out,        38728\ngithub,                             level 5 with dict copy,             advanced one pass small out,        38755\ngithub,                             level 5 with dict load,             advanced one pass small out,        41248\ngithub,                             level 6,                            advanced one pass small out,        135122\ngithub,                             level 6 with dict,                  advanced one pass small out,        38669\ngithub,                             level 6 with dict dms,              advanced one pass small out,        38669\ngithub,                             level 6 with dict dds,              advanced one pass small out,        38638\ngithub,                             level 6 with dict copy,             advanced one pass small out,        38665\ngithub,                             level 6 with dict load,             advanced one pass small out,        41153\ngithub,                             level 7 row 1,                      advanced one pass small out,        134584\ngithub,                             level 7 row 1 with dict dms,        advanced one pass small out,        38765\ngithub,                             level 7 row 1 with dict dds,        advanced one pass small out,        38749\ngithub,                             level 7 row 1 with dict copy,       advanced one pass small out,        38759\ngithub,                             level 7 row 1 with dict load,       advanced one pass small out,        43227\ngithub,                             level 7 row 2,                      advanced one pass small out,        135122\ngithub,                             level 7 row 2 with dict dms,        advanced one pass small out,        38860\ngithub,                             level 7 row 2 with dict dds,        advanced one pass small out,        38766\ngithub,                             level 7 row 2 with dict copy,       advanced one pass small out,        38834\ngithub,                             level 7 row 2 with dict load,       advanced one pass small out,        41153\ngithub,                             level 7,                            advanced one pass small out,        135122\ngithub,                             level 7 with dict,                  advanced one pass small out,        38765\ngithub,                             level 7 with dict dms,              advanced one pass small out,        38765\ngithub,                             level 7 with dict dds,              advanced one pass small out,        38749\ngithub,                             level 7 with dict copy,             advanced one pass small out,        38759\ngithub,                             level 7 with dict load,             advanced one pass small out,        41153\ngithub,                             level 9,                            advanced one pass small out,        135122\ngithub,                             level 9 with dict,                  advanced one pass small out,        39439\ngithub,                             level 9 with dict dms,              advanced one pass small out,        39439\ngithub,                             level 9 with dict dds,              advanced one pass small out,        39393\ngithub,                             level 9 with dict copy,             advanced one pass small out,        39362\ngithub,                             level 9 with dict load,             advanced one pass small out,        42148\ngithub,                             level 11 row 1,                     advanced one pass small out,        135367\ngithub,                             level 11 row 1 with dict dms,       advanced one pass small out,        39671\ngithub,                             level 11 row 1 with dict dds,       advanced one pass small out,        39671\ngithub,                             level 11 row 1 with dict copy,      advanced one pass small out,        39651\ngithub,                             level 11 row 1 with dict load,      advanced one pass small out,        41744\ngithub,                             level 11 row 2,                     advanced one pass small out,        135367\ngithub,                             level 11 row 2 with dict dms,       advanced one pass small out,        39671\ngithub,                             level 11 row 2 with dict dds,       advanced one pass small out,        39671\ngithub,                             level 11 row 2 with dict copy,      advanced one pass small out,        39651\ngithub,                             level 11 row 2 with dict load,      advanced one pass small out,        41744\ngithub,                             level 12 row 1,                     advanced one pass small out,        134402\ngithub,                             level 12 row 1 with dict dms,       advanced one pass small out,        39677\ngithub,                             level 12 row 1 with dict dds,       advanced one pass small out,        39677\ngithub,                             level 12 row 1 with dict copy,      advanced one pass small out,        39677\ngithub,                             level 12 row 1 with dict load,      advanced one pass small out,        41553\ngithub,                             level 12 row 2,                     advanced one pass small out,        134402\ngithub,                             level 12 row 2 with dict dms,       advanced one pass small out,        39677\ngithub,                             level 12 row 2 with dict dds,       advanced one pass small out,        39677\ngithub,                             level 12 row 2 with dict copy,      advanced one pass small out,        39677\ngithub,                             level 12 row 2 with dict load,      advanced one pass small out,        41553\ngithub,                             level 13,                           advanced one pass small out,        132878\ngithub,                             level 13 with dict,                 advanced one pass small out,        39900\ngithub,                             level 13 with dict dms,             advanced one pass small out,        39900\ngithub,                             level 13 with dict dds,             advanced one pass small out,        39900\ngithub,                             level 13 with dict copy,            advanced one pass small out,        39948\ngithub,                             level 13 with dict load,            advanced one pass small out,        42643\ngithub,                             level 16,                           advanced one pass small out,        133209\ngithub,                             level 16 with dict,                 advanced one pass small out,        37902\ngithub,                             level 16 with dict dms,             advanced one pass small out,        37902\ngithub,                             level 16 with dict dds,             advanced one pass small out,        37902\ngithub,                             level 16 with dict copy,            advanced one pass small out,        37892\ngithub,                             level 16 with dict load,            advanced one pass small out,        42434\ngithub,                             level 19,                           advanced one pass small out,        132879\ngithub,                             level 19 with dict,                 advanced one pass small out,        37916\ngithub,                             level 19 with dict dms,             advanced one pass small out,        37916\ngithub,                             level 19 with dict dds,             advanced one pass small out,        37916\ngithub,                             level 19 with dict copy,            advanced one pass small out,        37906\ngithub,                             level 19 with dict load,            advanced one pass small out,        40405\ngithub,                             no source size,                     advanced one pass small out,        136331\ngithub,                             no source size with dict,           advanced one pass small out,        41118\ngithub,                             long distance mode,                 advanced one pass small out,        136331\ngithub,                             multithreaded,                      advanced one pass small out,        136331\ngithub,                             multithreaded long distance mode,   advanced one pass small out,        136331\ngithub,                             small window log,                   advanced one pass small out,        136331\ngithub,                             small hash log,                     advanced one pass small out,        135590\ngithub,                             small chain log,                    advanced one pass small out,        136341\ngithub,                             explicit params,                    advanced one pass small out,        137727\ngithub,                             uncompressed literals,              advanced one pass small out,        165909\ngithub,                             uncompressed literals optimal,      advanced one pass small out,        152667\ngithub,                             huffman literals,                   advanced one pass small out,        142365\ngithub,                             multithreaded with advanced params, advanced one pass small out,        165909\ngithub.tar,                         level -5,                           advanced one pass small out,        52173\ngithub.tar,                         level -5 with dict,                 advanced one pass small out,        51161\ngithub.tar,                         level -3,                           advanced one pass small out,        45783\ngithub.tar,                         level -3 with dict,                 advanced one pass small out,        44768\ngithub.tar,                         level -1,                           advanced one pass small out,        42606\ngithub.tar,                         level -1 with dict,                 advanced one pass small out,        41397\ngithub.tar,                         level 0,                            advanced one pass small out,        38884\ngithub.tar,                         level 0 with dict,                  advanced one pass small out,        37995\ngithub.tar,                         level 0 with dict dms,              advanced one pass small out,        38114\ngithub.tar,                         level 0 with dict dds,              advanced one pass small out,        38114\ngithub.tar,                         level 0 with dict copy,             advanced one pass small out,        37995\ngithub.tar,                         level 0 with dict load,             advanced one pass small out,        37956\ngithub.tar,                         level 1,                            advanced one pass small out,        39200\ngithub.tar,                         level 1 with dict,                  advanced one pass small out,        38189\ngithub.tar,                         level 1 with dict dms,              advanced one pass small out,        38398\ngithub.tar,                         level 1 with dict dds,              advanced one pass small out,        38398\ngithub.tar,                         level 1 with dict copy,             advanced one pass small out,        38189\ngithub.tar,                         level 1 with dict load,             advanced one pass small out,        38393\ngithub.tar,                         level 3,                            advanced one pass small out,        38884\ngithub.tar,                         level 3 with dict,                  advanced one pass small out,        37995\ngithub.tar,                         level 3 with dict dms,              advanced one pass small out,        38114\ngithub.tar,                         level 3 with dict dds,              advanced one pass small out,        38114\ngithub.tar,                         level 3 with dict copy,             advanced one pass small out,        37995\ngithub.tar,                         level 3 with dict load,             advanced one pass small out,        37956\ngithub.tar,                         level 4,                            advanced one pass small out,        38880\ngithub.tar,                         level 4 with dict,                  advanced one pass small out,        37948\ngithub.tar,                         level 4 with dict dms,              advanced one pass small out,        37995\ngithub.tar,                         level 4 with dict dds,              advanced one pass small out,        37995\ngithub.tar,                         level 4 with dict copy,             advanced one pass small out,        37948\ngithub.tar,                         level 4 with dict load,             advanced one pass small out,        37927\ngithub.tar,                         level 5 row 1,                      advanced one pass small out,        39651\ngithub.tar,                         level 5 row 1 with dict dms,        advanced one pass small out,        39043\ngithub.tar,                         level 5 row 1 with dict dds,        advanced one pass small out,        39069\ngithub.tar,                         level 5 row 1 with dict copy,       advanced one pass small out,        39145\ngithub.tar,                         level 5 row 1 with dict load,       advanced one pass small out,        39000\ngithub.tar,                         level 5 row 2,                      advanced one pass small out,        39701\ngithub.tar,                         level 5 row 2 with dict dms,        advanced one pass small out,        39365\ngithub.tar,                         level 5 row 2 with dict dds,        advanced one pass small out,        39233\ngithub.tar,                         level 5 row 2 with dict copy,       advanced one pass small out,        39715\ngithub.tar,                         level 5 row 2 with dict load,       advanced one pass small out,        39158\ngithub.tar,                         level 5,                            advanced one pass small out,        39651\ngithub.tar,                         level 5 with dict,                  advanced one pass small out,        39145\ngithub.tar,                         level 5 with dict dms,              advanced one pass small out,        39043\ngithub.tar,                         level 5 with dict dds,              advanced one pass small out,        39069\ngithub.tar,                         level 5 with dict copy,             advanced one pass small out,        39145\ngithub.tar,                         level 5 with dict load,             advanced one pass small out,        39000\ngithub.tar,                         level 6,                            advanced one pass small out,        39282\ngithub.tar,                         level 6 with dict,                  advanced one pass small out,        38656\ngithub.tar,                         level 6 with dict dms,              advanced one pass small out,        38640\ngithub.tar,                         level 6 with dict dds,              advanced one pass small out,        38643\ngithub.tar,                         level 6 with dict copy,             advanced one pass small out,        38656\ngithub.tar,                         level 6 with dict load,             advanced one pass small out,        38647\ngithub.tar,                         level 7 row 1,                      advanced one pass small out,        38005\ngithub.tar,                         level 7 row 1 with dict dms,        advanced one pass small out,        37832\ngithub.tar,                         level 7 row 1 with dict dds,        advanced one pass small out,        37857\ngithub.tar,                         level 7 row 1 with dict copy,       advanced one pass small out,        37839\ngithub.tar,                         level 7 row 1 with dict load,       advanced one pass small out,        37286\ngithub.tar,                         level 7 row 2,                      advanced one pass small out,        38077\ngithub.tar,                         level 7 row 2 with dict dms,        advanced one pass small out,        38012\ngithub.tar,                         level 7 row 2 with dict dds,        advanced one pass small out,        38014\ngithub.tar,                         level 7 row 2 with dict copy,       advanced one pass small out,        38101\ngithub.tar,                         level 7 row 2 with dict load,       advanced one pass small out,        37402\ngithub.tar,                         level 7,                            advanced one pass small out,        38005\ngithub.tar,                         level 7 with dict,                  advanced one pass small out,        37839\ngithub.tar,                         level 7 with dict dms,              advanced one pass small out,        37832\ngithub.tar,                         level 7 with dict dds,              advanced one pass small out,        37857\ngithub.tar,                         level 7 with dict copy,             advanced one pass small out,        37839\ngithub.tar,                         level 7 with dict load,             advanced one pass small out,        37286\ngithub.tar,                         level 9,                            advanced one pass small out,        36723\ngithub.tar,                         level 9 with dict,                  advanced one pass small out,        36531\ngithub.tar,                         level 9 with dict dms,              advanced one pass small out,        36615\ngithub.tar,                         level 9 with dict dds,              advanced one pass small out,        36682\ngithub.tar,                         level 9 with dict copy,             advanced one pass small out,        36531\ngithub.tar,                         level 9 with dict load,             advanced one pass small out,        36322\ngithub.tar,                         level 11 row 1,                     advanced one pass small out,        36085\ngithub.tar,                         level 11 row 1 with dict dms,       advanced one pass small out,        36963\ngithub.tar,                         level 11 row 1 with dict dds,       advanced one pass small out,        36963\ngithub.tar,                         level 11 row 1 with dict copy,      advanced one pass small out,        36557\ngithub.tar,                         level 11 row 1 with dict load,      advanced one pass small out,        36423\ngithub.tar,                         level 11 row 2,                     advanced one pass small out,        36110\ngithub.tar,                         level 11 row 2 with dict dms,       advanced one pass small out,        36963\ngithub.tar,                         level 11 row 2 with dict dds,       advanced one pass small out,        36963\ngithub.tar,                         level 11 row 2 with dict copy,      advanced one pass small out,        36557\ngithub.tar,                         level 11 row 2 with dict load,      advanced one pass small out,        36459\ngithub.tar,                         level 12 row 1,                     advanced one pass small out,        36085\ngithub.tar,                         level 12 row 1 with dict dms,       advanced one pass small out,        36986\ngithub.tar,                         level 12 row 1 with dict dds,       advanced one pass small out,        36986\ngithub.tar,                         level 12 row 1 with dict copy,      advanced one pass small out,        36609\ngithub.tar,                         level 12 row 1 with dict load,      advanced one pass small out,        36423\ngithub.tar,                         level 12 row 2,                     advanced one pass small out,        36110\ngithub.tar,                         level 12 row 2 with dict dms,       advanced one pass small out,        36986\ngithub.tar,                         level 12 row 2 with dict dds,       advanced one pass small out,        36986\ngithub.tar,                         level 12 row 2 with dict copy,      advanced one pass small out,        36609\ngithub.tar,                         level 12 row 2 with dict load,      advanced one pass small out,        36459\ngithub.tar,                         level 13,                           advanced one pass small out,        35501\ngithub.tar,                         level 13 with dict,                 advanced one pass small out,        37130\ngithub.tar,                         level 13 with dict dms,             advanced one pass small out,        37220\ngithub.tar,                         level 13 with dict dds,             advanced one pass small out,        37220\ngithub.tar,                         level 13 with dict copy,            advanced one pass small out,        37130\ngithub.tar,                         level 13 with dict load,            advanced one pass small out,        36010\ngithub.tar,                         level 16,                           advanced one pass small out,        40466\ngithub.tar,                         level 16 with dict,                 advanced one pass small out,        33375\ngithub.tar,                         level 16 with dict dms,             advanced one pass small out,        33207\ngithub.tar,                         level 16 with dict dds,             advanced one pass small out,        33207\ngithub.tar,                         level 16 with dict copy,            advanced one pass small out,        33375\ngithub.tar,                         level 16 with dict load,            advanced one pass small out,        39081\ngithub.tar,                         level 19,                           advanced one pass small out,        32262\ngithub.tar,                         level 19 with dict,                 advanced one pass small out,        32701\ngithub.tar,                         level 19 with dict dms,             advanced one pass small out,        32565\ngithub.tar,                         level 19 with dict dds,             advanced one pass small out,        32565\ngithub.tar,                         level 19 with dict copy,            advanced one pass small out,        32701\ngithub.tar,                         level 19 with dict load,            advanced one pass small out,        32428\ngithub.tar,                         no source size,                     advanced one pass small out,        38884\ngithub.tar,                         no source size with dict,           advanced one pass small out,        37995\ngithub.tar,                         long distance mode,                 advanced one pass small out,        40156\ngithub.tar,                         multithreaded,                      advanced one pass small out,        38884\ngithub.tar,                         multithreaded long distance mode,   advanced one pass small out,        40139\ngithub.tar,                         small window log,                   advanced one pass small out,        198535\ngithub.tar,                         small hash log,                     advanced one pass small out,        129870\ngithub.tar,                         small chain log,                    advanced one pass small out,        41669\ngithub.tar,                         explicit params,                    advanced one pass small out,        41385\ngithub.tar,                         uncompressed literals,              advanced one pass small out,        41562\ngithub.tar,                         uncompressed literals optimal,      advanced one pass small out,        35356\ngithub.tar,                         huffman literals,                   advanced one pass small out,        38921\ngithub.tar,                         multithreaded with advanced params, advanced one pass small out,        41562\nsilesia,                            level -5,                           advanced streaming,                 6853462\nsilesia,                            level -3,                           advanced streaming,                 6502349\nsilesia,                            level -1,                           advanced streaming,                 6172125\nsilesia,                            level 0,                            advanced streaming,                 4835804\nsilesia,                            level 1,                            advanced streaming,                 5301644\nsilesia,                            level 3,                            advanced streaming,                 4835804\nsilesia,                            level 4,                            advanced streaming,                 4773049\nsilesia,                            level 5 row 1,                      advanced streaming,                 4664679\nsilesia,                            level 5 row 2,                      advanced streaming,                 4667307\nsilesia,                            level 5,                            advanced streaming,                 4664679\nsilesia,                            level 6,                            advanced streaming,                 4601116\nsilesia,                            level 7 row 1,                      advanced streaming,                 4567082\nsilesia,                            level 7 row 2,                      advanced streaming,                 4561992\nsilesia,                            level 7,                            advanced streaming,                 4567082\nsilesia,                            level 9,                            advanced streaming,                 4542474\nsilesia,                            level 11 row 1,                     advanced streaming,                 4502322\nsilesia,                            level 11 row 2,                     advanced streaming,                 4500050\nsilesia,                            level 12 row 1,                     advanced streaming,                 4502322\nsilesia,                            level 12 row 2,                     advanced streaming,                 4500050\nsilesia,                            level 13,                           advanced streaming,                 4490650\nsilesia,                            level 16,                           advanced streaming,                 4358094\nsilesia,                            level 19,                           advanced streaming,                 4265908\nsilesia,                            no source size,                     advanced streaming,                 4835768\nsilesia,                            long distance mode,                 advanced streaming,                 4827032\nsilesia,                            multithreaded,                      advanced streaming,                 4833065\nsilesia,                            multithreaded long distance mode,   advanced streaming,                 4824293\nsilesia,                            small window log,                   advanced streaming,                 7110591\nsilesia,                            small hash log,                     advanced streaming,                 6525259\nsilesia,                            small chain log,                    advanced streaming,                 4911577\nsilesia,                            explicit params,                    advanced streaming,                 4792505\nsilesia,                            uncompressed literals,              advanced streaming,                 5116404\nsilesia,                            uncompressed literals optimal,      advanced streaming,                 4316533\nsilesia,                            huffman literals,                   advanced streaming,                 5317620\nsilesia,                            multithreaded with advanced params, advanced streaming,                 5118187\nsilesia.tar,                        level -5,                           advanced streaming,                 6853184\nsilesia.tar,                        level -3,                           advanced streaming,                 6503455\nsilesia.tar,                        level -1,                           advanced streaming,                 6175761\nsilesia.tar,                        level 0,                            advanced streaming,                 4846783\nsilesia.tar,                        level 1,                            advanced streaming,                 5306719\nsilesia.tar,                        level 3,                            advanced streaming,                 4846783\nsilesia.tar,                        level 4,                            advanced streaming,                 4785332\nsilesia.tar,                        level 5 row 1,                      advanced streaming,                 4664523\nsilesia.tar,                        level 5 row 2,                      advanced streaming,                 4668292\nsilesia.tar,                        level 5,                            advanced streaming,                 4664523\nsilesia.tar,                        level 6,                            advanced streaming,                 4599420\nsilesia.tar,                        level 7 row 1,                      advanced streaming,                 4565332\nsilesia.tar,                        level 7 row 2,                      advanced streaming,                 4561064\nsilesia.tar,                        level 7,                            advanced streaming,                 4565332\nsilesia.tar,                        level 9,                            advanced streaming,                 4539391\nsilesia.tar,                        level 11 row 1,                     advanced streaming,                 4498530\nsilesia.tar,                        level 11 row 2,                     advanced streaming,                 4497297\nsilesia.tar,                        level 12 row 1,                     advanced streaming,                 4498097\nsilesia.tar,                        level 12 row 2,                     advanced streaming,                 4497497\nsilesia.tar,                        level 13,                           advanced streaming,                 4486652\nsilesia.tar,                        level 16,                           advanced streaming,                 4358029\nsilesia.tar,                        level 19,                           advanced streaming,                 4258228\nsilesia.tar,                        no source size,                     advanced streaming,                 4846779\nsilesia.tar,                        long distance mode,                 advanced streaming,                 4825842\nsilesia.tar,                        multithreaded,                      advanced streaming,                 4836000\nsilesia.tar,                        multithreaded long distance mode,   advanced streaming,                 4827826\nsilesia.tar,                        small window log,                   advanced streaming,                 7117024\nsilesia.tar,                        small hash log,                     advanced streaming,                 6529503\nsilesia.tar,                        small chain log,                    advanced streaming,                 4915956\nsilesia.tar,                        explicit params,                    advanced streaming,                 4791739\nsilesia.tar,                        uncompressed literals,              advanced streaming,                 5123274\nsilesia.tar,                        uncompressed literals optimal,      advanced streaming,                 4306968\nsilesia.tar,                        huffman literals,                   advanced streaming,                 5323245\nsilesia.tar,                        multithreaded with advanced params, advanced streaming,                 5116579\ngithub,                             level -5,                           advanced streaming,                 204407\ngithub,                             level -5 with dict,                 advanced streaming,                 45832\ngithub,                             level -3,                           advanced streaming,                 193253\ngithub,                             level -3 with dict,                 advanced streaming,                 44671\ngithub,                             level -1,                           advanced streaming,                 175468\ngithub,                             level -1 with dict,                 advanced streaming,                 41825\ngithub,                             level 0,                            advanced streaming,                 136331\ngithub,                             level 0 with dict,                  advanced streaming,                 41118\ngithub,                             level 0 with dict dms,              advanced streaming,                 41118\ngithub,                             level 0 with dict dds,              advanced streaming,                 41118\ngithub,                             level 0 with dict copy,             advanced streaming,                 41124\ngithub,                             level 0 with dict load,             advanced streaming,                 41847\ngithub,                             level 1,                            advanced streaming,                 142365\ngithub,                             level 1 with dict,                  advanced streaming,                 41266\ngithub,                             level 1 with dict dms,              advanced streaming,                 41266\ngithub,                             level 1 with dict dds,              advanced streaming,                 41266\ngithub,                             level 1 with dict copy,             advanced streaming,                 41279\ngithub,                             level 1 with dict load,             advanced streaming,                 43331\ngithub,                             level 3,                            advanced streaming,                 136331\ngithub,                             level 3 with dict,                  advanced streaming,                 41118\ngithub,                             level 3 with dict dms,              advanced streaming,                 41118\ngithub,                             level 3 with dict dds,              advanced streaming,                 41118\ngithub,                             level 3 with dict copy,             advanced streaming,                 41124\ngithub,                             level 3 with dict load,             advanced streaming,                 41847\ngithub,                             level 4,                            advanced streaming,                 136199\ngithub,                             level 4 with dict,                  advanced streaming,                 41229\ngithub,                             level 4 with dict dms,              advanced streaming,                 41229\ngithub,                             level 4 with dict dds,              advanced streaming,                 41229\ngithub,                             level 4 with dict copy,             advanced streaming,                 41216\ngithub,                             level 4 with dict load,             advanced streaming,                 41548\ngithub,                             level 5 row 1,                      advanced streaming,                 134584\ngithub,                             level 5 row 1 with dict dms,        advanced streaming,                 38754\ngithub,                             level 5 row 1 with dict dds,        advanced streaming,                 38728\ngithub,                             level 5 row 1 with dict copy,       advanced streaming,                 38755\ngithub,                             level 5 row 1 with dict load,       advanced streaming,                 41899\ngithub,                             level 5 row 2,                      advanced streaming,                 135121\ngithub,                             level 5 row 2 with dict dms,        advanced streaming,                 38938\ngithub,                             level 5 row 2 with dict dds,        advanced streaming,                 38732\ngithub,                             level 5 row 2 with dict copy,       advanced streaming,                 38934\ngithub,                             level 5 row 2 with dict load,       advanced streaming,                 41248\ngithub,                             level 5,                            advanced streaming,                 135121\ngithub,                             level 5 with dict,                  advanced streaming,                 38754\ngithub,                             level 5 with dict dms,              advanced streaming,                 38754\ngithub,                             level 5 with dict dds,              advanced streaming,                 38728\ngithub,                             level 5 with dict copy,             advanced streaming,                 38755\ngithub,                             level 5 with dict load,             advanced streaming,                 41248\ngithub,                             level 6,                            advanced streaming,                 135122\ngithub,                             level 6 with dict,                  advanced streaming,                 38669\ngithub,                             level 6 with dict dms,              advanced streaming,                 38669\ngithub,                             level 6 with dict dds,              advanced streaming,                 38638\ngithub,                             level 6 with dict copy,             advanced streaming,                 38665\ngithub,                             level 6 with dict load,             advanced streaming,                 41153\ngithub,                             level 7 row 1,                      advanced streaming,                 134584\ngithub,                             level 7 row 1 with dict dms,        advanced streaming,                 38765\ngithub,                             level 7 row 1 with dict dds,        advanced streaming,                 38749\ngithub,                             level 7 row 1 with dict copy,       advanced streaming,                 38759\ngithub,                             level 7 row 1 with dict load,       advanced streaming,                 43227\ngithub,                             level 7 row 2,                      advanced streaming,                 135122\ngithub,                             level 7 row 2 with dict dms,        advanced streaming,                 38860\ngithub,                             level 7 row 2 with dict dds,        advanced streaming,                 38766\ngithub,                             level 7 row 2 with dict copy,       advanced streaming,                 38834\ngithub,                             level 7 row 2 with dict load,       advanced streaming,                 41153\ngithub,                             level 7,                            advanced streaming,                 135122\ngithub,                             level 7 with dict,                  advanced streaming,                 38765\ngithub,                             level 7 with dict dms,              advanced streaming,                 38765\ngithub,                             level 7 with dict dds,              advanced streaming,                 38749\ngithub,                             level 7 with dict copy,             advanced streaming,                 38759\ngithub,                             level 7 with dict load,             advanced streaming,                 41153\ngithub,                             level 9,                            advanced streaming,                 135122\ngithub,                             level 9 with dict,                  advanced streaming,                 39439\ngithub,                             level 9 with dict dms,              advanced streaming,                 39439\ngithub,                             level 9 with dict dds,              advanced streaming,                 39393\ngithub,                             level 9 with dict copy,             advanced streaming,                 39362\ngithub,                             level 9 with dict load,             advanced streaming,                 42148\ngithub,                             level 11 row 1,                     advanced streaming,                 135367\ngithub,                             level 11 row 1 with dict dms,       advanced streaming,                 39671\ngithub,                             level 11 row 1 with dict dds,       advanced streaming,                 39671\ngithub,                             level 11 row 1 with dict copy,      advanced streaming,                 39651\ngithub,                             level 11 row 1 with dict load,      advanced streaming,                 41744\ngithub,                             level 11 row 2,                     advanced streaming,                 135367\ngithub,                             level 11 row 2 with dict dms,       advanced streaming,                 39671\ngithub,                             level 11 row 2 with dict dds,       advanced streaming,                 39671\ngithub,                             level 11 row 2 with dict copy,      advanced streaming,                 39651\ngithub,                             level 11 row 2 with dict load,      advanced streaming,                 41744\ngithub,                             level 12 row 1,                     advanced streaming,                 134402\ngithub,                             level 12 row 1 with dict dms,       advanced streaming,                 39677\ngithub,                             level 12 row 1 with dict dds,       advanced streaming,                 39677\ngithub,                             level 12 row 1 with dict copy,      advanced streaming,                 39677\ngithub,                             level 12 row 1 with dict load,      advanced streaming,                 41553\ngithub,                             level 12 row 2,                     advanced streaming,                 134402\ngithub,                             level 12 row 2 with dict dms,       advanced streaming,                 39677\ngithub,                             level 12 row 2 with dict dds,       advanced streaming,                 39677\ngithub,                             level 12 row 2 with dict copy,      advanced streaming,                 39677\ngithub,                             level 12 row 2 with dict load,      advanced streaming,                 41553\ngithub,                             level 13,                           advanced streaming,                 132878\ngithub,                             level 13 with dict,                 advanced streaming,                 39900\ngithub,                             level 13 with dict dms,             advanced streaming,                 39900\ngithub,                             level 13 with dict dds,             advanced streaming,                 39900\ngithub,                             level 13 with dict copy,            advanced streaming,                 39948\ngithub,                             level 13 with dict load,            advanced streaming,                 42643\ngithub,                             level 16,                           advanced streaming,                 133209\ngithub,                             level 16 with dict,                 advanced streaming,                 37902\ngithub,                             level 16 with dict dms,             advanced streaming,                 37902\ngithub,                             level 16 with dict dds,             advanced streaming,                 37902\ngithub,                             level 16 with dict copy,            advanced streaming,                 37892\ngithub,                             level 16 with dict load,            advanced streaming,                 42434\ngithub,                             level 19,                           advanced streaming,                 132879\ngithub,                             level 19 with dict,                 advanced streaming,                 37916\ngithub,                             level 19 with dict dms,             advanced streaming,                 37916\ngithub,                             level 19 with dict dds,             advanced streaming,                 37916\ngithub,                             level 19 with dict copy,            advanced streaming,                 37906\ngithub,                             level 19 with dict load,            advanced streaming,                 40405\ngithub,                             no source size,                     advanced streaming,                 136331\ngithub,                             no source size with dict,           advanced streaming,                 41118\ngithub,                             long distance mode,                 advanced streaming,                 136331\ngithub,                             multithreaded,                      advanced streaming,                 136331\ngithub,                             multithreaded long distance mode,   advanced streaming,                 136331\ngithub,                             small window log,                   advanced streaming,                 136331\ngithub,                             small hash log,                     advanced streaming,                 135590\ngithub,                             small chain log,                    advanced streaming,                 136341\ngithub,                             explicit params,                    advanced streaming,                 137727\ngithub,                             uncompressed literals,              advanced streaming,                 165909\ngithub,                             uncompressed literals optimal,      advanced streaming,                 152667\ngithub,                             huffman literals,                   advanced streaming,                 142365\ngithub,                             multithreaded with advanced params, advanced streaming,                 165909\ngithub.tar,                         level -5,                           advanced streaming,                 52273\ngithub.tar,                         level -5 with dict,                 advanced streaming,                 51297\ngithub.tar,                         level -3,                           advanced streaming,                 45783\ngithub.tar,                         level -3 with dict,                 advanced streaming,                 44853\ngithub.tar,                         level -1,                           advanced streaming,                 42687\ngithub.tar,                         level -1 with dict,                 advanced streaming,                 41486\ngithub.tar,                         level 0,                            advanced streaming,                 38884\ngithub.tar,                         level 0 with dict,                  advanced streaming,                 37995\ngithub.tar,                         level 0 with dict dms,              advanced streaming,                 38114\ngithub.tar,                         level 0 with dict dds,              advanced streaming,                 38114\ngithub.tar,                         level 0 with dict copy,             advanced streaming,                 37995\ngithub.tar,                         level 0 with dict load,             advanced streaming,                 37956\ngithub.tar,                         level 1,                            advanced streaming,                 39346\ngithub.tar,                         level 1 with dict,                  advanced streaming,                 38251\ngithub.tar,                         level 1 with dict dms,              advanced streaming,                 38557\ngithub.tar,                         level 1 with dict dds,              advanced streaming,                 38557\ngithub.tar,                         level 1 with dict copy,             advanced streaming,                 38251\ngithub.tar,                         level 1 with dict load,             advanced streaming,                 38503\ngithub.tar,                         level 3,                            advanced streaming,                 38884\ngithub.tar,                         level 3 with dict,                  advanced streaming,                 37995\ngithub.tar,                         level 3 with dict dms,              advanced streaming,                 38114\ngithub.tar,                         level 3 with dict dds,              advanced streaming,                 38114\ngithub.tar,                         level 3 with dict copy,             advanced streaming,                 37995\ngithub.tar,                         level 3 with dict load,             advanced streaming,                 37956\ngithub.tar,                         level 4,                            advanced streaming,                 38880\ngithub.tar,                         level 4 with dict,                  advanced streaming,                 37948\ngithub.tar,                         level 4 with dict dms,              advanced streaming,                 37995\ngithub.tar,                         level 4 with dict dds,              advanced streaming,                 37995\ngithub.tar,                         level 4 with dict copy,             advanced streaming,                 37948\ngithub.tar,                         level 4 with dict load,             advanced streaming,                 37927\ngithub.tar,                         level 5 row 1,                      advanced streaming,                 39651\ngithub.tar,                         level 5 row 1 with dict dms,        advanced streaming,                 39043\ngithub.tar,                         level 5 row 1 with dict dds,        advanced streaming,                 39069\ngithub.tar,                         level 5 row 1 with dict copy,       advanced streaming,                 39145\ngithub.tar,                         level 5 row 1 with dict load,       advanced streaming,                 39000\ngithub.tar,                         level 5 row 2,                      advanced streaming,                 39701\ngithub.tar,                         level 5 row 2 with dict dms,        advanced streaming,                 39365\ngithub.tar,                         level 5 row 2 with dict dds,        advanced streaming,                 39233\ngithub.tar,                         level 5 row 2 with dict copy,       advanced streaming,                 39715\ngithub.tar,                         level 5 row 2 with dict load,       advanced streaming,                 39158\ngithub.tar,                         level 5,                            advanced streaming,                 39651\ngithub.tar,                         level 5 with dict,                  advanced streaming,                 39145\ngithub.tar,                         level 5 with dict dms,              advanced streaming,                 39043\ngithub.tar,                         level 5 with dict dds,              advanced streaming,                 39069\ngithub.tar,                         level 5 with dict copy,             advanced streaming,                 39145\ngithub.tar,                         level 5 with dict load,             advanced streaming,                 39000\ngithub.tar,                         level 6,                            advanced streaming,                 39282\ngithub.tar,                         level 6 with dict,                  advanced streaming,                 38656\ngithub.tar,                         level 6 with dict dms,              advanced streaming,                 38640\ngithub.tar,                         level 6 with dict dds,              advanced streaming,                 38643\ngithub.tar,                         level 6 with dict copy,             advanced streaming,                 38656\ngithub.tar,                         level 6 with dict load,             advanced streaming,                 38647\ngithub.tar,                         level 7 row 1,                      advanced streaming,                 38005\ngithub.tar,                         level 7 row 1 with dict dms,        advanced streaming,                 37832\ngithub.tar,                         level 7 row 1 with dict dds,        advanced streaming,                 37857\ngithub.tar,                         level 7 row 1 with dict copy,       advanced streaming,                 37839\ngithub.tar,                         level 7 row 1 with dict load,       advanced streaming,                 37286\ngithub.tar,                         level 7 row 2,                      advanced streaming,                 38077\ngithub.tar,                         level 7 row 2 with dict dms,        advanced streaming,                 38012\ngithub.tar,                         level 7 row 2 with dict dds,        advanced streaming,                 38014\ngithub.tar,                         level 7 row 2 with dict copy,       advanced streaming,                 38101\ngithub.tar,                         level 7 row 2 with dict load,       advanced streaming,                 37402\ngithub.tar,                         level 7,                            advanced streaming,                 38005\ngithub.tar,                         level 7 with dict,                  advanced streaming,                 37839\ngithub.tar,                         level 7 with dict dms,              advanced streaming,                 37832\ngithub.tar,                         level 7 with dict dds,              advanced streaming,                 37857\ngithub.tar,                         level 7 with dict copy,             advanced streaming,                 37839\ngithub.tar,                         level 7 with dict load,             advanced streaming,                 37286\ngithub.tar,                         level 9,                            advanced streaming,                 36723\ngithub.tar,                         level 9 with dict,                  advanced streaming,                 36531\ngithub.tar,                         level 9 with dict dms,              advanced streaming,                 36615\ngithub.tar,                         level 9 with dict dds,              advanced streaming,                 36682\ngithub.tar,                         level 9 with dict copy,             advanced streaming,                 36531\ngithub.tar,                         level 9 with dict load,             advanced streaming,                 36322\ngithub.tar,                         level 11 row 1,                     advanced streaming,                 36085\ngithub.tar,                         level 11 row 1 with dict dms,       advanced streaming,                 36963\ngithub.tar,                         level 11 row 1 with dict dds,       advanced streaming,                 36963\ngithub.tar,                         level 11 row 1 with dict copy,      advanced streaming,                 36557\ngithub.tar,                         level 11 row 1 with dict load,      advanced streaming,                 36423\ngithub.tar,                         level 11 row 2,                     advanced streaming,                 36110\ngithub.tar,                         level 11 row 2 with dict dms,       advanced streaming,                 36963\ngithub.tar,                         level 11 row 2 with dict dds,       advanced streaming,                 36963\ngithub.tar,                         level 11 row 2 with dict copy,      advanced streaming,                 36557\ngithub.tar,                         level 11 row 2 with dict load,      advanced streaming,                 36459\ngithub.tar,                         level 12 row 1,                     advanced streaming,                 36085\ngithub.tar,                         level 12 row 1 with dict dms,       advanced streaming,                 36986\ngithub.tar,                         level 12 row 1 with dict dds,       advanced streaming,                 36986\ngithub.tar,                         level 12 row 1 with dict copy,      advanced streaming,                 36609\ngithub.tar,                         level 12 row 1 with dict load,      advanced streaming,                 36423\ngithub.tar,                         level 12 row 2,                     advanced streaming,                 36110\ngithub.tar,                         level 12 row 2 with dict dms,       advanced streaming,                 36986\ngithub.tar,                         level 12 row 2 with dict dds,       advanced streaming,                 36986\ngithub.tar,                         level 12 row 2 with dict copy,      advanced streaming,                 36609\ngithub.tar,                         level 12 row 2 with dict load,      advanced streaming,                 36459\ngithub.tar,                         level 13,                           advanced streaming,                 35501\ngithub.tar,                         level 13 with dict,                 advanced streaming,                 37130\ngithub.tar,                         level 13 with dict dms,             advanced streaming,                 37220\ngithub.tar,                         level 13 with dict dds,             advanced streaming,                 37220\ngithub.tar,                         level 13 with dict copy,            advanced streaming,                 37130\ngithub.tar,                         level 13 with dict load,            advanced streaming,                 36010\ngithub.tar,                         level 16,                           advanced streaming,                 40466\ngithub.tar,                         level 16 with dict,                 advanced streaming,                 33375\ngithub.tar,                         level 16 with dict dms,             advanced streaming,                 33207\ngithub.tar,                         level 16 with dict dds,             advanced streaming,                 33207\ngithub.tar,                         level 16 with dict copy,            advanced streaming,                 33375\ngithub.tar,                         level 16 with dict load,            advanced streaming,                 39081\ngithub.tar,                         level 19,                           advanced streaming,                 32262\ngithub.tar,                         level 19 with dict,                 advanced streaming,                 32701\ngithub.tar,                         level 19 with dict dms,             advanced streaming,                 32565\ngithub.tar,                         level 19 with dict dds,             advanced streaming,                 32565\ngithub.tar,                         level 19 with dict copy,            advanced streaming,                 32701\ngithub.tar,                         level 19 with dict load,            advanced streaming,                 32428\ngithub.tar,                         no source size,                     advanced streaming,                 38881\ngithub.tar,                         no source size with dict,           advanced streaming,                 38111\ngithub.tar,                         long distance mode,                 advanced streaming,                 40156\ngithub.tar,                         multithreaded,                      advanced streaming,                 38884\ngithub.tar,                         multithreaded long distance mode,   advanced streaming,                 40139\ngithub.tar,                         small window log,                   advanced streaming,                 199553\ngithub.tar,                         small hash log,                     advanced streaming,                 129870\ngithub.tar,                         small chain log,                    advanced streaming,                 41669\ngithub.tar,                         explicit params,                    advanced streaming,                 41385\ngithub.tar,                         uncompressed literals,              advanced streaming,                 41562\ngithub.tar,                         uncompressed literals optimal,      advanced streaming,                 35356\ngithub.tar,                         huffman literals,                   advanced streaming,                 38998\ngithub.tar,                         multithreaded with advanced params, advanced streaming,                 41562\nsilesia,                            level -5,                           old streaming,                      6853462\nsilesia,                            level -3,                           old streaming,                      6502349\nsilesia,                            level -1,                           old streaming,                      6172125\nsilesia,                            level 0,                            old streaming,                      4835804\nsilesia,                            level 1,                            old streaming,                      5301644\nsilesia,                            level 3,                            old streaming,                      4835804\nsilesia,                            level 4,                            old streaming,                      4773049\nsilesia,                            level 5,                            old streaming,                      4664679\nsilesia,                            level 6,                            old streaming,                      4601116\nsilesia,                            level 7,                            old streaming,                      4567082\nsilesia,                            level 9,                            old streaming,                      4542474\nsilesia,                            level 13,                           old streaming,                      4490650\nsilesia,                            level 16,                           old streaming,                      4358094\nsilesia,                            level 19,                           old streaming,                      4265908\nsilesia,                            no source size,                     old streaming,                      4835768\nsilesia,                            uncompressed literals,              old streaming,                      4835804\nsilesia,                            uncompressed literals optimal,      old streaming,                      4265908\nsilesia,                            huffman literals,                   old streaming,                      6172125\nsilesia.tar,                        level -5,                           old streaming,                      6853184\nsilesia.tar,                        level -3,                           old streaming,                      6503455\nsilesia.tar,                        level -1,                           old streaming,                      6175761\nsilesia.tar,                        level 0,                            old streaming,                      4846783\nsilesia.tar,                        level 1,                            old streaming,                      5306719\nsilesia.tar,                        level 3,                            old streaming,                      4846783\nsilesia.tar,                        level 4,                            old streaming,                      4785332\nsilesia.tar,                        level 5,                            old streaming,                      4664523\nsilesia.tar,                        level 6,                            old streaming,                      4599420\nsilesia.tar,                        level 7,                            old streaming,                      4565332\nsilesia.tar,                        level 9,                            old streaming,                      4539391\nsilesia.tar,                        level 13,                           old streaming,                      4486652\nsilesia.tar,                        level 16,                           old streaming,                      4358029\nsilesia.tar,                        level 19,                           old streaming,                      4258228\nsilesia.tar,                        no source size,                     old streaming,                      4846779\nsilesia.tar,                        uncompressed literals,              old streaming,                      4846783\nsilesia.tar,                        uncompressed literals optimal,      old streaming,                      4258228\nsilesia.tar,                        huffman literals,                   old streaming,                      6175761\ngithub,                             level -5,                           old streaming,                      204407\ngithub,                             level -5 with dict,                 old streaming,                      45832\ngithub,                             level -3,                           old streaming,                      193253\ngithub,                             level -3 with dict,                 old streaming,                      44671\ngithub,                             level -1,                           old streaming,                      175468\ngithub,                             level -1 with dict,                 old streaming,                      41825\ngithub,                             level 0,                            old streaming,                      136331\ngithub,                             level 0 with dict,                  old streaming,                      41118\ngithub,                             level 1,                            old streaming,                      142365\ngithub,                             level 1 with dict,                  old streaming,                      41266\ngithub,                             level 3,                            old streaming,                      136331\ngithub,                             level 3 with dict,                  old streaming,                      41118\ngithub,                             level 4,                            old streaming,                      136199\ngithub,                             level 4 with dict,                  old streaming,                      41229\ngithub,                             level 5,                            old streaming,                      135121\ngithub,                             level 5 with dict,                  old streaming,                      38754\ngithub,                             level 6,                            old streaming,                      135122\ngithub,                             level 6 with dict,                  old streaming,                      38669\ngithub,                             level 7,                            old streaming,                      135122\ngithub,                             level 7 with dict,                  old streaming,                      38765\ngithub,                             level 9,                            old streaming,                      135122\ngithub,                             level 9 with dict,                  old streaming,                      39439\ngithub,                             level 13,                           old streaming,                      132878\ngithub,                             level 13 with dict,                 old streaming,                      39900\ngithub,                             level 16,                           old streaming,                      133209\ngithub,                             level 16 with dict,                 old streaming,                      37902\ngithub,                             level 19,                           old streaming,                      132879\ngithub,                             level 19 with dict,                 old streaming,                      37916\ngithub,                             no source size,                     old streaming,                      140599\ngithub,                             no source size with dict,           old streaming,                      40652\ngithub,                             uncompressed literals,              old streaming,                      136331\ngithub,                             uncompressed literals optimal,      old streaming,                      132879\ngithub,                             huffman literals,                   old streaming,                      175468\ngithub.tar,                         level -5,                           old streaming,                      52273\ngithub.tar,                         level -5 with dict,                 old streaming,                      51297\ngithub.tar,                         level -3,                           old streaming,                      45783\ngithub.tar,                         level -3 with dict,                 old streaming,                      44853\ngithub.tar,                         level -1,                           old streaming,                      42687\ngithub.tar,                         level -1 with dict,                 old streaming,                      41486\ngithub.tar,                         level 0,                            old streaming,                      38884\ngithub.tar,                         level 0 with dict,                  old streaming,                      37995\ngithub.tar,                         level 1,                            old streaming,                      39346\ngithub.tar,                         level 1 with dict,                  old streaming,                      38251\ngithub.tar,                         level 3,                            old streaming,                      38884\ngithub.tar,                         level 3 with dict,                  old streaming,                      37995\ngithub.tar,                         level 4,                            old streaming,                      38880\ngithub.tar,                         level 4 with dict,                  old streaming,                      37948\ngithub.tar,                         level 5,                            old streaming,                      39651\ngithub.tar,                         level 5 with dict,                  old streaming,                      39145\ngithub.tar,                         level 6,                            old streaming,                      39282\ngithub.tar,                         level 6 with dict,                  old streaming,                      38656\ngithub.tar,                         level 7,                            old streaming,                      38005\ngithub.tar,                         level 7 with dict,                  old streaming,                      37839\ngithub.tar,                         level 9,                            old streaming,                      36723\ngithub.tar,                         level 9 with dict,                  old streaming,                      36531\ngithub.tar,                         level 13,                           old streaming,                      35501\ngithub.tar,                         level 13 with dict,                 old streaming,                      37130\ngithub.tar,                         level 16,                           old streaming,                      40466\ngithub.tar,                         level 16 with dict,                 old streaming,                      33375\ngithub.tar,                         level 19,                           old streaming,                      32262\ngithub.tar,                         level 19 with dict,                 old streaming,                      32701\ngithub.tar,                         no source size,                     old streaming,                      38881\ngithub.tar,                         no source size with dict,           old streaming,                      38111\ngithub.tar,                         uncompressed literals,              old streaming,                      38884\ngithub.tar,                         uncompressed literals optimal,      old streaming,                      32262\ngithub.tar,                         huffman literals,                   old streaming,                      42687\nsilesia,                            level -5,                           old streaming advanced,             6853462\nsilesia,                            level -3,                           old streaming advanced,             6502349\nsilesia,                            level -1,                           old streaming advanced,             6172125\nsilesia,                            level 0,                            old streaming advanced,             4835804\nsilesia,                            level 1,                            old streaming advanced,             5301644\nsilesia,                            level 3,                            old streaming advanced,             4835804\nsilesia,                            level 4,                            old streaming advanced,             4773049\nsilesia,                            level 5,                            old streaming advanced,             4664679\nsilesia,                            level 6,                            old streaming advanced,             4601116\nsilesia,                            level 7,                            old streaming advanced,             4567082\nsilesia,                            level 9,                            old streaming advanced,             4542474\nsilesia,                            level 13,                           old streaming advanced,             4490650\nsilesia,                            level 16,                           old streaming advanced,             4358094\nsilesia,                            level 19,                           old streaming advanced,             4265908\nsilesia,                            no source size,                     old streaming advanced,             4835768\nsilesia,                            long distance mode,                 old streaming advanced,             4835804\nsilesia,                            multithreaded,                      old streaming advanced,             4835804\nsilesia,                            multithreaded long distance mode,   old streaming advanced,             4835804\nsilesia,                            small window log,                   old streaming advanced,             7110591\nsilesia,                            small hash log,                     old streaming advanced,             6525259\nsilesia,                            small chain log,                    old streaming advanced,             4911577\nsilesia,                            explicit params,                    old streaming advanced,             4792505\nsilesia,                            uncompressed literals,              old streaming advanced,             4835804\nsilesia,                            uncompressed literals optimal,      old streaming advanced,             4265908\nsilesia,                            huffman literals,                   old streaming advanced,             6172125\nsilesia,                            multithreaded with advanced params, old streaming advanced,             4835804\nsilesia.tar,                        level -5,                           old streaming advanced,             6853184\nsilesia.tar,                        level -3,                           old streaming advanced,             6503455\nsilesia.tar,                        level -1,                           old streaming advanced,             6175761\nsilesia.tar,                        level 0,                            old streaming advanced,             4846783\nsilesia.tar,                        level 1,                            old streaming advanced,             5306719\nsilesia.tar,                        level 3,                            old streaming advanced,             4846783\nsilesia.tar,                        level 4,                            old streaming advanced,             4785332\nsilesia.tar,                        level 5,                            old streaming advanced,             4664523\nsilesia.tar,                        level 6,                            old streaming advanced,             4599420\nsilesia.tar,                        level 7,                            old streaming advanced,             4565332\nsilesia.tar,                        level 9,                            old streaming advanced,             4539391\nsilesia.tar,                        level 13,                           old streaming advanced,             4486652\nsilesia.tar,                        level 16,                           old streaming advanced,             4358029\nsilesia.tar,                        level 19,                           old streaming advanced,             4258228\nsilesia.tar,                        no source size,                     old streaming advanced,             4846779\nsilesia.tar,                        long distance mode,                 old streaming advanced,             4846783\nsilesia.tar,                        multithreaded,                      old streaming advanced,             4846783\nsilesia.tar,                        multithreaded long distance mode,   old streaming advanced,             4846783\nsilesia.tar,                        small window log,                   old streaming advanced,             7117027\nsilesia.tar,                        small hash log,                     old streaming advanced,             6529503\nsilesia.tar,                        small chain log,                    old streaming advanced,             4915956\nsilesia.tar,                        explicit params,                    old streaming advanced,             4791739\nsilesia.tar,                        uncompressed literals,              old streaming advanced,             4846783\nsilesia.tar,                        uncompressed literals optimal,      old streaming advanced,             4258228\nsilesia.tar,                        huffman literals,                   old streaming advanced,             6175761\nsilesia.tar,                        multithreaded with advanced params, old streaming advanced,             4846783\ngithub,                             level -5,                           old streaming advanced,             213265\ngithub,                             level -5 with dict,                 old streaming advanced,             46708\ngithub,                             level -3,                           old streaming advanced,             196126\ngithub,                             level -3 with dict,                 old streaming advanced,             45476\ngithub,                             level -1,                           old streaming advanced,             181107\ngithub,                             level -1 with dict,                 old streaming advanced,             42060\ngithub,                             level 0,                            old streaming advanced,             141101\ngithub,                             level 0 with dict,                  old streaming advanced,             41074\ngithub,                             level 1,                            old streaming advanced,             143693\ngithub,                             level 1 with dict,                  old streaming advanced,             42430\ngithub,                             level 3,                            old streaming advanced,             141101\ngithub,                             level 3 with dict,                  old streaming advanced,             41074\ngithub,                             level 4,                            old streaming advanced,             141101\ngithub,                             level 4 with dict,                  old streaming advanced,             41046\ngithub,                             level 5,                            old streaming advanced,             139402\ngithub,                             level 5 with dict,                  old streaming advanced,             38723\ngithub,                             level 6,                            old streaming advanced,             138676\ngithub,                             level 6 with dict,                  old streaming advanced,             38744\ngithub,                             level 7,                            old streaming advanced,             138676\ngithub,                             level 7 with dict,                  old streaming advanced,             38875\ngithub,                             level 9,                            old streaming advanced,             138676\ngithub,                             level 9 with dict,                  old streaming advanced,             38941\ngithub,                             level 13,                           old streaming advanced,             138676\ngithub,                             level 13 with dict,                 old streaming advanced,             39725\ngithub,                             level 16,                           old streaming advanced,             138575\ngithub,                             level 16 with dict,                 old streaming advanced,             40804\ngithub,                             level 19,                           old streaming advanced,             132879\ngithub,                             level 19 with dict,                 old streaming advanced,             37916\ngithub,                             no source size,                     old streaming advanced,             140599\ngithub,                             no source size with dict,           old streaming advanced,             40608\ngithub,                             long distance mode,                 old streaming advanced,             141101\ngithub,                             multithreaded,                      old streaming advanced,             141101\ngithub,                             multithreaded long distance mode,   old streaming advanced,             141101\ngithub,                             small window log,                   old streaming advanced,             141101\ngithub,                             small hash log,                     old streaming advanced,             141597\ngithub,                             small chain log,                    old streaming advanced,             139275\ngithub,                             explicit params,                    old streaming advanced,             140937\ngithub,                             uncompressed literals,              old streaming advanced,             141101\ngithub,                             uncompressed literals optimal,      old streaming advanced,             132879\ngithub,                             huffman literals,                   old streaming advanced,             181107\ngithub,                             multithreaded with advanced params, old streaming advanced,             141101\ngithub.tar,                         level -5,                           old streaming advanced,             52273\ngithub.tar,                         level -5 with dict,                 old streaming advanced,             51249\ngithub.tar,                         level -3,                           old streaming advanced,             45783\ngithub.tar,                         level -3 with dict,                 old streaming advanced,             45093\ngithub.tar,                         level -1,                           old streaming advanced,             42687\ngithub.tar,                         level -1 with dict,                 old streaming advanced,             41762\ngithub.tar,                         level 0,                            old streaming advanced,             38884\ngithub.tar,                         level 0 with dict,                  old streaming advanced,             38013\ngithub.tar,                         level 1,                            old streaming advanced,             39346\ngithub.tar,                         level 1 with dict,                  old streaming advanced,             38507\ngithub.tar,                         level 3,                            old streaming advanced,             38884\ngithub.tar,                         level 3 with dict,                  old streaming advanced,             38013\ngithub.tar,                         level 4,                            old streaming advanced,             38880\ngithub.tar,                         level 4 with dict,                  old streaming advanced,             38063\ngithub.tar,                         level 5,                            old streaming advanced,             39651\ngithub.tar,                         level 5 with dict,                  old streaming advanced,             39018\ngithub.tar,                         level 6,                            old streaming advanced,             39282\ngithub.tar,                         level 6 with dict,                  old streaming advanced,             38635\ngithub.tar,                         level 7,                            old streaming advanced,             38005\ngithub.tar,                         level 7 with dict,                  old streaming advanced,             37264\ngithub.tar,                         level 9,                            old streaming advanced,             36723\ngithub.tar,                         level 9 with dict,                  old streaming advanced,             36241\ngithub.tar,                         level 13,                           old streaming advanced,             35501\ngithub.tar,                         level 13 with dict,                 old streaming advanced,             35807\ngithub.tar,                         level 16,                           old streaming advanced,             40466\ngithub.tar,                         level 16 with dict,                 old streaming advanced,             38578\ngithub.tar,                         level 19,                           old streaming advanced,             32262\ngithub.tar,                         level 19 with dict,                 old streaming advanced,             32678\ngithub.tar,                         no source size,                     old streaming advanced,             38881\ngithub.tar,                         no source size with dict,           old streaming advanced,             38076\ngithub.tar,                         long distance mode,                 old streaming advanced,             38884\ngithub.tar,                         multithreaded,                      old streaming advanced,             38884\ngithub.tar,                         multithreaded long distance mode,   old streaming advanced,             38884\ngithub.tar,                         small window log,                   old streaming advanced,             199556\ngithub.tar,                         small hash log,                     old streaming advanced,             129870\ngithub.tar,                         small chain log,                    old streaming advanced,             41669\ngithub.tar,                         explicit params,                    old streaming advanced,             41385\ngithub.tar,                         uncompressed literals,              old streaming advanced,             38884\ngithub.tar,                         uncompressed literals optimal,      old streaming advanced,             32262\ngithub.tar,                         huffman literals,                   old streaming advanced,             42687\ngithub.tar,                         multithreaded with advanced params, old streaming advanced,             38884\ngithub,                             level -5 with dict,                 old streaming cdict,                45832\ngithub,                             level -3 with dict,                 old streaming cdict,                44671\ngithub,                             level -1 with dict,                 old streaming cdict,                41825\ngithub,                             level 0 with dict,                  old streaming cdict,                41118\ngithub,                             level 1 with dict,                  old streaming cdict,                41266\ngithub,                             level 3 with dict,                  old streaming cdict,                41118\ngithub,                             level 4 with dict,                  old streaming cdict,                41229\ngithub,                             level 5 with dict,                  old streaming cdict,                38754\ngithub,                             level 6 with dict,                  old streaming cdict,                38669\ngithub,                             level 7 with dict,                  old streaming cdict,                38765\ngithub,                             level 9 with dict,                  old streaming cdict,                39439\ngithub,                             level 13 with dict,                 old streaming cdict,                39900\ngithub,                             level 16 with dict,                 old streaming cdict,                37902\ngithub,                             level 19 with dict,                 old streaming cdict,                37916\ngithub,                             no source size with dict,           old streaming cdict,                40652\ngithub.tar,                         level -5 with dict,                 old streaming cdict,                51407\ngithub.tar,                         level -3 with dict,                 old streaming cdict,                45254\ngithub.tar,                         level -1 with dict,                 old streaming cdict,                41973\ngithub.tar,                         level 0 with dict,                  old streaming cdict,                37956\ngithub.tar,                         level 1 with dict,                  old streaming cdict,                38503\ngithub.tar,                         level 3 with dict,                  old streaming cdict,                37956\ngithub.tar,                         level 4 with dict,                  old streaming cdict,                37927\ngithub.tar,                         level 5 with dict,                  old streaming cdict,                39000\ngithub.tar,                         level 6 with dict,                  old streaming cdict,                38647\ngithub.tar,                         level 7 with dict,                  old streaming cdict,                37286\ngithub.tar,                         level 9 with dict,                  old streaming cdict,                36322\ngithub.tar,                         level 13 with dict,                 old streaming cdict,                36010\ngithub.tar,                         level 16 with dict,                 old streaming cdict,                39081\ngithub.tar,                         level 19 with dict,                 old streaming cdict,                32428\ngithub.tar,                         no source size with dict,           old streaming cdict,                38111\ngithub,                             level -5 with dict,                 old streaming advanced cdict,       46708\ngithub,                             level -3 with dict,                 old streaming advanced cdict,       45476\ngithub,                             level -1 with dict,                 old streaming advanced cdict,       42060\ngithub,                             level 0 with dict,                  old streaming advanced cdict,       41074\ngithub,                             level 1 with dict,                  old streaming advanced cdict,       42430\ngithub,                             level 3 with dict,                  old streaming advanced cdict,       41074\ngithub,                             level 4 with dict,                  old streaming advanced cdict,       41046\ngithub,                             level 5 with dict,                  old streaming advanced cdict,       38723\ngithub,                             level 6 with dict,                  old streaming advanced cdict,       38744\ngithub,                             level 7 with dict,                  old streaming advanced cdict,       38875\ngithub,                             level 9 with dict,                  old streaming advanced cdict,       38941\ngithub,                             level 13 with dict,                 old streaming advanced cdict,       39725\ngithub,                             level 16 with dict,                 old streaming advanced cdict,       40804\ngithub,                             level 19 with dict,                 old streaming advanced cdict,       37916\ngithub,                             no source size with dict,           old streaming advanced cdict,       40608\ngithub.tar,                         level -5 with dict,                 old streaming advanced cdict,       50907\ngithub.tar,                         level -3 with dict,                 old streaming advanced cdict,       45032\ngithub.tar,                         level -1 with dict,                 old streaming advanced cdict,       41589\ngithub.tar,                         level 0 with dict,                  old streaming advanced cdict,       38013\ngithub.tar,                         level 1 with dict,                  old streaming advanced cdict,       38294\ngithub.tar,                         level 3 with dict,                  old streaming advanced cdict,       38013\ngithub.tar,                         level 4 with dict,                  old streaming advanced cdict,       38063\ngithub.tar,                         level 5 with dict,                  old streaming advanced cdict,       39018\ngithub.tar,                         level 6 with dict,                  old streaming advanced cdict,       38635\ngithub.tar,                         level 7 with dict,                  old streaming advanced cdict,       37264\ngithub.tar,                         level 9 with dict,                  old streaming advanced cdict,       36241\ngithub.tar,                         level 13 with dict,                 old streaming advanced cdict,       35807\ngithub.tar,                         level 16 with dict,                 old streaming advanced cdict,       38578\ngithub.tar,                         level 19 with dict,                 old streaming advanced cdict,       32678\ngithub.tar,                         no source size with dict,           old streaming advanced cdict,       38076\n"
  },
  {
    "path": "tests/regression/test.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include <assert.h>\n#include <getopt.h>\n#include <stdio.h>\n#include <string.h>\n\n#include \"config.h\"\n#include \"data.h\"\n#include \"method.h\"\n\nstatic int g_max_name_len = 0;\n\n/** Check if a name contains a comma or is too long. */\nstatic int is_name_bad(char const* name) {\n    if (name == NULL)\n        return 1;\n    int const len = strlen(name);\n    if (len > g_max_name_len)\n        g_max_name_len = len;\n    for (; *name != '\\0'; ++name)\n        if (*name == ',')\n            return 1;\n    return 0;\n}\n\n/** Check if any of the names contain a comma. */\nstatic int are_names_bad() {\n    for (size_t method = 0; methods[method] != NULL; ++method)\n        if (is_name_bad(methods[method]->name)) {\n            fprintf(stderr, \"method name %s is bad\\n\", methods[method]->name);\n            return 1;\n        }\n    for (size_t datum = 0; data[datum] != NULL; ++datum)\n        if (is_name_bad(data[datum]->name)) {\n            fprintf(stderr, \"data name %s is bad\\n\", data[datum]->name);\n            return 1;\n        }\n    for (size_t config = 0; configs[config] != NULL; ++config)\n        if (is_name_bad(configs[config]->name)) {\n            fprintf(stderr, \"config name %s is bad\\n\", configs[config]->name);\n            return 1;\n        }\n    return 0;\n}\n\n/**\n * Option parsing using getopt.\n * When you add a new option update: long_options, long_extras, and\n * short_options.\n */\n\n/** Option variables filled by parse_args. */\nstatic char const* g_output = NULL;\nstatic char const* g_diff = NULL;\nstatic char const* g_cache = NULL;\nstatic char const* g_zstdcli = NULL;\nstatic char const* g_config = NULL;\nstatic char const* g_data = NULL;\nstatic char const* g_method = NULL;\n\ntypedef enum {\n    required_option,\n    optional_option,\n    help_option,\n} option_type;\n\n/**\n * Extra state that we need to keep per-option that we can't store in getopt.\n */\nstruct option_extra {\n    int id; /**< The short option name, used as an id. */\n    char const* help; /**< The help message. */\n    option_type opt_type; /**< The option type: required, optional, or help. */\n    char const** value; /**< The value to set or NULL if no_argument. */\n};\n\n/** The options. */\nstatic struct option long_options[] = {\n    {\"cache\", required_argument, NULL, 'c'},\n    {\"output\", required_argument, NULL, 'o'},\n    {\"zstd\", required_argument, NULL, 'z'},\n    {\"config\", required_argument, NULL, 128},\n    {\"data\", required_argument, NULL, 129},\n    {\"method\", required_argument, NULL, 130},\n    {\"diff\", required_argument, NULL, 'd'},\n    {\"help\", no_argument, NULL, 'h'},\n};\n\nstatic size_t const nargs = sizeof(long_options) / sizeof(long_options[0]);\n\n/** The extra info for the options. Must be in the same order as the options. */\nstatic struct option_extra long_extras[] = {\n    {'c', \"the cache directory\", required_option, &g_cache},\n    {'o', \"write the results here\", required_option, &g_output},\n    {'z', \"zstd cli tool\", required_option, &g_zstdcli},\n    {128, \"use this config\", optional_option, &g_config},\n    {129, \"use this data\", optional_option, &g_data},\n    {130, \"use this method\", optional_option, &g_method},\n    {'d', \"compare the results to this file\", optional_option, &g_diff},\n    {'h', \"display this message\", help_option, NULL},\n};\n\n/** The short options. Must correspond to the options. */\nstatic char const short_options[] = \"c:d:ho:z:\";\n\n/** Return the help string for the option type. */\nstatic char const* required_message(option_type opt_type) {\n    switch (opt_type) {\n        case required_option:\n            return \"[required]\";\n        case optional_option:\n            return \"[optional]\";\n        case help_option:\n            return \"\";\n        default:\n            assert(0);\n            return NULL;\n    }\n}\n\n/** Print the help for the program. */\nstatic void print_help(void) {\n    fprintf(stderr, \"regression test runner\\n\");\n    size_t const nargs = sizeof(long_options) / sizeof(long_options[0]);\n    for (size_t i = 0; i < nargs; ++i) {\n        if (long_options[i].val < 128) {\n            /* Long / short  - help [option type] */\n            fprintf(\n                stderr,\n                \"--%s / -%c \\t- %s %s\\n\",\n                long_options[i].name,\n                long_options[i].val,\n                long_extras[i].help,\n                required_message(long_extras[i].opt_type));\n        } else {\n            /* Short / long  - help [option type] */\n            fprintf(\n                stderr,\n                \"--%s      \\t- %s %s\\n\",\n                long_options[i].name,\n                long_extras[i].help,\n                required_message(long_extras[i].opt_type));\n        }\n    }\n}\n\n/** Parse the arguments. Return 0 on success. Print help on failure. */\nstatic int parse_args(int argc, char** argv) {\n    int option_index = 0;\n    int c;\n\n    while (1) {\n        c = getopt_long(argc, argv, short_options, long_options, &option_index);\n        if (c == -1)\n            break;\n\n        int found = 0;\n        for (size_t i = 0; i < nargs; ++i) {\n            if (c == long_extras[i].id && long_extras[i].value != NULL) {\n                *long_extras[i].value = optarg;\n                found = 1;\n                break;\n            }\n        }\n        if (found)\n            continue;\n\n        switch (c) {\n            case 'h':\n            case '?':\n            default:\n                print_help();\n                return 1;\n        }\n    }\n\n    int bad = 0;\n    for (size_t i = 0; i < nargs; ++i) {\n        if (long_extras[i].opt_type != required_option)\n            continue;\n        if (long_extras[i].value == NULL)\n            continue;\n        if (*long_extras[i].value != NULL)\n            continue;\n        fprintf(\n            stderr,\n            \"--%s is a required argument but is not set\\n\",\n            long_options[i].name);\n        bad = 1;\n    }\n    if (bad) {\n        fprintf(stderr, \"\\n\");\n        print_help();\n        return 1;\n    }\n\n    return 0;\n}\n\n/** Helper macro to print to stderr and a file. */\n#define tprintf(file, ...)            \\\n    do {                              \\\n        fprintf(file, __VA_ARGS__);   \\\n        fprintf(stderr, __VA_ARGS__); \\\n    } while (0)\n/** Helper macro to flush stderr and a file. */\n#define tflush(file)    \\\n    do {                \\\n        fflush(file);   \\\n        fflush(stderr); \\\n    } while (0)\n\nvoid tprint_names(\n    FILE* results,\n    char const* data_name,\n    char const* config_name,\n    char const* method_name) {\n    int const data_padding = g_max_name_len - strlen(data_name);\n    int const config_padding = g_max_name_len - strlen(config_name);\n    int const method_padding = g_max_name_len - strlen(method_name);\n\n    tprintf(\n        results,\n        \"%s, %*s%s, %*s%s, %*s\",\n        data_name,\n        data_padding,\n        \"\",\n        config_name,\n        config_padding,\n        \"\",\n        method_name,\n        method_padding,\n        \"\");\n}\n\n/**\n * Run all the regression tests and record the results table to results and\n * stderr progressively.\n */\nstatic int run_all(FILE* results) {\n    tprint_names(results, \"Data\", \"Config\", \"Method\");\n    tprintf(results, \"Total compressed size\\n\");\n    for (size_t method = 0; methods[method] != NULL; ++method) {\n        if (g_method != NULL && strcmp(methods[method]->name, g_method))\n            continue;\n        for (size_t datum = 0; data[datum] != NULL; ++datum) {\n            if (g_data != NULL && strcmp(data[datum]->name, g_data))\n                continue;\n            /* Create the state common to all configs */\n            method_state_t* state = methods[method]->create(data[datum]);\n            for (size_t config = 0; configs[config] != NULL; ++config) {\n                if (g_config != NULL && strcmp(configs[config]->name, g_config))\n                    continue;\n                if (config_skip_data(configs[config], data[datum]))\n                    continue;\n                /* Print the result for the (method, data, config) tuple. */\n                result_t const result =\n                    methods[method]->compress(state, configs[config]);\n                if (result_is_skip(result))\n                    continue;\n                tprint_names(\n                    results,\n                    data[datum]->name,\n                    configs[config]->name,\n                    methods[method]->name);\n                if (result_is_error(result)) {\n                    tprintf(results, \"%s\\n\", result_get_error_string(result));\n                } else {\n                    tprintf(\n                        results,\n                        \"%llu\\n\",\n                        (unsigned long long)result_get_data(result).total_size);\n                }\n                tflush(results);\n            }\n            methods[method]->destroy(state);\n        }\n    }\n    return 0;\n}\n\n/** memcmp() the old results file and the new results file. */\nstatic int diff_results(char const* actual_file, char const* expected_file) {\n    data_buffer_t const actual = data_buffer_read(actual_file);\n    data_buffer_t const expected = data_buffer_read(expected_file);\n    int ret = 1;\n\n    if (actual.data == NULL) {\n        fprintf(stderr, \"failed to open results '%s' for diff\\n\", actual_file);\n        goto out;\n    }\n    if (expected.data == NULL) {\n        fprintf(\n            stderr,\n            \"failed to open previous results '%s' for diff\\n\",\n            expected_file);\n        goto out;\n    }\n\n    ret = data_buffer_compare(actual, expected);\n    if (ret != 0) {\n        fprintf(\n            stderr,\n            \"actual results '%s' does not match expected results '%s'\\n\",\n            actual_file,\n            expected_file);\n    } else {\n        fprintf(stderr, \"actual results match expected results\\n\");\n    }\nout:\n    data_buffer_free(actual);\n    data_buffer_free(expected);\n    return ret;\n}\n\nint main(int argc, char** argv) {\n    /* Parse args and validate modules. */\n    int ret = parse_args(argc, argv);\n    if (ret != 0)\n        return ret;\n\n    if (are_names_bad())\n        return 1;\n\n    /* Initialize modules. */\n    method_set_zstdcli(g_zstdcli);\n    ret = data_init(g_cache);\n    if (ret != 0) {\n        fprintf(stderr, \"data_init() failed with error=%s\\n\", strerror(ret));\n        return 1;\n    }\n\n    /* Run the regression tests. */\n    ret = 1;\n    FILE* results = fopen(g_output, \"w\");\n    if (results == NULL) {\n        fprintf(stderr, \"Failed to open the output file\\n\");\n        goto out;\n    }\n    ret = run_all(results);\n    fclose(results);\n\n    if (ret != 0)\n        goto out;\n\n    if (g_diff)\n        /* Diff the new results with the previous results. */\n        ret = diff_results(g_output, g_diff);\n\nout:\n    data_finish();\n    return ret;\n}\n"
  },
  {
    "path": "tests/roundTripCrash.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/*\n  This program takes a file in input,\n  performs a zstd round-trip test (compression - decompress)\n  compares the result with original\n  and generates a crash (double free) on corruption detection.\n*/\n\n/*===========================================\n*   Dependencies\n*==========================================*/\n#include <stddef.h>     /* size_t */\n#include <stdlib.h>     /* malloc, free, exit */\n#include <stdio.h>      /* fprintf */\n#include <string.h>     /* strcmp */\n#include <sys/types.h>  /* stat */\n#include <sys/stat.h>   /* stat */\n#include \"xxhash.h\"\n\n#define ZSTD_STATIC_LINKING_ONLY\n#include \"zstd.h\"\n\n/*===========================================\n*   Macros\n*==========================================*/\n#define MIN(a,b)  ( (a) < (b) ? (a) : (b) )\n\nstatic void crash(int errorCode){\n    /* abort if AFL/libfuzzer, exit otherwise */\n    #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION /* could also use __AFL_COMPILER */\n        abort();\n    #else\n        exit(errorCode);\n    #endif\n}\n\n#define CHECK_Z(f) {                            \\\n    size_t const err = f;                       \\\n    if (ZSTD_isError(err)) {                    \\\n        fprintf(stderr,                         \\\n                \"Error=> %s: %s\",               \\\n                #f, ZSTD_getErrorName(err));    \\\n        crash(1);                                \\\n}   }\n\n/** roundTripTest() :\n*   Compresses `srcBuff` into `compressedBuff`,\n*   then decompresses `compressedBuff` into `resultBuff`.\n*   Compression level used is derived from first content byte.\n*   @return : result of decompression, which should be == `srcSize`\n*          or an error code if either compression or decompression fails.\n*   Note : `compressedBuffCapacity` should be `>= ZSTD_compressBound(srcSize)`\n*          for compression to be guaranteed to work */\nstatic size_t roundTripTest(void* resultBuff, size_t resultBuffCapacity,\n                            void* compressedBuff, size_t compressedBuffCapacity,\n                      const void* srcBuff, size_t srcBuffSize)\n{\n    static const int maxClevel = 19;\n    size_t const hashLength = MIN(128, srcBuffSize);\n    unsigned const h32 = XXH32(srcBuff, hashLength, 0);\n    int const cLevel = h32 % maxClevel;\n    size_t const cSize = ZSTD_compress(compressedBuff, compressedBuffCapacity, srcBuff, srcBuffSize, cLevel);\n    if (ZSTD_isError(cSize)) {\n        fprintf(stderr, \"Compression error : %s \\n\", ZSTD_getErrorName(cSize));\n        return cSize;\n    }\n    return ZSTD_decompress(resultBuff, resultBuffCapacity, compressedBuff, cSize);\n}\n\n/** cctxParamRoundTripTest() :\n *  Same as roundTripTest() except allows experimenting with ZSTD_CCtx_params. */\nstatic size_t cctxParamRoundTripTest(void* resultBuff, size_t resultBuffCapacity,\n                            void* compressedBuff, size_t compressedBuffCapacity,\n                      const void* srcBuff, size_t srcBuffSize)\n{\n    ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n    ZSTD_CCtx_params* const cctxParams = ZSTD_createCCtxParams();\n    ZSTD_inBuffer inBuffer = { srcBuff, srcBuffSize, 0 };\n    ZSTD_outBuffer outBuffer = { compressedBuff, compressedBuffCapacity, 0 };\n\n    static const int maxClevel = 19;\n    size_t const hashLength = MIN(128, srcBuffSize);\n    unsigned const h32 = XXH32(srcBuff, hashLength, 0);\n    int const cLevel = h32 % maxClevel;\n\n    /* Set parameters */\n    CHECK_Z( ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_compressionLevel, cLevel) );\n    CHECK_Z( ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_nbWorkers, 2) );\n    CHECK_Z( ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_overlapLog, 5) );\n\n\n    /* Apply parameters */\n    CHECK_Z( ZSTD_CCtx_setParametersUsingCCtxParams(cctx, cctxParams) );\n\n    CHECK_Z (ZSTD_compressStream2(cctx, &outBuffer, &inBuffer, ZSTD_e_end) );\n\n    ZSTD_freeCCtxParams(cctxParams);\n    ZSTD_freeCCtx(cctx);\n\n    return ZSTD_decompress(resultBuff, resultBuffCapacity, compressedBuff, outBuffer.pos);\n}\n\nstatic size_t checkBuffers(const void* buff1, const void* buff2, size_t buffSize)\n{\n    const char* ip1 = (const char*)buff1;\n    const char* ip2 = (const char*)buff2;\n    size_t pos;\n\n    for (pos=0; pos<buffSize; pos++)\n        if (ip1[pos]!=ip2[pos])\n            break;\n\n    return pos;\n}\n\nstatic void roundTripCheck(const void* srcBuff, size_t srcBuffSize, int testCCtxParams)\n{\n    size_t const cBuffSize = ZSTD_compressBound(srcBuffSize);\n    void* cBuff = malloc(cBuffSize);\n    void* rBuff = malloc(cBuffSize);\n\n    if (!cBuff || !rBuff) {\n        fprintf(stderr, \"not enough memory ! \\n\");\n        exit (1);\n    }\n\n    {   size_t const result = testCCtxParams ?\n                  cctxParamRoundTripTest(rBuff, cBuffSize, cBuff, cBuffSize, srcBuff, srcBuffSize)\n                : roundTripTest(rBuff, cBuffSize, cBuff, cBuffSize, srcBuff, srcBuffSize);\n        if (ZSTD_isError(result)) {\n            fprintf(stderr, \"roundTripTest error : %s \\n\", ZSTD_getErrorName(result));\n            crash(1);\n        }\n        if (result != srcBuffSize) {\n            fprintf(stderr, \"Incorrect regenerated size : %u != %u\\n\", (unsigned)result, (unsigned)srcBuffSize);\n            crash(1);\n        }\n        if (checkBuffers(srcBuff, rBuff, srcBuffSize) != srcBuffSize) {\n            fprintf(stderr, \"Silent decoding corruption !!!\");\n            crash(1);\n        }\n    }\n\n    free(cBuff);\n    free(rBuff);\n}\n\n\nstatic size_t getFileSize(const char* infilename)\n{\n    int r;\n#if defined(_MSC_VER)\n    struct _stat64 statbuf;\n    r = _stat64(infilename, &statbuf);\n    if (r || !(statbuf.st_mode & S_IFREG)) return 0;   /* No good... */\n#else\n    struct stat statbuf;\n    r = stat(infilename, &statbuf);\n    if (r || !S_ISREG(statbuf.st_mode)) return 0;   /* No good... */\n#endif\n    return (size_t)statbuf.st_size;\n}\n\n\nstatic int isDirectory(const char* infilename)\n{\n    int r;\n#if defined(_MSC_VER)\n    struct _stat64 statbuf;\n    r = _stat64(infilename, &statbuf);\n    if (!r && (statbuf.st_mode & _S_IFDIR)) return 1;\n#else\n    struct stat statbuf;\n    r = stat(infilename, &statbuf);\n    if (!r && S_ISDIR(statbuf.st_mode)) return 1;\n#endif\n    return 0;\n}\n\n\n/** loadFile() :\n*   requirement : `buffer` size >= `fileSize` */\nstatic void loadFile(void* buffer, const char* fileName, size_t fileSize)\n{\n    FILE* const f = fopen(fileName, \"rb\");\n    if (isDirectory(fileName)) {\n        fprintf(stderr, \"Ignoring %s directory \\n\", fileName);\n        exit(2);\n    }\n    if (f==NULL) {\n        fprintf(stderr, \"Impossible to open %s \\n\", fileName);\n        exit(3);\n    }\n    {   size_t const readSize = fread(buffer, 1, fileSize, f);\n        if (readSize != fileSize) {\n            fprintf(stderr, \"Error reading %s \\n\", fileName);\n            exit(5);\n    }   }\n    fclose(f);\n}\n\n\nstatic void fileCheck(const char* fileName, int testCCtxParams)\n{\n    size_t const fileSize = getFileSize(fileName);\n    void* const buffer = malloc(fileSize + !fileSize /* avoid 0 */);\n    if (!buffer) {\n        fprintf(stderr, \"not enough memory \\n\");\n        exit(4);\n    }\n    loadFile(buffer, fileName, fileSize);\n    roundTripCheck(buffer, fileSize, testCCtxParams);\n    free (buffer);\n}\n\nint main(int argCount, const char** argv) {\n    int argNb = 1;\n    int testCCtxParams = 0;\n    if (argCount < 2) {\n        fprintf(stderr, \"Error : no argument : need input file \\n\");\n        exit(9);\n    }\n\n    if (!strcmp(argv[argNb], \"--cctxParams\")) {\n      testCCtxParams = 1;\n      argNb++;\n    }\n\n    fileCheck(argv[argNb], testCCtxParams);\n    fprintf(stderr, \"no pb detected\\n\");\n    return 0;\n}\n"
  },
  {
    "path": "tests/seqgen.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"seqgen.h\"\n#include \"mem.h\"\n#include <string.h>\n\n#define MIN(a, b)  ((a) < (b) ? (a) : (b))\n\nstatic const size_t kMatchBytes = 128;\n\n#define SEQ_rotl32(x,r) ((x << r) | (x >> (32 - r)))\nstatic BYTE SEQ_randByte(unsigned* src)\n{\n    static const U32 prime1 = 2654435761U;\n    static const U32 prime2 = 2246822519U;\n    U32 rand32 = *src;\n    rand32 *= prime1;\n    rand32 ^= prime2;\n    rand32  = SEQ_rotl32(rand32, 13);\n    *src = rand32;\n    return (BYTE)(rand32 >> 5);\n}\n\nSEQ_stream SEQ_initStream(unsigned seed)\n{\n    SEQ_stream stream;\n    stream.state = 0;\n    XXH64_reset(&stream.xxh, 0);\n    stream.seed = seed;\n    return stream;\n}\n\n/* Generates a single guard byte, then match length + 1 of a different byte,\n * then another guard byte.\n */\nstatic size_t SEQ_gen_matchLength(SEQ_stream* stream, unsigned value,\n                                  SEQ_outBuffer* out)\n{\n    typedef enum {\n        ml_first_byte = 0,\n        ml_match_bytes,\n        ml_last_byte,\n    } ml_state;\n    BYTE* const ostart = (BYTE*)out->dst;\n    BYTE* const oend = ostart + out->size;\n    BYTE* op = ostart + out->pos;\n\n    switch ((ml_state)stream->state) {\n    case ml_first_byte:\n        /* Generate a single byte and pick a different byte for the match */\n        if (op >= oend) {\n            stream->bytesLeft = 1;\n            break;\n        }\n        *op = SEQ_randByte(&stream->seed) & 0xFF;\n        do {\n            stream->saved = SEQ_randByte(&stream->seed) & 0xFF;\n        } while (*op == stream->saved);\n        ++op;\n        /* State transition */\n        stream->state = ml_match_bytes;\n        stream->bytesLeft = value + 1;\n    /* fall-through */\n    case ml_match_bytes: {\n        /* Copy matchLength + 1 bytes to the output buffer */\n        size_t const setLength = MIN(stream->bytesLeft, (size_t)(oend - op));\n        if (setLength > 0) {\n            memset(op, stream->saved, setLength);\n            op += setLength;\n            stream->bytesLeft -= setLength;\n        }\n        if (stream->bytesLeft > 0)\n            break;\n        /* State transition */\n        stream->state = ml_last_byte;\n    }\n    /* fall-through */\n    case ml_last_byte:\n        /* Generate a single byte and pick a different byte for the match */\n        if (op >= oend) {\n            stream->bytesLeft = 1;\n            break;\n        }\n        do {\n            *op = SEQ_randByte(&stream->seed) & 0xFF;\n        } while (*op == stream->saved);\n        ++op;\n        /* State transition */\n    /* fall-through */\n    default:\n        stream->state = 0;\n        stream->bytesLeft = 0;\n        break;\n    }\n    XXH64_update(&stream->xxh, ostart + out->pos, (op - ostart) - out->pos);\n    out->pos = op - ostart;\n    return stream->bytesLeft;\n}\n\n/* Saves the current seed then generates kMatchBytes random bytes >= 128.\n * Generates literal length - kMatchBytes random bytes < 128.\n * Generates another kMatchBytes using the saved seed to generate a match.\n * This way the match is easy to find for the compressors.\n */\nstatic size_t SEQ_gen_litLength(SEQ_stream* stream, unsigned value, SEQ_outBuffer* out)\n{\n    typedef enum {\n        ll_start = 0,\n        ll_run_bytes,\n        ll_literals,\n        ll_run_match,\n    } ll_state;\n    BYTE* const ostart = (BYTE*)out->dst;\n    BYTE* const oend = ostart + out->size;\n    BYTE* op = ostart + out->pos;\n\n    switch ((ll_state)stream->state) {\n    case ll_start:\n        stream->state = ll_run_bytes;\n        stream->saved = stream->seed;\n        stream->bytesLeft = MIN(kMatchBytes, value);\n    /* fall-through */\n    case ll_run_bytes:\n        while (stream->bytesLeft > 0 && op < oend) {\n            *op++ = SEQ_randByte(&stream->seed) | 0x80;\n            --stream->bytesLeft;\n        }\n        if (stream->bytesLeft > 0)\n            break;\n        /* State transition */\n        stream->state = ll_literals;\n        stream->bytesLeft = value - MIN(kMatchBytes, value);\n    /* fall-through */\n    case ll_literals:\n        while (stream->bytesLeft > 0 && op < oend) {\n            *op++ = SEQ_randByte(&stream->seed) & 0x7F;\n            --stream->bytesLeft;\n        }\n        if (stream->bytesLeft > 0)\n            break;\n        /* State transition */\n        stream->state = ll_run_match;\n        stream->bytesLeft = MIN(kMatchBytes, value);\n    /* fall-through */\n    case ll_run_match: {\n        while (stream->bytesLeft > 0 && op < oend) {\n            *op++ = SEQ_randByte(&stream->saved) | 0x80;\n            --stream->bytesLeft;\n        }\n        if (stream->bytesLeft > 0)\n            break;\n    }\n    /* fall-through */\n    default:\n        stream->state = 0;\n        stream->bytesLeft = 0;\n        break;\n    }\n    XXH64_update(&stream->xxh, ostart + out->pos, (op - ostart) - out->pos);\n    out->pos = op - ostart;\n    return stream->bytesLeft;\n}\n\n/* Saves the current seed then generates kMatchBytes random bytes >= 128.\n * Generates offset - kMatchBytes of zeros to get a large offset without\n * polluting the hash tables.\n * Generates another kMatchBytes using the saved seed to generate a with the\n * required offset.\n */\nstatic size_t SEQ_gen_offset(SEQ_stream* stream, unsigned value, SEQ_outBuffer* out)\n{\n    typedef enum {\n        of_start = 0,\n        of_run_bytes,\n        of_offset,\n        of_run_match,\n    } of_state;\n    BYTE* const ostart = (BYTE*)out->dst;\n    BYTE* const oend = ostart + out->size;\n    BYTE* op = ostart + out->pos;\n\n    switch ((of_state)stream->state) {\n    case of_start:\n        stream->state = of_run_bytes;\n        stream->saved = stream->seed;\n        stream->bytesLeft = MIN(value, kMatchBytes);\n    /* fall-through */\n    case of_run_bytes: {\n        while (stream->bytesLeft > 0 && op < oend) {\n            *op++ = SEQ_randByte(&stream->seed) | 0x80;\n            --stream->bytesLeft;\n        }\n        if (stream->bytesLeft > 0)\n            break;\n        /* State transition */\n        stream->state = of_offset;\n        stream->bytesLeft = value - MIN(value, kMatchBytes);\n    }\n    /* fall-through */\n    case of_offset: {\n        /* Copy matchLength + 1 bytes to the output buffer */\n        size_t const setLength = MIN(stream->bytesLeft, (size_t)(oend - op));\n        if (setLength > 0) {\n            memset(op, 0, setLength);\n            op += setLength;\n            stream->bytesLeft -= setLength;\n        }\n        if (stream->bytesLeft > 0)\n            break;\n        /* State transition */\n        stream->state = of_run_match;\n        stream->bytesLeft = MIN(value, kMatchBytes);\n    }\n    /* fall-through */\n    case of_run_match: {\n        while (stream->bytesLeft > 0 && op < oend) {\n            *op++ = SEQ_randByte(&stream->saved) | 0x80;\n            --stream->bytesLeft;\n        }\n        if (stream->bytesLeft > 0)\n            break;\n    }\n    /* fall-through */\n    default:\n        stream->state = 0;\n        stream->bytesLeft = 0;\n        break;\n    }\n    XXH64_update(&stream->xxh, ostart + out->pos, (op - ostart) - out->pos);\n    out->pos = op - ostart;\n    return stream->bytesLeft;\n}\n\n/* Returns the number of bytes left to generate.\n * Must pass the same type/value until it returns 0.\n */\nsize_t SEQ_gen(SEQ_stream* stream, SEQ_gen_type type, unsigned value, SEQ_outBuffer* out)\n{\n    switch (type) {\n        case SEQ_gen_ml: return SEQ_gen_matchLength(stream, value, out);\n        case SEQ_gen_ll: return SEQ_gen_litLength(stream, value, out);\n        case SEQ_gen_of: return SEQ_gen_offset(stream, value, out);\n        case SEQ_gen_max: /* fall-through */\n        default: return 0;\n    }\n}\n\n/* Returns the xxhash of the data produced so far */\nXXH64_hash_t SEQ_digest(SEQ_stream const* stream)\n{\n    return XXH64_digest(&stream->xxh);\n}\n"
  },
  {
    "path": "tests/seqgen.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef SEQGEN_H\n#define SEQGEN_H\n\n#define XXH_STATIC_LINKING_ONLY\n\n#include \"xxhash.h\"\n#include <stddef.h>   /* size_t */\n\ntypedef enum {\n    SEQ_gen_ml = 0,\n    SEQ_gen_ll,\n    SEQ_gen_of,\n    SEQ_gen_max /* Must be the last value */\n} SEQ_gen_type;\n\n/* Internal state, do not use */\ntypedef struct {\n    XXH64_state_t xxh; /* xxh state for all the data produced so far (seed=0) */\n    unsigned seed;\n    int state; /* enum to control state machine (clean=0) */\n    unsigned saved;\n    size_t bytesLeft;\n} SEQ_stream;\n\nSEQ_stream SEQ_initStream(unsigned seed);\n\ntypedef struct {\n    void* dst;\n    size_t size;\n    size_t pos;\n} SEQ_outBuffer;\n\n/* Returns non-zero until the current type/value has been generated.\n * Must pass the same type/value until it returns 0.\n *\n * Recommended to pick a value in the middle of the range you want, since there\n * may be some noise that causes actual results to be slightly different.\n * We try to be more accurate for smaller values.\n *\n * NOTE: Very small values don't work well (< 6).\n */\nsize_t SEQ_gen(SEQ_stream* stream, SEQ_gen_type type, unsigned value,\n               SEQ_outBuffer* out);\n\n/* Returns the xxhash of the data produced so far */\nXXH64_hash_t SEQ_digest(SEQ_stream const* stream);\n\n#endif /* SEQGEN_H */\n"
  },
  {
    "path": "tests/test-license.py",
    "content": "#!/usr/bin/env python3\n\n# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ################################################################\n\nimport enum\nimport glob\nimport os\nimport re\nimport sys\n\nROOT = os.path.join(os.path.dirname(__file__), \"..\")\n\nRELDIRS = [\n    \"doc\",\n    \"examples\",\n    \"lib\",\n    \"programs\",\n    \"tests\",\n    \"contrib/linux-kernel\",\n]\n\nREL_EXCLUDES = [\n    \"contrib/linux-kernel/test/include\",\n]\n\ndef to_abs(d):\n    return os.path.normpath(os.path.join(ROOT, d)) + \"/\"\n\nDIRS = [to_abs(d) for d in RELDIRS]\nEXCLUDES = [to_abs(d) for d in REL_EXCLUDES]\n\nSUFFIXES = [\n    \".c\",\n    \".h\",\n    \"Makefile\",\n    \".mk\",\n    \".py\",\n    \".S\",\n]\n\n# License should certainly be in the first 10 KB.\nMAX_BYTES = 10000\nMAX_LINES = 50\n\nLICENSE_LINES = [\n    \"This source code is licensed under both the BSD-style license (found in the\",\n    \"LICENSE file in the root directory of this source tree) and the GPLv2 (found\",\n    \"in the COPYING file in the root directory of this source tree).\",\n    \"You may select, at your option, one of the above-listed licenses.\",\n]\n\nCOPYRIGHT_EXCEPTIONS = {\n    # From zstdmt\n    \"threading.c\",\n    \"threading.h\",\n    # From divsufsort\n    \"divsufsort.c\",\n    \"divsufsort.h\",\n}\n\nLICENSE_EXCEPTIONS = {\n    # From divsufsort\n    \"divsufsort.c\",\n    \"divsufsort.h\",\n    # License is slightly different because it references GitHub\n    \"linux_zstd.h\",\n}\n\n\ndef valid_copyright(lines):\n    YEAR_REGEX = re.compile(\"\\d\\d\\d\\d|present\")\n    for line in lines:\n        line = line.strip()\n        if \"Copyright\" not in line:\n            continue\n        if \"present\" in line:\n            return (False, f\"Copyright line '{line}' contains 'present'!\")\n        if \"Meta Platforms, Inc\" not in line:\n            return (False, f\"Copyright line '{line}' does not contain 'Meta Platforms, Inc'\")\n        year = YEAR_REGEX.search(line)\n        if year is not None:\n            return (False, f\"Copyright line '{line}' contains {year.group(0)}; it should be yearless\")\n        if \" (c) \" not in line:\n            return (False, f\"Copyright line '{line}' does not contain ' (c) '!\")\n        return (True, \"\")\n    return (False, \"Copyright not found!\")\n\n\ndef valid_license(lines):\n    for b in range(len(lines)):\n        if LICENSE_LINES[0] not in lines[b]:\n            continue\n        for l in range(len(LICENSE_LINES)):\n            if LICENSE_LINES[l] not in lines[b + l]:\n                message = f\"\"\"Invalid license line found starting on line {b + l}!\nExpected: '{LICENSE_LINES[l]}'\nActual: '{lines[b + l]}'\"\"\"\n                return (False, message)\n        return (True, \"\")\n    return (False, \"License not found!\")\n\n\ndef valid_file(filename):\n    with open(filename, \"r\") as f:\n        lines = f.readlines(MAX_BYTES)\n    lines = lines[:min(len(lines), MAX_LINES)]\n\n    ok = True\n    if os.path.basename(filename) not in COPYRIGHT_EXCEPTIONS:\n        c_ok, c_msg = valid_copyright(lines)\n        if not c_ok:\n            print(f\"{filename}: {c_msg}\", file=sys.stderr)\n            ok = False\n    if os.path.basename(filename) not in LICENSE_EXCEPTIONS:\n        l_ok, l_msg = valid_license(lines)\n        if not l_ok:\n            print(f\"{filename}: {l_msg}\", file=sys.stderr)\n            ok = False\n    return ok\n\n\ndef exclude(filename):\n    for x in EXCLUDES:\n        if filename.startswith(x):\n            return True\n    return False\n\ndef main():\n    invalid_files = []\n    for directory in DIRS:\n        for suffix in SUFFIXES:\n            files = set(glob.glob(f\"{directory}/**/*{suffix}\", recursive=True))\n            for filename in files:\n                if exclude(filename):\n                    continue\n                if not valid_file(filename):\n                    invalid_files.append(filename)\n    if len(invalid_files) > 0:\n        print(\"Fail!\", file=sys.stderr)\n        for f in invalid_files:\n            print(f)\n        return 1\n    else:\n        print(\"Pass!\", file=sys.stderr)\n        return 0\n\nif __name__ == \"__main__\":\n    sys.exit(main())\n"
  },
  {
    "path": "tests/test-variants.sh",
    "content": "#!/bin/sh\nset -e\nset -u\nset -x\n\n\nSCRIPT_DIR=$(cd \"$(dirname \"$0\")\" && pwd)\nPROG_DIR=\"$SCRIPT_DIR/../programs\"\n\nZSTD=\"$PROG_DIR/zstd\"\nZSTD_COMPRESS=\"$PROG_DIR/zstd-compress\"\nZSTD_DECOMPRESS=\"$PROG_DIR/zstd-decompress\"\nZSTD_NOLEGACY=\"$PROG_DIR/zstd-nolegacy\"\nZSTD_DICTBUILDER=\"$PROG_DIR/zstd-dictBuilder\"\nZSTD_FRUGAL=\"$PROG_DIR/zstd-frugal\"\nZSTD_NOMT=\"$PROG_DIR/zstd-nomt\"\n\nprintln() {\n    printf '%b\\n' \"${*}\"\n}\n\ndie() {\n    println \"$@\" 1>&2\n    exit 1\n}\n\nsymbol_present() {\n\t(nm $1 || echo \"symbol_present $@ failed\") | grep $2\n}\n\nsymbol_not_present() {\n\tsymbol_present $@ && die \"Binary '$1' mistakenly contains symbol '$2'\" ||:\n}\n\ncompress_not_present() {\n\tsymbol_not_present \"$1\" ZSTD_compress\n}\n\ndecompress_not_present() {\n\tsymbol_not_present \"$1\" ZSTD_decompress\n}\n\ndict_not_present() {\n\tsymbol_not_present \"$1\" ZDICT_\n\tsymbol_not_present \"$1\" COVER_\n}\n\ncliextra_not_present() {\n\tsymbol_not_present \"$1\" TRACE_\n\tsymbol_not_present \"$1\" BMK_\n}\n\nlegacy_not_present() {\n\tsymbol_not_present \"$1\" ZSTDv0\n}\n\ntest_help() {\n\t\"$1\" --help | grep -- \"$2\"\n}\n\ntest_no_help() {\n\ttest_help $@ && die \"'$1' supports '$2' when it shouldn't\" ||:\n}\n\nextras_not_present() {\n\tdict_not_present $@\n\tlegacy_not_present $@\n\tcliextra_not_present $@\n\ttest_no_help $@ \"--train\"\n\ttest_no_help $@ \"-b#\"\n}\n\ntest_compress() {\n\techo \"hello\" | \"$1\" | \"$ZSTD\" -t\n}\n\ntest_decompress() {\n\techo \"hello\" | \"$ZSTD\" | \"$1\" -t\n}\n\ntest_zstd() {\n\ttest_compress $@\n\ttest_decompress $@\n}\n\nextras_not_present \"$ZSTD_FRUGAL\"\nextras_not_present \"$ZSTD_COMPRESS\"\nextras_not_present \"$ZSTD_DECOMPRESS\"\n\ncompress_not_present \"$ZSTD_DECOMPRESS\"\n\ndecompress_not_present \"$ZSTD_COMPRESS\"\ndecompress_not_present \"$ZSTD_DICTBUILDER\"\n\ncliextra_not_present \"$ZSTD_DICTBUILDER\"\n\nlegacy_not_present \"$ZSTD_DICTBUILDER\"\nlegacy_not_present \"$ZSTD_NOLEGACY\"\n\nsymbol_not_present \"$ZSTD\" ZSTDv01\nsymbol_not_present \"$ZSTD\" ZSTDv02\nsymbol_not_present \"$ZSTD\" ZSTDv03\nsymbol_not_present \"$ZSTD\" ZSTDv04\n\ntest_compress \"$ZSTD_COMPRESS\"\ntest_decompress \"$ZSTD_DECOMPRESS\"\n\ntest_zstd \"$ZSTD_FRUGAL\"\ntest_zstd \"$ZSTD_NOLEGACY\"\n\ntest_help \"$ZSTD\" '-b#'\ntest_help \"$ZSTD\" --train\ntest_help \"$ZSTD_DICTBUILDER\" --train\n\nprintln \"Success!\"\n"
  },
  {
    "path": "tests/test-zstd-versions.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Test zstd interoperability between versions\"\"\"\n\n# ################################################################\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under both the BSD-style license (found in the\n# LICENSE file in the root directory of this source tree) and the GPLv2 (found\n# in the COPYING file in the root directory of this source tree).\n# You may select, at your option, one of the above-listed licenses.\n# ################################################################\n\nimport filecmp\nimport glob\nimport hashlib\nimport os\nimport shutil\nimport sys\nimport subprocess\nfrom subprocess import Popen, PIPE\n\nrepo_url = 'https://github.com/facebook/zstd.git'\ntmp_dir_name = 'tests/versionsTest'\nmake_cmd = 'make'\nmake_args = ['-j','CFLAGS=-O0']\ngit_cmd = 'git'\ntest_dat_src = 'README.md'\ntest_dat = 'test_dat'\nhead = 'vdevel'\ndict_source = 'dict_source'\ndict_globs = [\n    'programs/*.c',\n    'lib/common/*.c',\n    'lib/compress/*.c',\n    'lib/decompress/*.c',\n    'lib/dictBuilder/*.c',\n    'lib/legacy/*.c',\n    'programs/*.h',\n    'lib/common/*.h',\n    'lib/compress/*.h',\n    'lib/dictBuilder/*.h',\n    'lib/legacy/*.h'\n]\n\n\ndef execute(command, print_output=False, print_error=True, param_shell=False):\n    popen = Popen(command, stdout=PIPE, stderr=PIPE, shell=param_shell)\n    stdout_lines, stderr_lines = popen.communicate()\n    stderr_lines = stderr_lines.decode(\"utf-8\")\n    stdout_lines = stdout_lines.decode(\"utf-8\")\n    if print_output:\n        print(stdout_lines)\n        print(stderr_lines)\n    if popen.returncode is not None and popen.returncode != 0:\n        if not print_output and print_error:\n            print(stderr_lines)\n    return popen.returncode\n\n\ndef proc(cmd_args, pipe=True, dummy=False):\n    if dummy:\n        return\n    if pipe:\n        subproc = Popen(cmd_args, stdout=PIPE, stderr=PIPE)\n    else:\n        subproc = Popen(cmd_args)\n    return subproc.communicate()\n\n\ndef make(targets, pipe=True):\n    cmd = [make_cmd] + make_args + targets\n    cmd_str = str(cmd)\n    print('compilation command : ' + cmd_str)\n    return proc(cmd, pipe)\n\n\ndef git(args, pipe=True):\n    return proc([git_cmd] + args, pipe)\n\n\ndef get_git_tags():\n    stdout, stderr = git(['tag', '-l', 'v[0-9].[0-9].[0-9]'])\n    tags = stdout.decode('utf-8').split()\n    return tags\n\n\ndef dict_ok(tag, dict_name, sample):\n    if not os.path.isfile(dict_name):\n        return False\n    try:\n        cmd = ['./zstd.' + tag, '-D', dict_name]\n        with open(sample, \"rb\") as i:\n            subprocess.check_call(cmd, stdin=i, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)\n        return True\n    except:\n        return False\n\n\ndef create_dict(tag, dict_source_path, fallback_tag=None):\n    dict_name = 'dict.' + tag\n    if not os.path.isfile(dict_name):\n        cFiles = glob.glob(dict_source_path + \"/*.c\")\n        hFiles = glob.glob(dict_source_path + \"/*.h\")\n        # Ensure the dictionary builder is deterministic\n        files = sorted(cFiles + hFiles)\n        if tag == 'v0.5.0':\n            result = execute('./dictBuilder.' + tag + ' ' + ' '.join(files) + ' -o ' + dict_name, print_output=False, param_shell=True)\n        else:\n            result = execute('./zstd.' + tag + ' -f --train ' + ' '.join(files) + ' -o ' + dict_name, print_output=False, param_shell=True)\n        if result == 0 and dict_ok(tag, dict_name, files[0]):\n            print(dict_name + ' created')\n        elif fallback_tag is not None:\n            fallback_dict_name = 'dict.' + fallback_tag\n            print('creating dictionary ' + dict_name + ' failed, falling back to ' + fallback_dict_name)\n            shutil.copy(fallback_dict_name, dict_name)\n        else:\n            raise RuntimeError('ERROR: creating of ' + dict_name + ' failed')\n    else:\n        print(dict_name + ' already exists')\n\n\ndef zstd(tag, args, input_file, output_file):\n    \"\"\"\n    Zstd compress input_file to output_file.\n    Need this helper because 0.5.0 is broken when stdout is not a TTY.\n    Throws an exception if the command returns non-zero.\n    \"\"\"\n    with open(input_file, \"rb\") as i:\n        with open(output_file, \"wb\") as o:\n            cmd = ['./zstd.' + tag] + args\n            print(\"Running: '{}', input={}, output={}\" .format(\n                ' '.join(cmd), input_file, output_file\n            ))\n            result = subprocess.run(cmd, stdin=i, stdout=o, stderr=subprocess.PIPE)\n            print(\"Stderr: {}\".format(result.stderr.decode(\"ascii\")))\n            result.check_returncode()\n\n\ndef dict_compress_sample(tag, sample):\n    dict_name = 'dict.' + tag\n    verbose = ['-v', '-v', '-v']\n    zstd(tag, ['-D', dict_name, '-1'] + verbose, sample, sample + '_01_64_' + tag + '_dictio.zst')\n    zstd(tag, ['-D', dict_name, '-3'], sample, sample + '_03_64_' + tag + '_dictio.zst')\n    zstd(tag, ['-D', dict_name, '-5'], sample, sample + '_05_64_' + tag + '_dictio.zst')\n    zstd(tag, ['-D', dict_name, '-9'], sample, sample + '_09_64_' + tag + '_dictio.zst')\n    zstd(tag, ['-D', dict_name, '-15'], sample, sample + '_15_64_' + tag + '_dictio.zst')\n    zstd(tag, ['-D', dict_name, '-18'], sample, sample + '_18_64_' + tag + '_dictio.zst')\n    # zstdFiles = glob.glob(\"*.zst*\")\n    # print(zstdFiles)\n    print(tag + \" : dict compression completed\")\n\n\ndef compress_sample(tag, sample):\n    zstd(tag, ['-1'], sample, sample + '_01_64_' + tag + '_nodict.zst')\n    zstd(tag, ['-3'], sample, sample + '_03_64_' + tag + '_nodict.zst')\n    zstd(tag, ['-5'], sample, sample + '_05_64_' + tag + '_nodict.zst')\n    zstd(tag, ['-9'], sample, sample + '_09_64_' + tag + '_nodict.zst')\n    zstd(tag, ['-15'], sample, sample + '_15_64_' + tag + '_nodict.zst')\n    zstd(tag, ['-18'], sample, sample + '_18_64_' + tag + '_nodict.zst')\n    # zstdFiles = glob.glob(\"*.zst*\")\n    # print(zstdFiles)\n    print(tag + \" : compression completed\")\n\n\n# https://stackoverflow.com/a/19711609/2132223\ndef sha1_of_file(filepath):\n    with open(filepath, 'rb') as f:\n        return hashlib.sha1(f.read()).hexdigest()\n\n\ndef remove_duplicates():\n    list_of_zst = sorted(glob.glob('*.zst'))\n    for i, ref_zst in enumerate(list_of_zst):\n        if not os.path.isfile(ref_zst):\n            continue\n        for j in range(i + 1, len(list_of_zst)):\n            compared_zst = list_of_zst[j]\n            if not os.path.isfile(compared_zst):\n                continue\n            if filecmp.cmp(ref_zst, compared_zst):\n                os.remove(compared_zst)\n                print('duplicated : {} == {}'.format(ref_zst, compared_zst))\n\n\ndef decompress_zst(tag):\n    dec_error = 0\n    list_zst = sorted(glob.glob('*_nodict.zst'))\n    for file_zst in list_zst:\n        print(file_zst + ' ' + tag)\n        file_dec = file_zst + '_d64_' + tag + '.dec'\n        zstd(tag, ['-d'], file_zst, file_dec)\n        if not filecmp.cmp(file_dec, test_dat):\n            raise RuntimeError('Decompression failed: tag={} file={}'.format(tag, file_zst))\n        else:\n            print('OK     ')\n\n\ndef decompress_dict(tag):\n    dec_error = 0\n    list_zst = sorted(glob.glob('*_dictio.zst'))\n    for file_zst in list_zst:\n        dict_tag = file_zst[0:len(file_zst)-11]  # remove \"_dictio.zst\"\n        if head in dict_tag: # find vdevel\n            dict_tag = head\n        else:\n            dict_tag = dict_tag[dict_tag.rfind('v'):]\n        if tag == 'v0.6.0' and dict_tag < 'v0.6.0':\n            continue\n        dict_name = 'dict.' + dict_tag\n        print(file_zst + ' ' + tag + ' dict=' + dict_tag)\n        file_dec = file_zst + '_d64_' + tag + '.dec'\n        zstd(tag, ['-D', dict_name, '-d'], file_zst, file_dec)\n        if not filecmp.cmp(file_dec, test_dat):\n            raise RuntimeError('Decompression failed: tag={} file={}'.format(tag, file_zst))\n        else:\n            print('OK     ')\n\n\nif __name__ == '__main__':\n    error_code = 0\n    base_dir = os.getcwd() + '/..'                  # /path/to/zstd\n    tmp_dir = base_dir + '/' + tmp_dir_name         # /path/to/zstd/tests/versionsTest\n    clone_dir = tmp_dir + '/' + 'zstd'              # /path/to/zstd/tests/versionsTest/zstd\n    dict_source_path = tmp_dir + '/' + dict_source  # /path/to/zstd/tests/versionsTest/dict_source\n    programs_dir = base_dir + '/programs'           # /path/to/zstd/programs\n    os.makedirs(tmp_dir, exist_ok=True)\n\n    # since Travis clones limited depth, we should clone full repository\n    if not os.path.isdir(clone_dir):\n        git(['clone', repo_url, clone_dir])\n\n    shutil.copy2(base_dir + '/' + test_dat_src, tmp_dir + '/' + test_dat)\n\n    # Retrieve all release tags\n    print('Retrieve all release tags :')\n    os.chdir(clone_dir)\n    alltags = get_git_tags() + [head]\n    tags = [t for t in alltags if t >= 'v0.5.0']\n    print(tags)\n\n    # Build all release zstd\n    for tag in tags:\n        os.chdir(base_dir)\n        dst_zstd = '{}/zstd.{}'.format(tmp_dir, tag)  # /path/to/zstd/tests/versionsTest/zstd.<TAG>\n        if not os.path.isfile(dst_zstd) or tag == head:\n            if tag != head:\n                print('-----------------------------------------------')\n                print('compiling ' + tag)\n                print('-----------------------------------------------')\n                r_dir = '{}/{}'.format(tmp_dir, tag)  # /path/to/zstd/tests/versionsTest/<TAG>\n                os.makedirs(r_dir, exist_ok=True)\n                os.chdir(clone_dir)\n                git(['--work-tree=' + r_dir, 'checkout', tag, '--', '.'], False)\n                if tag == 'v0.5.0':\n                    os.chdir(r_dir + '/dictBuilder')  # /path/to/zstd/tests/versionsTest/v0.5.0/dictBuilder\n                    make(['clean'], False)   # separate 'clean' target to allow parallel build\n                    make(['dictBuilder'], False)\n                    shutil.copy2('dictBuilder', '{}/dictBuilder.{}'.format(tmp_dir, tag))\n                os.chdir(r_dir + '/programs')  # /path/to/zstd/tests/versionsTest/<TAG>/programs\n                make(['clean'], False)  # separate 'clean' target to allow parallel build\n                # Enable legacy support for cross-version compatibility testing.\n                # Use ZSTD_LEGACY_SUPPORT=1 for v0.6.x due to a bug where headers\n                # check for ==1 but code checks for >=1.\n                # Use ZSTD_LEGACY_SUPPORT=5 for v1.2.0+ because =1 includes old\n                # legacy files (v01-v04) that have missing includes in newer versions.\n                if tag < 'v1.2.0':\n                    make(['zstd', 'ZSTD_LEGACY_SUPPORT=1'], False)\n                else:\n                    make(['zstd', 'ZSTD_LEGACY_SUPPORT=5'], False)\n            else:\n                os.chdir(programs_dir)\n                print('-----------------------------------------------')\n                print('compiling head')\n                print('-----------------------------------------------')\n                # Enable legacy support for head to test cross-version compatibility\n                # (legacy support is disabled by default since v1.6.0)\n                make(['zstd', 'ZSTD_LEGACY_SUPPORT=5'], False)\n            shutil.copy2('zstd', dst_zstd)\n\n    # remove any remaining *.zst and *.dec from previous test\n    os.chdir(tmp_dir)\n    for compressed in glob.glob(\"*.zst\"):\n        os.remove(compressed)\n    for dec in glob.glob(\"*.dec\"):\n        os.remove(dec)\n\n    # copy *.c and *.h to a temporary directory (\"dict_source\")\n    if not os.path.isdir(dict_source_path):\n        os.mkdir(dict_source_path)\n        for dict_glob in dict_globs:\n            files = glob.glob(dict_glob, root_dir=base_dir)\n            for file in files:\n                file = os.path.join(base_dir, file)\n                print(\"copying \" + file + \" to \" + dict_source_path)\n                shutil.copy(file, dict_source_path)\n\n    print('-----------------------------------------------')\n    print('Compress test.dat by all released zstd')\n    print('-----------------------------------------------')\n\n    create_dict(head, dict_source_path)\n    for tag in tags:\n        print(tag)\n        if tag >= 'v0.5.0':\n            create_dict(tag, dict_source_path, head)\n            dict_compress_sample(tag, test_dat)\n            remove_duplicates()\n            decompress_dict(tag)\n        compress_sample(tag, test_dat)\n        remove_duplicates()\n        decompress_zst(tag)\n\n    print('')\n    print('Enumerate different compressed files')\n    zstds = sorted(glob.glob('*.zst'))\n    for zstd in zstds:\n        print(zstd + ' : ' + repr(os.path.getsize(zstd)) + ', ' + sha1_of_file(zstd))\n"
  },
  {
    "path": "tests/test_process_substitution.bash",
    "content": "#!/usr/bin/env bash\n# test_process_substitution.bash\n# Test zstd's support for process substitution with --filelist\n\n# Process arguments\nZSTD_PATH=\"zstd\"  # Default to using zstd from PATH\nif [ $# -ge 1 ]; then\n    ZSTD_PATH=\"$1\"\nfi\n\necho \"Using zstd executable: $ZSTD_PATH\"\n\nset -e  # Exit on error\n\n# Set up test directory and files\necho \"Setting up test environment...\"\nTEST_DIR=\"tmp_process_substit\"\nrm -rf \"$TEST_DIR\"\nmkdir -p \"$TEST_DIR\"\necho \"Content of file 1\" > \"$TEST_DIR/file1.txt\"\necho \"Content of file 2\" > \"$TEST_DIR/file2.txt\"\necho \"Content of file 3\" > \"$TEST_DIR/file3.txt\"\n\n# Clean up any previous test artifacts\nrm -f \"$TEST_DIR/output.zst\" \"$TEST_DIR/output_echo.zst\" \"$TEST_DIR/output_cat.zst\"\nrm -rf \"$TEST_DIR/extracted\"\nmkdir -p \"$TEST_DIR/extracted\"\n\necho \"=== Testing process substitution with --filelist ===\"\n\n# Test 1: Basic process substitution with find\necho \"Test 1: Basic process substitution (find command)\"\n\"$ZSTD_PATH\" --filelist=<(find \"$TEST_DIR\" -name \"*.txt\" | sort) -c > \"$TEST_DIR/output.zst\"\n\nif [ -f \"$TEST_DIR/output.zst\" ]; then\n    echo \"✓ Test 1 PASSED: Output file was created\"\nelse\n    echo \"✗ Test 1 FAILED: Output file was not created\"\n    exit 1\nfi\n\n# Test 2: Process substitution with echo\necho \"Test 2: Process substitution (echo command)\"\n\"$ZSTD_PATH\" --filelist=<(echo -e \"$TEST_DIR/file1.txt\\n$TEST_DIR/file2.txt\") -c > \"$TEST_DIR/output_echo.zst\"\n\nif [ -f \"$TEST_DIR/output_echo.zst\" ]; then\n    echo \"✓ Test 2 PASSED: Output file was created\"\nelse\n    echo \"✗ Test 2 FAILED: Output file was not created\"\n    exit 1\nfi\n\n# Test 3: Process substitution with cat\necho \"Test 3: Process substitution (cat command)\"\necho -e \"$TEST_DIR/file1.txt\\n$TEST_DIR/file3.txt\" > \"$TEST_DIR/filelist.txt\"\n\"$ZSTD_PATH\" --filelist=<(cat \"$TEST_DIR/filelist.txt\") -c > \"$TEST_DIR/output_cat.zst\"\n\nif [ -f \"$TEST_DIR/output_cat.zst\" ]; then\n    echo \"✓ Test 3 PASSED: Output file was created\"\nelse\n    echo \"✗ Test 3 FAILED: Output file was not created\"\n    exit 1\nfi\n\n# Test 4: Verify contents of archives\necho \"Test 4: Verifying archive contents\"\n\"$ZSTD_PATH\" -d \"$TEST_DIR/output.zst\" -o \"$TEST_DIR/extracted/combined.out\"\n\nif grep -q \"Content of file 1\" \"$TEST_DIR/extracted/combined.out\" &&\n   grep -q \"Content of file 2\" \"$TEST_DIR/extracted/combined.out\" &&\n   grep -q \"Content of file 3\" \"$TEST_DIR/extracted/combined.out\"; then\n    echo \"✓ Test 4 PASSED: All files were correctly archived and extracted\"\nelse\n    echo \"✗ Test 4 FAILED: Not all expected content was found in the extracted file\"\n    exit 1\nfi\n\n# Test 5: Edge case with empty list\necho \"Test 5: Process substitution with empty input\"\n\"$ZSTD_PATH\" --filelist=<(echo \"\") -c > \"$TEST_DIR/output_empty.zst\" 2>/dev/null || true\n\nif [ -f \"$TEST_DIR/output_empty.zst\" ]; then\n    echo \"✓ Test 5 PASSED: Handled empty input gracefully\"\nelse\n    echo \"✓ Test 5 PASSED: Properly rejected empty input\"\nfi\n\n# cleanup\nrm -rf \"$TEST_DIR\"\n\necho \"All tests completed successfully!\"\n\n"
  },
  {
    "path": "tests/zstreamtest.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/*-************************************\n *  Compiler specific\n **************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  define _CRT_SECURE_NO_WARNINGS   /* fgets */\n#  pragma warning(disable : 4127)   /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4146)   /* disable: C4146: minus unsigned expression */\n#endif\n\n\n/*-************************************\n *  Includes\n **************************************/\n#include <stdlib.h>       /* free */\n#include <stdio.h>        /* fgets, sscanf */\n#include <string.h>       /* strcmp */\n#include <time.h>         /* time_t, time(), to randomize seed */\n#include <assert.h>       /* assert */\n#include \"timefn.h\"       /* UTIL_time_t, UTIL_getTime */\n#include \"mem.h\"\n#define ZSTD_DISABLE_DEPRECATE_WARNINGS /* No deprecation warnings, we still test some deprecated functions */\n#define ZSTD_STATIC_LINKING_ONLY  /* ZSTD_maxCLevel, ZSTD_customMem, ZSTD_getDictID_fromFrame */\n#include \"zstd.h\"         /* ZSTD_compressBound */\n#include \"zstd_errors.h\"  /* ZSTD_error_srcSize_wrong */\n#include \"zdict.h\"        /* ZDICT_trainFromBuffer */\n#include \"datagen.h\"      /* RDG_genBuffer */\n#define XXH_STATIC_LINKING_ONLY   /* XXH64_state_t */\n#include \"xxhash.h\"       /* XXH64_* */\n#include \"seqgen.h\"\n#include \"util.h\"\n#include \"timefn.h\"       /* UTIL_time_t, UTIL_clockSpanMicro, UTIL_getTime */\n#include \"external_matchfinder.h\"   /* zstreamSequenceProducer, EMF_testCase */\n\n/*-************************************\n *  Constants\n **************************************/\n#define KB *(1U<<10)\n#define MB *(1U<<20)\n#define GB *(1U<<30)\n\nstatic const int nbTestsDefault = 10000;\nstatic const U32 g_cLevelMax_smallTests = 10;\n#define COMPRESSIBLE_NOISE_LENGTH (10 MB)\n#define FUZ_COMPRESSIBILITY_DEFAULT 50\nstatic const U32 prime32 = 2654435761U;\n\n\n/*-************************************\n *  Display Macros\n **************************************/\n#define DISPLAY(...)          fprintf(stderr, __VA_ARGS__)\n#define DISPLAYLEVEL(l, ...)  if (g_displayLevel>=l) {                     \\\n                                  DISPLAY(__VA_ARGS__);                    \\\n                                  if (g_displayLevel>=4) fflush(stderr); }\nstatic U32 g_displayLevel = 2;\n\nstatic const U64 g_refreshRate = SEC_TO_MICRO / 6;\nstatic UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER;\n\n#define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \\\n            if ((UTIL_clockSpanMicro(g_displayClock) > g_refreshRate) || (g_displayLevel>=4)) \\\n            { g_displayClock = UTIL_getTime(); DISPLAY(__VA_ARGS__); \\\n            if (g_displayLevel>=4) fflush(stderr); } }\n\nstatic U64 g_clockTime = 0;\n\n\n/*-*******************************************************\n *  Check macros\n *********************************************************/\n#undef MIN\n#undef MAX\n#define MIN(a,b) ((a)<(b)?(a):(b))\n#define MAX(a,b) ((a)>(b)?(a):(b))\n/*! FUZ_rand() :\n    @return : a 27 bits random value, from a 32-bits `seed`.\n    `seed` is also modified */\n#define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r)))\nstatic U32 FUZ_rand(U32* seedPtr)\n{\n    static const U32 prime2 = 2246822519U;\n    U32 rand32 = *seedPtr;\n    rand32 *= prime32;\n    rand32 += prime2;\n    rand32  = FUZ_rotl32(rand32, 13);\n    *seedPtr = rand32;\n    return rand32 >> 5;\n}\n\n#define CHECK(cond, ...) {                                   \\\n    if (cond) {                                              \\\n        DISPLAY(\"Error => \");                                \\\n        DISPLAY(__VA_ARGS__);                                \\\n        DISPLAY(\" (seed %u, test nb %u, line %u) \\n\",        \\\n                (unsigned)seed, testNb, __LINE__);           \\\n        goto _output_error;                                  \\\n}   }\n\n#define CHECK_Z(f) {                                         \\\n    size_t const err = f;                                    \\\n    CHECK(ZSTD_isError(err), \"%s : %s \",                     \\\n          #f, ZSTD_getErrorName(err));                       \\\n}\n\n#define CHECK_RET(ret, cond, ...) {                          \\\n    if (cond) {                                              \\\n        DISPLAY(\"Error %llu => \", (unsigned long long)ret);  \\\n        DISPLAY(__VA_ARGS__);                                \\\n        DISPLAY(\" (line %u)\\n\", __LINE__);                   \\\n        return ret;                                          \\\n}   }\n\n#define CHECK_RET_Z(f) {                                     \\\n    size_t const err = f;                                    \\\n    CHECK_RET(err, ZSTD_isError(err), \"%s : %s \",            \\\n          #f, ZSTD_getErrorName(err));                       \\\n}\n\n\n/*======================================================\n *   Basic Unit tests\n *======================================================*/\n\ntypedef struct {\n    void* start;\n    size_t size;\n    size_t filled;\n} buffer_t;\n\nstatic const buffer_t kBuffNull = { NULL, 0 , 0 };\n\nstatic void FUZ_freeDictionary(buffer_t dict)\n{\n    free(dict.start);\n}\n\nstatic buffer_t FUZ_createDictionary(const void* src, size_t srcSize, size_t blockSize, size_t requestedDictSize)\n{\n    buffer_t dict = kBuffNull;\n    size_t const nbBlocks = (srcSize + (blockSize-1)) / blockSize;\n    size_t* const blockSizes = (size_t*)malloc(nbBlocks * sizeof(size_t));\n    if (!blockSizes) return kBuffNull;\n    dict.start = malloc(requestedDictSize);\n    if (!dict.start) { free(blockSizes); return kBuffNull; }\n    {   size_t nb;\n        for (nb=0; nb<nbBlocks-1; nb++) blockSizes[nb] = blockSize;\n        blockSizes[nbBlocks-1] = srcSize - (blockSize * (nbBlocks-1));\n    }\n    {   size_t const dictSize = ZDICT_trainFromBuffer(dict.start, requestedDictSize, src, blockSizes, (unsigned)nbBlocks);\n        free(blockSizes);\n        if (ZDICT_isError(dictSize)) { FUZ_freeDictionary(dict); return kBuffNull; }\n        dict.size = requestedDictSize;\n        dict.filled = dictSize;\n        return dict;\n    }\n}\n\n/* Round trips data and updates xxh with the decompressed data produced */\nstatic size_t SEQ_roundTrip(ZSTD_CCtx* cctx, ZSTD_DCtx* dctx,\n                            XXH64_state_t* xxh, void* data, size_t size,\n                            ZSTD_EndDirective endOp)\n{\n    static BYTE compressed[1024];\n    static BYTE uncompressed[1024];\n\n    ZSTD_inBuffer cin = {data, size, 0};\n    size_t cret;\n\n    do {\n        ZSTD_outBuffer cout = { compressed, sizeof(compressed), 0 };\n        ZSTD_inBuffer din   = { compressed, 0, 0 };\n        ZSTD_outBuffer dout = { uncompressed, 0, 0 };\n\n        cret = ZSTD_compressStream2(cctx, &cout, &cin, endOp);\n        if (ZSTD_isError(cret))\n            return cret;\n\n        din.size = cout.pos;\n        while (din.pos < din.size || (endOp == ZSTD_e_end && cret == 0)) {\n            size_t dret;\n\n            dout.pos = 0;\n            dout.size = sizeof(uncompressed);\n            dret = ZSTD_decompressStream(dctx, &dout, &din);\n            if (ZSTD_isError(dret))\n                return dret;\n            XXH64_update(xxh, dout.dst, dout.pos);\n            if (dret == 0)\n                break;\n        }\n    } while (cin.pos < cin.size || (endOp != ZSTD_e_continue && cret != 0));\n    return 0;\n}\n\n/* Generates some data and round trips it */\nstatic size_t SEQ_generateRoundTrip(ZSTD_CCtx* cctx, ZSTD_DCtx* dctx,\n                                    XXH64_state_t* xxh, SEQ_stream* seq,\n                                    SEQ_gen_type type, unsigned value)\n{\n    static BYTE data[1024];\n    size_t gen;\n\n    do {\n        SEQ_outBuffer sout = {data, sizeof(data), 0};\n        size_t ret;\n        gen = SEQ_gen(seq, type, value, &sout);\n\n        ret = SEQ_roundTrip(cctx, dctx, xxh, sout.dst, sout.pos, ZSTD_e_continue);\n        if (ZSTD_isError(ret))\n            return ret;\n    } while (gen != 0);\n\n    return 0;\n}\n\nstatic size_t getCCtxParams(ZSTD_CCtx* zc, ZSTD_parameters* savedParams)\n{\n    int value;\n    CHECK_RET_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_windowLog, (int*)&savedParams->cParams.windowLog));\n    CHECK_RET_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_hashLog, (int*)&savedParams->cParams.hashLog));\n    CHECK_RET_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_chainLog, (int*)&savedParams->cParams.chainLog));\n    CHECK_RET_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_searchLog, (int*)&savedParams->cParams.searchLog));\n    CHECK_RET_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_minMatch, (int*)&savedParams->cParams.minMatch));\n    CHECK_RET_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_targetLength, (int*)&savedParams->cParams.targetLength));\n    CHECK_RET_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_strategy, &value));\n    savedParams->cParams.strategy = value;\n\n    CHECK_RET_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_checksumFlag, &savedParams->fParams.checksumFlag));\n    CHECK_RET_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_contentSizeFlag, &savedParams->fParams.contentSizeFlag));\n    CHECK_RET_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_dictIDFlag, &value));\n    savedParams->fParams.noDictIDFlag = !value;\n    return 0;\n}\n\nstatic U32 badParameters(ZSTD_CCtx* zc, ZSTD_parameters const savedParams)\n{\n    ZSTD_parameters params;\n    if (ZSTD_isError(getCCtxParams(zc, &params))) return 10;\n    CHECK_RET(1, params.cParams.windowLog != savedParams.cParams.windowLog, \"windowLog\");\n    CHECK_RET(2, params.cParams.hashLog != savedParams.cParams.hashLog, \"hashLog\");\n    CHECK_RET(3, params.cParams.chainLog != savedParams.cParams.chainLog, \"chainLog\");\n    CHECK_RET(4, params.cParams.searchLog != savedParams.cParams.searchLog, \"searchLog\");\n    CHECK_RET(5, params.cParams.minMatch != savedParams.cParams.minMatch, \"minMatch\");\n    CHECK_RET(6, params.cParams.targetLength != savedParams.cParams.targetLength, \"targetLength\");\n\n    CHECK_RET(7, params.fParams.checksumFlag != savedParams.fParams.checksumFlag, \"checksumFlag\");\n    CHECK_RET(8, params.fParams.contentSizeFlag != savedParams.fParams.contentSizeFlag, \"contentSizeFlag\");\n    CHECK_RET(9, params.fParams.noDictIDFlag != savedParams.fParams.noDictIDFlag, \"noDictIDFlag\");\n    return 0;\n}\n\nstatic int basicUnitTests(U32 seed, double compressibility, int bigTests)\n{\n    size_t const CNBufferSize = COMPRESSIBLE_NOISE_LENGTH;\n    void* CNBuffer = malloc(CNBufferSize);\n    size_t const skippableFrameSize = 200 KB;\n    size_t const compressedBufferSize = (8 + skippableFrameSize) + ZSTD_compressBound(COMPRESSIBLE_NOISE_LENGTH);\n    void* compressedBuffer = malloc(compressedBufferSize);\n    size_t const decodedBufferSize = CNBufferSize;\n    void* decodedBuffer = malloc(decodedBufferSize);\n    size_t cSize;\n    int testResult = 0;\n    int testNb = 1;\n    U32 coreSeed = 0;  /* this name to conform with CHECK_Z macro display */\n    ZSTD_CStream* zc = ZSTD_createCStream();\n    ZSTD_DStream* zd = ZSTD_createDStream();\n    ZSTD_CCtx* mtctx = ZSTD_createCCtx();\n\n    ZSTD_inBuffer  inBuff, inBuff2;\n    ZSTD_outBuffer outBuff;\n    buffer_t dictionary = kBuffNull;\n    size_t const dictSize = 128 KB;\n    unsigned dictID = 0;\n\n    /* Create compressible test buffer */\n    if (!CNBuffer || !compressedBuffer || !decodedBuffer || !zc || !zd || !mtctx) {\n        DISPLAY(\"Not enough memory, aborting \\n\");\n        goto _output_error;\n    }\n    RDG_genBuffer(CNBuffer, CNBufferSize, compressibility, 0., seed);\n\n    CHECK_Z(ZSTD_CCtx_setParameter(mtctx, ZSTD_c_nbWorkers, 2));\n\n    /* Create dictionary */\n    DISPLAYLEVEL(3, \"creating dictionary for unit tests \\n\");\n    dictionary = FUZ_createDictionary(CNBuffer, CNBufferSize / 3, 16 KB, 48 KB);\n    if (!dictionary.start) {\n        DISPLAY(\"Error creating dictionary, aborting \\n\");\n        goto _output_error;\n    }\n    dictID = ZDICT_getDictID(dictionary.start, dictionary.filled);\n\n    /* Basic compression test */\n    DISPLAYLEVEL(3, \"test%3i : compress %u bytes : \", testNb++, COMPRESSIBLE_NOISE_LENGTH);\n    CHECK_Z( ZSTD_initCStream(zc, 1 /* cLevel */) );\n    outBuff.dst = (char*)(compressedBuffer);\n    outBuff.size = compressedBufferSize;\n    outBuff.pos = 0;\n    inBuff.src = CNBuffer;\n    inBuff.size = CNBufferSize;\n    inBuff.pos = 0;\n    CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) );\n    if (inBuff.pos != inBuff.size) goto _output_error;   /* entire input should be consumed */\n    { size_t const r = ZSTD_endStream(zc, &outBuff);\n      if (r != 0) goto _output_error; }  /* error, or some data not flushed */\n    DISPLAYLEVEL(3, \"OK (%u bytes)\\n\", (unsigned)outBuff.pos);\n\n    /* generate skippable frame */\n    MEM_writeLE32(compressedBuffer, ZSTD_MAGIC_SKIPPABLE_START);\n    MEM_writeLE32(((char*)compressedBuffer)+4, (U32)skippableFrameSize);\n    cSize = skippableFrameSize + 8;\n\n    /* Basic compression test using dict */\n    DISPLAYLEVEL(3, \"test%3i : skipframe + compress %u bytes : \", testNb++, COMPRESSIBLE_NOISE_LENGTH);\n    CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) );\n    CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_compressionLevel, 1) );\n    CHECK_Z( ZSTD_CCtx_loadDictionary(zc, CNBuffer, dictSize) );\n    outBuff.dst = (char*)(compressedBuffer)+cSize;\n    assert(compressedBufferSize > cSize);\n    outBuff.size = compressedBufferSize - cSize;\n    outBuff.pos = 0;\n    inBuff.src = CNBuffer;\n    inBuff.size = CNBufferSize;\n    inBuff.pos = 0;\n    CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) );\n    if (inBuff.pos != inBuff.size) goto _output_error;   /* entire input should be consumed */\n    { size_t const r = ZSTD_endStream(zc, &outBuff);\n      if (r != 0) goto _output_error; }  /* error, or some data not flushed */\n    cSize += outBuff.pos;\n    DISPLAYLEVEL(3, \"OK (%u bytes : %.2f%%)\\n\",\n                    (unsigned)cSize, (double)cSize/COMPRESSIBLE_NOISE_LENGTH*100);\n\n    /* context size functions */\n    DISPLAYLEVEL(3, \"test%3i : estimate CStream size : \", testNb++);\n    {   ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBufferSize, dictSize);\n        size_t const cstreamSize = ZSTD_estimateCStreamSize_usingCParams(cParams);\n        size_t const cdictSize = ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy); /* uses ZSTD_initCStream_usingDict() */\n        if (ZSTD_isError(cstreamSize)) goto _output_error;\n        if (ZSTD_isError(cdictSize)) goto _output_error;\n        DISPLAYLEVEL(3, \"OK (%u bytes) \\n\", (unsigned)(cstreamSize + cdictSize));\n    }\n\n    /* context size functions */\n    DISPLAYLEVEL(3, \"test%3i : estimate CStream size using CCtxParams : \", testNb++);\n    {   ZSTD_CCtx_params* const params = ZSTD_createCCtxParams();\n        size_t cstreamSize, cctxSize;\n        CHECK_Z( ZSTD_CCtxParams_setParameter(params, ZSTD_c_compressionLevel, 19) );\n        cstreamSize = ZSTD_estimateCStreamSize_usingCCtxParams(params);\n        CHECK_Z(cstreamSize);\n        cctxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params);\n        CHECK_Z(cctxSize);\n        if (cstreamSize <= cctxSize + 2 * ZSTD_BLOCKSIZE_MAX) goto _output_error;\n        ZSTD_freeCCtxParams(params);\n        DISPLAYLEVEL(3, \"OK \\n\");\n    }\n\n    DISPLAYLEVEL(3, \"test%3i : check actual CStream size : \", testNb++);\n    {   size_t const s = ZSTD_sizeof_CStream(zc);\n        if (ZSTD_isError(s)) goto _output_error;\n        DISPLAYLEVEL(3, \"OK (%u bytes) \\n\", (unsigned)s);\n    }\n\n    /* Attempt bad compression parameters */\n    DISPLAYLEVEL(3, \"test%3i : use bad compression parameters with ZSTD_initCStream_advanced : \", testNb++);\n    {   size_t r;\n        ZSTD_parameters params = ZSTD_getParams(1, 0, 0);\n        params.cParams.minMatch = 2;\n        r = ZSTD_initCStream_advanced(zc, NULL, 0, params, 0);\n        if (!ZSTD_isError(r)) goto _output_error;\n        DISPLAYLEVEL(3, \"init error : %s \\n\", ZSTD_getErrorName(r));\n    }\n\n    /* skippable frame test */\n    DISPLAYLEVEL(3, \"test%3i : decompress skippable frame : \", testNb++);\n    CHECK_Z( ZSTD_initDStream_usingDict(zd, CNBuffer, dictSize) );\n    inBuff.src = compressedBuffer;\n    inBuff.size = cSize;\n    inBuff.pos = 0;\n    outBuff.dst = decodedBuffer;\n    outBuff.size = CNBufferSize;\n    outBuff.pos = 0;\n    {   size_t const r = ZSTD_decompressStream(zd, &outBuff, &inBuff);\n        DISPLAYLEVEL(5, \" ( ZSTD_decompressStream => %u ) \", (unsigned)r);\n        if (r != 0) goto _output_error;\n    }\n    if (outBuff.pos != 0) goto _output_error;   /* skippable frame output len is 0 */\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* Basic decompression test */\n    inBuff2 = inBuff;\n    DISPLAYLEVEL(3, \"test%3i : decompress %u bytes : \", testNb++, COMPRESSIBLE_NOISE_LENGTH);\n    ZSTD_initDStream_usingDict(zd, CNBuffer, dictSize);\n    CHECK_Z( ZSTD_DCtx_setParameter(zd, ZSTD_d_windowLogMax, ZSTD_WINDOWLOG_LIMIT_DEFAULT+1) );  /* large limit */\n    { size_t const remaining = ZSTD_decompressStream(zd, &outBuff, &inBuff);\n      if (remaining != 0) goto _output_error; }  /* should reach end of frame == 0; otherwise, some data left, or an error */\n    if (outBuff.pos != CNBufferSize) goto _output_error;   /* should regenerate the same amount */\n    if (inBuff.pos != inBuff.size) goto _output_error;   /* should have read the entire frame */\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* Reuse without init */\n    DISPLAYLEVEL(3, \"test%3i : decompress again without init (reuse previous settings): \", testNb++);\n    outBuff.pos = 0;\n    { size_t const remaining = ZSTD_decompressStream(zd, &outBuff, &inBuff2);\n      if (remaining != 0) goto _output_error; }  /* should reach end of frame == 0; otherwise, some data left, or an error */\n    if (outBuff.pos != CNBufferSize) goto _output_error;   /* should regenerate the same amount */\n    if (inBuff.pos != inBuff.size) goto _output_error;   /* should have read the entire frame */\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* check regenerated data is byte exact */\n    DISPLAYLEVEL(3, \"test%3i : check decompressed result : \", testNb++);\n    {   size_t i;\n        for (i=0; i<CNBufferSize; i++) {\n            if (((BYTE*)decodedBuffer)[i] != ((BYTE*)CNBuffer)[i]) goto _output_error;\n    }   }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* check decompression fails early if first bytes are wrong */\n    DISPLAYLEVEL(3, \"test%3i : early decompression error if first bytes are incorrect : \", testNb++);\n    {   const char buf[3] = { 0 };  /* too short, not enough to start decoding header */\n        ZSTD_inBuffer inb = { buf, sizeof(buf), 0 };\n        size_t const remaining = ZSTD_decompressStream(zd, &outBuff, &inb);\n        if (!ZSTD_isError(remaining)) goto _output_error; /* should have errored out immediately (note: this does not test the exact error code) */\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* context size functions */\n    DISPLAYLEVEL(3, \"test%3i : estimate DStream size : \", testNb++);\n    {   ZSTD_FrameHeader fhi;\n        const void* cStart = (char*)compressedBuffer + (skippableFrameSize + 8);\n        size_t const gfhError = ZSTD_getFrameHeader(&fhi, cStart, cSize);\n        if (gfhError!=0) goto _output_error;\n        DISPLAYLEVEL(5, \" (windowSize : %u) \", (unsigned)fhi.windowSize);\n        {   size_t const s = ZSTD_estimateDStreamSize((size_t)fhi.windowSize)\n                            /* uses ZSTD_initDStream_usingDict() */\n                           + ZSTD_estimateDDictSize(dictSize, ZSTD_dlm_byCopy);\n            if (ZSTD_isError(s)) goto _output_error;\n            DISPLAYLEVEL(3, \"OK (%u bytes) \\n\", (unsigned)s);\n    }   }\n\n    DISPLAYLEVEL(3, \"test%3i : check actual DStream size : \", testNb++);\n    { size_t const s = ZSTD_sizeof_DStream(zd);\n      if (ZSTD_isError(s)) goto _output_error;\n      DISPLAYLEVEL(3, \"OK (%u bytes) \\n\", (unsigned)s);\n    }\n\n    /* Decompression by small increment */\n    DISPLAYLEVEL(3, \"test%3i : decompress byte-by-byte : \", testNb++);\n    {   /* skippable frame */\n        size_t r = 1;\n        ZSTD_initDStream_usingDict(zd, CNBuffer, dictSize);\n        inBuff.src = compressedBuffer;\n        outBuff.dst = decodedBuffer;\n        inBuff.pos = 0;\n        outBuff.pos = 0;\n        while (r) {   /* skippable frame */\n            size_t const inSize = (FUZ_rand(&coreSeed) & 15) + 1;\n            size_t const outSize = (FUZ_rand(&coreSeed) & 15) + 1;\n            inBuff.size = inBuff.pos + inSize;\n            outBuff.size = outBuff.pos + outSize;\n            r = ZSTD_decompressStream(zd, &outBuff, &inBuff);\n            if (ZSTD_isError(r)) DISPLAYLEVEL(4, \"ZSTD_decompressStream on skippable frame error : %s \\n\", ZSTD_getErrorName(r));\n            if (ZSTD_isError(r)) goto _output_error;\n        }\n        /* normal frame */\n        ZSTD_initDStream_usingDict(zd, CNBuffer, dictSize);\n        r=1;\n        while (r) {\n            size_t const inSize = FUZ_rand(&coreSeed) & 15;\n            size_t const outSize = (FUZ_rand(&coreSeed) & 15) + (!inSize);   /* avoid having both sizes at 0 => would trigger a no_forward_progress error */\n            inBuff.size = inBuff.pos + inSize;\n            outBuff.size = outBuff.pos + outSize;\n            r = ZSTD_decompressStream(zd, &outBuff, &inBuff);\n            if (ZSTD_isError(r)) DISPLAYLEVEL(4, \"ZSTD_decompressStream error : %s \\n\", ZSTD_getErrorName(r));\n            if (ZSTD_isError(r)) goto _output_error;\n        }\n    }\n    if (outBuff.pos != CNBufferSize) DISPLAYLEVEL(4, \"outBuff.pos != CNBufferSize : should have regenerated same amount ! \\n\");\n    if (outBuff.pos != CNBufferSize) goto _output_error;   /* should regenerate the same amount */\n    if (inBuff.pos != cSize) DISPLAYLEVEL(4, \"inBuff.pos != cSize : should have real all input ! \\n\");\n    if (inBuff.pos != cSize) goto _output_error;   /* should have read the entire frame */\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* check regenerated data is byte exact */\n    DISPLAYLEVEL(3, \"test%3i : check decompressed result : \", testNb++);\n    {   size_t i;\n        for (i=0; i<CNBufferSize; i++) {\n            if (((BYTE*)decodedBuffer)[i] != ((BYTE*)CNBuffer)[i]) goto _output_error;\n    }   }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* Decompression forward progress */\n    DISPLAYLEVEL(3, \"test%3i : generate error when ZSTD_decompressStream() doesn't progress : \", testNb++);\n    {   /* skippable frame */\n        size_t r = 0;\n        int decNb = 0;\n        int const maxDec = 100;\n        inBuff.src = compressedBuffer;\n        inBuff.size = cSize;\n        inBuff.pos = 0;\n\n        outBuff.dst = decodedBuffer;\n        outBuff.pos = 0;\n        outBuff.size = CNBufferSize-1;   /* 1 byte missing */\n\n        for (decNb=0; decNb<maxDec; decNb++) {\n            if (r==0) ZSTD_initDStream_usingDict(zd, CNBuffer, dictSize);\n            r = ZSTD_decompressStream(zd, &outBuff, &inBuff);\n            if (ZSTD_isError(r)) break;\n        }\n        if (!ZSTD_isError(r)) DISPLAYLEVEL(4, \"ZSTD_decompressStream should have triggered a no_forward_progress error \\n\");\n        if (!ZSTD_isError(r)) goto _output_error;   /* should have triggered no_forward_progress error */\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : NULL output and NULL input : \", testNb++);\n    inBuff.src = NULL;\n    inBuff.size = 0;\n    inBuff.pos = 0;\n    outBuff.dst = NULL;\n    outBuff.size = 0;\n    outBuff.pos = 0;\n    CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) );\n    CHECK(inBuff.pos != inBuff.size, \"Entire input should be consumed\");\n    CHECK_Z( ZSTD_endStream(zc, &outBuff) );\n    outBuff.dst = (char*)(compressedBuffer);\n    outBuff.size = compressedBufferSize;\n    outBuff.pos = 0;\n    {   size_t const r = ZSTD_endStream(zc, &outBuff);\n        CHECK(r != 0, \"Error or some data not flushed (ret=%i)\", ZSTD_getErrorCode(r));\n    }\n    inBuff.src = outBuff.dst;\n    inBuff.size = outBuff.pos;\n    inBuff.pos = 0;\n    outBuff.dst = NULL;\n    outBuff.size = 0;\n    outBuff.pos = 0;\n    CHECK_Z( ZSTD_initDStream(zd) );\n    {   size_t const ret = ZSTD_decompressStream(zd, &outBuff, &inBuff);\n        if (ret != 0) goto _output_error;\n    }\n    DISPLAYLEVEL(3, \"OK\\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : NULL output buffer with non-NULL input : \", testNb++);\n    {\n        const char* test = \"aa\";\n        inBuff.src = test;\n        inBuff.size = 2;\n        inBuff.pos = 0;\n        outBuff.dst = NULL;\n        outBuff.size = 0;\n        outBuff.pos = 0;\n        CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) );\n        CHECK(inBuff.pos != inBuff.size, \"Entire input should be consumed\");\n        CHECK_Z( ZSTD_endStream(zc, &outBuff) );\n        outBuff.dst = (char*)(compressedBuffer);\n        outBuff.size = compressedBufferSize;\n        outBuff.pos = 0;\n        {   size_t const r = ZSTD_endStream(zc, &outBuff);\n            CHECK(r != 0, \"Error or some data not flushed (ret=%i)\", ZSTD_getErrorCode(r));\n        }\n        inBuff.src = outBuff.dst;\n        inBuff.size = outBuff.pos;\n        inBuff.pos = 0;\n        outBuff.dst = NULL;\n        outBuff.size = 0;\n        outBuff.pos = 0;\n        CHECK_Z( ZSTD_initDStream(zd) );\n        CHECK_Z(ZSTD_decompressStream(zd, &outBuff, &inBuff));\n    }\n\n    DISPLAYLEVEL(3, \"OK\\n\");\n    /* _srcSize compression test */\n    DISPLAYLEVEL(3, \"test%3i : compress_srcSize %u bytes : \", testNb++, COMPRESSIBLE_NOISE_LENGTH);\n    CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) );\n    CHECK_Z( ZSTD_CCtx_refCDict(zc, NULL) );\n    CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_compressionLevel, 1) );\n    CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, CNBufferSize) );\n    outBuff.dst = (char*)(compressedBuffer);\n    outBuff.size = compressedBufferSize;\n    outBuff.pos = 0;\n    inBuff.src = CNBuffer;\n    inBuff.size = CNBufferSize;\n    inBuff.pos = 0;\n    CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) );\n    CHECK(inBuff.pos != inBuff.size, \"Entire input should be consumed\");\n    {   size_t const r = ZSTD_endStream(zc, &outBuff);\n        CHECK(r != 0, \"Error or some data not flushed (ret=%i)\", ZSTD_getErrorCode(r));\n    }\n    {   unsigned long long origSize = ZSTD_findDecompressedSize(outBuff.dst, outBuff.pos);\n        CHECK(origSize == ZSTD_CONTENTSIZE_UNKNOWN, \"Unknown!\");\n        CHECK((size_t)origSize != CNBufferSize, \"Exact original size must be present (got %llu)\", origSize);\n    }\n    DISPLAYLEVEL(3, \"OK (%u bytes : %.2f%%)\\n\", (unsigned)cSize, (double)cSize/COMPRESSIBLE_NOISE_LENGTH*100);\n\n    /* wrong _srcSize compression test */\n    DISPLAYLEVEL(3, \"test%3i : too large srcSize : %u bytes : \", testNb++, COMPRESSIBLE_NOISE_LENGTH-1);\n    CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) );\n    CHECK_Z( ZSTD_CCtx_refCDict(zc, NULL) );\n    CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_compressionLevel, 1) );\n    CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, CNBufferSize+1) );\n    outBuff.dst = (char*)(compressedBuffer);\n    outBuff.size = compressedBufferSize;\n    outBuff.pos = 0;\n    inBuff.src = CNBuffer;\n    inBuff.size = CNBufferSize;\n    inBuff.pos = 0;\n    CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) );\n    if (inBuff.pos != inBuff.size) goto _output_error;   /* entire input should be consumed */\n    { size_t const r = ZSTD_endStream(zc, &outBuff);\n      if (ZSTD_getErrorCode(r) != ZSTD_error_srcSize_wrong) goto _output_error;    /* must fail : wrong srcSize */\n      DISPLAYLEVEL(3, \"OK (error detected : %s) \\n\", ZSTD_getErrorName(r)); }\n\n    /* wrong _srcSize compression test */\n    DISPLAYLEVEL(3, \"test%3i : too small srcSize : %u bytes : \", testNb++, COMPRESSIBLE_NOISE_LENGTH-1);\n    CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) );\n    CHECK_Z( ZSTD_CCtx_refCDict(zc, NULL) );\n    CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_compressionLevel, 1) );\n    CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, CNBufferSize-1) );\n    outBuff.dst = (char*)(compressedBuffer);\n    outBuff.size = compressedBufferSize;\n    outBuff.pos = 0;\n    inBuff.src = CNBuffer;\n    inBuff.size = CNBufferSize;\n    inBuff.pos = 0;\n    {   size_t const r = ZSTD_compressStream(zc, &outBuff, &inBuff);\n        if (ZSTD_getErrorCode(r) != ZSTD_error_srcSize_wrong) goto _output_error;    /* must fail : wrong srcSize */\n        DISPLAYLEVEL(3, \"OK (error detected : %s) \\n\", ZSTD_getErrorName(r));\n    }\n\n    DISPLAYLEVEL(3, \"test%3i : wrong srcSize !contentSizeFlag : %u bytes : \", testNb++, COMPRESSIBLE_NOISE_LENGTH-1);\n    {   CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) );\n        CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_contentSizeFlag, 0) );\n        CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, CNBufferSize - MIN(CNBufferSize, 200 KB)) );\n        outBuff.dst = (char*)compressedBuffer;\n        outBuff.size = compressedBufferSize;\n        outBuff.pos = 0;\n        inBuff.src = CNBuffer;\n        inBuff.size = CNBufferSize;\n        inBuff.pos = 0;\n        {   size_t const r = ZSTD_compressStream(zc, &outBuff, &inBuff);\n            if (ZSTD_getErrorCode(r) != ZSTD_error_srcSize_wrong) goto _output_error;    /* must fail : wrong srcSize */\n            DISPLAYLEVEL(3, \"OK (error detected : %s) \\n\", ZSTD_getErrorName(r));\n    }   }\n\n    /* Compression state reuse scenario */\n    DISPLAYLEVEL(3, \"test%3i : context reuse : \", testNb++);\n    ZSTD_freeCStream(zc);\n    zc = ZSTD_createCStream();\n    if (zc==NULL) goto _output_error;   /* memory allocation issue */\n    /* use 1 */\n    {   size_t const inSize = 513;\n        DISPLAYLEVEL(5, \"use1 \");\n        CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) );\n        CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_compressionLevel, 19) );\n        CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, inSize) );\n        inBuff.src = CNBuffer;\n        inBuff.size = inSize;\n        inBuff.pos = 0;\n        outBuff.dst = (char*)(compressedBuffer)+cSize;\n        outBuff.size = ZSTD_compressBound(inSize);\n        outBuff.pos = 0;\n        DISPLAYLEVEL(5, \"compress1 \");\n        CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) );\n        if (inBuff.pos != inBuff.size) goto _output_error;   /* entire input should be consumed */\n        DISPLAYLEVEL(5, \"end1 \");\n        if (ZSTD_endStream(zc, &outBuff) != 0) goto _output_error;  /* error, or some data not flushed */\n    }\n    /* use 2 */\n    {   size_t const inSize = 1025;   /* will not continue, because tables auto-adjust and are therefore different size */\n        DISPLAYLEVEL(5, \"use2 \");\n        CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) );\n        CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_compressionLevel, 19) );\n        CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, inSize) );\n        inBuff.src = CNBuffer;\n        inBuff.size = inSize;\n        inBuff.pos = 0;\n        outBuff.dst = (char*)(compressedBuffer)+cSize;\n        outBuff.size = ZSTD_compressBound(inSize);\n        outBuff.pos = 0;\n        DISPLAYLEVEL(5, \"compress2 \");\n        CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) );\n        if (inBuff.pos != inBuff.size) goto _output_error;   /* entire input should be consumed */\n        DISPLAYLEVEL(5, \"end2 \");\n        if (ZSTD_endStream(zc, &outBuff) != 0) goto _output_error;   /* error, or some data not flushed */\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* Decompression single pass with empty frame */\n    cSize = ZSTD_compress(compressedBuffer, compressedBufferSize, NULL, 0, 1);\n    CHECK_Z(cSize);\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_decompressStream() single pass on empty frame : \", testNb++);\n    {   ZSTD_DCtx* dctx = ZSTD_createDCtx();\n        size_t const dctxSize = ZSTD_sizeof_DCtx(dctx);\n        CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_stableOutBuffer, 1));\n\n        outBuff.dst = decodedBuffer;\n        outBuff.pos = 0;\n        outBuff.size = CNBufferSize;\n\n        inBuff.src = compressedBuffer;\n        inBuff.size = cSize;\n        inBuff.pos = 0;\n        {   size_t const r = ZSTD_decompressStream(dctx, &outBuff, &inBuff);\n            CHECK_Z(r);\n            CHECK(r != 0, \"Entire frame must be decompressed\");\n            CHECK(outBuff.pos != 0, \"Wrong size!\");\n            CHECK(memcmp(CNBuffer, outBuff.dst, CNBufferSize) != 0, \"Corruption!\");\n        }\n        CHECK(dctxSize != ZSTD_sizeof_DCtx(dctx), \"No buffers allocated\");\n        ZSTD_freeDCtx(dctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : maxBlockSize = 2KB : \", testNb++);\n    {\n        ZSTD_DCtx* dctx = ZSTD_createDCtx();\n        size_t singlePassSize, streamingSize, streaming2KSize;\n\n        {\n            ZSTD_CCtx* cctx = ZSTD_createCCtx();\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 18));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_contentSizeFlag, 0));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, 2048));\n            cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBufferSize);\n            CHECK_Z(cSize);\n            ZSTD_freeCCtx(cctx);\n        }\n\n        CHECK_Z(ZSTD_decompressDCtx(dctx, decodedBuffer, CNBufferSize, compressedBuffer, cSize));\n        singlePassSize = ZSTD_sizeof_DCtx(dctx);\n        CHECK_Z(singlePassSize);\n\n        inBuff.src = compressedBuffer;\n        inBuff.size = cSize;\n\n        outBuff.dst = decodedBuffer;\n        outBuff.size = decodedBufferSize;\n\n        CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_maxBlockSize, 2048));\n        inBuff.pos = 0;\n        outBuff.pos = 0;\n        {\n            size_t const r = ZSTD_decompressStream(dctx, &outBuff, &inBuff);\n            CHECK_Z(r);\n            CHECK(r != 0, \"Entire frame must be decompressed\");\n        }\n        streaming2KSize = ZSTD_sizeof_DCtx(dctx);\n        CHECK_Z(streaming2KSize);\n\n        CHECK_Z(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters));\n        inBuff.pos = 0;\n        outBuff.pos = 0;\n        {\n            size_t const r = ZSTD_decompressStream(dctx, &outBuff, &inBuff);\n            CHECK_Z(r);\n            CHECK(r != 0, \"Entire frame must be decompressed\");\n        }\n        streamingSize = ZSTD_sizeof_DCtx(dctx);\n        CHECK_Z(streamingSize);\n\n        CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_maxBlockSize, 1024));\n        inBuff.pos = 0;\n        outBuff.pos = 0;\n        CHECK(!ZSTD_isError(ZSTD_decompressStream(dctx, &outBuff, &inBuff)), \"decompression must fail\");\n\n        CHECK(streamingSize < singlePassSize + (1 << 18) + 3 * ZSTD_BLOCKSIZE_MAX, \"Streaming doesn't use the right amount of memory\");\n        CHECK(streamingSize != streaming2KSize + 3 * (ZSTD_BLOCKSIZE_MAX - 2048), \"ZSTD_d_blockSizeMax didn't save the right amount of memory\");\n        DISPLAYLEVEL(3, \"| %u | %u | %u | \", (unsigned)singlePassSize, (unsigned)streaming2KSize, (unsigned)streamingSize);\n\n        ZSTD_freeDCtx(dctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* Decompression with ZSTD_d_stableOutBuffer */\n    cSize = ZSTD_compress(compressedBuffer, compressedBufferSize, CNBuffer, CNBufferSize, 1);\n    CHECK_Z(cSize);\n    {   ZSTD_DCtx* dctx = ZSTD_createDCtx();\n        size_t const dctxSize0 = ZSTD_sizeof_DCtx(dctx);\n        size_t dctxSize1;\n        CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_stableOutBuffer, 1));\n\n        outBuff.dst = decodedBuffer;\n        outBuff.pos = 0;\n        outBuff.size = CNBufferSize;\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_decompressStream() single pass : \", testNb++);\n        inBuff.src = compressedBuffer;\n        inBuff.size = cSize;\n        inBuff.pos = 0;\n        {   size_t const r = ZSTD_decompressStream(dctx, &outBuff, &inBuff);\n            CHECK_Z(r);\n            CHECK(r != 0, \"Entire frame must be decompressed\");\n            CHECK(outBuff.pos != CNBufferSize, \"Wrong size!\");\n            CHECK(memcmp(CNBuffer, outBuff.dst, CNBufferSize) != 0, \"Corruption!\");\n        }\n        CHECK(dctxSize0 != ZSTD_sizeof_DCtx(dctx), \"No buffers allocated\");\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_decompressStream() stable out buffer : \", testNb++);\n        outBuff.pos = 0;\n        inBuff.pos = 0;\n        inBuff.size = 0;\n        while (inBuff.pos < cSize) {\n            inBuff.size += MIN(cSize - inBuff.pos, 1 + (FUZ_rand(&coreSeed) & 15));\n            CHECK_Z(ZSTD_decompressStream(dctx, &outBuff, &inBuff));\n        }\n        CHECK(outBuff.pos != CNBufferSize, \"Wrong size!\");\n        CHECK(memcmp(CNBuffer, outBuff.dst, CNBufferSize) != 0, \"Corruption!\");\n        dctxSize1 = ZSTD_sizeof_DCtx(dctx);\n        CHECK(!(dctxSize0 < dctxSize1), \"Input buffer allocated\");\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_decompressStream() stable out buffer too small : \", testNb++);\n        ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only);\n        CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_stableOutBuffer, 1));\n        inBuff.src = compressedBuffer;\n        inBuff.size = cSize;\n        inBuff.pos = 0;\n        outBuff.pos = 0;\n        outBuff.size = CNBufferSize - 1;\n        {   size_t const r = ZSTD_decompressStream(dctx, &outBuff, &inBuff);\n            CHECK(ZSTD_getErrorCode(r) != ZSTD_error_dstSize_tooSmall, \"Must error but got %s\", ZSTD_getErrorName(r));\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_decompressStream() stable out buffer modified : \", testNb++);\n        ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only);\n        CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_stableOutBuffer, 1));\n        inBuff.src = compressedBuffer;\n        inBuff.size = cSize - 1;\n        inBuff.pos = 0;\n        outBuff.pos = 0;\n        outBuff.size = CNBufferSize;\n        CHECK_Z(ZSTD_decompressStream(dctx, &outBuff, &inBuff));\n        ++inBuff.size;\n        outBuff.pos = 0;\n        {   size_t const r = ZSTD_decompressStream(dctx, &outBuff, &inBuff);\n            CHECK(ZSTD_getErrorCode(r) != ZSTD_error_dstBuffer_wrong, \"Must error but got %s\", ZSTD_getErrorName(r));\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_decompressStream() buffered output : \", testNb++);\n        ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only);\n        CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_stableOutBuffer, 0));\n        outBuff.pos = 0;\n        inBuff.pos = 0;\n        inBuff.size = 0;\n        while (inBuff.pos < cSize) {\n            inBuff.size += MIN(cSize - inBuff.pos, 1 + (FUZ_rand(&coreSeed) & 15));\n            CHECK_Z(ZSTD_decompressStream(dctx, &outBuff, &inBuff));\n        }\n        CHECK(outBuff.pos != CNBufferSize, \"Wrong size!\");\n        CHECK(memcmp(CNBuffer, outBuff.dst, CNBufferSize) != 0, \"Corruption!\");\n        CHECK(!(dctxSize1 < ZSTD_sizeof_DCtx(dctx)), \"Output buffer allocated\");\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        ZSTD_freeDCtx(dctx);\n    }\n\n    /* Compression with ZSTD_c_stable{In,Out}Buffer */\n    {   ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n        ZSTD_inBuffer in;\n        ZSTD_outBuffer out;\n        size_t cctxSize1;\n        size_t cctxSize2;\n        assert(cctx != NULL);\n        in.src = CNBuffer;\n        in.size = CNBufferSize;\n        out.dst = compressedBuffer;\n        out.size = compressedBufferSize;\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1));\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_compress2() uses stable input and output : \", testNb++);\n        CHECK_Z(cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBufferSize));\n        CHECK(!(cSize < ZSTD_compressBound(CNBufferSize)), \"cSize too large for test\");\n        /* check that compression fits with just a 8-bytes margin */\n        CHECK_Z(cSize = ZSTD_compress2(cctx, compressedBuffer, cSize+8, CNBuffer, CNBufferSize));\n        CHECK_Z(cctxSize1 = ZSTD_sizeof_CCtx(cctx));\n        /* @cctxSize2 : sizeof_CCtx when doing full streaming (no stable in/out) */\n        {   ZSTD_CCtx* const cctx2 = ZSTD_createCCtx();\n            assert(cctx2 != NULL);\n            in.pos = out.pos = 0;\n            CHECK_Z(ZSTD_compressStream2(cctx2, &out, &in, ZSTD_e_continue));\n            CHECK(!(ZSTD_compressStream2(cctx2, &out, &in, ZSTD_e_end) == 0), \"Not finished\");\n            CHECK_Z(cctxSize2 = ZSTD_sizeof_CCtx(cctx2));\n            ZSTD_freeCCtx(cctx2);\n        }\n        /* @cctxSize1 : sizeof_CCtx when doing single-shot compression (no streaming) */\n        {   ZSTD_CCtx* const cctx1 = ZSTD_createCCtx();\n            ZSTD_parameters params = ZSTD_getParams(0, CNBufferSize, 0);\n            size_t cSize3;\n            assert(cctx1 != NULL);\n            params.fParams.checksumFlag = 1;\n            cSize3 = ZSTD_compress_advanced(cctx1, compressedBuffer, compressedBufferSize, CNBuffer, CNBufferSize, NULL, 0, params);\n            CHECK_Z(cSize3);\n            CHECK(!(cSize == cSize3), \"Must be same compressed size\");\n            CHECK(!(cctxSize1 == ZSTD_sizeof_CCtx(cctx1)), \"Must be same CCtx size\");\n            ZSTD_freeCCtx(cctx1);\n        }\n        CHECK(!(cctxSize1 < cctxSize2), \"Stable buffers means less allocated size\");\n        CHECK_Z(ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, cSize));\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_compress2() doesn't modify user parameters : \", testNb++);\n        {   int stableInBuffer;\n            int stableOutBuffer;\n            CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_stableInBuffer, &stableInBuffer));\n            CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_stableOutBuffer, &stableOutBuffer));\n            CHECK(!(stableInBuffer == 0), \"Modified\");\n            CHECK(!(stableOutBuffer == 0), \"Modified\");\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_stableInBuffer, 1));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_stableOutBuffer, 1));\n            CHECK_Z(cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBufferSize));\n            CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_stableInBuffer, &stableInBuffer));\n            CHECK_Z(ZSTD_CCtx_getParameter(cctx, ZSTD_c_stableOutBuffer, &stableOutBuffer));\n            CHECK(!(stableInBuffer == 1), \"Modified\");\n            CHECK(!(stableOutBuffer == 1), \"Modified\");\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_compressStream2() with ZSTD_c_stableInBuffer and ZSTD_c_stableOutBuffer : \", testNb++);\n        CHECK_Z(ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_stableInBuffer, 1));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_stableOutBuffer, 1));\n        in.pos = out.pos = 0;\n        CHECK(!(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end) == 0), \"Not finished\");\n        CHECK_Z(ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, cSize));\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_compressStream2() ZSTD_c_stableInBuffer and ZSTD_c_stableOutBuffer allocated size : \", testNb++);\n        {   size_t const cctxSize = ZSTD_sizeof_CCtx(cctx);\n            CHECK(!(cctxSize1 == cctxSize), \"Must be the same size as single pass\");\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_compressStream2() with ZSTD_c_stableInBuffer only : \", testNb++);\n        CHECK_Z(ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_stableInBuffer, 1));\n        in.pos = out.pos = 0;\n        out.size = cSize / 4;\n        for (;;) {\n            size_t const ret = ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end);\n            CHECK_Z(ret);\n            if (ret == 0)\n                break;\n            out.size = MIN(out.size + cSize / 4, compressedBufferSize);\n        }\n        CHECK_Z(ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, out.pos));\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_compressStream2() ZSTD_c_stableInBuffer modify buffer : \", testNb++);\n        in.pos = out.pos = 0;\n        out.size = cSize / 4;\n        CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));\n        in.src = (char const*)in.src + in.pos;\n        in.size -= in.pos;\n        in.pos = 0;\n        {   size_t const ret = ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end);\n            CHECK(!ZSTD_isError(ret), \"Must error\");\n            CHECK(!(ZSTD_getErrorCode(ret) == ZSTD_error_stabilityCondition_notRespected), \"Must be this error\");\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        /* stableSrc + streaming */\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_c_stableInBuffer compatibility with compressStream, flushStream and endStream : \", testNb++);\n        CHECK_Z( ZSTD_initCStream(cctx, 1) );\n        CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_stableInBuffer, 1) );\n        {   ZSTD_inBuffer inBuf;\n            ZSTD_outBuffer outBuf;\n            const size_t nonZeroStartPos = 18;\n            const size_t inputSize = 500;\n            inBuf.src = CNBuffer;\n            inBuf.size = 100;\n            inBuf.pos = nonZeroStartPos;\n            outBuf.dst = (char*)(compressedBuffer)+cSize;\n            outBuf.size = ZSTD_compressBound(inputSize);\n            outBuf.pos = 0;\n            CHECK_Z( ZSTD_compressStream(cctx, &outBuf, &inBuf) );\n            inBuf.size = 200;\n            CHECK_Z( ZSTD_compressStream(cctx, &outBuf, &inBuf) );\n            CHECK_Z( ZSTD_flushStream(cctx, &outBuf) );\n            inBuf.size = nonZeroStartPos + inputSize;\n            CHECK_Z( ZSTD_compressStream(cctx, &outBuf, &inBuf) );\n            CHECK(ZSTD_endStream(cctx, &outBuf) != 0, \"compression should be successful and fully flushed\");\n            {   const void* const realSrcStart = (const char*)inBuf.src + nonZeroStartPos;\n                void* const verifBuf = (char*)outBuf.dst + outBuf.pos;\n                const size_t decSize = ZSTD_decompress(verifBuf, inputSize, outBuf.dst, outBuf.pos);\n                CHECK_Z(decSize);\n                CHECK(decSize != inputSize, \"regenerated %u bytes, instead of %u\", (unsigned)decSize, (unsigned)inputSize);\n                CHECK(memcmp(realSrcStart, verifBuf, inputSize) != 0, \"regenerated data different from original\");\n        }   }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        /* stableSrc + streaming */\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_c_stableInBuffer compatibility with compressStream2, using different end directives : \", testNb++);\n        CHECK_Z( ZSTD_initCStream(cctx, 1) );\n        CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_stableInBuffer, 1) );\n        {   ZSTD_inBuffer inBuf;\n            ZSTD_outBuffer outBuf;\n            const size_t nonZeroStartPos = 18;\n            const size_t inputSize = 500;\n            inBuf.src = CNBuffer;\n            inBuf.size = 100;\n            inBuf.pos = nonZeroStartPos;\n            outBuf.dst = (char*)(compressedBuffer)+cSize;\n            outBuf.size = ZSTD_compressBound(inputSize);\n            outBuf.pos = 0;\n            CHECK_Z( ZSTD_compressStream2(cctx, &outBuf, &inBuf, ZSTD_e_continue) );\n            inBuf.size = 200;\n            CHECK_Z( ZSTD_compressStream2(cctx, &outBuf, &inBuf, ZSTD_e_continue) );\n            CHECK_Z( ZSTD_compressStream2(cctx, &outBuf, &inBuf, ZSTD_e_flush) );\n            inBuf.size = nonZeroStartPos + inputSize;\n            CHECK_Z( ZSTD_compressStream2(cctx, &outBuf, &inBuf, ZSTD_e_continue) );\n            CHECK( ZSTD_compressStream2(cctx, &outBuf, &inBuf, ZSTD_e_end) != 0, \"compression should be successful and fully flushed\");\n            {   const void* const realSrcStart = (const char*)inBuf.src + nonZeroStartPos;\n                void* const verifBuf = (char*)outBuf.dst + outBuf.pos;\n                const size_t decSize = ZSTD_decompress(verifBuf, inputSize, outBuf.dst, outBuf.pos);\n                CHECK_Z(decSize);\n                CHECK(decSize != inputSize, \"regenerated %u bytes, instead of %u\", (unsigned)decSize, (unsigned)inputSize);\n                CHECK(memcmp(realSrcStart, verifBuf, inputSize) != 0, \"regenerated data different from original\");\n        }   }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_compressStream2() with ZSTD_c_stableInBuffer: context size : \", testNb++);\n        {   size_t const cctxSize = ZSTD_sizeof_CCtx(cctx);\n            DISPLAYLEVEL(4, \"cctxSize1=%u; cctxSize=%u; cctxSize2=%u : \", (unsigned)cctxSize1, (unsigned)cctxSize, (unsigned)cctxSize2);\n            CHECK(!(cctxSize1 < cctxSize), \"Must be bigger than single-pass\");\n            CHECK(!(cctxSize < cctxSize2), \"Must be smaller than streaming\");\n            cctxSize1 = cctxSize;\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_compressStream2() with ZSTD_c_stableOutBuffer only : \", testNb++);\n        CHECK_Z(ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1));\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_stableOutBuffer, 1));\n        in.src = CNBuffer;\n        in.pos = out.pos = 0;\n        in.size = MIN(CNBufferSize, 10);\n        out.size = compressedBufferSize;\n        CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush));\n        in.pos = 0;\n        in.size = CNBufferSize - in.size;\n        CHECK(!(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end) == 0), \"Not finished\");\n        CHECK_Z(ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, out.pos));\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_compressStream2() ZSTD_c_stableOutBuffer modify buffer : \", testNb++);\n        in.pos = out.pos = 0;\n        in.size = CNBufferSize;\n        CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue));\n        in.pos = out.pos = 0;\n        {   size_t const ret = ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue);\n            CHECK(!ZSTD_isError(ret), \"Must have errored\");\n            CHECK(!(ZSTD_getErrorCode(ret) == ZSTD_error_stabilityCondition_notRespected), \"Must be this error\");\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        DISPLAYLEVEL(3, \"test%3i : ZSTD_compressStream2() with ZSTD_c_stableOutBuffer: context size : \", testNb++);\n        {   size_t const cctxSize = ZSTD_sizeof_CCtx(cctx);\n            DISPLAYLEVEL(4, \"cctxSize1=%u; cctxSize=%u; cctxSize2=%u : \", (unsigned)cctxSize1, (unsigned)cctxSize, (unsigned)cctxSize2);\n            CHECK(!(cctxSize1 < cctxSize), \"Must be bigger than single-pass and stableInBuffer\");\n            CHECK(!(cctxSize < cctxSize2), \"Must be smaller than streaming\");\n        }\n        DISPLAYLEVEL(3, \"OK \\n\");\n\n        ZSTD_freeCCtx(cctx);\n    }\n\n    /* CDict scenario */\n    DISPLAYLEVEL(3, \"test%3i : digested dictionary : \", testNb++);\n    {   ZSTD_CDict* const cdict = ZSTD_createCDict(dictionary.start, dictionary.filled, 1 /*byRef*/ );\n        size_t const initError = ZSTD_initCStream_usingCDict(zc, cdict);\n        DISPLAYLEVEL(5, \"ZSTD_initCStream_usingCDict result : %u \", (unsigned)initError);\n        if (ZSTD_isError(initError)) goto _output_error;\n        outBuff.dst = compressedBuffer;\n        outBuff.size = compressedBufferSize;\n        outBuff.pos = 0;\n        inBuff.src = CNBuffer;\n        inBuff.size = CNBufferSize;\n        inBuff.pos = 0;\n        DISPLAYLEVEL(5, \"- starting ZSTD_compressStream \");\n        CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) );\n        if (inBuff.pos != inBuff.size) goto _output_error;   /* entire input should be consumed */\n        {   size_t const r = ZSTD_endStream(zc, &outBuff);\n            DISPLAYLEVEL(5, \"- ZSTD_endStream result : %u \", (unsigned)r);\n            if (r != 0) goto _output_error;  /* error, or some data not flushed */\n        }\n        cSize = outBuff.pos;\n        ZSTD_freeCDict(cdict);\n        DISPLAYLEVEL(3, \"OK (%u bytes : %.2f%%)\\n\", (unsigned)cSize, (double)cSize/CNBufferSize*100);\n    }\n\n    DISPLAYLEVEL(3, \"test%3i : check CStream size : \", testNb++);\n    { size_t const s = ZSTD_sizeof_CStream(zc);\n      if (ZSTD_isError(s)) goto _output_error;\n      DISPLAYLEVEL(3, \"OK (%u bytes) \\n\", (unsigned)s);\n    }\n\n    DISPLAYLEVEL(4, \"test%3i : check Dictionary ID : \", testNb++);\n    { unsigned const dID = ZSTD_getDictID_fromFrame(compressedBuffer, cSize);\n      if (dID != dictID) goto _output_error;\n      DISPLAYLEVEL(4, \"OK (%u) \\n\", dID);\n    }\n\n    /* DDict scenario */\n    DISPLAYLEVEL(3, \"test%3i : decompress %u bytes with digested dictionary : \", testNb++, (unsigned)CNBufferSize);\n    {   ZSTD_DDict* const ddict = ZSTD_createDDict(dictionary.start, dictionary.filled);\n        size_t const initError = ZSTD_initDStream_usingDDict(zd, ddict);\n        if (ZSTD_isError(initError)) goto _output_error;\n        outBuff.dst = decodedBuffer;\n        outBuff.size = CNBufferSize;\n        outBuff.pos = 0;\n        inBuff.src = compressedBuffer;\n        inBuff.size = cSize;\n        inBuff.pos = 0;\n        { size_t const r = ZSTD_decompressStream(zd, &outBuff, &inBuff);\n          if (r != 0) goto _output_error; }  /* should reach end of frame == 0; otherwise, some data left, or an error */\n        if (outBuff.pos != CNBufferSize) goto _output_error;   /* should regenerate the same amount */\n        if (inBuff.pos != inBuff.size) goto _output_error;   /* should have read the entire frame */\n        ZSTD_freeDDict(ddict);\n        DISPLAYLEVEL(3, \"OK \\n\");\n    }\n\n    /* Memory restriction */\n    DISPLAYLEVEL(3, \"test%3i : maxWindowSize < frame requirement : \", testNb++);\n    ZSTD_initDStream_usingDict(zd, CNBuffer, dictSize);\n    CHECK_Z( ZSTD_DCtx_setParameter(zd, ZSTD_d_windowLogMax, 10) );  /* too small limit */\n    outBuff.dst = decodedBuffer;\n    outBuff.size = CNBufferSize;\n    outBuff.pos = 0;\n    inBuff.src = compressedBuffer;\n    inBuff.size = cSize;\n    inBuff.pos = 0;\n    { size_t const r = ZSTD_decompressStream(zd, &outBuff, &inBuff);\n      if (!ZSTD_isError(r)) goto _output_error;  /* must fail : frame requires > 100 bytes */\n      DISPLAYLEVEL(3, \"OK (%s)\\n\", ZSTD_getErrorName(r)); }\n    ZSTD_DCtx_reset(zd, ZSTD_reset_session_and_parameters);   /* leave zd in good shape for next tests */\n\n    DISPLAYLEVEL(3, \"test%3i : dictionary source size and level : \", testNb++);\n    {   ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n        int const maxLevel = 16;   /* first level with zstd_opt */\n        int level;\n        assert(maxLevel < ZSTD_maxCLevel());\n        CHECK_Z( ZSTD_DCtx_loadDictionary_byReference(dctx, dictionary.start, dictionary.filled) );\n        for (level = 1; level <= maxLevel; ++level) {\n            ZSTD_CDict* const cdict = ZSTD_createCDict(dictionary.start, dictionary.filled, level);\n            size_t const maxSize = MIN(1 MB, CNBufferSize);\n            size_t size;\n            for (size = 512; size <= maxSize; size <<= 1) {\n                U64 const crcOrig = XXH64(CNBuffer, size, 0);\n                ZSTD_CCtx* const cctx = ZSTD_createCCtx();\n                ZSTD_parameters savedParams;\n                getCCtxParams(cctx, &savedParams);\n                outBuff.dst = compressedBuffer;\n                outBuff.size = compressedBufferSize;\n                outBuff.pos = 0;\n                inBuff.src = CNBuffer;\n                inBuff.size = size;\n                inBuff.pos = 0;\n                CHECK_Z(ZSTD_CCtx_refCDict(cctx, cdict));\n                CHECK_Z(ZSTD_compressStream2(cctx, &outBuff, &inBuff, ZSTD_e_end));\n                CHECK(badParameters(cctx, savedParams), \"Bad CCtx params\");\n                if (inBuff.pos != inBuff.size) goto _output_error;\n                {   ZSTD_outBuffer decOut = {decodedBuffer, size, 0};\n                    ZSTD_inBuffer decIn = {outBuff.dst, outBuff.pos, 0};\n                    CHECK_Z( ZSTD_decompressStream(dctx, &decOut, &decIn) );\n                    if (decIn.pos != decIn.size) goto _output_error;\n                    if (decOut.pos != size) goto _output_error;\n                    {   U64 const crcDec = XXH64(decOut.dst, decOut.pos, 0);\n                        if (crcDec != crcOrig) goto _output_error;\n                }   }\n                ZSTD_freeCCtx(cctx);\n            }\n            ZSTD_freeCDict(cdict);\n        }\n        ZSTD_freeDCtx(dctx);\n    }\n    DISPLAYLEVEL(3, \"OK\\n\");\n\n    ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters);\n    CHECK_Z( ZSTD_CCtx_loadDictionary(zc, dictionary.start, dictionary.filled) );\n    cSize = ZSTD_compress2(zc, compressedBuffer, compressedBufferSize, CNBuffer, MIN(CNBufferSize, 100 KB));\n    CHECK_Z(cSize);\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_decompressStream() with dictionary : \", testNb++);\n    {\n        ZSTD_DCtx* dctx = ZSTD_createDCtx();\n        /* We should fail to decompress without a dictionary. */\n        ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);\n        {   ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};\n            ZSTD_inBuffer in = {compressedBuffer, cSize, 0};\n            size_t const ret = ZSTD_decompressStream(dctx, &out, &in);\n            if (!ZSTD_isError(ret)) goto _output_error;\n        }\n        /* We should succeed to decompress with the dictionary. */\n        ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);\n        CHECK_Z( ZSTD_DCtx_loadDictionary(dctx, dictionary.start, dictionary.filled) );\n        {   ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};\n            ZSTD_inBuffer in = {compressedBuffer, cSize, 0};\n            if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;\n            if (in.pos != in.size) goto _output_error;\n        }\n        /* The dictionary should persist across calls. */\n        {   ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};\n            ZSTD_inBuffer in = {compressedBuffer, cSize, 0};\n            if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;\n            if (in.pos != in.size) goto _output_error;\n        }\n        /* The dictionary should not be cleared by ZSTD_reset_session_only. */\n        ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only);\n        {   ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};\n            ZSTD_inBuffer in = {compressedBuffer, cSize, 0};\n            if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;\n            if (in.pos != in.size) goto _output_error;\n        }\n        /* When we reset the context the dictionary is cleared. */\n        ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);\n        {   ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};\n            ZSTD_inBuffer in = {compressedBuffer, cSize, 0};\n            size_t const ret = ZSTD_decompressStream(dctx, &out, &in);\n            if (!ZSTD_isError(ret)) goto _output_error;\n        }\n        ZSTD_freeDCtx(dctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_resetDStream() with dictionary : \", testNb++);\n    {\n        ZSTD_DCtx* dctx = ZSTD_createDCtx();\n        /* We should succeed to decompress with the dictionary. */\n        ZSTD_resetDStream(dctx);\n        CHECK_Z( ZSTD_DCtx_loadDictionary(dctx, dictionary.start, dictionary.filled) );\n        {   ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};\n            ZSTD_inBuffer in = {compressedBuffer, cSize, 0};\n            if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;\n            if (in.pos != in.size) goto _output_error;\n        }\n        /* The dictionary should not be cleared by ZSTD_resetDStream(). */\n        ZSTD_resetDStream(dctx);\n        {   ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};\n            ZSTD_inBuffer in = {compressedBuffer, cSize, 0};\n            if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;\n            if (in.pos != in.size) goto _output_error;\n        }\n        /* The dictionary should be cleared by ZSTD_initDStream(). */\n        CHECK_Z( ZSTD_initDStream(dctx) );\n        {   ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};\n            ZSTD_inBuffer in = {compressedBuffer, cSize, 0};\n            size_t const ret = ZSTD_decompressStream(dctx, &out, &in);\n            if (!ZSTD_isError(ret)) goto _output_error;\n        }\n        ZSTD_freeDCtx(dctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_decompressStream() with ddict : \", testNb++);\n    {\n        ZSTD_DCtx* dctx = ZSTD_createDCtx();\n        ZSTD_DDict* ddict = ZSTD_createDDict(dictionary.start, dictionary.filled);\n        /* We should succeed to decompress with the ddict. */\n        ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);\n        CHECK_Z( ZSTD_DCtx_refDDict(dctx, ddict) );\n        {   ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};\n            ZSTD_inBuffer in = {compressedBuffer, cSize, 0};\n            if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;\n            if (in.pos != in.size) goto _output_error;\n        }\n        /* The ddict should persist across calls. */\n        {   ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};\n            ZSTD_inBuffer in = {compressedBuffer, cSize, 0};\n            if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;\n            if (in.pos != in.size) goto _output_error;\n        }\n        /* When we reset the context the ddict is cleared. */\n        ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);\n        {   ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};\n            ZSTD_inBuffer in = {compressedBuffer, cSize, 0};\n            size_t const ret = ZSTD_decompressStream(dctx, &out, &in);\n            if (!ZSTD_isError(ret)) goto _output_error;\n        }\n        ZSTD_freeDCtx(dctx);\n        ZSTD_freeDDict(ddict);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_decompressDCtx() with prefix : \", testNb++);\n    {\n        ZSTD_DCtx* dctx = ZSTD_createDCtx();\n        /* We should succeed to decompress with the prefix. */\n        ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters);\n        CHECK_Z( ZSTD_DCtx_refPrefix_advanced(dctx, dictionary.start, dictionary.filled, ZSTD_dct_auto) );\n        {   ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};\n            ZSTD_inBuffer in = {compressedBuffer, cSize, 0};\n            if (ZSTD_decompressStream(dctx, &out, &in) != 0) goto _output_error;\n            if (in.pos != in.size) goto _output_error;\n        }\n        /* The prefix should be cleared after the first compression. */\n        {   ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};\n            ZSTD_inBuffer in = {compressedBuffer, cSize, 0};\n            size_t const ret = ZSTD_decompressStream(dctx, &out, &in);\n            if (!ZSTD_isError(ret)) goto _output_error;\n        }\n        ZSTD_freeDCtx(dctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_initDStream*() with dictionary : \", testNb++);\n    {\n        ZSTD_DCtx* dctx = ZSTD_createDCtx();\n        ZSTD_DDict* ddict = ZSTD_createDDict(dictionary.start, dictionary.filled);\n        size_t ret;\n        /* We should succeed to decompress with the dictionary. */\n        CHECK_Z( ZSTD_initDStream_usingDict(dctx, dictionary.start, dictionary.filled) );\n        CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, decodedBufferSize, compressedBuffer, cSize) );\n        /* The dictionary should persist across calls. */\n        CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, decodedBufferSize, compressedBuffer, cSize) );\n        /* We should succeed to decompress with the ddict. */\n        CHECK_Z( ZSTD_initDStream_usingDDict(dctx, ddict) );\n        CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, decodedBufferSize, compressedBuffer, cSize) );\n        /* The ddict should persist across calls. */\n        CHECK_Z( ZSTD_decompressDCtx(dctx, decodedBuffer, decodedBufferSize, compressedBuffer, cSize) );\n        /* When we reset the context the ddict is cleared. */\n        CHECK_Z( ZSTD_initDStream(dctx) );\n        ret = ZSTD_decompressDCtx(dctx, decodedBuffer, decodedBufferSize, compressedBuffer, cSize);\n        if (!ZSTD_isError(ret)) goto _output_error;\n        ZSTD_freeDCtx(dctx);\n        ZSTD_freeDDict(ddict);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_initCStream_usingCDict_advanced with masked dictID : \", testNb++);\n    {   ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBufferSize, dictionary.filled);\n        ZSTD_frameParameters const fParams = { 1 /* contentSize */, 1 /* checksum */, 1 /* noDictID */};\n        ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictionary.start, dictionary.filled, ZSTD_dlm_byRef, ZSTD_dct_auto, cParams, ZSTD_defaultCMem);\n        size_t const initError = ZSTD_initCStream_usingCDict_advanced(zc, cdict, fParams, CNBufferSize);\n        if (ZSTD_isError(initError)) goto _output_error;\n        outBuff.dst = compressedBuffer;\n        outBuff.size = compressedBufferSize;\n        outBuff.pos = 0;\n        inBuff.src = CNBuffer;\n        inBuff.size = CNBufferSize;\n        inBuff.pos = 0;\n        CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) );\n        if (inBuff.pos != inBuff.size) goto _output_error;  /* entire input should be consumed */\n        { size_t const r = ZSTD_endStream(zc, &outBuff);\n          if (r != 0) goto _output_error; }  /* error, or some data not flushed */\n        cSize = outBuff.pos;\n        ZSTD_freeCDict(cdict);\n        DISPLAYLEVEL(3, \"OK (%u bytes : %.2f%%)\\n\", (unsigned)cSize, (double)cSize/CNBufferSize*100);\n    }\n\n    DISPLAYLEVEL(3, \"test%3i : try retrieving dictID from frame : \", testNb++);\n    {   U32 const did = ZSTD_getDictID_fromFrame(compressedBuffer, cSize);\n        if (did != 0) goto _output_error;\n    }\n    DISPLAYLEVEL(3, \"OK (not detected) \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : decompress without dictionary : \", testNb++);\n    {   size_t const r = ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, cSize);\n        if (!ZSTD_isError(r)) goto _output_error;  /* must fail : dictionary not used */\n        DISPLAYLEVEL(3, \"OK (%s)\\n\", ZSTD_getErrorName(r));\n    }\n\n    DISPLAYLEVEL(3, \"test%3i : compress with ZSTD_CCtx_refPrefix : \", testNb++);\n    CHECK_Z( ZSTD_CCtx_refPrefix(zc, dictionary.start, dictionary.filled) );\n    outBuff.dst = compressedBuffer;\n    outBuff.size = compressedBufferSize;\n    outBuff.pos = 0;\n    inBuff.src = CNBuffer;\n    inBuff.size = CNBufferSize;\n    inBuff.pos = 0;\n    CHECK_Z( ZSTD_compressStream2(zc, &outBuff, &inBuff, ZSTD_e_end) );\n    if (inBuff.pos != inBuff.size) goto _output_error;  /* entire input should be consumed */\n    cSize = outBuff.pos;\n    DISPLAYLEVEL(3, \"OK (%u bytes : %.2f%%)\\n\", (unsigned)cSize, (double)cSize/CNBufferSize*100);\n\n    DISPLAYLEVEL(3, \"test%3i : decompress with ZSTD_DCtx_refPrefix : \", testNb++);\n    CHECK_Z( ZSTD_DCtx_refPrefix(zd, dictionary.start, dictionary.filled) );\n    outBuff.dst = decodedBuffer;\n    outBuff.size = CNBufferSize;\n    outBuff.pos = 0;\n    inBuff.src = compressedBuffer;\n    inBuff.size = cSize;\n    inBuff.pos = 0;\n    CHECK_Z( ZSTD_decompressStream(zd, &outBuff, &inBuff) );\n    if (inBuff.pos != inBuff.size) goto _output_error;  /* entire input should be consumed */\n    if (outBuff.pos != CNBufferSize) goto _output_error;  /* must regenerate whole input */\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : decompress without dictionary (should fail): \", testNb++);\n    {   size_t const r = ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, cSize);\n        if (!ZSTD_isError(r)) goto _output_error;  /* must fail : dictionary not used */\n        DISPLAYLEVEL(3, \"OK (%s)\\n\", ZSTD_getErrorName(r));\n    }\n\n    DISPLAYLEVEL(3, \"test%3i : compress again with ZSTD_compressStream2 : \", testNb++);\n    outBuff.dst = compressedBuffer;\n    outBuff.size = compressedBufferSize;\n    outBuff.pos = 0;\n    inBuff.src = CNBuffer;\n    inBuff.size = CNBufferSize;\n    inBuff.pos = 0;\n    CHECK_Z( ZSTD_compressStream2(zc, &outBuff, &inBuff, ZSTD_e_end) );\n    if (inBuff.pos != inBuff.size) goto _output_error;  /* entire input should be consumed */\n    cSize = outBuff.pos;\n    DISPLAYLEVEL(3, \"OK (%u bytes : %.2f%%)\\n\", (unsigned)cSize, (double)cSize/CNBufferSize*100);\n\n    DISPLAYLEVEL(3, \"test%3i : decompress without dictionary (should work): \", testNb++);\n    CHECK_Z( ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, cSize) );\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* Empty srcSize */\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_initCStream_advanced with pledgedSrcSize=0 and dict : \", testNb++);\n    {   ZSTD_parameters params = ZSTD_getParams(5, 0, 0);\n        params.fParams.contentSizeFlag = 1;\n        CHECK_Z( ZSTD_initCStream_advanced(zc, dictionary.start, dictionary.filled, params, 0 /* pledgedSrcSize==0 means \"empty\" when params.fParams.contentSizeFlag is set */) );\n    } /* cstream advanced shall write content size = 0 */\n    outBuff.dst = compressedBuffer;\n    outBuff.size = compressedBufferSize;\n    outBuff.pos = 0;\n    inBuff.src = CNBuffer;\n    inBuff.size = 0;\n    inBuff.pos = 0;\n    CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) );\n    if (ZSTD_endStream(zc, &outBuff) != 0) goto _output_error;\n    cSize = outBuff.pos;\n    if (ZSTD_findDecompressedSize(compressedBuffer, cSize) != 0) goto _output_error;\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : pledgedSrcSize == 0 behaves properly with ZSTD_initCStream_advanced : \", testNb++);\n    {   ZSTD_parameters params = ZSTD_getParams(5, 0, 0);\n        params.fParams.contentSizeFlag = 1;\n        CHECK_Z( ZSTD_initCStream_advanced(zc, NULL, 0, params, 0) );\n    } /* cstream advanced shall write content size = 0 */\n    inBuff.src = CNBuffer;\n    inBuff.size = 0;\n    inBuff.pos = 0;\n    outBuff.dst = compressedBuffer;\n    outBuff.size = compressedBufferSize;\n    outBuff.pos = 0;\n    CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) );\n    if (ZSTD_endStream(zc, &outBuff) != 0) goto _output_error;\n    cSize = outBuff.pos;\n    if (ZSTD_findDecompressedSize(compressedBuffer, cSize) != 0) goto _output_error;\n\n    CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) );\n    CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, ZSTD_CONTENTSIZE_UNKNOWN) );\n    outBuff.dst = compressedBuffer;\n    outBuff.size = compressedBufferSize;\n    outBuff.pos = 0;\n    inBuff.src = CNBuffer;\n    inBuff.size = 0;\n    inBuff.pos = 0;\n    CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) );\n    if (ZSTD_endStream(zc, &outBuff) != 0) goto _output_error;\n    cSize = outBuff.pos;\n    if (ZSTD_findDecompressedSize(compressedBuffer, cSize) != ZSTD_CONTENTSIZE_UNKNOWN) goto _output_error;\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* Basic multithreading compression test */\n    DISPLAYLEVEL(3, \"test%3i : compress %u bytes with multiple threads : \", testNb++, COMPRESSIBLE_NOISE_LENGTH);\n    {   int jobSize;\n        CHECK_Z( ZSTD_CCtx_getParameter(mtctx, ZSTD_c_jobSize, &jobSize));\n        CHECK(jobSize != 0, \"job size non-zero\");\n        CHECK_Z( ZSTD_CCtx_getParameter(mtctx, ZSTD_c_jobSize, &jobSize));\n        CHECK(jobSize != 0, \"job size non-zero\");\n    }\n    outBuff.dst = compressedBuffer;\n    outBuff.size = compressedBufferSize;\n    outBuff.pos = 0;\n    inBuff.src = CNBuffer;\n    inBuff.size = CNBufferSize;\n    inBuff.pos = 0;\n    {   size_t const compressResult = ZSTD_compressStream2(mtctx, &outBuff, &inBuff, ZSTD_e_end);\n        if (compressResult != 0) goto _output_error;  /* compression must be completed in a single round */\n    }\n    if (inBuff.pos != inBuff.size) goto _output_error;   /* entire input should be consumed */\n    {   size_t const compressedSize = ZSTD_findFrameCompressedSize(compressedBuffer, outBuff.pos);\n        if (compressedSize != outBuff.pos) goto _output_error;  /* must be a full valid frame */\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* Complex multithreading + dictionary test */\n    {   U32 const nbWorkers = 2;\n        size_t const jobSize = 4 * 1 MB;\n        size_t const srcSize = jobSize * nbWorkers;  /* we want each job to have predictable size */\n        size_t const segLength = 2 KB;\n        size_t const offset = 600 KB;   /* must be larger than window defined in cdict */\n        size_t const start = jobSize + (offset-1);\n        const BYTE* const srcToCopy = (const BYTE*)CNBuffer + start;\n        BYTE* const dst = (BYTE*)CNBuffer + start - offset;\n        DISPLAYLEVEL(3, \"test%3i : compress %u bytes with multiple threads + dictionary : \", testNb++, (unsigned)srcSize);\n        CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_compressionLevel, 3) );\n        CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_nbWorkers, nbWorkers) );\n        CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_jobSize, (int)jobSize) );\n        assert(start > offset);\n        assert(start + segLength < COMPRESSIBLE_NOISE_LENGTH);\n        memcpy(dst, srcToCopy, segLength);   /* create a long repetition at long distance for job 2 */\n        outBuff.dst = compressedBuffer;\n        outBuff.size = compressedBufferSize;\n        outBuff.pos = 0;\n        inBuff.src = CNBuffer;\n        inBuff.size = srcSize; assert(srcSize < COMPRESSIBLE_NOISE_LENGTH);\n        inBuff.pos = 0;\n    }\n    {   ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, 4 KB, dictionary.filled);   /* intentionally lies on estimatedSrcSize, to push cdict into targeting a small window size */\n        ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictionary.start, dictionary.filled, ZSTD_dlm_byRef, ZSTD_dct_fullDict, cParams, ZSTD_defaultCMem);\n        DISPLAYLEVEL(5, \"cParams.windowLog = %u : \", cParams.windowLog);\n        CHECK_Z( ZSTD_CCtx_refCDict(zc, cdict) );\n        CHECK_Z( ZSTD_compressStream2(zc, &outBuff, &inBuff, ZSTD_e_end) );\n        CHECK_Z( ZSTD_CCtx_refCDict(zc, NULL) );  /* do not keep a reference to cdict, as its lifetime ends */\n        ZSTD_freeCDict(cdict);\n    }\n    if (inBuff.pos != inBuff.size) goto _output_error;   /* entire input should be consumed */\n    cSize = outBuff.pos;\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : decompress large frame created from multiple threads + dictionary : \", testNb++);\n    {   ZSTD_DStream* const dstream = ZSTD_createDCtx();\n        ZSTD_FrameHeader zfh;\n        ZSTD_getFrameHeader(&zfh, compressedBuffer, cSize);\n        DISPLAYLEVEL(5, \"frame windowsize = %u : \", (unsigned)zfh.windowSize);\n        outBuff.dst = decodedBuffer;\n        outBuff.size = CNBufferSize;\n        outBuff.pos = 0;\n        inBuff.src = compressedBuffer;\n        inBuff.pos = 0;\n        CHECK_Z( ZSTD_initDStream_usingDict(dstream, dictionary.start, dictionary.filled) );\n        inBuff.size = 1;  /* avoid shortcut to single-pass mode */\n        CHECK_Z( ZSTD_decompressStream(dstream, &outBuff, &inBuff) );\n        inBuff.size = cSize;\n        CHECK_Z( ZSTD_decompressStream(dstream, &outBuff, &inBuff) );\n        if (inBuff.pos != inBuff.size) goto _output_error;   /* entire input should be consumed */\n        ZSTD_freeDStream(dstream);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : check dictionary FSE tables can represent every code : \", testNb++);\n    {   unsigned const kMaxWindowLog = 24;\n        unsigned value;\n        ZSTD_compressionParameters cParams = ZSTD_getCParams(3, 1ULL << kMaxWindowLog, 1024);\n        ZSTD_CDict* cdict;\n        ZSTD_DDict* ddict;\n        SEQ_stream seq = SEQ_initStream(0x87654321);\n        SEQ_gen_type type;\n        XXH64_state_t xxh;\n\n        XXH64_reset(&xxh, 0);\n        cParams.windowLog = kMaxWindowLog;\n        cdict = ZSTD_createCDict_advanced(dictionary.start, dictionary.filled, ZSTD_dlm_byRef, ZSTD_dct_fullDict, cParams, ZSTD_defaultCMem);\n        ddict = ZSTD_createDDict(dictionary.start, dictionary.filled);\n\n        if (!cdict || !ddict) goto _output_error;\n\n        ZSTD_CCtx_reset(zc, ZSTD_reset_session_only);\n        ZSTD_resetDStream(zd);\n        CHECK_Z(ZSTD_CCtx_refCDict(zc, cdict));\n        CHECK_Z(ZSTD_initDStream_usingDDict(zd, ddict));\n        CHECK_Z(ZSTD_DCtx_setParameter(zd, ZSTD_d_windowLogMax, kMaxWindowLog));\n        /* Test all values < 300 */\n        for (value = 0; value < 300; ++value) {\n            for (type = (SEQ_gen_type)0; type < SEQ_gen_max; ++type) {\n                CHECK_Z(SEQ_generateRoundTrip(zc, zd, &xxh, &seq, type, value));\n            }\n        }\n        /* Test values 2^8 to 2^17 */\n        for (value = (1 << 8); value < (1 << 17); value <<= 1) {\n            for (type = (SEQ_gen_type)0; type < SEQ_gen_max; ++type) {\n                CHECK_Z(SEQ_generateRoundTrip(zc, zd, &xxh, &seq, type, value));\n                CHECK_Z(SEQ_generateRoundTrip(zc, zd, &xxh, &seq, type, value + (value >> 2)));\n            }\n        }\n        /* Test offset values up to the max window log */\n        for (value = 8; value <= kMaxWindowLog; ++value) {\n            CHECK_Z(SEQ_generateRoundTrip(zc, zd, &xxh, &seq, SEQ_gen_of, (1U << value) - 1));\n        }\n\n        CHECK_Z(SEQ_roundTrip(zc, zd, &xxh, NULL, 0, ZSTD_e_end));\n        CHECK(SEQ_digest(&seq) != XXH64_digest(&xxh), \"SEQ XXH64 does not match\");\n\n        ZSTD_freeCDict(cdict);\n        ZSTD_freeDDict(ddict);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_initCStream_srcSize sets requestedParams : \", testNb++);\n    {   int level;\n        CHECK_Z(ZSTD_initCStream_srcSize(zc, 11, ZSTD_CONTENTSIZE_UNKNOWN));\n        CHECK_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_compressionLevel, &level));\n        CHECK(level != 11, \"Compression level does not match\");\n        CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) );\n        CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, ZSTD_CONTENTSIZE_UNKNOWN) );\n        CHECK_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_compressionLevel, &level));\n        CHECK(level != 11, \"Compression level does not match\");\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_initCStream_advanced sets requestedParams : \", testNb++);\n    {   ZSTD_parameters const params = ZSTD_getParams(9, 0, 0);\n        CHECK_Z(ZSTD_initCStream_advanced(zc, NULL, 0, params, ZSTD_CONTENTSIZE_UNKNOWN));\n        CHECK(badParameters(zc, params), \"Compression parameters do not match\");\n        CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) );\n        CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, ZSTD_CONTENTSIZE_UNKNOWN) );\n        CHECK(badParameters(zc, params), \"Compression parameters do not match\");\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_c_srcSizeHint bounds : \", testNb++);\n    ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters);\n    CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_srcSizeHint, INT_MAX));\n    {   int srcSizeHint;\n        CHECK_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_srcSizeHint, &srcSizeHint));\n        CHECK(!(srcSizeHint == INT_MAX), \"srcSizeHint doesn't match\");\n    }\n    CHECK(!ZSTD_isError(ZSTD_CCtx_setParameter(zc, ZSTD_c_srcSizeHint, -1)), \"Out of range doesn't error\");\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : ZSTD_lazy compress with hashLog = 29 and searchLog = 4 : \", testNb++);\n    if (MEM_64bits()) {\n        ZSTD_outBuffer out = { compressedBuffer, compressedBufferSize, 0 };\n        ZSTD_inBuffer in = { CNBuffer, CNBufferSize, 0 };\n        CHECK_Z(ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters));\n        CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_strategy, ZSTD_lazy));\n        /* Force enable the row based match finder */\n        CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_useRowMatchFinder, ZSTD_ps_enable));\n        CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_searchLog, 4));\n        /* Set windowLog to 29 so the hashLog doesn't get sized down */\n        CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_windowLog, 29));\n        CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_hashLog, 29));\n        CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_checksumFlag, 1));\n        /* Compress with continue first so the hashLog doesn't get sized down */\n        CHECK_Z(ZSTD_compressStream2(zc, &out, &in, ZSTD_e_continue));\n        CHECK_Z(ZSTD_compressStream2(zc, &out, &in, ZSTD_e_end));\n        cSize = out.pos;\n        CHECK_Z(ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, cSize));\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : Test offset == windowSize : \", testNb++);\n    {\n        int windowLog;\n        int const kMaxWindowLog = bigTests ? 29 : 26;\n        size_t const kNbSequences = 10000;\n        size_t const kMaxSrcSize = ((size_t)1 << kMaxWindowLog) + 10 * kNbSequences;\n        char* src = calloc(kMaxSrcSize, 1);\n        ZSTD_Sequence* sequences = malloc(sizeof(ZSTD_Sequence) * kNbSequences);\n        for (windowLog = ZSTD_WINDOWLOG_MIN; windowLog <= kMaxWindowLog; ++windowLog) {\n            size_t const srcSize = ((size_t)1 << windowLog) + 10 * (kNbSequences - 1);\n\n            sequences[0].offset = 32;\n            sequences[0].litLength = 32;\n            sequences[0].matchLength = (1u << windowLog) - 32;\n            sequences[0].rep = 0;\n            {\n                size_t i;\n                for (i = 1; i < kNbSequences; ++i) {\n                    sequences[i].offset = (1u << windowLog) - (FUZ_rand(&seed) % 8);\n                    sequences[i].litLength = FUZ_rand(&seed) & 7;\n                    sequences[i].matchLength = 10 - sequences[i].litLength;\n                    sequences[i].rep = 0;\n                }\n            }\n\n            CHECK_Z(ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters));\n            CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_checksumFlag, 1));\n            CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_minMatch, 3));\n            CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_validateSequences, 1));\n            CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_windowLog, windowLog));\n            assert(srcSize <= kMaxSrcSize);\n            cSize = ZSTD_compressSequences(zc, compressedBuffer, compressedBufferSize, sequences, kNbSequences, src, srcSize);\n            CHECK_Z(cSize);\n            CHECK_Z(ZSTD_DCtx_reset(zd, ZSTD_reset_session_and_parameters));\n            CHECK_Z(ZSTD_DCtx_setParameter(zd, ZSTD_d_windowLogMax, windowLog))\n            {\n                ZSTD_inBuffer in = {compressedBuffer, cSize, 0};\n                size_t decompressedBytes = 0;\n                for (;;) {\n                    ZSTD_outBuffer out = {decodedBuffer, decodedBufferSize, 0};\n                    size_t const ret = ZSTD_decompressStream(zd, &out, &in);\n                    CHECK_Z(ret);\n                    CHECK(decompressedBytes + out.pos > srcSize, \"Output too large\");\n                    CHECK(memcmp(out.dst, src + decompressedBytes, out.pos), \"Corrupted\");\n                    decompressedBytes += out.pos;\n                    if (ret == 0) {\n                        break;\n                    }\n                }\n                CHECK(decompressedBytes != srcSize, \"Output wrong size\");\n            }\n        }\n        free(sequences);\n        free(src);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* Overlen overwriting window data bug */\n    DISPLAYLEVEL(3, \"test%3i : wildcopy doesn't overwrite potential match data : \", testNb++);\n    {   /* This test has a window size of 1024 bytes and consists of 3 blocks:\n            1. 'a' repeated 517 times\n            2. 'b' repeated 516 times\n            3. a compressed block with no literals and 3 sequence commands:\n                litlength = 0, offset = 24, match length = 24\n                litlength = 0, offset = 24, match length = 3 (this one creates an overlength write of length 2*WILDCOPY_OVERLENGTH - 3)\n                litlength = 0, offset = 1021, match length = 3 (this one will try to read from overwritten data if the buffer is too small) */\n\n        const char* testCase =\n            \"\\x28\\xB5\\x2F\\xFD\\x04\\x00\\x4C\\x00\\x00\\x10\\x61\\x61\\x01\\x00\\x00\\x2A\"\n            \"\\x80\\x05\\x44\\x00\\x00\\x08\\x62\\x01\\x00\\x00\\x2A\\x20\\x04\\x5D\\x00\\x00\"\n            \"\\x00\\x03\\x40\\x00\\x00\\x64\\x60\\x27\\xB0\\xE0\\x0C\\x67\\x62\\xCE\\xE0\";\n        ZSTD_DStream* const zds = ZSTD_createDStream();\n        if (zds==NULL) goto _output_error;\n\n        CHECK_Z( ZSTD_initDStream(zds) );\n        inBuff.src = testCase;\n        inBuff.size = 47;\n        inBuff.pos = 0;\n        outBuff.dst = decodedBuffer;\n        outBuff.size = CNBufferSize;\n        outBuff.pos = 0;\n\n        while (inBuff.pos < inBuff.size) {\n            CHECK_Z( ZSTD_decompressStream(zds, &outBuff, &inBuff) );\n        }\n\n        ZSTD_freeDStream(zds);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* Small Sequence Section bug */\n    DISPLAYLEVEL(3, \"test%3i : decompress blocks with small sequences section : \", testNb++);\n    {   /* This test consists of 3 blocks. Each block has one sequence.\n            The sequence has literal length of 10, match length of 10 and offset of 10.\n            The sequence value and compression mode for the blocks are following:\n            The order of values are ll, ml, of.\n              - First block  : (10, 7, 13) (rle, rle, rle)\n                 - size of sequences section: 6 bytes (1 byte for nbSeq, 1 byte for encoding mode, 3 bytes for rle, 1 byte bitstream)\n              - Second block : (10, 7, 1) (repeat, repeat, rle)\n                 - size of sequences section: 4 bytes (1 byte for nbSeq, 1 byte for encoding mode, 1 bytes for rle, 1 byte bitstream)\n              - Third block  : (10, 7, 1) (repeat, repeat, repeat)\n                 - size of sequences section: 3 bytes (1 byte for nbSeq, 1 byte for encoding mode, 1 byte bitstream) */\n\n        unsigned char compressed[] = {\n            0x28, 0xb5, 0x2f, 0xfd, 0x24, 0x3c, 0x35, 0x01, 0x00, 0xf0, 0x85, 0x08,\n            0xc2, 0xc4, 0x70, 0xcf, 0xd7, 0xc0, 0x96, 0x7e, 0x4c, 0x6b, 0xa9, 0x8b,\n            0xbc, 0xc5, 0xb6, 0xd9, 0x7f, 0x4c, 0xf1, 0x05, 0xa6, 0x54, 0xef, 0xac,\n            0x69, 0x94, 0x89, 0x1c, 0x03, 0x44, 0x0a, 0x07, 0x00, 0xb4, 0x04, 0x80,\n            0x40, 0x0a, 0xa4\n        };\n        unsigned int compressedSize = 51;\n        unsigned char decompressed[] = {\n            0x85, 0x08, 0xc2, 0xc4, 0x70, 0xcf, 0xd7, 0xc0, 0x96, 0x7e, 0x85, 0x08,\n            0xc2, 0xc4, 0x70, 0xcf, 0xd7, 0xc0, 0x96, 0x7e, 0x4c, 0x6b, 0xa9, 0x8b,\n            0xbc, 0xc5, 0xb6, 0xd9, 0x7f, 0x4c, 0x4c, 0x6b, 0xa9, 0x8b, 0xbc, 0xc5,\n            0xb6, 0xd9, 0x7f, 0x4c, 0xf1, 0x05, 0xa6, 0x54, 0xef, 0xac, 0x69, 0x94,\n            0x89, 0x1c, 0xf1, 0x05, 0xa6, 0x54, 0xef, 0xac, 0x69, 0x94, 0x89, 0x1c\n        };\n        unsigned int decompressedSize = 60;\n\n        ZSTD_DStream* const zds = ZSTD_createDStream();\n        if (zds==NULL) goto _output_error;\n\n        CHECK_Z( ZSTD_initDStream(zds) );\n        inBuff.src = compressed;\n        inBuff.size = compressedSize;\n        inBuff.pos = 0;\n        outBuff.dst = decodedBuffer;\n        outBuff.size = CNBufferSize;\n        outBuff.pos = 0;\n\n        CHECK(ZSTD_decompressStream(zds, &outBuff, &inBuff) != 0,\n              \"Decompress did not reach the end of frame\");\n        CHECK(inBuff.pos != inBuff.size, \"Decompress did not fully consume input\");\n        CHECK(outBuff.pos != decompressedSize, \"Decompressed size does not match\");\n        CHECK(memcmp(outBuff.dst, decompressed, decompressedSize) != 0,\n              \"Decompressed data does not match\");\n\n        ZSTD_freeDStream(zds);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : raw block can be streamed: \", testNb++);\n    {   size_t const inputSize = 10000;\n        size_t const compCapacity = ZSTD_compressBound(inputSize);\n        BYTE* const input = (BYTE*)malloc(inputSize);\n        BYTE* const comp = (BYTE*)malloc(compCapacity);\n        BYTE* const decomp = (BYTE*)malloc(inputSize);\n\n        CHECK(input == NULL || comp == NULL || decomp == NULL, \"failed to alloc buffers\");\n\n        RDG_genBuffer(input, inputSize, 0.0, 0.0, seed);\n        {   size_t const compSize = ZSTD_compress(comp, compCapacity, input, inputSize, -(int)inputSize);\n            ZSTD_inBuffer in = { comp, 0, 0 };\n            ZSTD_outBuffer out = { decomp, 0, 0 };\n            CHECK_Z(compSize);\n            CHECK_Z( ZSTD_DCtx_reset(zd, ZSTD_reset_session_and_parameters) );\n            while (in.size < compSize) {\n                in.size = MIN(in.size + 100, compSize);\n                while (in.pos < in.size) {\n                    size_t const outPos = out.pos;\n                    if (out.pos == out.size) {\n                        out.size = MIN(out.size + 10, inputSize);\n                    }\n                    CHECK_Z( ZSTD_decompressStream(zd, &out, &in) );\n                    CHECK(!(out.pos > outPos), \"We are not streaming (no output generated)\");\n                }\n            }\n            CHECK(in.pos != compSize, \"Not all input consumed!\");\n            CHECK(out.pos != inputSize, \"Not all output produced!\");\n        }\n        CHECK(memcmp(input, decomp, inputSize), \"round trip failed!\");\n\n        free(input);\n        free(comp);\n        free(decomp);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : dictionary + uncompressible block + reusing tables checks offset table validity: \", testNb++);\n    {   ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(\n            dictionary.start, dictionary.filled,\n            ZSTD_dlm_byRef, ZSTD_dct_fullDict,\n            ZSTD_getCParams(3, 0, dictionary.filled),\n            ZSTD_defaultCMem);\n        const size_t inbufsize = 2 * 128 * 1024; /* 2 blocks */\n        const size_t outbufsize = ZSTD_compressBound(inbufsize);\n        size_t inbufpos = 0;\n        size_t cursegmentlen;\n        BYTE *inbuf = (BYTE *)malloc(inbufsize);\n        BYTE *outbuf = (BYTE *)malloc(outbufsize);\n        BYTE *checkbuf = (BYTE *)malloc(inbufsize);\n        size_t ret;\n\n        CHECK(cdict == NULL, \"failed to alloc cdict\");\n        CHECK(inbuf == NULL, \"failed to alloc input buffer\");\n\n        /* first block is uncompressible */\n        cursegmentlen = 128 * 1024;\n        RDG_genBuffer(inbuf + inbufpos, cursegmentlen, 0., 0., seed);\n        inbufpos += cursegmentlen;\n\n        /* second block is compressible */\n        cursegmentlen = 128 * 1024 - 256;\n        RDG_genBuffer(inbuf + inbufpos, cursegmentlen, 0.05, 0., seed);\n        inbufpos += cursegmentlen;\n\n        /* and includes a very long backref */\n        cursegmentlen = 128;\n        memcpy(inbuf + inbufpos, (BYTE*)dictionary.start + 256, cursegmentlen);\n        inbufpos += cursegmentlen;\n\n        /* and includes a very long backref */\n        cursegmentlen = 128;\n        memcpy(inbuf + inbufpos, (BYTE*)dictionary.start + 128, cursegmentlen);\n        inbufpos += cursegmentlen;\n\n        ret = ZSTD_compress_usingCDict(zc, outbuf, outbufsize, inbuf, inbufpos, cdict);\n        CHECK_Z(ret);\n\n        ret = ZSTD_decompress_usingDict(zd, checkbuf, inbufsize, outbuf, ret, dictionary.start, dictionary.filled);\n        CHECK_Z(ret);\n\n        CHECK(memcmp(inbuf, checkbuf, inbufpos), \"start and finish buffers don't match\");\n\n        ZSTD_freeCDict(cdict);\n        free(inbuf);\n        free(outbuf);\n        free(checkbuf);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : dictionary + small blocks + reusing tables checks offset table validity: \", testNb++);\n    {   ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(\n            dictionary.start, dictionary.filled,\n            ZSTD_dlm_byRef, ZSTD_dct_fullDict,\n            ZSTD_getCParams(3, 0, dictionary.filled),\n            ZSTD_defaultCMem);\n        ZSTD_outBuffer out = {compressedBuffer, compressedBufferSize, 0};\n        int remainingInput = 256 * 1024;\n        int offset;\n\n        CHECK_Z(ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters));\n        CHECK_Z(ZSTD_CCtx_refCDict(zc, cdict));\n        CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_checksumFlag, 1));\n        /* Write a bunch of 6 byte blocks */\n        while (remainingInput > 0) {\n          char testBuffer[6] = { 0x66, 0x66, 0x66, 0x66, 0x66, 0x66 };\n          const size_t kSmallBlockSize = sizeof(testBuffer);\n          ZSTD_inBuffer in = {testBuffer, kSmallBlockSize, 0};\n\n          CHECK_Z(ZSTD_compressStream2(zc, &out, &in, ZSTD_e_flush));\n          CHECK(in.pos != in.size, \"input not fully consumed\");\n          remainingInput -= (int)kSmallBlockSize;\n        }\n        /* Write several very long offset matches into the dictionary */\n        for (offset = 1024; offset >= 0; offset -= 128) {\n          ZSTD_inBuffer in = {(BYTE*)dictionary.start + offset, 128, 0};\n          ZSTD_EndDirective flush = offset > 0 ? ZSTD_e_continue : ZSTD_e_end;\n          CHECK_Z(ZSTD_compressStream2(zc, &out, &in, flush));\n          CHECK(in.pos != in.size, \"input not fully consumed\");\n        }\n        /* Ensure decompression works */\n        CHECK_Z(ZSTD_decompress_usingDict(zd, decodedBuffer, CNBufferSize, out.dst, out.pos, dictionary.start, dictionary.filled));\n\n        ZSTD_freeCDict(cdict);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : Block-Level External Sequence Producer API: \", testNb++);\n    {\n        size_t const dstBufSize = ZSTD_compressBound(CNBufferSize);\n        BYTE* const dstBuf = (BYTE*)malloc(dstBufSize);\n        size_t const checkBufSize = CNBufferSize;\n        BYTE* const checkBuf = (BYTE*)malloc(checkBufSize);\n        int enableFallback;\n        EMF_testCase sequenceProducerState;\n\n        CHECK(dstBuf == NULL || checkBuf == NULL, \"allocation failed\");\n\n        CHECK_Z(ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters));\n\n        /* Reference external matchfinder outside the test loop to\n         * check that the reference is preserved across compressions */\n        ZSTD_registerSequenceProducer(zc, &sequenceProducerState, zstreamSequenceProducer);\n\n        for (enableFallback = 0; enableFallback <= 1; enableFallback++) {\n            size_t testCaseId;\n            size_t const numTestCases = 9;\n\n            EMF_testCase const testCases[] = {\n                EMF_ONE_BIG_SEQ,\n                EMF_LOTS_OF_SEQS,\n                EMF_ZERO_SEQS,\n                EMF_BIG_ERROR,\n                EMF_SMALL_ERROR,\n                EMF_INVALID_OFFSET,\n                EMF_INVALID_MATCHLEN,\n                EMF_INVALID_LITLEN,\n                EMF_INVALID_LAST_LITS\n            };\n\n            ZSTD_ErrorCode const errorCodes[] = {\n                ZSTD_error_no_error,\n                ZSTD_error_no_error,\n                ZSTD_error_sequenceProducer_failed,\n                ZSTD_error_sequenceProducer_failed,\n                ZSTD_error_sequenceProducer_failed,\n                ZSTD_error_externalSequences_invalid,\n                ZSTD_error_externalSequences_invalid,\n                ZSTD_error_externalSequences_invalid,\n                ZSTD_error_externalSequences_invalid\n            };\n\n            for (testCaseId = 0; testCaseId < numTestCases; testCaseId++) {\n                size_t res;\n\n                int const compressionShouldSucceed = (\n                    (errorCodes[testCaseId] == ZSTD_error_no_error) ||\n                    (enableFallback && errorCodes[testCaseId] == ZSTD_error_sequenceProducer_failed)\n                );\n\n                int const testWithSequenceValidation = (\n                    testCases[testCaseId] == EMF_INVALID_OFFSET\n                );\n\n                sequenceProducerState = testCases[testCaseId];\n\n                ZSTD_CCtx_reset(zc, ZSTD_reset_session_only);\n                CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_validateSequences, testWithSequenceValidation));\n                CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_enableSeqProducerFallback, enableFallback));\n                res = ZSTD_compress2(zc, dstBuf, dstBufSize, CNBuffer, CNBufferSize);\n\n                if (compressionShouldSucceed) {\n                    CHECK(ZSTD_isError(res), \"EMF: Compression error: %s\", ZSTD_getErrorName(res));\n                    CHECK_Z(ZSTD_decompress(checkBuf, checkBufSize, dstBuf, res));\n                    CHECK(memcmp(CNBuffer, checkBuf, CNBufferSize) != 0, \"EMF: Corruption!\");\n                } else {\n                    CHECK(!ZSTD_isError(res), \"EMF: Should have raised an error!\");\n                    CHECK(\n                        ZSTD_getErrorCode(res) != errorCodes[testCaseId],\n                        \"EMF: Wrong error code: %s\", ZSTD_getErrorName(res)\n                    );\n                }\n            }\n\n            /* Test compression with external matchfinder + empty src buffer */\n            {\n                size_t res;\n                sequenceProducerState = EMF_ZERO_SEQS;\n                ZSTD_CCtx_reset(zc, ZSTD_reset_session_only);\n                CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_enableSeqProducerFallback, enableFallback));\n                res = ZSTD_compress2(zc, dstBuf, dstBufSize, CNBuffer, 0);\n                CHECK(ZSTD_isError(res), \"EMF: Compression error: %s\", ZSTD_getErrorName(res));\n                CHECK(ZSTD_decompress(checkBuf, checkBufSize, dstBuf, res) != 0, \"EMF: Empty src round trip failed!\");\n            }\n        }\n\n        /* Test that reset clears the external matchfinder */\n        CHECK_Z(ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters));\n        sequenceProducerState = EMF_BIG_ERROR; /* ensure zstd will fail if the matchfinder wasn't cleared */\n        CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_enableSeqProducerFallback, 0));\n        CHECK_Z(ZSTD_compress2(zc, dstBuf, dstBufSize, CNBuffer, CNBufferSize));\n\n        /* Test that registering mFinder == NULL clears the external matchfinder */\n        ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters);\n        ZSTD_registerSequenceProducer(zc, &sequenceProducerState, zstreamSequenceProducer);\n        sequenceProducerState = EMF_BIG_ERROR; /* ensure zstd will fail if the matchfinder wasn't cleared */\n        CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_enableSeqProducerFallback, 0));\n        ZSTD_registerSequenceProducer(zc, NULL, NULL); /* clear the external matchfinder */\n        CHECK_Z(ZSTD_compress2(zc, dstBuf, dstBufSize, CNBuffer, CNBufferSize));\n\n        /* Test that external matchfinder doesn't interact with older APIs */\n        ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters);\n        ZSTD_registerSequenceProducer(zc, &sequenceProducerState, zstreamSequenceProducer);\n        sequenceProducerState = EMF_BIG_ERROR; /* ensure zstd will fail if the matchfinder is used */\n        CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_enableSeqProducerFallback, 0));\n        CHECK_Z(ZSTD_compressCCtx(zc, dstBuf, dstBufSize, CNBuffer, CNBufferSize, 3));\n\n        /* Test that compression returns the correct error with LDM */\n        CHECK_Z(ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters));\n        {\n            size_t res;\n            ZSTD_registerSequenceProducer(zc, &sequenceProducerState, zstreamSequenceProducer);\n            CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable));\n            res = ZSTD_compress2(zc, dstBuf, dstBufSize, CNBuffer, CNBufferSize);\n            CHECK(!ZSTD_isError(res), \"EMF: Should have raised an error!\");\n            CHECK(\n                ZSTD_getErrorCode(res) != ZSTD_error_parameter_combination_unsupported,\n                \"EMF: Wrong error code: %s\", ZSTD_getErrorName(res)\n            );\n        }\n\n#ifdef ZSTD_MULTITHREAD\n        /* Test that compression returns the correct error with nbWorkers > 0 */\n        CHECK_Z(ZSTD_CCtx_reset(zc, ZSTD_reset_session_and_parameters));\n        {\n            size_t res;\n            ZSTD_registerSequenceProducer(zc, &sequenceProducerState, zstreamSequenceProducer);\n            CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_nbWorkers, 1));\n            res = ZSTD_compress2(zc, dstBuf, dstBufSize, CNBuffer, CNBufferSize);\n            CHECK(!ZSTD_isError(res), \"EMF: Should have raised an error!\");\n            CHECK(\n                ZSTD_getErrorCode(res) != ZSTD_error_parameter_combination_unsupported,\n                \"EMF: Wrong error code: %s\", ZSTD_getErrorName(res)\n            );\n        }\n#endif\n\n        free(dstBuf);\n        free(checkBuf);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n\n    /* Test maxBlockSize cctx param functionality */\n    DISPLAYLEVEL(3, \"test%3i : Testing maxBlockSize PR#3418: \", testNb++);\n    {\n        ZSTD_CCtx* cctx = ZSTD_createCCtx();\n\n        /* Quick test to make sure maxBlockSize bounds are enforced */\n        assert(ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, ZSTD_BLOCKSIZE_MAX_MIN - 1)));\n        assert(ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, ZSTD_BLOCKSIZE_MAX + 1)));\n\n        /* Test maxBlockSize < windowSize and windowSize < maxBlockSize*/\n        {\n            size_t srcSize = 2 << 10;\n            void* const src = CNBuffer;\n            size_t dstSize = ZSTD_compressBound(srcSize);\n            void* const dst1 = compressedBuffer;\n            void* const dst2 = (BYTE*)compressedBuffer + dstSize;\n            size_t size1, size2;\n            void* const checkBuf = malloc(srcSize);\n            memset(src, 'x', srcSize);\n\n            /* maxBlockSize = 1KB */\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, 1u << 10));\n            size1 = ZSTD_compress2(cctx, dst1, dstSize, src, srcSize);\n\n            if (ZSTD_isError(size1)) goto _output_error;\n            CHECK_Z(ZSTD_decompress(checkBuf, srcSize, dst1, size1));\n            CHECK(memcmp(src, checkBuf, srcSize) != 0, \"Corruption!\");\n\n            /* maxBlockSize = 3KB */\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, 3u << 10));\n            size2 = ZSTD_compress2(cctx, dst2, dstSize, src, srcSize);\n\n            if (ZSTD_isError(size2)) goto _output_error;\n            CHECK_Z(ZSTD_decompress(checkBuf, srcSize, dst2, size2));\n            CHECK(memcmp(src, checkBuf, srcSize) != 0, \"Corruption!\");\n\n            assert(size1 - size2 == 4); /* We add another RLE block with header + character */\n            assert(memcmp(dst1, dst2, size2) != 0); /* Compressed output should not be equal */\n\n            /* maxBlockSize = 1KB, windowLog = 10 */\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, 1u << 10));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 10));\n            size1 = ZSTD_compress2(cctx, dst1, dstSize, src, srcSize);\n\n            if (ZSTD_isError(size1)) goto _output_error;\n            CHECK_Z(ZSTD_decompress(checkBuf, srcSize, dst1, size1));\n            CHECK(memcmp(src, checkBuf, srcSize) != 0, \"Corruption!\");\n\n            /* maxBlockSize = 3KB, windowLog = 10 */\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, 3u << 10));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 10));\n            size2 = ZSTD_compress2(cctx, dst2, dstSize, src, srcSize);\n\n            if (ZSTD_isError(size2)) goto _output_error;\n            CHECK_Z(ZSTD_decompress(checkBuf, srcSize, dst2, size2));\n            CHECK(memcmp(src, checkBuf, srcSize) != 0, \"Corruption!\");\n\n            assert(size1 == size2);\n            assert(memcmp(dst1, dst2, size1) == 0); /* Compressed output should be equal */\n\n            free(checkBuf);\n        }\n\n        ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n\n        /* Test maxBlockSize = 0 is valid */\n        {   size_t srcSize = 256 << 10;\n            void* const src = CNBuffer;\n            size_t dstSize = ZSTD_compressBound(srcSize);\n            void* const dst1 = compressedBuffer;\n            void* const dst2 = (BYTE*)compressedBuffer + dstSize;\n            size_t size1, size2;\n            void* const checkBuf = malloc(srcSize);\n\n            /* maxBlockSize = 0 */\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, 0));\n            size1 = ZSTD_compress2(cctx, dst1, dstSize, src, srcSize);\n\n            if (ZSTD_isError(size1)) goto _output_error;\n            CHECK_Z(ZSTD_decompress(checkBuf, srcSize, dst1, size1));\n            CHECK(memcmp(src, checkBuf, srcSize) != 0, \"Corruption!\");\n\n            /* maxBlockSize = ZSTD_BLOCKSIZE_MAX */\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, ZSTD_BLOCKSIZE_MAX));\n            size2 = ZSTD_compress2(cctx, dst2, dstSize, src, srcSize);\n\n            if (ZSTD_isError(size2)) goto _output_error;\n            CHECK_Z(ZSTD_decompress(checkBuf, srcSize, dst2, size2));\n            CHECK(memcmp(src, checkBuf, srcSize) != 0, \"Corruption!\");\n\n            assert(size1 == size2);\n            assert(memcmp(dst1, dst2, size1) == 0); /* Compressed output should be equal */\n            free(checkBuf);\n        }\n        ZSTD_freeCCtx(cctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    /* Test Sequence Validation */\n    DISPLAYLEVEL(3, \"test%3i : Testing sequence validation: \", testNb++);\n    {\n        ZSTD_CCtx* cctx = ZSTD_createCCtx();\n\n        /* Test minMatch >= 4, matchLength < 4 */\n        {\n            size_t srcSize = 11;\n            void* const src = CNBuffer;\n            size_t dstSize = ZSTD_compressBound(srcSize);\n            void* const dst = compressedBuffer;\n            size_t const kNbSequences = 4;\n            ZSTD_Sequence* sequences = malloc(sizeof(ZSTD_Sequence) * kNbSequences);\n\n            memset(src, 'x', srcSize);\n\n            sequences[0] = (ZSTD_Sequence) {1, 1, 3, 0};\n            sequences[1] = (ZSTD_Sequence) {1, 0, 3, 0};\n            sequences[2] = (ZSTD_Sequence) {1, 0, 3, 0};\n            sequences[3] = (ZSTD_Sequence) {0, 1, 0, 0};\n\n            /* Test with sequence validation */\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, 5));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_validateSequences, 1));\n\n            cSize = ZSTD_compressSequences(cctx, dst, dstSize,\n                                   sequences, kNbSequences,\n                                   src, srcSize);\n\n            CHECK(!ZSTD_isError(cSize), \"Should throw an error\"); /* maxNbSeq is too small and an assert will fail */\n            CHECK(ZSTD_getErrorCode(cSize) != ZSTD_error_externalSequences_invalid, \"Wrong error code: %s\", ZSTD_getErrorName(cSize)); /* fails sequence validation */\n\n            ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n\n            /* Test without sequence validation */\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, 5));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_validateSequences, 0));\n\n            cSize = ZSTD_compressSequences(cctx, dst, dstSize,\n                                   sequences, kNbSequences,\n                                   src, srcSize);\n\n            CHECK(!ZSTD_isError(cSize), \"Should throw an error\"); /* maxNbSeq is too small and an assert will fail */\n            CHECK(ZSTD_getErrorCode(cSize) != ZSTD_error_externalSequences_invalid, \"Wrong error code: %s\", ZSTD_getErrorName(cSize)); /* fails sequence validation */\n\n            free(sequences);\n        }\n\n        ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n\n\n        /* Test with no block delim */\n        {\n            size_t srcSize = 4;\n            void* const src = CNBuffer;\n            size_t dstSize = ZSTD_compressBound(srcSize);\n            void* const dst = compressedBuffer;\n            size_t const kNbSequences = 1;\n            ZSTD_Sequence* sequences = malloc(sizeof(ZSTD_Sequence) * kNbSequences);\n            void* const checkBuf = malloc(srcSize);\n\n            memset(src, 'x', srcSize);\n\n            sequences[0] = (ZSTD_Sequence) {1, 1, 3, 0};\n\n            /* Test with sequence validation */\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, 3));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, ZSTD_sf_noBlockDelimiters));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_validateSequences, 1));\n\n            cSize = ZSTD_compressSequences(cctx, dst, dstSize,\n                                   sequences, kNbSequences,\n                                   src, srcSize);\n\n            CHECK(ZSTD_isError(cSize), \"Should not throw an error\");\n            CHECK_Z(ZSTD_decompress(checkBuf, srcSize, dst, cSize));\n            CHECK(memcmp(src, checkBuf, srcSize) != 0, \"Corruption!\");\n\n            free(sequences);\n            free(checkBuf);\n        }\n\n        ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n\n        { /* Test case with two additional sequences */\n            size_t srcSize = 19;\n            void* const src = CNBuffer;\n            size_t dstSize = ZSTD_compressBound(srcSize);\n            void* const dst = compressedBuffer;\n            size_t const kNbSequences = 7;\n            ZSTD_Sequence* sequences = malloc(sizeof(ZSTD_Sequence) * kNbSequences);\n\n            memset(src, 'x', srcSize);\n\n            sequences[0] = (ZSTD_Sequence) {1, 1, 3, 0};\n            sequences[1] = (ZSTD_Sequence) {1, 0, 3, 0};\n            sequences[2] = (ZSTD_Sequence) {1, 0, 3, 0};\n            sequences[3] = (ZSTD_Sequence) {1, 0, 3, 0};\n            sequences[4] = (ZSTD_Sequence) {1, 0, 3, 0};\n            sequences[5] = (ZSTD_Sequence) {1, 0, 3, 0};\n            sequences[6] = (ZSTD_Sequence) {0, 0, 0, 0};\n\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, 5));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_validateSequences, 1));\n\n            cSize = ZSTD_compressSequences(cctx, dst, dstSize,\n                                   sequences, kNbSequences,\n                                   src, srcSize);\n\n            CHECK(!ZSTD_isError(cSize), \"Should throw an error\"); /* maxNbSeq is too small and an assert will fail */\n            CHECK(ZSTD_getErrorCode(cSize) != ZSTD_error_externalSequences_invalid, \"Wrong error code: %s\", ZSTD_getErrorName(cSize)); /* fails sequence validation */\n\n            ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);\n\n            /* Test without sequence validation */\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, 5));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters));\n            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_validateSequences, 0));\n\n            cSize = ZSTD_compressSequences(cctx, dst, dstSize,\n                                   sequences, kNbSequences,\n                                   src, srcSize);\n\n            CHECK(!ZSTD_isError(cSize), \"Should throw an error\"); /* maxNbSeq is too small and an assert will fail */\n            CHECK(ZSTD_getErrorCode(cSize) != ZSTD_error_externalSequences_invalid, \"Wrong error code: %s\", ZSTD_getErrorName(cSize)); /* fails sequence validation */\n\n            free(sequences);\n        }\n        ZSTD_freeCCtx(cctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n\n    DISPLAYLEVEL(3, \"test%3i : Testing large offset with small window size: \", testNb++);\n    {\n        ZSTD_CCtx* cctx = ZSTD_createCCtx();\n        ZSTD_DCtx* dctx = ZSTD_createDCtx();\n\n        /* Test large offset, small window size*/\n        {\n            size_t srcSize = 21;\n            void* const src = CNBuffer;\n            size_t dstSize = ZSTD_compressBound(srcSize);\n            void* const dst = compressedBuffer;\n            size_t const kNbSequences = 4;\n            ZSTD_Sequence* sequences = malloc(sizeof(ZSTD_Sequence) * kNbSequences);\n            void* const checkBuf = malloc(srcSize);\n            const size_t largeDictSize = 1 << 25;\n            ZSTD_CDict* cdict = NULL;\n            ZSTD_DDict* ddict = NULL;\n\n            /* Generate large dictionary */\n            void* dictBuffer = calloc(largeDictSize, 1);\n            ZSTD_compressionParameters cParams = ZSTD_getCParams(1, srcSize, largeDictSize);\n            cParams.minMatch = ZSTD_MINMATCH_MIN;\n            cParams.hashLog = ZSTD_HASHLOG_MIN;\n            cParams.chainLog = ZSTD_CHAINLOG_MIN;\n\n            cdict = ZSTD_createCDict_advanced(dictBuffer, largeDictSize, ZSTD_dlm_byRef, ZSTD_dct_rawContent, cParams, ZSTD_defaultCMem);\n            ddict = ZSTD_createDDict_advanced(dictBuffer, largeDictSize, ZSTD_dlm_byRef, ZSTD_dct_rawContent, ZSTD_defaultCMem);\n\n            ZSTD_CCtx_refCDict(cctx, cdict);\n            ZSTD_DCtx_refDDict(dctx, ddict);\n\n            sequences[0] = (ZSTD_Sequence) {3, 3, 3, 0};\n            sequences[1] = (ZSTD_Sequence) {1 << 25, 0, 3, 0};\n            sequences[2] = (ZSTD_Sequence) {1 << 25, 0, 9, 0};\n            sequences[3] = (ZSTD_Sequence) {3, 0, 3, 0};\n\n            cSize = ZSTD_compressSequences(cctx, dst, dstSize,\n                                   sequences, kNbSequences,\n                                   src, srcSize);\n\n            CHECK(ZSTD_isError(cSize), \"Should not throw an error\");\n\n            {\n                size_t dSize = ZSTD_decompressDCtx(dctx, checkBuf, srcSize, dst, cSize);\n                CHECK(ZSTD_isError(dSize), \"Should not throw an error\");\n                CHECK(memcmp(src, checkBuf, srcSize) != 0, \"Corruption!\");\n            }\n\n            free(sequences);\n            free(checkBuf);\n            free(dictBuffer);\n            ZSTD_freeCDict(cdict);\n            ZSTD_freeDDict(ddict);\n        }\n        ZSTD_freeCCtx(cctx);\n        ZSTD_freeDCtx(dctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : Testing external sequence producer with static CCtx (one-shot): \", testNb++);\n    {\n        size_t const dstBufSize = ZSTD_compressBound(CNBufferSize);\n        BYTE* const dstBuf = (BYTE*)malloc(dstBufSize);\n        size_t const checkBufSize = CNBufferSize;\n        BYTE* const checkBuf = (BYTE*)malloc(checkBufSize);\n        ZSTD_CCtx_params* params = ZSTD_createCCtxParams();\n        ZSTD_CCtx* staticCCtx;\n        void* cctxBuf;\n        EMF_testCase seqProdState;\n\n        CHECK_Z(ZSTD_CCtxParams_setParameter(params, ZSTD_c_validateSequences, 1));\n        CHECK_Z(ZSTD_CCtxParams_setParameter(params, ZSTD_c_enableSeqProducerFallback, 0));\n        ZSTD_CCtxParams_registerSequenceProducer(params, &seqProdState, zstreamSequenceProducer);\n\n        {\n            size_t const cctxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params);\n            cctxBuf = malloc(cctxSize);\n            staticCCtx = ZSTD_initStaticCCtx(cctxBuf, cctxSize);\n            CHECK_Z(ZSTD_CCtx_setParametersUsingCCtxParams(staticCCtx, params));\n        }\n\n        // Check that compression with external sequence producer succeeds when expected\n        seqProdState = EMF_LOTS_OF_SEQS;\n        {\n            size_t dResult;\n            size_t const cResult = ZSTD_compress2(staticCCtx, dstBuf, dstBufSize, CNBuffer, CNBufferSize);\n            CHECK(ZSTD_isError(cResult), \"EMF: Compression error: %s\", ZSTD_getErrorName(cResult));\n            dResult = ZSTD_decompress(checkBuf, checkBufSize, dstBuf, cResult);\n            CHECK(ZSTD_isError(dResult), \"EMF: Decompression error: %s\", ZSTD_getErrorName(dResult));\n            CHECK(dResult != CNBufferSize, \"EMF: Corruption!\");\n            CHECK(memcmp(CNBuffer, checkBuf, CNBufferSize) != 0, \"EMF: Corruption!\");\n        }\n\n        // Check that compression with external sequence producer fails when expected\n        seqProdState = EMF_BIG_ERROR;\n        {\n            size_t const cResult = ZSTD_compress2(staticCCtx, dstBuf, dstBufSize, CNBuffer, CNBufferSize);\n            CHECK(!ZSTD_isError(cResult), \"EMF: Should have raised an error!\");\n            CHECK(\n                ZSTD_getErrorCode(cResult) != ZSTD_error_sequenceProducer_failed,\n                \"EMF: Wrong error code: %s\", ZSTD_getErrorName(cResult)\n            );\n        }\n\n        free(dstBuf);\n        free(checkBuf);\n        free(cctxBuf);\n        ZSTD_freeCCtxParams(params);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : Testing external sequence producer with static CCtx (streaming): \", testNb++);\n    {\n        size_t const dstBufSize = ZSTD_compressBound(CNBufferSize);\n        BYTE* const dstBuf = (BYTE*)malloc(dstBufSize);\n        size_t const checkBufSize = CNBufferSize;\n        BYTE* const checkBuf = (BYTE*)malloc(checkBufSize);\n        ZSTD_CCtx_params* params = ZSTD_createCCtxParams();\n        ZSTD_CCtx* staticCCtx;\n        void* cctxBuf;\n        EMF_testCase seqProdState;\n\n        CHECK_Z(ZSTD_CCtxParams_setParameter(params, ZSTD_c_validateSequences, 1));\n        CHECK_Z(ZSTD_CCtxParams_setParameter(params, ZSTD_c_enableSeqProducerFallback, 0));\n        ZSTD_CCtxParams_registerSequenceProducer(params, &seqProdState, zstreamSequenceProducer);\n\n        {\n            size_t const cctxSize = ZSTD_estimateCStreamSize_usingCCtxParams(params);\n            cctxBuf = malloc(cctxSize);\n            staticCCtx = ZSTD_initStaticCCtx(cctxBuf, cctxSize);\n            CHECK_Z(ZSTD_CCtx_setParametersUsingCCtxParams(staticCCtx, params));\n        }\n\n        // Check that compression with external sequence producer succeeds when expected\n        seqProdState = EMF_LOTS_OF_SEQS;\n        {\n            ZSTD_inBuffer inBuf = { CNBuffer, CNBufferSize, 0 };\n            ZSTD_outBuffer outBuf = { dstBuf, dstBufSize, 0 };\n            size_t dResult;\n            CHECK_Z(ZSTD_compressStream(staticCCtx, &outBuf, &inBuf));\n            CHECK_Z(ZSTD_endStream(staticCCtx, &outBuf));\n            CHECK(inBuf.pos != inBuf.size, \"EMF: inBuf.pos != inBuf.size\");\n            dResult = ZSTD_decompress(checkBuf, checkBufSize, outBuf.dst, outBuf.pos);\n            CHECK(ZSTD_isError(dResult), \"EMF: Decompression error: %s\", ZSTD_getErrorName(dResult));\n            CHECK(dResult != CNBufferSize, \"EMF: Corruption!\");\n            CHECK(memcmp(CNBuffer, checkBuf, CNBufferSize) != 0, \"EMF: Corruption!\");\n        }\n\n        CHECK_Z(ZSTD_CCtx_reset(staticCCtx, ZSTD_reset_session_only));\n\n        // Check that compression with external sequence producer fails when expected\n        seqProdState = EMF_BIG_ERROR;\n        {\n            ZSTD_inBuffer inBuf = { CNBuffer, CNBufferSize, 0 };\n            ZSTD_outBuffer outBuf = { dstBuf, dstBufSize, 0 };\n            size_t const cResult = ZSTD_compressStream(staticCCtx, &outBuf, &inBuf);\n            CHECK(!ZSTD_isError(cResult), \"EMF: Should have raised an error!\");\n            CHECK(\n                ZSTD_getErrorCode(cResult) != ZSTD_error_sequenceProducer_failed,\n                \"EMF: Wrong error code: %s\", ZSTD_getErrorName(cResult)\n            );\n        }\n\n        free(dstBuf);\n        free(checkBuf);\n        free(cctxBuf);\n        ZSTD_freeCCtxParams(params);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : Decoder should reject invalid frame header on legacy frames: \", testNb++);\n    {\n        const unsigned char compressed[] = { 0x26,0xb5,0x2f,0xfd,0x50,0x91,0xfd,0xd8,0xb5 };\n        const size_t compressedSize = 9;\n        size_t const dSize = ZSTD_decompress(NULL, 0, compressed, compressedSize);\n        CHECK(!ZSTD_isError(dSize), \"must reject when legacy frame header is invalid\");\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n    DISPLAYLEVEL(3, \"test%3i : Test single-shot fallback for magicless mode: \", testNb++);\n    {\n        // Acquire resources\n        size_t const srcSize = COMPRESSIBLE_NOISE_LENGTH;\n        void* src = malloc(srcSize);\n        size_t const dstSize = ZSTD_compressBound(srcSize);\n        void* dst = malloc(dstSize);\n        size_t const valSize = srcSize;\n        void* val = malloc(valSize);\n        ZSTD_inBuffer inBuf = { dst, dstSize, 0 };\n        ZSTD_outBuffer outBuf = { val, valSize, 0 };\n        ZSTD_CCtx* cctx = ZSTD_createCCtx();\n        ZSTD_DCtx* dctx = ZSTD_createDCtx();\n        CHECK(!src || !dst || !val || !dctx || !cctx, \"memory allocation failure\");\n\n        // Write test data for decompression to dst\n        RDG_genBuffer(src, srcSize, compressibility, 0.0, 0xdeadbeef);\n        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_format, ZSTD_f_zstd1_magicless));\n        CHECK_Z(ZSTD_compress2(cctx, dst, dstSize, src, srcSize));\n\n        // Run decompression\n        CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, ZSTD_f_zstd1_magicless));\n        CHECK_Z(ZSTD_decompressStream(dctx, &outBuf, &inBuf));\n\n        // Validate\n        CHECK(outBuf.pos != srcSize, \"decompressed size must match\");\n        CHECK(memcmp(src, val, srcSize) != 0, \"decompressed data must match\");\n\n        // Cleanup\n        free(src); free(dst); free(val);\n        ZSTD_freeCCtx(cctx);\n        ZSTD_freeDCtx(dctx);\n    }\n    DISPLAYLEVEL(3, \"OK \\n\");\n\n_end:\n    FUZ_freeDictionary(dictionary);\n    ZSTD_freeCStream(zc);\n    ZSTD_freeDStream(zd);\n    ZSTD_freeCCtx(mtctx);\n    free(CNBuffer);\n    free(compressedBuffer);\n    free(decodedBuffer);\n    return testResult;\n\n_output_error:\n    testResult = 1;\n    DISPLAY(\"Error detected in Unit tests ! \\n\");\n    goto _end;\n}\n\n\n/* ======   Fuzzer tests   ====== */\n\nstatic size_t findDiff(const void* buf1, const void* buf2, size_t max)\n{\n    const BYTE* b1 = (const BYTE*)buf1;\n    const BYTE* b2 = (const BYTE*)buf2;\n    size_t u;\n    for (u=0; u<max; u++) {\n        if (b1[u] != b2[u]) break;\n    }\n    if (u==max) {\n        DISPLAY(\"=> No difference detected within %u bytes \\n\", (unsigned)max);\n        return u;\n    }\n    DISPLAY(\"Error at position %u / %u \\n\", (unsigned)u, (unsigned)max);\n    if (u>=3)\n        DISPLAY(\" %02X %02X %02X \",\n                b1[u-3], b1[u-2], b1[u-1]);\n    DISPLAY(\" :%02X:  %02X %02X %02X %02X %02X \\n\",\n            b1[u], b1[u+1], b1[u+2], b1[u+3], b1[u+4], b1[u+5]);\n    if (u>=3)\n        DISPLAY(\" %02X %02X %02X \",\n                b2[u-3], b2[u-2], b2[u-1]);\n    DISPLAY(\" :%02X:  %02X %02X %02X %02X %02X \\n\",\n            b2[u], b2[u+1], b2[u+2], b2[u+3], b2[u+4], b2[u+5]);\n    return u;\n}\n\nstatic size_t FUZ_rLogLength(U32* seed, U32 logLength)\n{\n    size_t const lengthMask = ((size_t)1 << logLength) - 1;\n    return (lengthMask+1) + (FUZ_rand(seed) & lengthMask);\n}\n\nstatic size_t FUZ_randomLength(U32* seed, U32 maxLog)\n{\n    U32 const logLength = FUZ_rand(seed) % maxLog;\n    return FUZ_rLogLength(seed, logLength);\n}\n\n/* Return value in range minVal <= v <= maxVal */\nstatic U32 FUZ_randomClampedLength(U32* seed, U32 minVal, U32 maxVal)\n{\n    U32 const mod = maxVal < minVal ? 1 : (maxVal + 1) - minVal;\n    return (U32)((FUZ_rand(seed) % mod) + minVal);\n}\n\nstatic int fuzzerTests(U32 seed, unsigned nbTests, unsigned startTest, double compressibility, int bigTests)\n{\n    U32 const maxSrcLog = bigTests ? 24 : 22;\n    static const U32 maxSampleLog = 19;\n    size_t const srcBufferSize = (size_t)1<<maxSrcLog;\n    BYTE* cNoiseBuffer[5];\n    size_t const copyBufferSize = srcBufferSize + ((size_t)1 << maxSampleLog);\n    BYTE*  const copyBuffer = (BYTE*)malloc (copyBufferSize);\n    size_t const cBufferSize = ZSTD_compressBound(srcBufferSize);\n    BYTE*  const cBuffer = (BYTE*)malloc (cBufferSize);\n    size_t const dstBufferSize = srcBufferSize;\n    BYTE*  const dstBuffer = (BYTE*)malloc (dstBufferSize);\n    int result = 0;\n    unsigned testNb = 0;\n    U32 coreSeed = seed;\n    ZSTD_CStream* zc = ZSTD_createCStream();   /* will be re-created sometimes */\n    ZSTD_DStream* zd = ZSTD_createDStream();   /* will be re-created sometimes */\n    ZSTD_DStream* const zd_noise = ZSTD_createDStream();\n    UTIL_time_t const startClock = UTIL_getTime();\n    const BYTE* dict = NULL;  /* can keep same dict on 2 consecutive tests */\n    size_t dictSize = 0;\n    U32 oldTestLog = 0;\n    U32 const cLevelMax = bigTests ? (U32)ZSTD_maxCLevel() : g_cLevelMax_smallTests;\n\n    /* allocations */\n    cNoiseBuffer[0] = (BYTE*)malloc (srcBufferSize);\n    cNoiseBuffer[1] = (BYTE*)malloc (srcBufferSize);\n    cNoiseBuffer[2] = (BYTE*)malloc (srcBufferSize);\n    cNoiseBuffer[3] = (BYTE*)malloc (srcBufferSize);\n    cNoiseBuffer[4] = (BYTE*)malloc (srcBufferSize);\n    CHECK (!cNoiseBuffer[0] || !cNoiseBuffer[1] || !cNoiseBuffer[2] || !cNoiseBuffer[3] || !cNoiseBuffer[4] ||\n           !copyBuffer || !dstBuffer || !cBuffer || !zc || !zd || !zd_noise ,\n           \"Not enough memory, fuzzer tests cancelled\");\n\n    /* Create initial samples */\n    RDG_genBuffer(cNoiseBuffer[0], srcBufferSize, 0.00, 0., coreSeed);    /* pure noise */\n    RDG_genBuffer(cNoiseBuffer[1], srcBufferSize, 0.05, 0., coreSeed);    /* barely compressible */\n    RDG_genBuffer(cNoiseBuffer[2], srcBufferSize, compressibility, 0., coreSeed);\n    RDG_genBuffer(cNoiseBuffer[3], srcBufferSize, 0.95, 0., coreSeed);    /* highly compressible */\n    RDG_genBuffer(cNoiseBuffer[4], srcBufferSize, 1.00, 0., coreSeed);    /* sparse content */\n    memset(copyBuffer, 0x65, copyBufferSize);                             /* make copyBuffer considered initialized */\n    ZSTD_initDStream_usingDict(zd, NULL, 0);  /* ensure at least one init */\n\n    /* catch up testNb */\n    for (testNb=1; testNb < startTest; testNb++)\n        FUZ_rand(&coreSeed);\n\n    /* test loop */\n    for ( ; (testNb <= nbTests) || (UTIL_clockSpanMicro(startClock) < g_clockTime) ; testNb++ ) {\n        U32 lseed;\n        const BYTE* srcBuffer;\n        size_t totalTestSize, totalGenSize, cSize;\n        XXH64_state_t xxhState;\n        U64 crcOrig;\n        U32 resetAllowed = 1;\n        size_t maxTestSize;\n\n        /* init */\n        FUZ_rand(&coreSeed);\n        lseed = coreSeed ^ prime32;\n        if (nbTests >= testNb) {\n            DISPLAYUPDATE(2, \"\\r%6u/%6u    \", testNb, nbTests);\n        } else {\n            DISPLAYUPDATE(2, \"\\r%6u        \", testNb);\n        }\n\n        /* states full reset (deliberately not synchronized) */\n        /* some issues can only happen when reusing states */\n        if ((FUZ_rand(&lseed) & 0xFF) == 131) {\n            ZSTD_freeCStream(zc);\n            zc = ZSTD_createCStream();\n            CHECK(zc==NULL, \"ZSTD_createCStream : allocation error\");\n            resetAllowed=0;\n        }\n        if ((FUZ_rand(&lseed) & 0xFF) == 132) {\n            ZSTD_freeDStream(zd);\n            zd = ZSTD_createDStream();\n            CHECK(zd==NULL, \"ZSTD_createDStream : allocation error\");\n            CHECK_Z( ZSTD_initDStream_usingDict(zd, NULL, 0) );  /* ensure at least one init */\n        }\n\n        /* srcBuffer selection [0-4] */\n        {   U32 buffNb = FUZ_rand(&lseed) & 0x7F;\n            if (buffNb & 7) buffNb=2;   /* most common : compressible (P) */\n            else {\n                buffNb >>= 3;\n                if (buffNb & 7) {\n                    const U32 tnb[2] = { 1, 3 };   /* barely/highly compressible */\n                    buffNb = tnb[buffNb >> 3];\n                } else {\n                    const U32 tnb[2] = { 0, 4 };   /* not compressible / sparse */\n                    buffNb = tnb[buffNb >> 3];\n            }   }\n            srcBuffer = cNoiseBuffer[buffNb];\n        }\n\n        /* compression init */\n        if ((FUZ_rand(&lseed)&1) /* at beginning, to keep same nb of rand */\n            && oldTestLog /* at least one test happened */ && resetAllowed) {\n            maxTestSize = FUZ_randomLength(&lseed, oldTestLog+2);\n            maxTestSize = MIN(maxTestSize, srcBufferSize-16);\n            {   U64 const pledgedSrcSize = (FUZ_rand(&lseed) & 3) ? ZSTD_CONTENTSIZE_UNKNOWN : maxTestSize;\n                CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) );\n                CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, pledgedSrcSize) );\n            }\n        } else {\n            U32 const testLog = FUZ_rand(&lseed) % maxSrcLog;\n            U32 const dictLog = FUZ_rand(&lseed) % maxSrcLog;\n            U32 const cLevelCandidate = ( FUZ_rand(&lseed) %\n                                ((unsigned)ZSTD_maxCLevel() -\n                                (MAX(testLog, dictLog) / 3)))\n                                 + 1;\n            U32 const cLevel = MIN(cLevelCandidate, cLevelMax);\n            maxTestSize = FUZ_rLogLength(&lseed, testLog);\n            oldTestLog = testLog;\n            /* random dictionary selection */\n            dictSize  = ((FUZ_rand(&lseed)&7)==1) ? FUZ_rLogLength(&lseed, dictLog) : 0;\n            {   size_t const dictStart = FUZ_rand(&lseed) % (srcBufferSize - dictSize);\n                dict = srcBuffer + dictStart;\n            }\n            {   U64 const pledgedSrcSize = (FUZ_rand(&lseed) & 3) ? ZSTD_CONTENTSIZE_UNKNOWN : maxTestSize;\n                CHECK_Z( ZSTD_CCtx_reset(zc, ZSTD_reset_session_only) );\n                CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_compressionLevel, (int)cLevel) );\n                CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_checksumFlag, FUZ_rand(&lseed) & 1) );\n                CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_contentSizeFlag, FUZ_rand(&lseed) & 1) );\n                CHECK_Z( ZSTD_CCtx_setParameter(zc, ZSTD_c_dictIDFlag, FUZ_rand(&lseed) & 1) );\n                CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, pledgedSrcSize) );\n                CHECK_Z( ZSTD_CCtx_loadDictionary(zc, dict, dictSize) );\n        }   }\n\n        /* multi-segments compression test */\n        XXH64_reset(&xxhState, 0);\n        {   ZSTD_outBuffer outBuff = { cBuffer, cBufferSize, 0 } ;\n            cSize=0;\n            totalTestSize=0;\n            while(totalTestSize < maxTestSize) {\n                /* compress random chunks into randomly sized dst buffers */\n                {   size_t const randomSrcSize = FUZ_randomLength(&lseed, maxSampleLog);\n                    size_t const srcSize = MIN(maxTestSize-totalTestSize, randomSrcSize);\n                    size_t const srcStart = FUZ_rand(&lseed) % (srcBufferSize - srcSize);\n                    size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);\n                    size_t const dstBuffSize = MIN(cBufferSize - cSize, randomDstSize);\n                    ZSTD_inBuffer inBuff = { srcBuffer+srcStart, srcSize, 0 };\n                    outBuff.size = outBuff.pos + dstBuffSize;\n\n                    CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) );\n\n                    XXH64_update(&xxhState, srcBuffer+srcStart, inBuff.pos);\n                    memcpy(copyBuffer+totalTestSize, srcBuffer+srcStart, inBuff.pos);\n                    totalTestSize += inBuff.pos;\n                }\n\n                /* random flush operation, to mess around */\n                if ((FUZ_rand(&lseed) & 15) == 0) {\n                    size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);\n                    size_t const adjustedDstSize = MIN(cBufferSize - cSize, randomDstSize);\n                    outBuff.size = outBuff.pos + adjustedDstSize;\n                    CHECK_Z( ZSTD_flushStream(zc, &outBuff) );\n            }   }\n\n            /* final frame epilogue */\n            {   size_t remainingToFlush = (size_t)(-1);\n                while (remainingToFlush) {\n                    size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);\n                    size_t const adjustedDstSize = MIN(cBufferSize - cSize, randomDstSize);\n                    outBuff.size = outBuff.pos + adjustedDstSize;\n                    remainingToFlush = ZSTD_endStream(zc, &outBuff);\n                    CHECK (ZSTD_isError(remainingToFlush), \"end error : %s\", ZSTD_getErrorName(remainingToFlush));\n            }   }\n            crcOrig = XXH64_digest(&xxhState);\n            cSize = outBuff.pos;\n        }\n\n        /* multi - fragments decompression test */\n        if (!dictSize /* don't reset if dictionary : could be different */ && (FUZ_rand(&lseed) & 1)) {\n            CHECK_Z ( ZSTD_resetDStream(zd) );\n        } else {\n            CHECK_Z ( ZSTD_initDStream_usingDict(zd, dict, dictSize) );\n        }\n        {   size_t decompressionResult = 1;\n            ZSTD_inBuffer  inBuff = { cBuffer, cSize, 0 };\n            ZSTD_outBuffer outBuff= { dstBuffer, dstBufferSize, 0 };\n            for (totalGenSize = 0 ; decompressionResult ; ) {\n                size_t const readCSrcSize = FUZ_randomLength(&lseed, maxSampleLog);\n                size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);\n                size_t const dstBuffSize = MIN(dstBufferSize - totalGenSize, randomDstSize);\n                inBuff.size = inBuff.pos + readCSrcSize;\n                outBuff.size = outBuff.pos + dstBuffSize;\n                decompressionResult = ZSTD_decompressStream(zd, &outBuff, &inBuff);\n                if (ZSTD_getErrorCode(decompressionResult) == ZSTD_error_checksum_wrong) {\n                    DISPLAY(\"checksum error : \\n\");\n                    findDiff(copyBuffer, dstBuffer, totalTestSize);\n                }\n                CHECK( ZSTD_isError(decompressionResult), \"decompression error : %s\",\n                       ZSTD_getErrorName(decompressionResult) );\n            }\n            CHECK (decompressionResult != 0, \"frame not fully decoded\");\n            CHECK (outBuff.pos != totalTestSize, \"decompressed data : wrong size (%u != %u)\",\n                    (unsigned)outBuff.pos, (unsigned)totalTestSize);\n            CHECK (inBuff.pos != cSize, \"compressed data should be fully read\")\n            {   U64 const crcDest = XXH64(dstBuffer, totalTestSize, 0);\n                if (crcDest!=crcOrig) findDiff(copyBuffer, dstBuffer, totalTestSize);\n                CHECK (crcDest!=crcOrig, \"decompressed data corrupted\");\n        }   }\n\n        /*=====   noisy/erroneous src decompression test   =====*/\n\n        /* add some noise */\n        {   U32 const nbNoiseChunks = (FUZ_rand(&lseed) & 7) + 2;\n            U32 nn; for (nn=0; nn<nbNoiseChunks; nn++) {\n                size_t const randomNoiseSize = FUZ_randomLength(&lseed, maxSampleLog);\n                size_t const noiseSize  = MIN((cSize/3) , randomNoiseSize);\n                size_t const noiseStart = FUZ_rand(&lseed) % (srcBufferSize - noiseSize);\n                size_t const cStart = FUZ_rand(&lseed) % (cSize - noiseSize);\n                memcpy(cBuffer+cStart, srcBuffer+noiseStart, noiseSize);\n        }   }\n\n        /* try decompression on noisy data */\n        CHECK_Z( ZSTD_initDStream(zd_noise) );   /* note : no dictionary */\n        {   ZSTD_inBuffer  inBuff = { cBuffer, cSize, 0 };\n            ZSTD_outBuffer outBuff= { dstBuffer, dstBufferSize, 0 };\n            while (outBuff.pos < dstBufferSize) {\n                size_t const randomCSrcSize = FUZ_randomLength(&lseed, maxSampleLog);\n                size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);\n                size_t const adjustedDstSize = MIN(dstBufferSize - outBuff.pos, randomDstSize);\n                size_t const adjustedCSrcSize = MIN(cSize - inBuff.pos, randomCSrcSize);\n                outBuff.size = outBuff.pos + adjustedDstSize;\n                inBuff.size  = inBuff.pos + adjustedCSrcSize;\n                {   size_t const decompressError = ZSTD_decompressStream(zd, &outBuff, &inBuff);\n                    if (ZSTD_isError(decompressError)) break;   /* error correctly detected */\n                    /* No forward progress possible */\n                    if (outBuff.pos < outBuff.size && inBuff.pos == cSize) break;\n    }   }   }   }\n    DISPLAY(\"\\r%u fuzzer tests completed   \\n\", testNb);\n\n_cleanup:\n    ZSTD_freeCStream(zc);\n    ZSTD_freeDStream(zd);\n    ZSTD_freeDStream(zd_noise);\n    free(cNoiseBuffer[0]);\n    free(cNoiseBuffer[1]);\n    free(cNoiseBuffer[2]);\n    free(cNoiseBuffer[3]);\n    free(cNoiseBuffer[4]);\n    free(copyBuffer);\n    free(cBuffer);\n    free(dstBuffer);\n    return result;\n\n_output_error:\n    result = 1;\n    goto _cleanup;\n}\n\n/** If useOpaqueAPI, sets param in cctxParams.\n *  Otherwise, sets the param in zc. */\nstatic size_t setCCtxParameter(ZSTD_CCtx* zc, ZSTD_CCtx_params* cctxParams,\n                               ZSTD_cParameter param, unsigned value,\n                               int useOpaqueAPI)\n{\n    if (useOpaqueAPI) {\n        return ZSTD_CCtxParams_setParameter(cctxParams, param, (int)value);\n    } else {\n        return ZSTD_CCtx_setParameter(zc, param, (int)value);\n    }\n}\n\n/* Tests for ZSTD_compress_generic() API */\nstatic int fuzzerTests_newAPI(U32 seed, int nbTests, int startTest,\n                              double compressibility, int bigTests)\n{\n    U32 const maxSrcLog = bigTests ? 24 : 22;\n    static const U32 maxSampleLog = 19;\n    size_t const srcBufferSize = (size_t)1<<maxSrcLog;\n    BYTE* cNoiseBuffer[5];\n    size_t const copyBufferSize= srcBufferSize + ((size_t)1 << maxSampleLog);\n    BYTE*  const copyBuffer = (BYTE*)malloc (copyBufferSize);\n    size_t const cBufferSize   = ZSTD_compressBound(srcBufferSize);\n    BYTE*  const cBuffer = (BYTE*)malloc (cBufferSize);\n    size_t const dstBufferSize = srcBufferSize;\n    BYTE*  const dstBuffer = (BYTE*)malloc (dstBufferSize);\n    U32 result = 0;\n    int testNb = 0;\n    U32 coreSeed = seed;\n    ZSTD_CCtx* zc = ZSTD_createCCtx();   /* will be reset sometimes */\n    ZSTD_DStream* zd = ZSTD_createDStream();   /* will be reset sometimes */\n    ZSTD_DStream* const zd_noise = ZSTD_createDStream();\n    UTIL_time_t const startClock = UTIL_getTime();\n    const BYTE* dict = NULL;   /* can keep same dict on 2 consecutive tests */\n    size_t dictSize = 0;\n    U32 oldTestLog = 0;\n    U32 windowLogMalus = 0;   /* can survive between 2 loops */\n    U32 const cLevelMax = bigTests ? (U32)ZSTD_maxCLevel()-1 : g_cLevelMax_smallTests;\n    U32 const nbThreadsMax = bigTests ? 4 : 2;\n    ZSTD_CCtx_params* cctxParams = ZSTD_createCCtxParams();\n\n    /* allocations */\n    cNoiseBuffer[0] = (BYTE*)malloc (srcBufferSize);\n    cNoiseBuffer[1] = (BYTE*)malloc (srcBufferSize);\n    cNoiseBuffer[2] = (BYTE*)malloc (srcBufferSize);\n    cNoiseBuffer[3] = (BYTE*)malloc (srcBufferSize);\n    cNoiseBuffer[4] = (BYTE*)malloc (srcBufferSize);\n    CHECK (!cNoiseBuffer[0] || !cNoiseBuffer[1] || !cNoiseBuffer[2] || !cNoiseBuffer[3] || !cNoiseBuffer[4] ||\n           !copyBuffer || !dstBuffer || !cBuffer || !zc || !zd || !zd_noise ,\n           \"Not enough memory, fuzzer tests cancelled\");\n\n    /* Create initial samples */\n    RDG_genBuffer(cNoiseBuffer[0], srcBufferSize, 0.00, 0., coreSeed);    /* pure noise */\n    RDG_genBuffer(cNoiseBuffer[1], srcBufferSize, 0.05, 0., coreSeed);    /* barely compressible */\n    RDG_genBuffer(cNoiseBuffer[2], srcBufferSize, compressibility, 0., coreSeed);\n    RDG_genBuffer(cNoiseBuffer[3], srcBufferSize, 0.95, 0., coreSeed);    /* highly compressible */\n    RDG_genBuffer(cNoiseBuffer[4], srcBufferSize, 1.00, 0., coreSeed);    /* sparse content */\n    memset(copyBuffer, 0x65, copyBufferSize);                             /* make copyBuffer considered initialized */\n    CHECK_Z( ZSTD_initDStream_usingDict(zd, NULL, 0) );   /* ensure at least one init */\n\n    /* catch up testNb */\n    for (testNb=1; testNb < startTest; testNb++)\n        FUZ_rand(&coreSeed);\n\n    /* test loop */\n    for ( ; (testNb <= nbTests) || (UTIL_clockSpanMicro(startClock) < g_clockTime) ; testNb++ ) {\n        U32 lseed;\n        int opaqueAPI;\n        const BYTE* srcBuffer;\n        size_t totalTestSize, totalGenSize, cSize;\n        XXH64_state_t xxhState;\n        U64 crcOrig;\n        U32 resetAllowed = 1;\n        size_t maxTestSize;\n        ZSTD_parameters savedParams;\n        int isRefPrefix = 0;\n        U64 pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;\n\n        /* init */\n        if (nbTests >= testNb) { DISPLAYUPDATE(2, \"\\r%6u/%6u    \", testNb, nbTests); }\n        else { DISPLAYUPDATE(2, \"\\r%6u          \", testNb); }\n        FUZ_rand(&coreSeed);\n        lseed = coreSeed ^ prime32;\n        DISPLAYLEVEL(5, \" ***  Test %u  *** \\n\", testNb);\n        opaqueAPI = FUZ_rand(&lseed) & 1;\n\n        /* states full reset (deliberately not synchronized) */\n        /* some issues can only happen when reusing states */\n        if ((FUZ_rand(&lseed) & 0xFF) == 131) {\n            DISPLAYLEVEL(5, \"Creating new context \\n\");\n            ZSTD_freeCCtx(zc);\n            zc = ZSTD_createCCtx();\n            CHECK(zc == NULL, \"ZSTD_createCCtx allocation error\");\n            resetAllowed = 0;\n        }\n        if ((FUZ_rand(&lseed) & 0xFF) == 132) {\n            ZSTD_freeDStream(zd);\n            zd = ZSTD_createDStream();\n            CHECK(zd == NULL, \"ZSTD_createDStream allocation error\");\n            ZSTD_initDStream_usingDict(zd, NULL, 0);  /* ensure at least one init */\n        }\n\n        /* srcBuffer selection [0-4] */\n        {   U32 buffNb = FUZ_rand(&lseed) & 0x7F;\n            if (buffNb & 7) buffNb=2;   /* most common : compressible (P) */\n            else {\n                buffNb >>= 3;\n                if (buffNb & 7) {\n                    const U32 tnb[2] = { 1, 3 };   /* barely/highly compressible */\n                    buffNb = tnb[buffNb >> 3];\n                } else {\n                    const U32 tnb[2] = { 0, 4 };   /* not compressible / sparse */\n                    buffNb = tnb[buffNb >> 3];\n            }   }\n            srcBuffer = cNoiseBuffer[buffNb];\n        }\n\n        /* compression init */\n        CHECK_Z( ZSTD_CCtx_loadDictionary(zc, NULL, 0) );   /* cancel previous dict /*/\n        if ((FUZ_rand(&lseed)&1) /* at beginning, to keep same nb of rand */\n          && oldTestLog   /* at least one test happened */\n          && resetAllowed) {\n            /* just set a compression level */\n            maxTestSize = FUZ_randomLength(&lseed, oldTestLog+2);\n            if (maxTestSize >= srcBufferSize) maxTestSize = srcBufferSize-1;\n            {   int const compressionLevel = (FUZ_rand(&lseed) % 5) + 1;\n                DISPLAYLEVEL(5, \"t%u : compression level : %i \\n\", testNb, compressionLevel);\n                CHECK_Z (setCCtxParameter(zc, cctxParams, ZSTD_c_compressionLevel, compressionLevel, opaqueAPI) );\n            }\n        } else {\n            U32 const testLog = FUZ_rand(&lseed) % maxSrcLog;\n            U32 const dictLog = FUZ_rand(&lseed) % maxSrcLog;\n            U32 const cLevelCandidate = (FUZ_rand(&lseed) %\n                               (ZSTD_maxCLevel() -\n                               (MAX(testLog, dictLog) / 2))) +\n                               1;\n            int const cLevel = MIN(cLevelCandidate, cLevelMax);\n            DISPLAYLEVEL(5, \"t%i: base cLevel : %u \\n\", testNb, cLevel);\n            maxTestSize = FUZ_rLogLength(&lseed, testLog);\n            DISPLAYLEVEL(5, \"t%i: maxTestSize : %u \\n\", testNb, (unsigned)maxTestSize);\n            oldTestLog = testLog;\n            /* random dictionary selection */\n            dictSize  = ((FUZ_rand(&lseed)&63)==1) ? FUZ_rLogLength(&lseed, dictLog) : 0;\n            {   size_t const dictStart = FUZ_rand(&lseed) % (srcBufferSize - dictSize);\n                dict = srcBuffer + dictStart;\n                if (!dictSize) dict=NULL;\n            }\n            pledgedSrcSize = (FUZ_rand(&lseed) & 3) ? ZSTD_CONTENTSIZE_UNKNOWN : maxTestSize;\n            {   ZSTD_compressionParameters cParams = ZSTD_getCParams(cLevel, pledgedSrcSize, dictSize);\n                const U32 windowLogMax = bigTests ? 24 : 20;\n                const U32 searchLogMax = bigTests ? 15 : 13;\n                if (dictSize)\n                    DISPLAYLEVEL(5, \"t%u: with dictionary of size : %u \\n\", testNb, (unsigned)dictSize);\n\n                /* mess with compression parameters */\n                cParams.windowLog += (FUZ_rand(&lseed) & 3) - 1;\n                cParams.windowLog = MIN(windowLogMax, cParams.windowLog);\n                cParams.hashLog += (FUZ_rand(&lseed) & 3) - 1;\n                cParams.chainLog += (FUZ_rand(&lseed) & 3) - 1;\n                cParams.searchLog += (FUZ_rand(&lseed) & 3) - 1;\n                cParams.searchLog = MIN(searchLogMax, cParams.searchLog);\n                cParams.minMatch += (FUZ_rand(&lseed) & 3) - 1;\n                cParams.targetLength = (U32)((cParams.targetLength + 1 ) * (0.5 + ((double)(FUZ_rand(&lseed) & 127) / 128)));\n                cParams = ZSTD_adjustCParams(cParams, pledgedSrcSize, dictSize);\n\n                if (FUZ_rand(&lseed) & 1) {\n                    DISPLAYLEVEL(5, \"t%u: windowLog : %u \\n\", testNb, cParams.windowLog);\n                    CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_windowLog, cParams.windowLog, opaqueAPI) );\n                    assert(cParams.windowLog >= ZSTD_WINDOWLOG_MIN);   /* guaranteed by ZSTD_adjustCParams() */\n                    windowLogMalus = (cParams.windowLog - ZSTD_WINDOWLOG_MIN) / 5;\n                }\n                if (FUZ_rand(&lseed) & 1) {\n                    DISPLAYLEVEL(5, \"t%u: hashLog : %u \\n\", testNb, cParams.hashLog);\n                    CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_hashLog, cParams.hashLog, opaqueAPI) );\n                }\n                if (FUZ_rand(&lseed) & 1) {\n                    DISPLAYLEVEL(5, \"t%u: chainLog : %u \\n\", testNb, cParams.chainLog);\n                    CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_chainLog, cParams.chainLog, opaqueAPI) );\n                }\n                if (FUZ_rand(&lseed) & 1) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_searchLog, cParams.searchLog, opaqueAPI) );\n                if (FUZ_rand(&lseed) & 1) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_minMatch, cParams.minMatch, opaqueAPI) );\n                if (FUZ_rand(&lseed) & 1) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_targetLength, cParams.targetLength, opaqueAPI) );\n\n                /* mess with long distance matching parameters */\n                if (bigTests) {\n                    if (FUZ_rand(&lseed) & 1) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_enableLongDistanceMatching, FUZ_randomClampedLength(&lseed, ZSTD_ps_auto, ZSTD_ps_disable), opaqueAPI) );\n                    if (FUZ_rand(&lseed) & 3) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_ldmHashLog, FUZ_randomClampedLength(&lseed, ZSTD_HASHLOG_MIN, 23), opaqueAPI) );\n                    if (FUZ_rand(&lseed) & 3) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_ldmMinMatch, FUZ_randomClampedLength(&lseed, ZSTD_LDM_MINMATCH_MIN, ZSTD_LDM_MINMATCH_MAX), opaqueAPI) );\n                    if (FUZ_rand(&lseed) & 3) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_ldmBucketSizeLog, FUZ_randomClampedLength(&lseed, ZSTD_LDM_BUCKETSIZELOG_MIN, ZSTD_LDM_BUCKETSIZELOG_MAX), opaqueAPI) );\n                    if (FUZ_rand(&lseed) & 3) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_ldmHashRateLog, FUZ_randomClampedLength(&lseed, ZSTD_LDM_HASHRATELOG_MIN, ZSTD_LDM_HASHRATELOG_MAX), opaqueAPI) );\n                    if (FUZ_rand(&lseed) & 3) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_srcSizeHint, FUZ_randomClampedLength(&lseed, ZSTD_SRCSIZEHINT_MIN, ZSTD_SRCSIZEHINT_MAX), opaqueAPI) );\n                }\n\n                /* mess with frame parameters */\n                if (FUZ_rand(&lseed) & 1) {\n                    int const checksumFlag = FUZ_rand(&lseed) & 1;\n                    DISPLAYLEVEL(5, \"t%u: frame checksum : %u \\n\", testNb, checksumFlag);\n                    CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_checksumFlag, checksumFlag, opaqueAPI) );\n                }\n                if (FUZ_rand(&lseed) & 1) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_dictIDFlag, FUZ_rand(&lseed) & 1, opaqueAPI) );\n                if (FUZ_rand(&lseed) & 1) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_contentSizeFlag, FUZ_rand(&lseed) & 1, opaqueAPI) );\n                if (FUZ_rand(&lseed) & 1) {\n                    DISPLAYLEVEL(5, \"t%u: pledgedSrcSize : %u \\n\", testNb, (unsigned)pledgedSrcSize);\n                    CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, pledgedSrcSize) );\n                } else {\n                    pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;\n                }\n\n                /* multi-threading parameters. Only adjust occasionally for small tests. */\n                if (bigTests || (FUZ_rand(&lseed) & 0xF) == 0xF) {\n                    U32 const nbThreadsCandidate = (FUZ_rand(&lseed) & 4) + 1;\n                    U32 const nbThreadsAdjusted = (windowLogMalus < nbThreadsCandidate) ? nbThreadsCandidate - windowLogMalus : 1;\n                    int const nbThreads = MIN(nbThreadsAdjusted, nbThreadsMax);\n                    DISPLAYLEVEL(5, \"t%i: nbThreads : %u \\n\", testNb, nbThreads);\n                    CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_nbWorkers, nbThreads, opaqueAPI) );\n                    if (nbThreads > 1) {\n                        U32 const jobLog = FUZ_rand(&lseed) % (testLog+1);\n                        CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_overlapLog, FUZ_rand(&lseed) % 10, opaqueAPI) );\n                        CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_jobSize, (U32)FUZ_rLogLength(&lseed, jobLog), opaqueAPI) );\n                    }\n                }\n                /* Enable rsyncable mode 1 in 4 times. */\n                {\n                    int const rsyncable = (FUZ_rand(&lseed) % 4 == 0);\n                    DISPLAYLEVEL(5, \"t%u: rsyncable : %d \\n\", testNb, rsyncable);\n                    setCCtxParameter(zc, cctxParams, ZSTD_c_rsyncable, rsyncable, opaqueAPI);\n                }\n\n                if (FUZ_rand(&lseed) & 1) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_forceMaxWindow, FUZ_rand(&lseed) & 1, opaqueAPI) );\n                if (FUZ_rand(&lseed) & 1) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_deterministicRefPrefix, FUZ_rand(&lseed) & 1, opaqueAPI) );\n\n                /* Set max block size parameters */\n                if (FUZ_rand(&lseed) & 1) {\n                    int maxBlockSize = (int)(FUZ_rand(&lseed) % ZSTD_BLOCKSIZE_MAX);\n                    maxBlockSize = MAX(1024, maxBlockSize);\n                    CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_maxBlockSize, maxBlockSize, opaqueAPI) );\n                }\n\n                /* Apply parameters */\n                if (opaqueAPI) {\n                    DISPLAYLEVEL(5, \"t%u: applying CCtxParams \\n\", testNb);\n                    CHECK_Z (ZSTD_CCtx_setParametersUsingCCtxParams(zc, cctxParams) );\n                }\n\n                if (FUZ_rand(&lseed) & 1) {\n                    if (FUZ_rand(&lseed) & 1) {\n                        CHECK_Z( ZSTD_CCtx_loadDictionary(zc, dict, dictSize) );\n                    } else {\n                        CHECK_Z( ZSTD_CCtx_loadDictionary_byReference(zc, dict, dictSize) );\n                    }\n                } else {\n                    isRefPrefix = 1;\n                    CHECK_Z( ZSTD_CCtx_refPrefix(zc, dict, dictSize) );\n                }\n        }   }\n\n        CHECK_Z(getCCtxParams(zc, &savedParams));\n\n        /* multi-segments compression test */\n        {   int iter;\n            int const startSeed = lseed;\n            XXH64_hash_t compressedCrcs[2];\n            for (iter = 0; iter < 2; ++iter, lseed = startSeed) {\n                ZSTD_outBuffer outBuff = { cBuffer, cBufferSize, 0 } ;\n                int const singlePass = (FUZ_rand(&lseed) & 3) == 0;\n                int nbWorkers;\n\n                XXH64_reset(&xxhState, 0);\n\n                CHECK_Z( ZSTD_CCtx_setPledgedSrcSize(zc, pledgedSrcSize) );\n                if (isRefPrefix) {\n                    DISPLAYLEVEL(6, \"t%u: Reloading prefix\\n\", testNb);\n                    /* Need to reload the prefix because it gets dropped after one compression */\n                    CHECK_Z( ZSTD_CCtx_refPrefix(zc, dict, dictSize) );\n                }\n\n                /* Adjust number of workers occasionally - result must be deterministic independent of nbWorkers */\n                CHECK_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_nbWorkers, &nbWorkers));\n                if (nbWorkers > 0 && (FUZ_rand(&lseed) & 7) == 0) {\n                    DISPLAYLEVEL(6, \"t%u: Modify nbWorkers: %d -> %d \\n\", testNb, nbWorkers, nbWorkers + iter);\n                    CHECK_Z(ZSTD_CCtx_setParameter(zc, ZSTD_c_nbWorkers, nbWorkers + iter));\n                }\n\n                if (singlePass) {\n                    ZSTD_inBuffer inBuff = { srcBuffer, maxTestSize, 0 };\n                    CHECK_Z(ZSTD_compressStream2(zc, &outBuff, &inBuff, ZSTD_e_end));\n                    DISPLAYLEVEL(6, \"t%u: Single pass compression: consumed %u bytes ; produced %u bytes \\n\",\n                        testNb, (unsigned)inBuff.pos, (unsigned)outBuff.pos);\n                    CHECK(inBuff.pos != inBuff.size, \"Input not consumed!\");\n                    crcOrig = XXH64(srcBuffer, maxTestSize, 0);\n                    totalTestSize = maxTestSize;\n                } else {\n                    outBuff.size = 0;\n                    for (totalTestSize=0 ; (totalTestSize < maxTestSize) ; ) {\n                        /* compress random chunks into randomly sized dst buffers */\n                        size_t const randomSrcSize = FUZ_randomLength(&lseed, maxSampleLog);\n                        size_t const srcSize = MIN(maxTestSize-totalTestSize, randomSrcSize);\n                        size_t const srcStart = FUZ_rand(&lseed) % (srcBufferSize - srcSize);\n                        ZSTD_EndDirective const flush = (FUZ_rand(&lseed) & 15) ? ZSTD_e_continue : ZSTD_e_flush;\n                        ZSTD_inBuffer inBuff = { srcBuffer+srcStart, srcSize, 0 };\n                        int forwardProgress;\n                        do {\n                            size_t const ipos = inBuff.pos;\n                            size_t const opos = outBuff.pos;\n                            size_t ret;\n                            if (outBuff.pos == outBuff.size) {\n                                size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog+1);\n                                size_t const dstBuffSize = MIN(cBufferSize - outBuff.pos, randomDstSize);\n                                outBuff.size = outBuff.pos + dstBuffSize;\n                            }\n                            CHECK_Z( ret = ZSTD_compressStream2(zc, &outBuff, &inBuff, flush) );\n                            DISPLAYLEVEL(6, \"t%u: compress consumed %u bytes (total : %u) ; flush: %u (total : %u) \\n\",\n                                testNb, (unsigned)inBuff.pos, (unsigned)(totalTestSize + inBuff.pos), (unsigned)flush, (unsigned)outBuff.pos);\n\n                            /* We've completed the flush */\n                            if (flush == ZSTD_e_flush && ret == 0)\n                                break;\n\n                            /* Ensure maximal forward progress for determinism */\n                            forwardProgress = (inBuff.pos != ipos) || (outBuff.pos != opos);\n                        } while (forwardProgress);\n                        assert(inBuff.pos == inBuff.size);\n\n                        XXH64_update(&xxhState, srcBuffer+srcStart, inBuff.pos);\n                        memcpy(copyBuffer+totalTestSize, srcBuffer+srcStart, inBuff.pos);\n                        totalTestSize += inBuff.pos;\n                    }\n\n                    /* final frame epilogue */\n                    {   size_t remainingToFlush = 1;\n                        while (remainingToFlush) {\n                            ZSTD_inBuffer inBuff = { NULL, 0, 0 };\n                            size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog+1);\n                            size_t const adjustedDstSize = MIN(cBufferSize - outBuff.pos, randomDstSize);\n                            outBuff.size = outBuff.pos + adjustedDstSize;\n                            DISPLAYLEVEL(6, \"t%u: End-flush into dst buffer of size %u \\n\", testNb, (unsigned)adjustedDstSize);\n                            /* ZSTD_e_end guarantees maximal forward progress */\n                            remainingToFlush = ZSTD_compressStream2(zc, &outBuff, &inBuff, ZSTD_e_end);\n                            DISPLAYLEVEL(6, \"t%u: Total flushed so far : %u bytes \\n\", testNb, (unsigned)outBuff.pos);\n                            CHECK( ZSTD_isError(remainingToFlush),\n                                \"ZSTD_compressStream2 w/ ZSTD_e_end error : %s\",\n                                ZSTD_getErrorName(remainingToFlush) );\n                    }   }\n                    crcOrig = XXH64_digest(&xxhState);\n                }\n                cSize = outBuff.pos;\n                compressedCrcs[iter] = XXH64(cBuffer, cSize, 0);\n                DISPLAYLEVEL(5, \"Frame completed : %u bytes \\n\", (unsigned)cSize);\n            }\n            CHECK(!(compressedCrcs[0] == compressedCrcs[1]), \"Compression is not deterministic!\");\n        }\n\n        CHECK(badParameters(zc, savedParams), \"CCtx params are wrong\");\n\n        /* multi - fragments decompression test */\n        if (FUZ_rand(&lseed) & 1) {\n            CHECK_Z(ZSTD_DCtx_reset(zd, ZSTD_reset_session_and_parameters));\n        }\n        if (!dictSize /* don't reset if dictionary : could be different */ && (FUZ_rand(&lseed) & 1)) {\n            DISPLAYLEVEL(5, \"resetting DCtx (dict:%p) \\n\", (void const*)dict);\n            CHECK_Z( ZSTD_resetDStream(zd) );\n        } else {\n            if (dictSize)\n                DISPLAYLEVEL(5, \"using dictionary of size %u \\n\", (unsigned)dictSize);\n            CHECK_Z( ZSTD_initDStream_usingDict(zd, dict, dictSize) );\n        }\n        if (FUZ_rand(&lseed) & 1) {\n            CHECK_Z(ZSTD_DCtx_setParameter(zd, ZSTD_d_disableHuffmanAssembly, FUZ_rand(&lseed) & 1));\n        }\n        if (FUZ_rand(&lseed) & 1) {\n            int maxBlockSize;\n            CHECK_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_maxBlockSize, &maxBlockSize));\n            CHECK_Z(ZSTD_DCtx_setParameter(zd, ZSTD_d_maxBlockSize, maxBlockSize));\n        } else {\n            CHECK_Z(ZSTD_DCtx_setParameter(zd, ZSTD_d_maxBlockSize, 0));\n        }\n        {   size_t decompressionResult = 1;\n            ZSTD_inBuffer  inBuff = { cBuffer, cSize, 0 };\n            ZSTD_outBuffer outBuff= { dstBuffer, dstBufferSize, 0 };\n            for (totalGenSize = 0 ; decompressionResult ; ) {\n                size_t const readCSrcSize = FUZ_randomLength(&lseed, maxSampleLog);\n                size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);\n                size_t const dstBuffSize = MIN(dstBufferSize - totalGenSize, randomDstSize);\n                inBuff.size = inBuff.pos + readCSrcSize;\n                outBuff.size = outBuff.pos + dstBuffSize;\n                DISPLAYLEVEL(6, \"decompression presented %u new bytes (pos:%u/%u)\\n\",\n                                (unsigned)readCSrcSize, (unsigned)inBuff.pos, (unsigned)cSize);\n                decompressionResult = ZSTD_decompressStream(zd, &outBuff, &inBuff);\n                DISPLAYLEVEL(6, \"so far: consumed = %u, produced = %u \\n\",\n                                (unsigned)inBuff.pos, (unsigned)outBuff.pos);\n                if (ZSTD_isError(decompressionResult)) {\n                    DISPLAY(\"ZSTD_decompressStream error : %s \\n\", ZSTD_getErrorName(decompressionResult));\n                    findDiff(copyBuffer, dstBuffer, totalTestSize);\n                }\n                CHECK (ZSTD_isError(decompressionResult), \"decompression error : %s\", ZSTD_getErrorName(decompressionResult));\n                CHECK (inBuff.pos > cSize, \"ZSTD_decompressStream consumes too much input : %u > %u \", (unsigned)inBuff.pos, (unsigned)cSize);\n            }\n            CHECK (inBuff.pos != cSize, \"compressed data should be fully read (%u != %u)\", (unsigned)inBuff.pos, (unsigned)cSize);\n            CHECK (outBuff.pos != totalTestSize, \"decompressed data : wrong size (%u != %u)\", (unsigned)outBuff.pos, (unsigned)totalTestSize);\n            {   U64 const crcDest = XXH64(dstBuffer, totalTestSize, 0);\n                if (crcDest!=crcOrig) findDiff(copyBuffer, dstBuffer, totalTestSize);\n                CHECK (crcDest!=crcOrig, \"decompressed data corrupted\");\n        }   }\n\n        /*=====   noisy/erroneous src decompression test   =====*/\n\n        /* add some noise */\n        {   U32 const nbNoiseChunks = (FUZ_rand(&lseed) & 7) + 2;\n            U32 nn; for (nn=0; nn<nbNoiseChunks; nn++) {\n                size_t const randomNoiseSize = FUZ_randomLength(&lseed, maxSampleLog);\n                size_t const noiseSize  = MIN((cSize/3) , randomNoiseSize);\n                size_t const noiseStart = FUZ_rand(&lseed) % (srcBufferSize - noiseSize);\n                size_t const cStart = FUZ_rand(&lseed) % (cSize - noiseSize);\n                memcpy(cBuffer+cStart, srcBuffer+noiseStart, noiseSize);\n        }   }\n\n        /* try decompression on noisy data */\n        if (FUZ_rand(&lseed) & 1) {\n            CHECK_Z(ZSTD_DCtx_reset(zd_noise, ZSTD_reset_session_and_parameters));\n        } else {\n            CHECK_Z(ZSTD_DCtx_reset(zd_noise, ZSTD_reset_session_only));\n        }\n        if (FUZ_rand(&lseed) & 1) {\n            CHECK_Z(ZSTD_DCtx_setParameter(zd_noise, ZSTD_d_disableHuffmanAssembly, FUZ_rand(&lseed) & 1));\n        }\n        {   ZSTD_inBuffer  inBuff = { cBuffer, cSize, 0 };\n            ZSTD_outBuffer outBuff= { dstBuffer, dstBufferSize, 0 };\n            while (outBuff.pos < dstBufferSize) {\n                size_t const randomCSrcSize = FUZ_randomLength(&lseed, maxSampleLog);\n                size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);\n                size_t const adjustedDstSize = MIN(dstBufferSize - outBuff.pos, randomDstSize);\n                size_t const adjustedCSrcSize = MIN(cSize - inBuff.pos, randomCSrcSize);\n                outBuff.size = outBuff.pos + adjustedDstSize;\n                inBuff.size  = inBuff.pos + adjustedCSrcSize;\n                {   size_t const decompressError = ZSTD_decompressStream(zd, &outBuff, &inBuff);\n                    if (ZSTD_isError(decompressError)) break;   /* error correctly detected */\n                    /* Good so far, but no more progress possible */\n                    if (outBuff.pos < outBuff.size && inBuff.pos == cSize) break;\n    }   }   }   }\n    DISPLAY(\"\\r%u fuzzer tests completed   \\n\", testNb-1);\n\n_cleanup:\n    ZSTD_freeCCtx(zc);\n    ZSTD_freeDStream(zd);\n    ZSTD_freeDStream(zd_noise);\n    ZSTD_freeCCtxParams(cctxParams);\n    free(cNoiseBuffer[0]);\n    free(cNoiseBuffer[1]);\n    free(cNoiseBuffer[2]);\n    free(cNoiseBuffer[3]);\n    free(cNoiseBuffer[4]);\n    free(copyBuffer);\n    free(cBuffer);\n    free(dstBuffer);\n    return result;\n\n_output_error:\n    result = 1;\n    goto _cleanup;\n}\n\n/*-*******************************************************\n*  Command line\n*********************************************************/\nstatic int FUZ_usage(const char* programName)\n{\n    DISPLAY( \"Usage :\\n\");\n    DISPLAY( \"      %s [args]\\n\", programName);\n    DISPLAY( \"\\n\");\n    DISPLAY( \"Arguments :\\n\");\n    DISPLAY( \" -i#    : Number of tests (default:%u)\\n\", nbTestsDefault);\n    DISPLAY( \" -T#    : Max duration to run for. Overrides number of tests. (e.g. -T1m or -T60s for one minute)\\n\");\n    DISPLAY( \" -s#    : Select seed (default:prompt user)\\n\");\n    DISPLAY( \" -t#    : Select starting test number (default:0)\\n\");\n    DISPLAY( \" -P#    : Select compressibility in %% (default:%i%%)\\n\", FUZ_COMPRESSIBILITY_DEFAULT);\n    DISPLAY( \" -v     : verbose\\n\");\n    DISPLAY( \" -p     : pause at the end\\n\");\n    DISPLAY( \" -h     : display help and exit\\n\");\n    return 0;\n}\n\ntypedef enum { simple_api, advanced_api } e_api;\n\nint main(int argc, const char** argv)\n{\n    U32 seed = 0;\n    int seedset = 0;\n    int nbTests = nbTestsDefault;\n    int testNb = 0;\n    int proba = FUZ_COMPRESSIBILITY_DEFAULT;\n    int result = 0;\n    int mainPause = 0;\n    int bigTests = (sizeof(size_t) == 8);\n    e_api selected_api = simple_api;\n    const char* const programName = argv[0];\n    int argNb;\n\n    /* Check command line */\n    for(argNb=1; argNb<argc; argNb++) {\n        const char* argument = argv[argNb];\n        assert(argument != NULL);\n\n        /* Parsing commands. Aggregated commands are allowed */\n        if (argument[0]=='-') {\n\n            if (!strcmp(argument, \"--newapi\")) { selected_api=advanced_api; testNb += !testNb; continue; }\n            if (!strcmp(argument, \"--no-big-tests\")) { bigTests=0; continue; }\n            if (!strcmp(argument, \"--big-tests\")) { bigTests=1; continue; }\n\n            argument++;\n            while (*argument!=0) {\n                switch(*argument)\n                {\n                case 'h':\n                    return FUZ_usage(programName);\n\n                case 'v':\n                    argument++;\n                    g_displayLevel++;\n                    break;\n\n                case 'q':\n                    argument++;\n                    g_displayLevel--;\n                    break;\n\n                case 'p': /* pause at the end */\n                    argument++;\n                    mainPause = 1;\n                    break;\n\n                case 'i':   /* limit tests by nb of iterations (default) */\n                    argument++;\n                    nbTests=0; g_clockTime=0;\n                    while ((*argument>='0') && (*argument<='9')) {\n                        nbTests *= 10;\n                        nbTests += *argument - '0';\n                        argument++;\n                    }\n                    break;\n\n                case 'T':   /* limit tests by time */\n                    argument++;\n                    nbTests=0; g_clockTime=0;\n                    while ((*argument>='0') && (*argument<='9')) {\n                        g_clockTime *= 10;\n                        g_clockTime += *argument - '0';\n                        argument++;\n                    }\n                    if (*argument=='m') {    /* -T1m == -T60 */\n                        g_clockTime *=60, argument++;\n                        if (*argument=='n') argument++; /* -T1mn == -T60 */\n                    } else if (*argument=='s') argument++; /* -T10s == -T10 */\n                    g_clockTime *= SEC_TO_MICRO;\n                    break;\n\n                case 's':   /* manually select seed */\n                    argument++;\n                    seedset=1;\n                    seed=0;\n                    while ((*argument>='0') && (*argument<='9')) {\n                        seed *= 10;\n                        seed += *argument - '0';\n                        argument++;\n                    }\n                    break;\n\n                case 't':   /* select starting test number */\n                    argument++;\n                    testNb=0;\n                    while ((*argument>='0') && (*argument<='9')) {\n                        testNb *= 10;\n                        testNb += *argument - '0';\n                        argument++;\n                    }\n                    break;\n\n                case 'P':   /* compressibility % */\n                    argument++;\n                    proba=0;\n                    while ((*argument>='0') && (*argument<='9')) {\n                        proba *= 10;\n                        proba += *argument - '0';\n                        argument++;\n                    }\n                    if (proba<0) proba=0;\n                    if (proba>100) proba=100;\n                    break;\n\n                default:\n                    return FUZ_usage(programName);\n                }\n    }   }   }   /* for(argNb=1; argNb<argc; argNb++) */\n\n    /* Get Seed */\n    DISPLAY(\"Starting zstream tester (%i-bits, %s)\\n\", (int)(sizeof(size_t)*8), ZSTD_VERSION_STRING);\n\n    if (!seedset) {\n        time_t const t = time(NULL);\n        U32 const h = XXH32(&t, sizeof(t), 1);\n        seed = h % 10000;\n    }\n\n    DISPLAY(\"Seed = %u\\n\", (unsigned)seed);\n    if (proba!=FUZ_COMPRESSIBILITY_DEFAULT) DISPLAY(\"Compressibility : %i%%\\n\", proba);\n\n    if (nbTests<=0) nbTests=1;\n\n    if (testNb==0) {\n        result = basicUnitTests(0, ((double)proba) / 100, bigTests);  /* constant seed for predictability */\n    }\n\n    if (!result) {\n        switch(selected_api)\n        {\n        case simple_api :\n            result = fuzzerTests(seed, nbTests, testNb, ((double)proba) / 100, bigTests);\n            break;\n        case advanced_api :\n            result = fuzzerTests_newAPI(seed, nbTests, testNb, ((double)proba) / 100, bigTests);\n            break;\n        default :\n            assert(0);   /* impossible */\n        }\n    }\n\n    if (mainPause) {\n        int unused;\n        DISPLAY(\"Press Enter \\n\");\n        unused = getchar();\n        (void)unused;\n    }\n    return result;\n}\n"
  },
  {
    "path": "zlibWrapper/.gitignore",
    "content": "# object artifacts\n*.o\n\n# Default result files\n_*\nexample\nexample_zstd.*\nexample_gz.*\nfitblk\nfitblk_zstd.*\nzwrapbench\nfoo.gz\n\nminigzip\nminigzip_zstd\nexample\nexample_zstd\nfitblk\nfitblk_zstd\nzwrapbench\n\n# Misc files\n*.bat\n*.zip\n*.txt\n\n# Directories\nminizip/\n"
  },
  {
    "path": "zlibWrapper/BUCK",
    "content": "cxx_library(\n    name='zlib_wrapper',\n    visibility=['PUBLIC'],\n    exported_linker_flags=['-lz'],\n    header_namespace='',\n    exported_headers=['zstd_zlibwrapper.h'],\n    headers=[\n        'gzcompatibility.h',\n        'gzguts.h',\n    ],\n    srcs=glob(['*.c']),\n    deps=[\n        '//lib:zstd',\n        '//lib:zstd_common',\n    ],\n)\n\ncxx_binary(\n    name='minigzip',\n    srcs=['examples/minigzip.c'],\n    deps=[':zlib_wrapper'],\n)\n"
  },
  {
    "path": "zlibWrapper/Makefile",
    "content": "# Makefile for example of using zstd wrapper for zlib\n#\n# make - compiles examples\n# make MOREFLAGS=-DZWRAP_USE_ZSTD=1 - compiles examples with zstd compression turned on\n# make test - runs examples\n\n\n# Paths to static and dynamic zlib and zstd libraries\n# Use \"make ZLIB_PATH=path/to/zlib ZLIB_LIBRARY=path/to/libz.so\" to select a path to library\nZLIB_LIBRARY ?= -lz\nZLIB_PATH ?= .\n\nZSTDLIBDIR = ../lib\nZSTDLIBRARY = $(ZSTDLIBDIR)/libzstd.a\nZLIBWRAPPER_PATH = .\nGZFILES = gzclose.o gzlib.o gzread.o gzwrite.o\nEXAMPLE_PATH = examples\nPROGRAMS_PATH = ../programs\nTEST_FILE = ../doc/zstd_compression_format.md\n\nvpath %.c $(PROGRAMS_PATH) $(EXAMPLE_PATH) $(ZLIBWRAPPER_PATH)\n\n\nCPPFLAGS += -DXXH_NAMESPACE=ZSTD_ -I$(ZLIB_PATH) -I$(PROGRAMS_PATH)       \\\n            -I$(ZSTDLIBDIR) -I$(ZSTDLIBDIR)/common -I$(ZLIBWRAPPER_PATH)\nSTDFLAGS  = -std=c89 -pedantic -Wno-long-long -Wno-variadic-macros -Wc++-compat \\\n            -DNO_snprintf -DNO_vsnprintf  # strict ANSI C89 is missing these prototypes\nDEBUGFLAGS= -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow -Wswitch-enum \\\n            -Wdeclaration-after-statement -Wstrict-prototypes -Wundef     \\\n            -Wstrict-aliasing=1\nCFLAGS   ?= -O3\nCFLAGS   += $(STDFLAGS) $(DEBUGFLAGS)\nCPPFLAGS += $(MOREFLAGS)\nLDLIBS   += $(ZLIB_LIBRARY)\n\n# Define *.exe as extension for Windows systems\nifneq (,$(filter Windows%,$(OS)))\nEXT =.exe\nelse\nEXT =\nendif\n\ndefault : release\n\nrelease : STDFLAGS =\nrelease : DEBUGFLAGS =\nrelease : all\n\nall: fitblk example zwrapbench minigzip\n\ntest: example fitblk example_zstd fitblk_zstd zwrapbench minigzip minigzip_zstd\n\t./example\n\t./example_zstd\n\t./fitblk 10240 <$(TEST_FILE)\n\t./fitblk 40960 <$(TEST_FILE)\n\t./fitblk_zstd 10240 <$(TEST_FILE)\n\t./fitblk_zstd 40960 <$(TEST_FILE)\n\t@echo ---- minigzip start ----\n\t./minigzip_zstd example$(EXT)\n\t#cp example$(EXT).gz example$(EXT)_zstd.gz\n\t./minigzip_zstd -d example$(EXT).gz\n\t./minigzip example$(EXT)\n\t#cp example$(EXT).gz example$(EXT)_gz.gz\n\t./minigzip_zstd -d example$(EXT).gz\n\t@echo ---- minigzip end ----\n\t./zwrapbench -qi1b3B1K $(TEST_FILE)\n\t./zwrapbench -rqi1b1e3 ../lib\n\n.PHONY: test-valgrind\n#test-valgrind: ZSTDLIBRARY = $(ZSTDLIBDIR)/libzstd.so\ntest-valgrind: VALGRIND = LD_LIBRARY_PATH=$(ZSTDLIBDIR) valgrind --track-origins=yes --leak-check=full --error-exitcode=1\ntest-valgrind: clean example fitblk example_zstd fitblk_zstd zwrapbench\n\t@echo \"\\n ---- valgrind tests ----\"\n\t$(VALGRIND) ./example\n\t$(VALGRIND) ./example_zstd\n\t$(VALGRIND) ./fitblk 10240 <$(TEST_FILE)\n\t$(VALGRIND) ./fitblk 40960 <$(TEST_FILE)\n\t$(VALGRIND) ./fitblk_zstd 10240 <$(TEST_FILE)\n\t$(VALGRIND) ./fitblk_zstd 40960 <$(TEST_FILE)\n\t$(VALGRIND) ./zwrapbench -qi1b3B1K $(TEST_FILE)\n\t$(VALGRIND) ./zwrapbench -rqi1b1e5 ../lib ../programs ../tests\n\n#.c.o:\n#\t$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@\n\nminigzip: minigzip.o zstd_zlibwrapper.o $(GZFILES) $(ZSTDLIBRARY)\n\nminigzip_zstd: minigzip.o zstdTurnedOn_zlibwrapper.o $(GZFILES) $(ZSTDLIBRARY)\n\t$(LINK.o) $^ $(LDLIBS) $(OUTPUT_OPTION)\n\nexample: example.o zstd_zlibwrapper.o $(GZFILES) $(ZSTDLIBRARY)\n\nexample_zstd: example.o zstdTurnedOn_zlibwrapper.o $(GZFILES) $(ZSTDLIBRARY)\n\t$(LINK.o) $^ $(LDLIBS) $(OUTPUT_OPTION)\n\nfitblk: fitblk.o zstd_zlibwrapper.o $(ZSTDLIBRARY)\n\nfitblk_zstd: fitblk.o zstdTurnedOn_zlibwrapper.o $(ZSTDLIBRARY)\n\t$(LINK.o) $^ $(LDLIBS) $(OUTPUT_OPTION)\n\nzwrapbench: zwrapbench.o zstd_zlibwrapper.o util.o timefn.o datagen.o $(ZSTDLIBRARY)\n\n\nzstd_zlibwrapper.o: zstd_zlibwrapper.h\n\nzstdTurnedOn_zlibwrapper.o: CPPFLAGS += -DZWRAP_USE_ZSTD=1\nzstdTurnedOn_zlibwrapper.o: zstd_zlibwrapper.c zstd_zlibwrapper.h\n\t$(COMPILE.c) $< $(OUTPUT_OPTION)\n\n\n$(ZSTDLIBRARY):\n\t$(MAKE) -C $(ZSTDLIBDIR) libzstd.a\n\n$(ZSTDLIBDIR)/libzstd.so:\n\t$(MAKE) -C $(ZSTDLIBDIR) libzstd\n\n\nclean:\n\t-$(RM) $(ZLIBWRAPPER_PATH)/*.o $(EXAMPLE_PATH)/*.o *.o foo.gz example$(EXT) example_zstd$(EXT) fitblk$(EXT) fitblk_zstd$(EXT) zwrapbench$(EXT) minigzip$(EXT) minigzip_zstd$(EXT)\n\t@echo Cleaning completed\n"
  },
  {
    "path": "zlibWrapper/README.md",
    "content": "Zstandard wrapper for zlib\n================================\n\nThe main objective of creating a zstd wrapper for [zlib](https://zlib.net/) is to allow a quick and smooth transition to zstd for projects already using zlib.\n\n#### Required files\n\nTo build the zstd wrapper for zlib the following files are required:\n- zlib.h\n- a static or dynamic zlib library\n- zlibWrapper/zstd_zlibwrapper.h\n- zlibWrapper/zstd_zlibwrapper.c\n- zlibWrapper/gz*.c files (gzclose.c, gzlib.c, gzread.c, gzwrite.c)\n- zlibWrapper/gz*.h files (gzcompatibility.h, gzguts.h)\n- a static or dynamic zstd library\n\nThe first two files are required by all projects using zlib and they are not included with the zstd distribution.\nThe further files are supplied with the zstd distribution.\n\n\n#### Embedding the zstd wrapper within your project\n\nLet's assume that your project that uses zlib is compiled with:\n```gcc project.o -lz```\n\nTo compile the zstd wrapper with your project you have to do the following:\n- change all references with `#include \"zlib.h\"` to `#include \"zstd_zlibwrapper.h\"`\n- compile your project with `zstd_zlibwrapper.c`, `gz*.c` and a static or dynamic zstd library\n\nThe linking should be changed to:\n```gcc project.o zstd_zlibwrapper.o gz*.c -lz -lzstd```\n\n\n#### Enabling zstd compression within your project\n\nAfter embedding the zstd wrapper within your project the zstd library is turned off by default.\nYour project should work as before with zlib. There are two options to enable zstd compression:\n- compilation with `-DZWRAP_USE_ZSTD=1` (or using `#define ZWRAP_USE_ZSTD 1` before `#include \"zstd_zlibwrapper.h\"`)\n- using the `void ZWRAP_useZSTDcompression(int turn_on)` function (declared in `#include \"zstd_zlibwrapper.h\"`)\n\nDuring decompression zlib and zstd streams are automatically detected and decompressed using a proper library.\nThis behavior can be changed using `ZWRAP_setDecompressionType(ZWRAP_FORCE_ZLIB)` what will make zlib decompression slightly faster.\n\n\n#### Example\nWe have taken the file `test/example.c` from [the zlib library distribution](https://zlib.net/) and copied it to [zlibWrapper/examples/example.c](examples/example.c).\nAfter compilation and execution it shows the following results: \n```\nzlib version 1.2.8 = 0x1280, compile flags = 0x65\nuncompress(): hello, hello!\ngzread(): hello, hello!\ngzgets() after gzseek:  hello!\ninflate(): hello, hello!\nlarge_inflate(): OK\nafter inflateSync(): hello, hello!\ninflate with dictionary: hello, hello!\n```\nThen we have changed `#include \"zlib.h\"` to `#include \"zstd_zlibwrapper.h\"`, compiled the [example.c](examples/example.c) file\nwith `-DZWRAP_USE_ZSTD=1` and linked with additional `zstd_zlibwrapper.o gz*.c -lzstd`.\nWe were forced to turn off the following functions: `test_flush`, `test_sync` which use currently unsupported features.\nAfter running it shows the following results:\n```\nzlib version 1.2.8 = 0x1280, compile flags = 0x65\nuncompress(): hello, hello!\ngzread(): hello, hello!\ngzgets() after gzseek:  hello!\ninflate(): hello, hello!\nlarge_inflate(): OK\ninflate with dictionary: hello, hello!\n```\nThe script used for compilation can be found at [zlibWrapper/Makefile](Makefile).\n\n\n#### The measurement of performance of Zstandard wrapper for zlib\n\nThe zstd distribution contains a tool called `zwrapbench` which can measure speed and ratio of zlib, zstd, and the wrapper.\nThe benchmark is conducted using given filenames or synthetic data if filenames are not provided.\nThe files are read into memory and processed independently.\nIt makes benchmark more precise as it eliminates I/O overhead. \nMany filenames can be supplied as multiple parameters, parameters with wildcards or names of directories can be used as parameters with the -r option.\nOne can select compression levels starting from `-b` and ending with `-e`. The `-i` parameter selects minimal time used for each of tested levels.\nWith `-B` option bigger files can be divided into smaller, independently compressed blocks. \nThe benchmark tool can be compiled with `make zwrapbench` using [zlibWrapper/Makefile](Makefile).\n\n\n#### Improving speed of streaming compression\n\nDuring streaming compression the compressor never knows how big is data to compress.\nZstandard compression can be improved by providing size of source data to the compressor. By default streaming compressor assumes that data is bigger than 256 KB but it can hurt compression speed on smaller data. \nThe zstd wrapper provides the `ZWRAP_setPledgedSrcSize()` function that allows to change a pledged source size for a given compression stream.\nThe function will change zstd compression parameters what may improve compression speed and/or ratio.\nIt should be called just after `deflateInit()`or `deflateReset()` and before `deflate()` or `deflateSetDictionary()`. The function is only helpful when data is compressed in blocks. There will be no change in case of `deflateInit()` or `deflateReset()`  immediately followed by `deflate(strm, Z_FINISH)`\nas this case is automatically detected.\n\n\n#### Reusing contexts\n\nThe ordinary zlib compression of two files/streams allocates two contexts:\n- for the 1st file calls `deflateInit`, `deflate`, `...`, `deflate`, `deflateEnd`\n- for the 2nd file calls `deflateInit`, `deflate`, `...`, `deflate`, `deflateEnd`\n\nThe speed of compression can be improved with reusing a single context with following steps:\n- initialize the context with `deflateInit`\n- for the 1st file call `deflate`, `...`, `deflate`\n- for the 2nd file call `deflateReset`, `deflate`, `...`, `deflate`\n- free the context with `deflateEnd`\n\nTo check the difference we made experiments using `zwrapbench -ri6b6` with zstd and zlib compression (both at level 6).\nThe input data was decompressed git repository downloaded from https://github.com/git/git/archive/master.zip which contains 2979 files.\nThe table below shows that reusing contexts has a minor influence on zlib but it gives improvement for zstd.\nIn our example (the last 2 lines) it gives 4% better compression speed and 5% better decompression speed.\n\n| Compression type                                  | Compression | Decompress.| Compr. size | Ratio |\n| ------------------------------------------------- | ------------| -----------| ----------- | ----- |\n| zlib 1.2.8                                        |  30.51 MB/s | 219.3 MB/s |     6819783 | 3.459 |\n| zlib 1.2.8 not reusing a context                  |  30.22 MB/s | 218.1 MB/s |     6819783 | 3.459 |\n| zlib 1.2.8 with zlibWrapper and reusing a context |  30.40 MB/s | 218.9 MB/s |     6819783 | 3.459 |\n| zlib 1.2.8 with zlibWrapper not reusing a context |  30.28 MB/s | 218.1 MB/s |     6819783 | 3.459 |\n| zstd 1.1.0 using ZSTD_CCtx                        |  68.35 MB/s | 430.9 MB/s |     6868521 | 3.435 |\n| zstd 1.1.0 using ZSTD_CStream                     |  66.63 MB/s | 422.3 MB/s |     6868521 | 3.435 |\n| zstd 1.1.0 with zlibWrapper and reusing a context |  54.01 MB/s | 403.2 MB/s |     6763482 | 3.488 |\n| zstd 1.1.0 with zlibWrapper not reusing a context |  51.59 MB/s | 383.7 MB/s |     6763482 | 3.488 |\n\n\n#### Compatibility issues\nAfter enabling zstd compression not all native zlib functions are supported. When calling unsupported methods they put error message into `strm->msg` and return Z_STREAM_ERROR.\n\nSupported methods:\n- deflateInit\n- deflate (with exception of Z_FULL_FLUSH, Z_BLOCK, and Z_TREES)\n- deflateSetDictionary\n- deflateEnd\n- deflateReset\n- deflateBound\n- inflateInit\n- inflate\n- inflateSetDictionary\n- inflateReset\n- inflateReset2\n- compress\n- compress2\n- compressBound\n- uncompress\n- gzip file access functions\n\nIgnored methods (they do nothing):\n- deflateParams\n\nUnsupported methods:\n- deflateCopy\n- deflateTune\n- deflatePending\n- deflatePrime\n- deflateSetHeader\n- inflateGetDictionary\n- inflateCopy\n- inflateSync\n- inflatePrime\n- inflateMark\n- inflateGetHeader\n- inflateBackInit\n- inflateBack\n- inflateBackEnd\n"
  },
  {
    "path": "zlibWrapper/examples/example.c",
    "content": "/* example.c contains minimal changes required to be compiled with zlibWrapper:\n * - #include \"zlib.h\" was changed to #include \"zstd_zlibwrapper.h\"\n * - test_flush() and test_sync() use functions not supported by zlibWrapper\n     therefore they are disabled while zstd compression is turned on     */\n\n/* example.c -- usage example of the zlib compression library\n */\n/*\n  Copyright (c) 1995-2006, 2011 Jean-loup Gailly\n\n This software is provided 'as-is', without any express or implied\n warranty. In no event will the authors be held liable for any damages\n arising from the use of this software.\n\n Permission is granted to anyone to use this software for any purpose,\n including commercial applications, and to alter it and redistribute it\n freely, subject to the following restrictions:\n\n 1. The origin of this software must not be misrepresented; you must not\n    claim that you wrote the original software. If you use this software\n    in a product, an acknowledgement in the product documentation would be\n    appreciated but is not required.\n 2. Altered source versions must be plainly marked as such, and must not be\n    misrepresented as being the original software.\n 3. This notice may not be removed or altered from any source distribution.\n */\n\n/* @(#) $Id$ */\n\n#include \"zstd_zlibwrapper.h\"\n#include <stdio.h>\n\n#ifdef STDC\n#  include <string.h>\n#  include <stdlib.h>\n#endif\n\n#if defined(VMS) || defined(RISCOS)\n#  define TESTFILE \"foo-gz\"\n#else\n#  define TESTFILE \"foo.gz\"\n#endif\n\n#define CHECK_ERR(err, msg) { \\\n    if (err != Z_OK) { \\\n        fprintf(stderr, \"%s error: %d\\n\", msg, err); \\\n        exit(1); \\\n    } \\\n}\n\nz_const char hello[] = \"hello, hello! I said hello, hello!\";\n/* \"hello world\" would be more standard, but the repeated \"hello\"\n * stresses the compression code better, sorry...\n */\n\nconst char dictionary[] = \"hello, hello!\";\nuLong dictId; /* Adler32 value of the dictionary */\n\nvoid test_deflate       _Z_OF((Byte *compr, uLong comprLen));\nvoid test_inflate       _Z_OF((Byte *compr, uLong comprLen,\n                            Byte *uncompr, uLong uncomprLen));\nvoid test_large_deflate _Z_OF((Byte *compr, uLong comprLen,\n                            Byte *uncompr, uLong uncomprLen));\nvoid test_large_inflate _Z_OF((Byte *compr, uLong comprLen,\n                            Byte *uncompr, uLong uncomprLen));\nvoid test_flush         _Z_OF((Byte *compr, uLong *comprLen));\nvoid test_sync          _Z_OF((Byte *compr, uLong comprLen,\n                            Byte *uncompr, uLong uncomprLen));\nvoid test_dict_deflate  _Z_OF((Byte *compr, uLong comprLen));\nvoid test_dict_inflate  _Z_OF((Byte *compr, uLong comprLen,\n                            Byte *uncompr, uLong uncomprLen));\nint  main               _Z_OF((int argc, char *argv[]));\n\n\n#ifdef Z_SOLO\n\nvoid *myalloc _Z_OF((void *, unsigned, unsigned));\nvoid myfree _Z_OF((void *, void *));\n\nvoid *myalloc(void *q, unsigned n, unsigned m)\n{\n    void *buf = calloc(n, m);\n    q = Z_NULL;\n  /*  printf(\"myalloc %p n=%d m=%d\\n\", buf, n, m); */\n    return buf;\n}\n\nvoid myfree(void *q, void *p)\n{\n  /*  printf(\"myfree %p\\n\", p); */\n    q = Z_NULL;\n    free(p);\n}\n\nstatic alloc_func zalloc = myalloc;\nstatic free_func zfree = myfree;\n\n#else /* !Z_SOLO */\n\nstatic alloc_func zalloc = (alloc_func)0;\nstatic free_func zfree = (free_func)0;\n\nvoid test_compress      _Z_OF((Byte *compr, uLong comprLen,\n                            Byte *uncompr, uLong uncomprLen));\nvoid test_gzio          _Z_OF((const char *fname,\n                            Byte *uncompr, uLong uncomprLen));\n\n/* ===========================================================================\n * Test compress() and uncompress()\n */\nvoid test_compress(Byte *compr, uLong comprLen, Byte *uncompr,\n                   uLong uncomprLen) {\n    int err;\n    uLong len = (uLong)strlen(hello)+1;\n\n    err = compress(compr, &comprLen, (const Bytef*)hello, len);\n    CHECK_ERR(err, \"compress\");\n\n    strcpy((char*)uncompr, \"garbage\");\n\n    err = uncompress(uncompr, &uncomprLen, compr, comprLen);\n    CHECK_ERR(err, \"uncompress\");\n\n    if (strcmp((char*)uncompr, hello)) {\n        fprintf(stderr, \"bad uncompress\\n\");\n        exit(1);\n    } else {\n        printf(\"uncompress(): %s\\n\", (char *)uncompr);\n    }\n}\n\n/* ===========================================================================\n * Test read/write of .gz files\n */\nvoid test_gzio(const char *fname, Byte *uncompr, uLong uncomprLen) {\n#ifdef NO_GZCOMPRESS\n    fprintf(stderr, \"NO_GZCOMPRESS -- gz* functions cannot compress\\n\");\n#else\n    int err;\n    int len = (int)strlen(hello)+1;\n    gzFile file;\n    z_off_t pos;\n\n    file = gzopen(fname, \"wb\");\n    if (file == NULL) {\n        fprintf(stderr, \"gzopen error\\n\");\n        exit(1);\n    }\n    gzputc(file, 'h');\n    if (gzputs(file, \"ello\") != 4) {\n        fprintf(stderr, \"gzputs err: %s\\n\", gzerror(file, &err));\n        exit(1);\n    }\n    if (gzprintf(file, \", %s! I said hello, hello!\", \"hello\") != 8+21) {\n        fprintf(stderr, \"gzprintf err: %s\\n\", gzerror(file, &err));\n        exit(1);\n    }\n    gzseek(file, 1L, SEEK_CUR); /* add one zero byte */\n    gzclose(file);\n\n    file = gzopen(fname, \"rb\");\n    if (file == NULL) {\n        fprintf(stderr, \"gzopen error\\n\");\n        exit(1);\n    }\n    strcpy((char*)uncompr, \"garbage\");\n\n    if (gzread(file, uncompr, (unsigned)uncomprLen) != len) {\n        fprintf(stderr, \"gzread err: %s\\n\", gzerror(file, &err));\n        exit(1);\n    }\n    if (strcmp((char*)uncompr, hello)) {\n        fprintf(stderr, \"bad gzread: %s\\n\", (char*)uncompr);\n        exit(1);\n    } else {\n        printf(\"gzread(): %s\\n\", (char*)uncompr);\n    }\n\n    pos = gzseek(file, -8L, SEEK_CUR);\n    if (pos != 6+21 || gztell(file) != pos) {\n        fprintf(stderr, \"gzseek error, pos=%ld, gztell=%ld\\n\",\n                (long)pos, (long)gztell(file));\n        exit(1);\n    }\n\n    if (gzgetc(file) != ' ') {\n        fprintf(stderr, \"gzgetc error\\n\");\n        exit(1);\n    }\n\n    if (gzungetc(' ', file) != ' ') {\n        fprintf(stderr, \"gzungetc error\\n\");\n        exit(1);\n    }\n\n    gzgets(file, (char*)uncompr, (int)uncomprLen);\n    if (strlen((char*)uncompr) != 7) { /* \" hello!\" */\n        fprintf(stderr, \"gzgets err after gzseek: %s\\n\", gzerror(file, &err));\n        exit(1);\n    }\n    if (strcmp((char*)uncompr, hello + 6+21)) {\n        fprintf(stderr, \"bad gzgets after gzseek\\n\");\n        exit(1);\n    } else {\n        printf(\"gzgets() after gzseek: %s\\n\", (char*)uncompr);\n    }\n\n    gzclose(file);\n#endif\n}\n\n#endif /* Z_SOLO */\n\n/* ===========================================================================\n * Test deflate() with small buffers\n */\nvoid test_deflate(Byte *compr, uLong comprLen) {\n    z_stream c_stream; /* compression stream */\n    int err;\n    uLong len = (uLong)strlen(hello)+1;\n\n    c_stream.zalloc = zalloc;\n    c_stream.zfree = zfree;\n    c_stream.opaque = (voidpf)0;\n\n    err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);\n    CHECK_ERR(err, \"deflateInit\");\n\n    c_stream.next_in  = (z_const unsigned char *)hello;\n    c_stream.next_out = compr;\n\n    while (c_stream.total_in != len && c_stream.total_out < comprLen) {\n        c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */\n        err = deflate(&c_stream, Z_NO_FLUSH);\n        CHECK_ERR(err, \"deflate\");\n    }\n    /* Finish the stream, still forcing small buffers: */\n    for (;;) {\n        c_stream.avail_out = 1;\n        err = deflate(&c_stream, Z_FINISH);\n        if (err == Z_STREAM_END) break;\n        CHECK_ERR(err, \"deflate\");\n    }\n\n    err = deflateEnd(&c_stream);\n    CHECK_ERR(err, \"deflateEnd\");\n}\n\n/* ===========================================================================\n * Test inflate() with small buffers\n */\nvoid test_inflate(Byte *compr, uLong comprLen, Byte *uncompr,\n                  uLong uncomprLen) {\n    int err;\n    z_stream d_stream; /* decompression stream */\n\n    strcpy((char*)uncompr, \"garbage\");\n\n    d_stream.zalloc = zalloc;\n    d_stream.zfree = zfree;\n    d_stream.opaque = (voidpf)0;\n\n    d_stream.next_in  = compr;\n    d_stream.avail_in = 0;\n    d_stream.next_out = uncompr;\n\n    err = inflateInit(&d_stream);\n    CHECK_ERR(err, \"inflateInit\");\n\n    while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {\n        d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */\n        err = inflate(&d_stream, Z_NO_FLUSH);\n        if (err == Z_STREAM_END) break;\n        CHECK_ERR(err, \"inflate\");\n    }\n\n    err = inflateEnd(&d_stream);\n    CHECK_ERR(err, \"inflateEnd\");\n\n    if (strcmp((char*)uncompr, hello)) {\n        fprintf(stderr, \"bad inflate\\n\");\n        exit(1);\n    } else {\n        printf(\"inflate(): %s\\n\", (char *)uncompr);\n    }\n}\n\n/* ===========================================================================\n * Test deflate() with large buffers and dynamic change of compression level\n */\nvoid test_large_deflate(Byte *compr, uLong comprLen, Byte *uncompr,\n                        uLong uncomprLen) {\n    z_stream c_stream; /* compression stream */\n    int err;\n\n    c_stream.zalloc = zalloc;\n    c_stream.zfree = zfree;\n    c_stream.opaque = (voidpf)0;\n\n    err = deflateInit(&c_stream, Z_BEST_SPEED);\n    CHECK_ERR(err, \"deflateInit\");\n\n    c_stream.next_out = compr;\n    c_stream.avail_out = (uInt)comprLen;\n\n    /* At this point, uncompr is still mostly zeroes, so it should compress\n     * very well:\n     */\n    c_stream.next_in = uncompr;\n    c_stream.avail_in = (uInt)uncomprLen;\n    err = deflate(&c_stream, Z_NO_FLUSH);\n    CHECK_ERR(err, \"deflate\");\n    if (c_stream.avail_in != 0) {\n        fprintf(stderr, \"deflate not greedy\\n\");\n        exit(1);\n    }\n\n    /* Feed in already compressed data and switch to no compression: */\n    deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);\n    c_stream.next_in = compr;\n    c_stream.avail_in = (uInt)comprLen/2;\n    err = deflate(&c_stream, Z_NO_FLUSH);\n    CHECK_ERR(err, \"deflate\");\n\n    /* Switch back to compressing mode: */\n    deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);\n    c_stream.next_in = uncompr;\n    c_stream.avail_in = (uInt)uncomprLen;\n    err = deflate(&c_stream, Z_NO_FLUSH);\n    CHECK_ERR(err, \"deflate\");\n\n    err = deflate(&c_stream, Z_FINISH);\n    if (err != Z_STREAM_END) {\n        fprintf(stderr, \"deflate should report Z_STREAM_END\\n\");\n        exit(1);\n    }\n    err = deflateEnd(&c_stream);\n    CHECK_ERR(err, \"deflateEnd\");\n}\n\n/* ===========================================================================\n * Test inflate() with large buffers\n */\nvoid test_large_inflate(Byte *compr, uLong comprLen, Byte *uncompr,\n                        uLong uncomprLen) {\n    int err;\n    z_stream d_stream; /* decompression stream */\n\n    strcpy((char*)uncompr, \"garbage\");\n\n    d_stream.zalloc = zalloc;\n    d_stream.zfree = zfree;\n    d_stream.opaque = (voidpf)0;\n\n    d_stream.next_in  = compr;\n    d_stream.avail_in = (uInt)comprLen;\n\n    err = inflateInit(&d_stream);\n    CHECK_ERR(err, \"inflateInit\");\n\n    for (;;) {\n        d_stream.next_out = uncompr;            /* discard the output */\n        d_stream.avail_out = (uInt)uncomprLen;\n        err = inflate(&d_stream, Z_NO_FLUSH);\n        if (err == Z_STREAM_END) break;\n        CHECK_ERR(err, \"large inflate\");\n    }\n\n    err = inflateEnd(&d_stream);\n    CHECK_ERR(err, \"inflateEnd\");\n\n    if (d_stream.total_out != 2*uncomprLen + comprLen/2) {\n        fprintf(stderr, \"bad large inflate: %ld\\n\", d_stream.total_out);\n        exit(1);\n    } else {\n        printf(\"large_inflate(): OK\\n\");\n    }\n}\n\n/* ===========================================================================\n * Test deflate() with full flush\n */\nvoid test_flush(Byte *compr, uLong *comprLen) {\n    z_stream c_stream; /* compression stream */\n    int err;\n    uInt len = (uInt)strlen(hello)+1;\n\n    c_stream.zalloc = zalloc;\n    c_stream.zfree = zfree;\n    c_stream.opaque = (voidpf)0;\n\n    err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);\n    CHECK_ERR(err, \"deflateInit\");\n\n    c_stream.next_in  = (z_const unsigned char *)hello;\n    c_stream.next_out = compr;\n    c_stream.avail_in = 3;\n    c_stream.avail_out = (uInt)*comprLen;\n    err = deflate(&c_stream, Z_FULL_FLUSH);\n    CHECK_ERR(err, \"deflate\");\n\n    compr[3]++; /* force an error in first compressed block */\n    c_stream.avail_in = len - 3;\n\n    err = deflate(&c_stream, Z_FINISH);\n    if (err != Z_STREAM_END) {\n        CHECK_ERR(err, \"deflate\");\n    }\n    err = deflateEnd(&c_stream);\n    CHECK_ERR(err, \"deflateEnd\");\n\n    *comprLen = c_stream.total_out;\n}\n\n/* ===========================================================================\n * Test inflateSync()\n */\nvoid test_sync(Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen) {\n    int err;\n    z_stream d_stream; /* decompression stream */\n\n    strcpy((char*)uncompr, \"garbage\");\n\n    d_stream.zalloc = zalloc;\n    d_stream.zfree = zfree;\n    d_stream.opaque = (voidpf)0;\n\n    d_stream.next_in  = compr;\n    d_stream.avail_in = 2; /* just read the zlib header */\n\n    err = inflateInit(&d_stream);\n    CHECK_ERR(err, \"inflateInit\");\n\n    d_stream.next_out = uncompr;\n    d_stream.avail_out = (uInt)uncomprLen;\n\n    inflate(&d_stream, Z_NO_FLUSH);\n    CHECK_ERR(err, \"inflate\");\n\n    d_stream.avail_in = (uInt)comprLen-2;   /* read all compressed data */\n    err = inflateSync(&d_stream);           /* but skip the damaged part */\n    CHECK_ERR(err, \"inflateSync\");\n\n    err = inflate(&d_stream, Z_FINISH);\n    if (err != Z_STREAM_END) {\n        fprintf(stderr, \"inflate reported %i != %i (Z_STREAM_END)\\n\", err, Z_STREAM_END);\n        /* Because of incorrect adler32 */\n        exit(1);\n    }\n    err = inflateEnd(&d_stream);\n    CHECK_ERR(err, \"inflateEnd\");\n\n    printf(\"after inflateSync(): hel%s\\n\", (char *)uncompr);\n}\n\n/* ===========================================================================\n * Test deflate() with preset dictionary\n */\nvoid test_dict_deflate(Byte *compr, uLong comprLen) {\n    z_stream c_stream; /* compression stream */\n    int err;\n\n    c_stream.zalloc = zalloc;\n    c_stream.zfree = zfree;\n    c_stream.opaque = (voidpf)0;\n\n    err = deflateInit(&c_stream, Z_BEST_COMPRESSION);\n    CHECK_ERR(err, \"deflateInit\");\n\n    err = deflateSetDictionary(&c_stream,\n                (const Bytef*)dictionary, (int)sizeof(dictionary));\n    CHECK_ERR(err, \"deflateSetDictionary\");\n\n    dictId = c_stream.adler;\n    c_stream.next_out = compr;\n    c_stream.avail_out = (uInt)comprLen;\n\n    c_stream.next_in = (z_const unsigned char *)hello;\n    c_stream.avail_in = (uInt)strlen(hello)+1;\n\n    err = deflate(&c_stream, Z_FINISH);\n    if (err != Z_STREAM_END) {\n        fprintf(stderr, \"deflate should report Z_STREAM_END\\n\");\n        exit(1);\n    }\n    err = deflateEnd(&c_stream);\n    CHECK_ERR(err, \"deflateEnd\");\n}\n\n/* ===========================================================================\n * Test inflate() with a preset dictionary\n */\nvoid test_dict_inflate(Byte *compr, uLong comprLen, Byte *uncompr,\n                       uLong uncomprLen) {\n    int err;\n    z_stream d_stream; /* decompression stream */\n\n    strcpy((char*)uncompr, \"garbage\");\n\n    d_stream.zalloc = zalloc;\n    d_stream.zfree = zfree;\n    d_stream.opaque = (voidpf)0;\n\n    d_stream.next_in  = compr;\n    d_stream.avail_in = (uInt)comprLen;\n\n    err = inflateInit(&d_stream);\n    CHECK_ERR(err, \"inflateInit\");\n\n    d_stream.next_out = uncompr;\n    d_stream.avail_out = (uInt)uncomprLen;\n\n    for (;;) {\n        err = inflate(&d_stream, Z_NO_FLUSH);\n        if (err == Z_STREAM_END) break;\n        if (err == Z_NEED_DICT) {\n            if (d_stream.adler != dictId) {\n                fprintf(stderr, \"unexpected dictionary\");\n                exit(1);\n            }\n            err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,\n                                       (int)sizeof(dictionary));\n        }\n        CHECK_ERR(err, \"inflate with dict\");\n    }\n\n    err = inflateEnd(&d_stream);\n    CHECK_ERR(err, \"inflateEnd\");\n\n    if (strcmp((char*)uncompr, hello)) {\n        fprintf(stderr, \"bad inflate with dict\\n\");\n        exit(1);\n    } else {\n        printf(\"inflate with dictionary: %s\\n\", (char *)uncompr);\n    }\n}\n\n/* ===========================================================================\n * Usage:  example [output.gz  [input.gz]]\n */\n\nint main(int argc, char *argv[]) {\n    Byte *compr, *uncompr;\n    uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */\n    uLong uncomprLen = comprLen;\n    static const char* myVersion = ZLIB_VERSION;\n\n    if (zlibVersion()[0] != myVersion[0]) {\n        fprintf(stderr, \"incompatible zlib version\\n\");\n        exit(1);\n\n    } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {\n        fprintf(stderr, \"warning: different zlib version\\n\");\n    }\n\n    printf(\"zlib version %s = 0x%04x, compile flags = 0x%lx\\n\",\n            ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags());\n    if (ZWRAP_isUsingZSTDcompression()) printf(\"zstd version %s\\n\", zstdVersion());\n\n    compr    = (Byte*)calloc((uInt)comprLen, 1);\n    uncompr  = (Byte*)calloc((uInt)uncomprLen, 1);\n    /* compr and uncompr are cleared to avoid reading uninitialized\n     * data and to ensure that uncompr compresses well.\n     */\n    if (compr == Z_NULL || uncompr == Z_NULL) {\n        printf(\"out of memory\\n\");\n        exit(1);\n    }\n\n#ifdef Z_SOLO\n    argc = strlen(argv[0]);\n#else\n    test_compress(compr, comprLen, uncompr, uncomprLen);\n\n    test_gzio((argc > 1 ? argv[1] : TESTFILE),\n          uncompr, uncomprLen);\n#endif\n\n    test_deflate(compr, comprLen);\n    test_inflate(compr, comprLen, uncompr, uncomprLen);\n\n    test_large_deflate(compr, comprLen, uncompr, uncomprLen);\n    test_large_inflate(compr, comprLen, uncompr, uncomprLen);\n\n    if (!ZWRAP_isUsingZSTDcompression()) {\n        test_flush(compr, &comprLen);\n        test_sync(compr, comprLen, uncompr, uncomprLen);\n    }\n    comprLen = uncomprLen;\n\n    test_dict_deflate(compr, comprLen);\n    test_dict_inflate(compr, comprLen, uncompr, uncomprLen);\n\n    free(compr);\n    free(uncompr);\n\n    return 0;\n}\n"
  },
  {
    "path": "zlibWrapper/examples/example_original.c",
    "content": "/* example.c -- usage example of the zlib compression library\n */\n/*\n Copyright (c) 1995-2006, 2011 Jean-loup Gailly\n\nThis software is provided 'as-is', without any express or implied\nwarranty. In no event will the authors be held liable for any damages\narising from the use of this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the following restrictions:\n\n1. The origin of this software must not be misrepresented; you must not\n   claim that you wrote the original software. If you use this software\n   in a product, an acknowledgement in the product documentation would be\n   appreciated but is not required.\n2. Altered source versions must be plainly marked as such, and must not be\n   misrepresented as being the original software.\n3. This notice may not be removed or altered from any source distribution.\n*/\n\n/* @(#) $Id$ */\n\n#include \"zlib.h\"\n#include <stdio.h>\n\n#ifdef STDC\n#  include <string.h>\n#  include <stdlib.h>\n#endif\n\n#if defined(VMS) || defined(RISCOS)\n#  define TESTFILE \"foo-gz\"\n#else\n#  define TESTFILE \"foo.gz\"\n#endif\n\n#define CHECK_ERR(err, msg) { \\\n    if (err != Z_OK) { \\\n        fprintf(stderr, \"%s error: %d\\n\", msg, err); \\\n        exit(1); \\\n    } \\\n}\n\nz_const char hello[] = \"hello, hello!\";\n/* \"hello world\" would be more standard, but the repeated \"hello\"\n * stresses the compression code better, sorry...\n */\n\nconst char dictionary[] = \"hello\";\nuLong dictId; /* Adler32 value of the dictionary */\n\nvoid test_deflate       _Z_OF((Byte *compr, uLong comprLen));\nvoid test_inflate       _Z_OF((Byte *compr, uLong comprLen,\n                            Byte *uncompr, uLong uncomprLen));\nvoid test_large_deflate _Z_OF((Byte *compr, uLong comprLen,\n                            Byte *uncompr, uLong uncomprLen));\nvoid test_large_inflate _Z_OF((Byte *compr, uLong comprLen,\n                            Byte *uncompr, uLong uncomprLen));\nvoid test_flush         _Z_OF((Byte *compr, uLong *comprLen));\nvoid test_sync          _Z_OF((Byte *compr, uLong comprLen,\n                            Byte *uncompr, uLong uncomprLen));\nvoid test_dict_deflate  _Z_OF((Byte *compr, uLong comprLen));\nvoid test_dict_inflate  _Z_OF((Byte *compr, uLong comprLen,\n                            Byte *uncompr, uLong uncomprLen));\nint  main               _Z_OF((int argc, char *argv[]));\n\n\n#ifdef Z_SOLO\n\nvoid *myalloc _Z_OF((void *, unsigned, unsigned));\nvoid myfree _Z_OF((void *, void *));\n\nvoid *myalloc(q, n, m)\n    void *q;\n    unsigned n, m;\n{\n    q = Z_NULL;\n    return calloc(n, m);\n}\n\nvoid myfree(void *q, void *p)\n{\n    q = Z_NULL;\n    free(p);\n}\n\nstatic alloc_func zalloc = myalloc;\nstatic free_func zfree = myfree;\n\n#else /* !Z_SOLO */\n\nstatic alloc_func zalloc = (alloc_func)0;\nstatic free_func zfree = (free_func)0;\n\nvoid test_compress      _Z_OF((Byte *compr, uLong comprLen,\n                            Byte *uncompr, uLong uncomprLen));\nvoid test_gzio          _Z_OF((const char *fname,\n                            Byte *uncompr, uLong uncomprLen));\n\n/* ===========================================================================\n * Test compress() and uncompress()\n */\nvoid test_compress(Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen)\n{\n    int err;\n    uLong len = (uLong)strlen(hello)+1;\n\n    err = compress(compr, &comprLen, (const Bytef*)hello, len);\n    CHECK_ERR(err, \"compress\");\n\n    strcpy((char*)uncompr, \"garbage\");\n\n    err = uncompress(uncompr, &uncomprLen, compr, comprLen);\n    CHECK_ERR(err, \"uncompress\");\n\n    if (strcmp((char*)uncompr, hello)) {\n        fprintf(stderr, \"bad uncompress\\n\");\n        exit(1);\n    } else {\n        printf(\"uncompress(): %s\\n\", (char *)uncompr);\n    }\n}\n\n/* ===========================================================================\n * Test read/write of .gz files\n */\nvoid test_gzio(const char *fname /* compressed file name */, Byte *uncompr,\n    uLong uncomprLen)\n{\n#ifdef NO_GZCOMPRESS\n    fprintf(stderr, \"NO_GZCOMPRESS -- gz* functions cannot compress\\n\");\n#else\n    int err;\n    int len = (int)strlen(hello)+1;\n    gzFile file;\n    z_off_t pos;\n\n    file = gzopen(fname, \"wb\");\n    if (file == NULL) {\n        fprintf(stderr, \"gzopen error\\n\");\n        exit(1);\n    }\n    gzputc(file, 'h');\n    if (gzputs(file, \"ello\") != 4) {\n        fprintf(stderr, \"gzputs err: %s\\n\", gzerror(file, &err));\n        exit(1);\n    }\n    if (gzprintf(file, \", %s!\", \"hello\") != 8) {\n        fprintf(stderr, \"gzprintf err: %s\\n\", gzerror(file, &err));\n        exit(1);\n    }\n    gzseek(file, 1L, SEEK_CUR); /* add one zero byte */\n    gzclose(file);\n\n    file = gzopen(fname, \"rb\");\n    if (file == NULL) {\n        fprintf(stderr, \"gzopen error\\n\");\n        exit(1);\n    }\n    strcpy((char*)uncompr, \"garbage\");\n\n    if (gzread(file, uncompr, (unsigned)uncomprLen) != len) {\n        fprintf(stderr, \"gzread err: %s\\n\", gzerror(file, &err));\n        exit(1);\n    }\n    if (strcmp((char*)uncompr, hello)) {\n        fprintf(stderr, \"bad gzread: %s\\n\", (char*)uncompr);\n        exit(1);\n    } else {\n        printf(\"gzread(): %s\\n\", (char*)uncompr);\n    }\n\n    pos = gzseek(file, -8L, SEEK_CUR);\n    if (pos != 6 || gztell(file) != pos) {\n        fprintf(stderr, \"gzseek error, pos=%ld, gztell=%ld\\n\",\n                (long)pos, (long)gztell(file));\n        exit(1);\n    }\n\n    if (gzgetc(file) != ' ') {\n        fprintf(stderr, \"gzgetc error\\n\");\n        exit(1);\n    }\n\n    if (gzungetc(' ', file) != ' ') {\n        fprintf(stderr, \"gzungetc error\\n\");\n        exit(1);\n    }\n\n    gzgets(file, (char*)uncompr, (int)uncomprLen);\n    if (strlen((char*)uncompr) != 7) { /* \" hello!\" */\n        fprintf(stderr, \"gzgets err after gzseek: %s\\n\", gzerror(file, &err));\n        exit(1);\n    }\n    if (strcmp((char*)uncompr, hello + 6)) {\n        fprintf(stderr, \"bad gzgets after gzseek\\n\");\n        exit(1);\n    } else {\n        printf(\"gzgets() after gzseek: %s\\n\", (char*)uncompr);\n    }\n\n    gzclose(file);\n#endif\n}\n\n#endif /* Z_SOLO */\n\n/* ===========================================================================\n * Test deflate() with small buffers\n */\nvoid test_deflate(Byte *compr, uLong comprLen)\n{\n    z_stream c_stream; /* compression stream */\n    int err;\n    uLong len = (uLong)strlen(hello)+1;\n\n    c_stream.zalloc = zalloc;\n    c_stream.zfree = zfree;\n    c_stream.opaque = (voidpf)0;\n\n    err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);\n    CHECK_ERR(err, \"deflateInit\");\n\n    c_stream.next_in  = (z_const unsigned char *)hello;\n    c_stream.next_out = compr;\n\n    while (c_stream.total_in != len && c_stream.total_out < comprLen) {\n        c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */\n        err = deflate(&c_stream, Z_NO_FLUSH);\n        CHECK_ERR(err, \"deflate\");\n    }\n    /* Finish the stream, still forcing small buffers: */\n    for (;;) {\n        c_stream.avail_out = 1;\n        err = deflate(&c_stream, Z_FINISH);\n        if (err == Z_STREAM_END) break;\n        CHECK_ERR(err, \"deflate\");\n    }\n\n    err = deflateEnd(&c_stream);\n    CHECK_ERR(err, \"deflateEnd\");\n}\n\n/* ===========================================================================\n * Test inflate() with small buffers\n */\nvoid test_inflate(Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen)\n{\n    int err;\n    z_stream d_stream; /* decompression stream */\n\n    strcpy((char*)uncompr, \"garbage\");\n\n    d_stream.zalloc = zalloc;\n    d_stream.zfree = zfree;\n    d_stream.opaque = (voidpf)0;\n\n    d_stream.next_in  = compr;\n    d_stream.avail_in = 0;\n    d_stream.next_out = uncompr;\n\n    err = inflateInit(&d_stream);\n    CHECK_ERR(err, \"inflateInit\");\n\n    while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {\n        d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */\n        err = inflate(&d_stream, Z_NO_FLUSH);\n        if (err == Z_STREAM_END) break;\n        CHECK_ERR(err, \"inflate\");\n    }\n\n    err = inflateEnd(&d_stream);\n    CHECK_ERR(err, \"inflateEnd\");\n\n    if (strcmp((char*)uncompr, hello)) {\n        fprintf(stderr, \"bad inflate\\n\");\n        exit(1);\n    } else {\n        printf(\"inflate(): %s\\n\", (char *)uncompr);\n    }\n}\n\n/* ===========================================================================\n * Test deflate() with large buffers and dynamic change of compression level\n */\nvoid test_large_deflate(Byte *compr, uLong comprLen, Byte *uncompr,\n    uLong uncomprLen)\n{\n    z_stream c_stream; /* compression stream */\n    int err;\n\n    c_stream.zalloc = zalloc;\n    c_stream.zfree = zfree;\n    c_stream.opaque = (voidpf)0;\n\n    err = deflateInit(&c_stream, Z_BEST_SPEED);\n    CHECK_ERR(err, \"deflateInit\");\n\n    c_stream.next_out = compr;\n    c_stream.avail_out = (uInt)comprLen;\n\n    /* At this point, uncompr is still mostly zeroes, so it should compress\n     * very well:\n     */\n    c_stream.next_in = uncompr;\n    c_stream.avail_in = (uInt)uncomprLen;\n    err = deflate(&c_stream, Z_NO_FLUSH);\n    CHECK_ERR(err, \"deflate\");\n    if (c_stream.avail_in != 0) {\n        fprintf(stderr, \"deflate not greedy\\n\");\n        exit(1);\n    }\n\n    /* Feed in already compressed data and switch to no compression: */\n    deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);\n    c_stream.next_in = compr;\n    c_stream.avail_in = (uInt)comprLen/2;\n    err = deflate(&c_stream, Z_NO_FLUSH);\n    CHECK_ERR(err, \"deflate\");\n\n    /* Switch back to compressing mode: */\n    deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);\n    c_stream.next_in = uncompr;\n    c_stream.avail_in = (uInt)uncomprLen;\n    err = deflate(&c_stream, Z_NO_FLUSH);\n    CHECK_ERR(err, \"deflate\");\n\n    err = deflate(&c_stream, Z_FINISH);\n    if (err != Z_STREAM_END) {\n        fprintf(stderr, \"deflate should report Z_STREAM_END\\n\");\n        exit(1);\n    }\n    err = deflateEnd(&c_stream);\n    CHECK_ERR(err, \"deflateEnd\");\n}\n\n/* ===========================================================================\n * Test inflate() with large buffers\n */\nvoid test_large_inflate(Byte *compr, uLong comprLen, Byte *uncompr,\n    uLong uncomprLen)\n{\n    int err;\n    z_stream d_stream; /* decompression stream */\n\n    strcpy((char*)uncompr, \"garbage\");\n\n    d_stream.zalloc = zalloc;\n    d_stream.zfree = zfree;\n    d_stream.opaque = (voidpf)0;\n\n    d_stream.next_in  = compr;\n    d_stream.avail_in = (uInt)comprLen;\n\n    err = inflateInit(&d_stream);\n    CHECK_ERR(err, \"inflateInit\");\n\n    for (;;) {\n        d_stream.next_out = uncompr;            /* discard the output */\n        d_stream.avail_out = (uInt)uncomprLen;\n        err = inflate(&d_stream, Z_NO_FLUSH);\n        if (err == Z_STREAM_END) break;\n        CHECK_ERR(err, \"large inflate\");\n    }\n\n    err = inflateEnd(&d_stream);\n    CHECK_ERR(err, \"inflateEnd\");\n\n    if (d_stream.total_out != 2*uncomprLen + comprLen/2) {\n        fprintf(stderr, \"bad large inflate: %ld\\n\", d_stream.total_out);\n        exit(1);\n    } else {\n        printf(\"large_inflate(): OK\\n\");\n    }\n}\n\n/* ===========================================================================\n * Test deflate() with full flush\n */\nvoid test_flush(Byte *compr, uLong comprLen)\n{\n    z_stream c_stream; /* compression stream */\n    int err;\n    uInt len = (uInt)strlen(hello)+1;\n\n    c_stream.zalloc = zalloc;\n    c_stream.zfree = zfree;\n    c_stream.opaque = (voidpf)0;\n\n    err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);\n    CHECK_ERR(err, \"deflateInit\");\n\n    c_stream.next_in  = (z_const unsigned char *)hello;\n    c_stream.next_out = compr;\n    c_stream.avail_in = 3;\n    c_stream.avail_out = (uInt)*comprLen;\n    err = deflate(&c_stream, Z_FULL_FLUSH);\n    CHECK_ERR(err, \"deflate\");\n\n    compr[3]++; /* force an error in first compressed block */\n    c_stream.avail_in = len - 3;\n\n    err = deflate(&c_stream, Z_FINISH);\n    if (err != Z_STREAM_END) {\n        CHECK_ERR(err, \"deflate\");\n    }\n    err = deflateEnd(&c_stream);\n    CHECK_ERR(err, \"deflateEnd\");\n\n    *comprLen = c_stream.total_out;\n}\n\n/* ===========================================================================\n * Test inflateSync()\n */\nvoid test_sync(Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen)\n{\n    int err;\n    z_stream d_stream; /* decompression stream */\n\n    strcpy((char*)uncompr, \"garbage\");\n\n    d_stream.zalloc = zalloc;\n    d_stream.zfree = zfree;\n    d_stream.opaque = (voidpf)0;\n\n    d_stream.next_in  = compr;\n    d_stream.avail_in = 2; /* just read the zlib header */\n\n    err = inflateInit(&d_stream);\n    CHECK_ERR(err, \"inflateInit\");\n\n    d_stream.next_out = uncompr;\n    d_stream.avail_out = (uInt)uncomprLen;\n\n    inflate(&d_stream, Z_NO_FLUSH);\n    CHECK_ERR(err, \"inflate\");\n\n    d_stream.avail_in = (uInt)comprLen-2;   /* read all compressed data */\n    err = inflateSync(&d_stream);           /* but skip the damaged part */\n    CHECK_ERR(err, \"inflateSync\");\n\n    err = inflate(&d_stream, Z_FINISH);\n    if (err != Z_DATA_ERROR) {\n        fprintf(stderr, \"inflate should report DATA_ERROR\\n\");\n        /* Because of incorrect adler32 */\n        exit(1);\n    }\n    err = inflateEnd(&d_stream);\n    CHECK_ERR(err, \"inflateEnd\");\n\n    printf(\"after inflateSync(): hel%s\\n\", (char *)uncompr);\n}\n\n/* ===========================================================================\n * Test deflate() with preset dictionary\n */\nvoid test_dict_deflate(Byte *compr, uLong comprLen)\n{\n    z_stream c_stream; /* compression stream */\n    int err;\n\n    c_stream.zalloc = zalloc;\n    c_stream.zfree = zfree;\n    c_stream.opaque = (voidpf)0;\n\n    err = deflateInit(&c_stream, Z_BEST_COMPRESSION);\n    CHECK_ERR(err, \"deflateInit\");\n\n    err = deflateSetDictionary(&c_stream,\n                (const Bytef*)dictionary, (int)sizeof(dictionary));\n    CHECK_ERR(err, \"deflateSetDictionary\");\n\n    dictId = c_stream.adler;\n    c_stream.next_out = compr;\n    c_stream.avail_out = (uInt)comprLen;\n\n    c_stream.next_in = (z_const unsigned char *)hello;\n    c_stream.avail_in = (uInt)strlen(hello)+1;\n\n    err = deflate(&c_stream, Z_FINISH);\n    if (err != Z_STREAM_END) {\n        fprintf(stderr, \"deflate should report Z_STREAM_END\\n\");\n        exit(1);\n    }\n    err = deflateEnd(&c_stream);\n    CHECK_ERR(err, \"deflateEnd\");\n}\n\n/* ===========================================================================\n * Test inflate() with a preset dictionary\n */\nvoid test_dict_inflate(Byte *compr, uLong comprLen, Byte *uncompr,\n    uLong uncomprLen)\n{\n    int err;\n    z_stream d_stream; /* decompression stream */\n\n    strcpy((char*)uncompr, \"garbage\");\n\n    d_stream.zalloc = zalloc;\n    d_stream.zfree = zfree;\n    d_stream.opaque = (voidpf)0;\n\n    d_stream.next_in  = compr;\n    d_stream.avail_in = (uInt)comprLen;\n\n    err = inflateInit(&d_stream);\n    CHECK_ERR(err, \"inflateInit\");\n\n    d_stream.next_out = uncompr;\n    d_stream.avail_out = (uInt)uncomprLen;\n\n    for (;;) {\n        err = inflate(&d_stream, Z_NO_FLUSH);\n        if (err == Z_STREAM_END) break;\n        if (err == Z_NEED_DICT) {\n            if (d_stream.adler != dictId) {\n                fprintf(stderr, \"unexpected dictionary\");\n                exit(1);\n            }\n            err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,\n                                       (int)sizeof(dictionary));\n        }\n        CHECK_ERR(err, \"inflate with dict\");\n    }\n\n    err = inflateEnd(&d_stream);\n    CHECK_ERR(err, \"inflateEnd\");\n\n    if (strcmp((char*)uncompr, hello)) {\n        fprintf(stderr, \"bad inflate with dict\\n\");\n        exit(1);\n    } else {\n        printf(\"inflate with dictionary: %s\\n\", (char *)uncompr);\n    }\n}\n\n/* ===========================================================================\n * Usage:  example [output.gz  [input.gz]]\n */\n\nint main(int argc, char *argv[])\n{\n    Byte *compr, *uncompr;\n    uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */\n    uLong uncomprLen = comprLen;\n    static const char* myVersion = ZLIB_VERSION;\n\n    if (zlibVersion()[0] != myVersion[0]) {\n        fprintf(stderr, \"incompatible zlib version\\n\");\n        exit(1);\n\n    } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {\n        fprintf(stderr, \"warning: different zlib version\\n\");\n    }\n\n    printf(\"zlib version %s = 0x%04x, compile flags = 0x%lx\\n\",\n            ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags());\n\n    compr    = (Byte*)calloc((uInt)comprLen, 1);\n    uncompr  = (Byte*)calloc((uInt)uncomprLen, 1);\n    /* compr and uncompr are cleared to avoid reading uninitialized\n     * data and to ensure that uncompr compresses well.\n     */\n    if (compr == Z_NULL || uncompr == Z_NULL) {\n        printf(\"out of memory\\n\");\n        exit(1);\n    }\n\n#ifdef Z_SOLO\n    argc = strlen(argv[0]);\n#else\n    test_compress(compr, comprLen, uncompr, uncomprLen);\n\n    test_gzio((argc > 1 ? argv[1] : TESTFILE),\n              uncompr, uncomprLen);\n#endif\n\n    test_deflate(compr, comprLen);\n    test_inflate(compr, comprLen, uncompr, uncomprLen);\n\n    test_large_deflate(compr, comprLen, uncompr, uncomprLen);\n    test_large_inflate(compr, comprLen, uncompr, uncomprLen);\n\n    test_flush(compr, &comprLen);\n    test_sync(compr, comprLen, uncompr, uncomprLen);\n    comprLen = uncomprLen;\n\n    test_dict_deflate(compr, comprLen);\n    test_dict_inflate(compr, comprLen, uncompr, uncomprLen);\n\n    free(compr);\n    free(uncompr);\n\n    return 0;\n}\n"
  },
  {
    "path": "zlibWrapper/examples/fitblk.c",
    "content": "/* fitblk.c contains minimal changes required to be compiled with zlibWrapper:\n * - #include \"zlib.h\" was changed to #include \"zstd_zlibwrapper.h\"\n * - writing block to stdout was disabled                          */\n\n/* fitblk.c: example of fitting compressed output to a specified size\n   Not copyrighted -- provided to the public domain\n   Version 1.1  25 November 2004  Mark Adler */\n\n/* Version history:\n   1.0  24 Nov 2004  First version\n   1.1  25 Nov 2004  Change deflateInit2() to deflateInit()\n                     Use fixed-size, stack-allocated raw buffers\n                     Simplify code moving compression to subroutines\n                     Use assert() for internal errors\n                     Add detailed description of approach\n */\n\n/* Approach to just fitting a requested compressed size:\n\n   fitblk performs three compression passes on a portion of the input\n   data in order to determine how much of that input will compress to\n   nearly the requested output block size.  The first pass generates\n   enough deflate blocks to produce output to fill the requested\n   output size plus a specified excess amount (see the EXCESS define\n   below).  The last deflate block may go quite a bit past that, but\n   is discarded.  The second pass decompresses and recompresses just\n   the compressed data that fit in the requested plus excess sized\n   buffer.  The deflate process is terminated after that amount of\n   input, which is less than the amount consumed on the first pass.\n   The last deflate block of the result will be of a comparable size\n   to the final product, so that the header for that deflate block and\n   the compression ratio for that block will be about the same as in\n   the final product.  The third compression pass decompresses the\n   result of the second step, but only the compressed data up to the\n   requested size minus an amount to allow the compressed stream to\n   complete (see the MARGIN define below).  That will result in a\n   final compressed stream whose length is less than or equal to the\n   requested size.  Assuming sufficient input and a requested size\n   greater than a few hundred bytes, the shortfall will typically be\n   less than ten bytes.\n\n   If the input is short enough that the first compression completes\n   before filling the requested output size, then that compressed\n   stream is return with no recompression.\n\n   EXCESS is chosen to be just greater than the shortfall seen in a\n   two pass approach similar to the above.  That shortfall is due to\n   the last deflate block compressing more efficiently with a smaller\n   header on the second pass.  EXCESS is set to be large enough so\n   that there is enough uncompressed data for the second pass to fill\n   out the requested size, and small enough so that the final deflate\n   block of the second pass will be close in size to the final deflate\n   block of the third and final pass.  MARGIN is chosen to be just\n   large enough to assure that the final compression has enough room\n   to complete in all cases.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <assert.h>\n#include \"zstd_zlibwrapper.h\"\n\n#define LOG_FITBLK(...)   /*printf(__VA_ARGS__)*/\n#define local static\n\n/* print nastygram and leave */\nlocal void quit(char *why)\n{\n    fprintf(stderr, \"fitblk abort: %s\\n\", why);\n    exit(1);\n}\n\n#define RAWLEN 4096    /* intermediate uncompressed buffer size */\n\n/* compress from file to def until provided buffer is full or end of\n   input reached; return last deflate() return value, or Z_ERRNO if\n   there was read error on the file */\nlocal int partcompress(FILE *in, z_streamp def)\n{\n    int ret, flush;\n    unsigned char raw[RAWLEN];\n\n    flush = Z_SYNC_FLUSH;\n    do {\n        def->avail_in = (uInt)fread(raw, 1, RAWLEN, in);\n        if (ferror(in))\n            return Z_ERRNO;\n        def->next_in = raw;\n        if (feof(in))\n            flush = Z_FINISH;\n        LOG_FITBLK(\"partcompress1 avail_in=%d total_in=%d avail_out=%d total_out=%d\\n\", (int)def->avail_in, (int)def->total_in, (int)def->avail_out, (int)def->total_out);\n        ret = deflate(def, flush);\n        LOG_FITBLK(\"partcompress2 ret=%d avail_in=%d total_in=%d avail_out=%d total_out=%d\\n\", ret, (int)def->avail_in, (int)def->total_in, (int)def->avail_out, (int)def->total_out);\n        assert(ret != Z_STREAM_ERROR);\n    } while (def->avail_out != 0 && flush == Z_SYNC_FLUSH);\n    return ret;\n}\n\n/* recompress from inf's input to def's output; the input for inf and\n   the output for def are set in those structures before calling;\n   return last deflate() return value, or Z_MEM_ERROR if inflate()\n   was not able to allocate enough memory when it needed to */\nlocal int recompress(z_streamp inf, z_streamp def)\n{\n    int ret, flush;\n    unsigned char raw[RAWLEN];\n\n    flush = Z_NO_FLUSH;\n    LOG_FITBLK(\"recompress start\\n\");\n    do {\n        /* decompress */\n        inf->avail_out = RAWLEN;\n        inf->next_out = raw;\n        LOG_FITBLK(\"recompress1inflate avail_in=%d total_in=%d avail_out=%d total_out=%d\\n\", (int)inf->avail_in, (int)inf->total_in, (int)inf->avail_out, (int)inf->total_out);\n        ret = inflate(inf, Z_NO_FLUSH);\n        LOG_FITBLK(\"recompress2inflate avail_in=%d total_in=%d avail_out=%d total_out=%d\\n\", (int)inf->avail_in, (int)inf->total_in, (int)inf->avail_out, (int)inf->total_out);\n        assert(ret != Z_STREAM_ERROR && ret != Z_DATA_ERROR &&\n               ret != Z_NEED_DICT);\n        if (ret == Z_MEM_ERROR)\n            return ret;\n\n        /* compress what was decompressed until done or no room */\n        def->avail_in = RAWLEN - inf->avail_out;\n        def->next_in = raw;\n        if (inf->avail_out != 0)\n            flush = Z_FINISH;\n        LOG_FITBLK(\"recompress1deflate avail_in=%d total_in=%d avail_out=%d total_out=%d\\n\", (int)def->avail_in, (int)def->total_in, (int)def->avail_out, (int)def->total_out);\n        ret = deflate(def, flush);\n        LOG_FITBLK(\"recompress2deflate ret=%d avail_in=%d total_in=%d avail_out=%d total_out=%d\\n\", ret, (int)def->avail_in, (int)def->total_in, (int)def->avail_out, (int)def->total_out);\n        assert(ret != Z_STREAM_ERROR);\n    } while (ret != Z_STREAM_END && def->avail_out != 0);\n    return ret;\n}\n\n#define EXCESS 256      /* empirically determined stream overage */\n#define MARGIN 8        /* amount to back off for completion */\n\n/* compress from stdin to fixed-size block on stdout */\nint main(int argc, char **argv)\n{\n    int ret;                /* return code */\n    unsigned size;          /* requested fixed output block size */\n    unsigned have;          /* bytes written by deflate() call */\n    unsigned char *blk;     /* intermediate and final stream */\n    unsigned char *tmp;     /* close to desired size stream */\n    z_stream def, inf;      /* zlib deflate and inflate states */\n\n    /* get requested output size */\n    if (argc != 2)\n        quit(\"need one argument: size of output block\");\n    ret = (int)strtol(argv[1], argv + 1, 10);\n    if (argv[1][0] != 0)\n        quit(\"argument must be a number\");\n    if (ret < 8)            /* 8 is minimum zlib stream size */\n        quit(\"need positive size of 8 or greater\");\n    size = (unsigned)ret;\n\n    printf(\"zlib version %s\\n\", ZLIB_VERSION);\n    if (ZWRAP_isUsingZSTDcompression()) printf(\"zstd version %s\\n\", zstdVersion());\n\n    /* allocate memory for buffers and compression engine */\n    blk = (unsigned char*)malloc(size + EXCESS);\n    def.zalloc = Z_NULL;\n    def.zfree = Z_NULL;\n    def.opaque = Z_NULL;\n    ret = deflateInit(&def, Z_DEFAULT_COMPRESSION);\n    if (ret != Z_OK || blk == NULL)\n        quit(\"out of memory\");\n\n    /* compress from stdin until output full, or no more input */\n    def.avail_out = size + EXCESS;\n    def.next_out = blk;\n    LOG_FITBLK(\"partcompress1 total_in=%d total_out=%d\\n\", (int)def.total_in, (int)def.total_out);\n    ret = partcompress(stdin, &def);\n    printf(\"partcompress total_in=%d total_out=%d\\n\", (int)def.total_in, (int)def.total_out);\n    if (ret == Z_ERRNO)\n        quit(\"error reading input\");\n\n    /* if it all fit, then size was undersubscribed -- done! */\n    if (ret == Z_STREAM_END && def.avail_out >= EXCESS) {\n        /* write block to stdout */\n        have = size + EXCESS - def.avail_out;\n   /*     if (fwrite(blk, 1, have, stdout) != have || ferror(stdout))\n    *         quit(\"error writing output\"); */\n\n        /* clean up and print results to stderr */\n        ret = deflateEnd(&def);\n        assert(ret != Z_STREAM_ERROR);\n        free(blk);\n        fprintf(stderr,\n                \"%u bytes unused out of %u requested (all input)\\n\",\n                size - have, size);\n        return 0;\n    }\n\n    /* it didn't all fit -- set up for recompression */\n    inf.zalloc = Z_NULL;\n    inf.zfree = Z_NULL;\n    inf.opaque = Z_NULL;\n    inf.avail_in = 0;\n    inf.next_in = Z_NULL;\n    ret = inflateInit(&inf);\n    tmp = (unsigned char*)malloc(size + EXCESS);\n    if (ret != Z_OK || tmp == NULL)\n        quit(\"out of memory\");\n    ret = deflateReset(&def);\n    assert(ret != Z_STREAM_ERROR);\n\n    /* do first recompression close to the right amount */\n    inf.avail_in = size + EXCESS;\n    inf.next_in = blk;\n    def.avail_out = size + EXCESS;\n    def.next_out = tmp;\n    LOG_FITBLK(\"recompress1 inf.total_in=%d def.total_out=%d\\n\", (int)inf.total_in, (int)def.total_out);\n    ret = recompress(&inf, &def);\n    LOG_FITBLK(\"recompress1 inf.total_in=%d def.total_out=%d\\n\", (int)inf.total_in, (int)def.total_out);\n    if (ret == Z_MEM_ERROR)\n        quit(\"out of memory\");\n\n    /* set up for next recompression */\n    ret = inflateReset(&inf);\n    assert(ret != Z_STREAM_ERROR);\n    ret = deflateReset(&def);\n    assert(ret != Z_STREAM_ERROR);\n\n    /* do second and final recompression (third compression) */\n    inf.avail_in = size - MARGIN;   /* assure stream will complete */\n    inf.next_in = tmp;\n    def.avail_out = size;\n    def.next_out = blk;\n    LOG_FITBLK(\"recompress2 inf.total_in=%d def.total_out=%d\\n\", (int)inf.total_in, (int)def.total_out);\n    ret = recompress(&inf, &def);\n    LOG_FITBLK(\"recompress2 inf.total_in=%d def.total_out=%d\\n\", (int)inf.total_in, (int)def.total_out);\n    if (ret == Z_MEM_ERROR)\n        quit(\"out of memory\");\n    assert(ret == Z_STREAM_END);    /* otherwise MARGIN too small */\n\n    /* done -- write block to stdout */\n    have = size - def.avail_out;\n    /* if (fwrite(blk, 1, have, stdout) != have || ferror(stdout))\n     *     quit(\"error writing output\"); */\n\n    /* clean up and print results to stderr */\n    free(tmp);\n    ret = inflateEnd(&inf);\n    assert(ret != Z_STREAM_ERROR);\n    ret = deflateEnd(&def);\n    assert(ret != Z_STREAM_ERROR);\n    free(blk);\n    fprintf(stderr,\n            \"%u bytes unused out of %u requested (%lu input)\\n\",\n            size - have, size, def.total_in);\n    return 0;\n}\n"
  },
  {
    "path": "zlibWrapper/examples/fitblk_original.c",
    "content": "/* fitblk.c: example of fitting compressed output to a specified size\n   Not copyrighted -- provided to the public domain\n   Version 1.1  25 November 2004  Mark Adler */\n\n/* Version history:\n   1.0  24 Nov 2004  First version\n   1.1  25 Nov 2004  Change deflateInit2() to deflateInit()\n                     Use fixed-size, stack-allocated raw buffers\n                     Simplify code moving compression to subroutines\n                     Use assert() for internal errors\n                     Add detailed description of approach\n */\n\n/* Approach to just fitting a requested compressed size:\n\n   fitblk performs three compression passes on a portion of the input\n   data in order to determine how much of that input will compress to\n   nearly the requested output block size.  The first pass generates\n   enough deflate blocks to produce output to fill the requested\n   output size plus a specified excess amount (see the EXCESS define\n   below).  The last deflate block may go quite a bit past that, but\n   is discarded.  The second pass decompresses and recompresses just\n   the compressed data that fit in the requested plus excess sized\n   buffer.  The deflate process is terminated after that amount of\n   input, which is less than the amount consumed on the first pass.\n   The last deflate block of the result will be of a comparable size\n   to the final product, so that the header for that deflate block and\n   the compression ratio for that block will be about the same as in\n   the final product.  The third compression pass decompresses the\n   result of the second step, but only the compressed data up to the\n   requested size minus an amount to allow the compressed stream to\n   complete (see the MARGIN define below).  That will result in a\n   final compressed stream whose length is less than or equal to the\n   requested size.  Assuming sufficient input and a requested size\n   greater than a few hundred bytes, the shortfall will typically be\n   less than ten bytes.\n\n   If the input is short enough that the first compression completes\n   before filling the requested output size, then that compressed\n   stream is return with no recompression.\n\n   EXCESS is chosen to be just greater than the shortfall seen in a\n   two pass approach similar to the above.  That shortfall is due to\n   the last deflate block compressing more efficiently with a smaller\n   header on the second pass.  EXCESS is set to be large enough so\n   that there is enough uncompressed data for the second pass to fill\n   out the requested size, and small enough so that the final deflate\n   block of the second pass will be close in size to the final deflate\n   block of the third and final pass.  MARGIN is chosen to be just\n   large enough to assure that the final compression has enough room\n   to complete in all cases.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <assert.h>\n#include \"zlib.h\"\n\n#define local static\n\n/* print nastygram and leave */\nlocal void quit(char *why)\n{\n    fprintf(stderr, \"fitblk abort: %s\\n\", why);\n    exit(1);\n}\n\n#define RAWLEN 4096    /* intermediate uncompressed buffer size */\n\n/* compress from file to def until provided buffer is full or end of\n   input reached; return last deflate() return value, or Z_ERRNO if\n   there was read error on the file */\nlocal int partcompress(FILE *in, z_streamp def)\n{\n    int ret, flush;\n    unsigned char raw[RAWLEN];\n\n    flush = Z_NO_FLUSH;\n    do {\n        def->avail_in = fread(raw, 1, RAWLEN, in);\n        if (ferror(in))\n            return Z_ERRNO;\n        def->next_in = raw;\n        if (feof(in))\n            flush = Z_FINISH;\n        ret = deflate(def, flush);\n        assert(ret != Z_STREAM_ERROR);\n    } while (def->avail_out != 0 && flush == Z_NO_FLUSH);\n    return ret;\n}\n\n/* recompress from inf's input to def's output; the input for inf and\n   the output for def are set in those structures before calling;\n   return last deflate() return value, or Z_MEM_ERROR if inflate()\n   was not able to allocate enough memory when it needed to */\nlocal int recompress(z_streamp inf, z_streamp def)\n{\n    int ret, flush;\n    unsigned char raw[RAWLEN];\n\n    flush = Z_NO_FLUSH;\n    do {\n        /* decompress */\n        inf->avail_out = RAWLEN;\n        inf->next_out = raw;\n        ret = inflate(inf, Z_NO_FLUSH);\n        assert(ret != Z_STREAM_ERROR && ret != Z_DATA_ERROR &&\n               ret != Z_NEED_DICT);\n        if (ret == Z_MEM_ERROR)\n            return ret;\n\n        /* compress what was decompressed until done or no room */\n        def->avail_in = RAWLEN - inf->avail_out;\n        def->next_in = raw;\n        if (inf->avail_out != 0)\n            flush = Z_FINISH;\n        ret = deflate(def, flush);\n        assert(ret != Z_STREAM_ERROR);\n    } while (ret != Z_STREAM_END && def->avail_out != 0);\n    return ret;\n}\n\n#define EXCESS 256      /* empirically determined stream overage */\n#define MARGIN 8        /* amount to back off for completion */\n\n/* compress from stdin to fixed-size block on stdout */\nint main(int argc, char **argv)\n{\n    int ret;                /* return code */\n    unsigned size;          /* requested fixed output block size */\n    unsigned have;          /* bytes written by deflate() call */\n    unsigned char *blk;     /* intermediate and final stream */\n    unsigned char *tmp;     /* close to desired size stream */\n    z_stream def, inf;      /* zlib deflate and inflate states */\n\n    /* get requested output size */\n    if (argc != 2)\n        quit(\"need one argument: size of output block\");\n    ret = strtol(argv[1], argv + 1, 10);\n    if (argv[1][0] != 0)\n        quit(\"argument must be a number\");\n    if (ret < 8)            /* 8 is minimum zlib stream size */\n        quit(\"need positive size of 8 or greater\");\n    size = (unsigned)ret;\n\n    /* allocate memory for buffers and compression engine */\n    blk = malloc(size + EXCESS);\n    def.zalloc = Z_NULL;\n    def.zfree = Z_NULL;\n    def.opaque = Z_NULL;\n    ret = deflateInit(&def, Z_DEFAULT_COMPRESSION);\n    if (ret != Z_OK || blk == NULL)\n        quit(\"out of memory\");\n\n    /* compress from stdin until output full, or no more input */\n    def.avail_out = size + EXCESS;\n    def.next_out = blk;\n    ret = partcompress(stdin, &def);\n    if (ret == Z_ERRNO)\n        quit(\"error reading input\");\n\n    /* if it all fit, then size was undersubscribed -- done! */\n    if (ret == Z_STREAM_END && def.avail_out >= EXCESS) {\n        /* write block to stdout */\n        have = size + EXCESS - def.avail_out;\n        if (fwrite(blk, 1, have, stdout) != have || ferror(stdout))\n            quit(\"error writing output\");\n\n        /* clean up and print results to stderr */\n        ret = deflateEnd(&def);\n        assert(ret != Z_STREAM_ERROR);\n        free(blk);\n        fprintf(stderr,\n                \"%u bytes unused out of %u requested (all input)\\n\",\n                size - have, size);\n        return 0;\n    }\n\n    /* it didn't all fit -- set up for recompression */\n    inf.zalloc = Z_NULL;\n    inf.zfree = Z_NULL;\n    inf.opaque = Z_NULL;\n    inf.avail_in = 0;\n    inf.next_in = Z_NULL;\n    ret = inflateInit(&inf);\n    tmp = malloc(size + EXCESS);\n    if (ret != Z_OK || tmp == NULL)\n        quit(\"out of memory\");\n    ret = deflateReset(&def);\n    assert(ret != Z_STREAM_ERROR);\n\n    /* do first recompression close to the right amount */\n    inf.avail_in = size + EXCESS;\n    inf.next_in = blk;\n    def.avail_out = size + EXCESS;\n    def.next_out = tmp;\n    ret = recompress(&inf, &def);\n    if (ret == Z_MEM_ERROR)\n        quit(\"out of memory\");\n\n    /* set up for next recompression */\n    ret = inflateReset(&inf);\n    assert(ret != Z_STREAM_ERROR);\n    ret = deflateReset(&def);\n    assert(ret != Z_STREAM_ERROR);\n\n    /* do second and final recompression (third compression) */\n    inf.avail_in = size - MARGIN;   /* assure stream will complete */\n    inf.next_in = tmp;\n    def.avail_out = size;\n    def.next_out = blk;\n    ret = recompress(&inf, &def);\n    if (ret == Z_MEM_ERROR)\n        quit(\"out of memory\");\n    assert(ret == Z_STREAM_END);    /* otherwise MARGIN too small */\n\n    /* done -- write block to stdout */\n    have = size - def.avail_out;\n    if (fwrite(blk, 1, have, stdout) != have || ferror(stdout))\n        quit(\"error writing output\");\n\n    /* clean up and print results to stderr */\n    free(tmp);\n    ret = inflateEnd(&inf);\n    assert(ret != Z_STREAM_ERROR);\n    ret = deflateEnd(&def);\n    assert(ret != Z_STREAM_ERROR);\n    free(blk);\n    fprintf(stderr,\n            \"%u bytes unused out of %u requested (%lu input)\\n\",\n            size - have, size, def.total_in);\n    return 0;\n}\n"
  },
  {
    "path": "zlibWrapper/examples/minigzip.c",
    "content": "/* minigzip.c contains minimal changes required to be compiled with zlibWrapper:\n * - #include \"zlib.h\" was changed to #include \"zstd_zlibwrapper.h\"        */\n\n/* minigzip.c -- simulate gzip using the zlib compression library\n * Copyright (C) 1995-2006, 2010, 2011 Jean-loup Gailly.\n * For conditions of distribution and use, see https://www.zlib.net/zlib_license.html\n */\n\n/*\n * minigzip is a minimal implementation of the gzip utility. This is\n * only an example of using zlib and isn't meant to replace the\n * full-featured gzip. No attempt is made to deal with file systems\n * limiting names to 14 or 8+3 characters, etc... Error checking is\n * very limited. So use minigzip only for testing; use gzip for the\n * real thing. On MSDOS, use only on file names without extension\n * or in pipe mode.\n */\n\n/* @(#) $Id$ */\n\n#define _POSIX_SOURCE /* fileno */\n\n#include \"zstd_zlibwrapper.h\"\n#include <stdio.h>\n\n#ifdef STDC\n#  include <string.h>\n#  include <stdlib.h>\n#endif\n\n#ifdef USE_MMAP\n#  include <sys/types.h>\n#  include <sys/mman.h>\n#  include <sys/stat.h>\n#endif\n\n#if defined(MSDOS) || defined(OS2) || defined(_WIN32) || defined(__CYGWIN__)\n#  include <fcntl.h>\n#  include <io.h>\n#  ifdef UNDER_CE\n#    include <stdlib.h>\n#  endif\n#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)\n#else\n#  define SET_BINARY_MODE(file)\n#endif\n\n#ifdef _MSC_VER\n#  define snprintf _snprintf\n#endif\n\n#ifdef VMS\n#  define unlink delete\n#  define GZ_SUFFIX \"-gz\"\n#endif\n#ifdef RISCOS\n#  define unlink remove\n#  define GZ_SUFFIX \"-gz\"\n#  define fileno(file) file->__file\n#endif\n#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os\n#  include <unix.h> /* for fileno */\n#endif\n\n#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE)\n#ifndef _WIN32 /* unlink already in stdio.h for WIN32 */\n  extern int unlink _Z_OF((const char *));\n#endif\n#endif\n\n#if defined(UNDER_CE)\n#  include <windows.h>\n#  define perror(s) pwinerror(s)\n\n/* Map the Windows error number in ERROR to a locale-dependent error\n   message string and return a pointer to it.  Typically, the values\n   for ERROR come from GetLastError.\n\n   The string pointed to shall not be modified by the application,\n   but may be overwritten by a subsequent call to strwinerror\n\n   The strwinerror function does not change the current setting\n   of GetLastError.  */\n\nstatic char *strwinerror(DWORD error)\n{\n    static char buf[1024];\n\n    wchar_t *msgbuf;\n    DWORD lasterr = GetLastError();\n    DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM\n        | FORMAT_MESSAGE_ALLOCATE_BUFFER,\n        NULL,\n        error,\n        0, /* Default language */\n        (LPVOID)&msgbuf,\n        0,\n        NULL);\n    if (chars != 0) {\n        /* If there is an \\r\\n appended, zap it.  */\n        if (chars >= 2\n            && msgbuf[chars - 2] == '\\r' && msgbuf[chars - 1] == '\\n') {\n            chars -= 2;\n            msgbuf[chars] = 0;\n        }\n\n        if (chars > sizeof (buf) - 1) {\n            chars = sizeof (buf) - 1;\n            msgbuf[chars] = 0;\n        }\n\n        wcstombs(buf, msgbuf, chars + 1);\n        LocalFree(msgbuf);\n    }\n    else {\n        sprintf(buf, \"unknown win32 error (%ld)\", error);\n    }\n\n    SetLastError(lasterr);\n    return buf;\n}\n\nstatic void pwinerror (const char *s)\n{\n    if (s && *s)\n        fprintf(stderr, \"%s: %s\\n\", s, strwinerror(GetLastError ()));\n    else\n        fprintf(stderr, \"%s\\n\", strwinerror(GetLastError ()));\n}\n\n#endif /* UNDER_CE */\n\n#ifndef GZ_SUFFIX\n#  define GZ_SUFFIX \".gz\"\n#endif\n#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)\n\n#define BUFLEN      16384\n#define MAX_NAME_LEN 1024\n\n#ifdef MAXSEG_64K\n#  define local static\n   /* Needed for systems with limitation on stack size. */\n#else\n#  define local\n#endif\n\n#ifdef Z_SOLO\n/* for Z_SOLO, create simplified gz* functions using deflate and inflate */\n\n#if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE)\n#  include <unistd.h>       /* for unlink() */\n#endif\n\nvoid *myalloc _Z_OF((void *, unsigned, unsigned));\nvoid myfree _Z_OF((void *, void *));\n\nvoid *myalloc(q, n, m)\n    void *q;\n    unsigned n, m;\n{\n    q = Z_NULL;\n    return calloc(n, m);\n}\n\nvoid myfree(q, p)\n    void *q, *p;\n{\n    q = Z_NULL;\n    free(p);\n}\n\ntypedef struct gzFile_s {\n    FILE *file;\n    int write;\n    int err;\n    char *msg;\n    z_stream strm;\n} *gzFile;\n\ngzFile gzopen _Z_OF((const char *, const char *));\ngzFile gzdopen _Z_OF((int, const char *));\ngzFile gz_open _Z_OF((const char *, int, const char *));\n\ngzFile gzopen(path, mode)\nconst char *path;\nconst char *mode;\n{\n    return gz_open(path, -1, mode);\n}\n\ngzFile gzdopen(fd, mode)\nint fd;\nconst char *mode;\n{\n    return gz_open(NULL, fd, mode);\n}\n\ngzFile gz_open(const char *path, int fd, const char *mode) {\n    gzFile gz;\n    int ret;\n\n    gz = malloc(sizeof(struct gzFile_s));\n    if (gz == NULL)\n        return NULL;\n    gz->write = strchr(mode, 'w') != NULL;\n    gz->strm.zalloc = myalloc;\n    gz->strm.zfree = myfree;\n    gz->strm.opaque = Z_NULL;\n    if (gz->write)\n        ret = deflateInit2(&(gz->strm), -1, 8, 15 + 16, 8, 0);\n    else {\n        gz->strm.next_in = 0;\n        gz->strm.avail_in = Z_NULL;\n        ret = inflateInit2(&(gz->strm), 15 + 16);\n    }\n    if (ret != Z_OK) {\n        free(gz);\n        return NULL;\n    }\n    gz->file = path == NULL ? fdopen(fd, gz->write ? \"wb\" : \"rb\") :\n                              fopen(path, gz->write ? \"wb\" : \"rb\");\n    if (gz->file == NULL) {\n        gz->write ? deflateEnd(&(gz->strm)) : inflateEnd(&(gz->strm));\n        free(gz);\n        return NULL;\n    }\n    gz->err = 0;\n    gz->msg = \"\";\n    return gz;\n}\n\nint gzwrite _Z_OF((gzFile, const void *, unsigned));\n\nint gzwrite(gzFile gz, const void *buf, unsigned len) {\n    z_stream *strm;\n    unsigned char out[BUFLEN] = { 0 };\n\n    if (gz == NULL || !gz->write)\n        return 0;\n    strm = &(gz->strm);\n    strm->next_in = (void *)buf;\n    strm->avail_in = len;\n    do {\n        strm->next_out = out;\n        strm->avail_out = BUFLEN;\n        (void)deflate(strm, Z_NO_FLUSH);\n        fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);\n    } while (strm->avail_out == 0);\n    return len;\n}\n\nint gzread _Z_OF((gzFile, void *, unsigned));\n\nint gzread(gzFile gz, void *buf, unsigned len) {\n    int ret;\n    unsigned got;\n    unsigned char in[1];\n    z_stream *strm;\n\n    if (gz == NULL || gz->write)\n        return 0;\n    if (gz->err)\n        return 0;\n    strm = &(gz->strm);\n    strm->next_out = (void *)buf;\n    strm->avail_out = len;\n    do {\n        got = fread(in, 1, 1, gz->file);\n        if (got == 0)\n            break;\n        strm->next_in = in;\n        strm->avail_in = 1;\n        ret = inflate(strm, Z_NO_FLUSH);\n        if (ret == Z_DATA_ERROR) {\n            gz->err = Z_DATA_ERROR;\n            gz->msg = strm->msg;\n            return 0;\n        }\n        if (ret == Z_STREAM_END)\n            inflateReset(strm);\n    } while (strm->avail_out);\n    return len - strm->avail_out;\n}\n\nint gzclose _Z_OF((gzFile));\n\nint gzclose(gzFile gz) {\n    z_stream *strm;\n    unsigned char out[BUFLEN] = { 0 };\n\n    if (gz == NULL)\n        return Z_STREAM_ERROR;\n    strm = &(gz->strm);\n    if (gz->write) {\n        strm->next_in = Z_NULL;\n        strm->avail_in = 0;\n        do {\n            strm->next_out = out;\n            strm->avail_out = BUFLEN;\n            (void)deflate(strm, Z_FINISH);\n            fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);\n        } while (strm->avail_out == 0);\n        deflateEnd(strm);\n    }\n    else\n        inflateEnd(strm);\n    fclose(gz->file);\n    free(gz);\n    return Z_OK;\n}\n\nconst char *gzerror _Z_OF((gzFile, int *));\n\nconst char *gzerror(gzFile gz, int *err)\n{\n    *err = gz->err;\n    return gz->msg;\n}\n\n#endif\n\nchar *prog;\n\nvoid error            _Z_OF((const char *msg));\nvoid gz_compress      _Z_OF((FILE   *in, gzFile out));\n#ifdef USE_MMAP\nint  gz_compress_mmap _Z_OF((FILE   *in, gzFile out));\n#endif\nvoid gz_uncompress    _Z_OF((gzFile in, FILE   *out));\nvoid file_compress    _Z_OF((char  *file, char *mode));\nvoid file_uncompress  _Z_OF((char  *file));\nint  main             _Z_OF((int argc, char *argv[]));\n\n/* ===========================================================================\n * Display error message and exit\n */\nvoid error(const char *msg)\n{\n    fprintf(stderr, \"%s: %s\\n\", prog, msg);\n    exit(1);\n}\n\n/* ===========================================================================\n * Compress input to output then close both files.\n */\n\nvoid gz_compress(FILE *in, gzFile out)\n{\n    local char buf[BUFLEN];\n    int len;\n    int err;\n\n#ifdef USE_MMAP\n    /* Try first compressing with mmap. If mmap fails (minigzip used in a\n     * pipe), use the normal fread loop.\n     */\n    if (gz_compress_mmap(in, out) == Z_OK) return;\n#endif\n    for (;;) {\n        len = (int)fread(buf, 1, sizeof(buf), in);\n        if (ferror(in)) {\n            perror(\"fread\");\n            exit(1);\n        }\n        if (len == 0) break;\n\n        if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));\n    }\n    fclose(in);\n    if (gzclose(out) != Z_OK) error(\"failed gzclose\");\n}\n\n#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */\n\n/* Try compressing the input file at once using mmap. Return Z_OK if\n * if success, Z_ERRNO otherwise.\n */\nint gz_compress_mmap(FILE *in, gzFile out) {\n    int len;\n    int err;\n    int ifd = fileno(in);\n    caddr_t buf;    /* mmap'ed buffer for the entire input file */\n    off_t buf_len;  /* length of the input file */\n    struct stat sb;\n\n    /* Determine the size of the file, needed for mmap: */\n    if (fstat(ifd, &sb) < 0) return Z_ERRNO;\n    buf_len = sb.st_size;\n    if (buf_len <= 0) return Z_ERRNO;\n\n    /* Now do the actual mmap: */\n    buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);\n    if (buf == (caddr_t)(-1)) return Z_ERRNO;\n\n    /* Compress the whole file at once: */\n    len = gzwrite(out, (char *)buf, (unsigned)buf_len);\n\n    if (len != (int)buf_len) error(gzerror(out, &err));\n\n    munmap(buf, buf_len);\n    fclose(in);\n    if (gzclose(out) != Z_OK) error(\"failed gzclose\");\n    return Z_OK;\n}\n#endif /* USE_MMAP */\n\n/* ===========================================================================\n * Uncompress input to output then close both files.\n */\nvoid gz_uncompress(gzFile in, FILE *out) {\n    local char buf[BUFLEN];\n    int len;\n    int err;\n\n    for (;;) {\n        len = gzread(in, buf, sizeof(buf));\n        if (len < 0) error (gzerror(in, &err));\n        if (len == 0) break;\n\n        if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {\n            error(\"failed fwrite\");\n        }\n    }\n    if (fclose(out)) error(\"failed fclose\");\n\n    if (gzclose(in) != Z_OK) error(\"failed gzclose\");\n}\n\n\n/* ===========================================================================\n * Compress the given file: create a corresponding .gz file and remove the\n * original.\n */\nvoid file_compress(char *file, char *mode) {\n    local char outfile[MAX_NAME_LEN];\n    FILE  *in;\n    gzFile out;\n\n    if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) {\n        fprintf(stderr, \"%s: filename too long\\n\", prog);\n        exit(1);\n    }\n\n    strcpy(outfile, file);\n    strcat(outfile, GZ_SUFFIX);\n\n    in = fopen(file, \"rb\");\n    if (in == NULL) {\n        perror(file);\n        exit(1);\n    }\n    out = gzopen(outfile, mode);\n    if (out == NULL) {\n        fprintf(stderr, \"%s: can't gzopen %s\\n\", prog, outfile);\n        exit(1);\n    }\n    gz_compress(in, out);\n\n    unlink(file);\n}\n\n\n/* ===========================================================================\n * Uncompress the given file and remove the original.\n */\nvoid file_uncompress(char *file) {\n    local char buf[MAX_NAME_LEN];\n    char *infile, *outfile;\n    FILE  *out;\n    gzFile in;\n    size_t len = strlen(file);\n\n    if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) {\n        fprintf(stderr, \"%s: filename too long\\n\", prog);\n        exit(1);\n    }\n\n    strcpy(buf, file);\n\n    if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {\n        infile = file;\n        outfile = buf;\n        outfile[len-3] = '\\0';\n    } else {\n        outfile = file;\n        infile = buf;\n        strcat(infile, GZ_SUFFIX);\n    }\n    in = gzopen(infile, \"rb\");\n    if (in == NULL) {\n        fprintf(stderr, \"%s: can't gzopen %s\\n\", prog, infile);\n        exit(1);\n    }\n    out = fopen(outfile, \"wb\");\n    if (out == NULL) {\n        perror(file);\n        exit(1);\n    }\n\n    gz_uncompress(in, out);\n\n    unlink(infile);\n}\n\n\n/* ===========================================================================\n * Usage:  minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...]\n *   -c : write to standard output\n *   -d : decompress\n *   -f : compress with Z_FILTERED\n *   -h : compress with Z_HUFFMAN_ONLY\n *   -r : compress with Z_RLE\n *   -1 to -9 : compression level\n */\n\nint main(int argc, char *argv[]) {\n    int copyout = 0;\n    int uncompr = 0;\n    gzFile file;\n    char *bname, outmode[20];\n\n    strcpy(outmode, \"wb6 \");\n\n    prog = argv[0];\n    bname = strrchr(argv[0], '/');\n    if (bname)\n      bname++;\n    else\n      bname = argv[0];\n    argc--, argv++;\n\n    if (!strcmp(bname, \"gunzip\"))\n      uncompr = 1;\n    else if (!strcmp(bname, \"zcat\"))\n      copyout = uncompr = 1;\n\n    while (argc > 0) {\n      if (strcmp(*argv, \"-c\") == 0)\n        copyout = 1;\n      else if (strcmp(*argv, \"-d\") == 0)\n        uncompr = 1;\n      else if (strcmp(*argv, \"-f\") == 0)\n        outmode[3] = 'f';\n      else if (strcmp(*argv, \"-h\") == 0)\n        outmode[3] = 'h';\n      else if (strcmp(*argv, \"-r\") == 0)\n        outmode[3] = 'R';\n      else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&\n               (*argv)[2] == 0)\n        outmode[2] = (*argv)[1];\n      else\n        break;\n      argc--, argv++;\n    }\n    if (outmode[3] == ' ')\n        outmode[3] = 0;\n    if (argc == 0) {\n        SET_BINARY_MODE(stdin);\n        SET_BINARY_MODE(stdout);\n        if (uncompr) {\n            file = gzdopen(fileno(stdin), \"rb\");\n            if (file == NULL) error(\"can't gzdopen stdin\");\n            gz_uncompress(file, stdout);\n        } else {\n            file = gzdopen(fileno(stdout), outmode);\n            if (file == NULL) error(\"can't gzdopen stdout\");\n            gz_compress(stdin, file);\n        }\n    } else {\n        if (copyout) {\n            SET_BINARY_MODE(stdout);\n        }\n        do {\n            if (uncompr) {\n                if (copyout) {\n                    file = gzopen(*argv, \"rb\");\n                    if (file == NULL)\n                        fprintf(stderr, \"%s: can't gzopen %s\\n\", prog, *argv);\n                    else\n                        gz_uncompress(file, stdout);\n                } else {\n                    file_uncompress(*argv);\n                }\n            } else {\n                if (copyout) {\n                    FILE * in = fopen(*argv, \"rb\");\n\n                    if (in == NULL) {\n                        perror(*argv);\n                    } else {\n                        file = gzdopen(fileno(stdout), outmode);\n                        if (file == NULL) error(\"can't gzdopen stdout\");\n\n                        gz_compress(in, file);\n                    }\n\n                } else {\n                    file_compress(*argv, outmode);\n                }\n            }\n        } while (argv++, --argc);\n    }\n    return 0;\n}\n"
  },
  {
    "path": "zlibWrapper/examples/zwrapbench.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n */\n\n\n/* *************************************\n*  Includes\n***************************************/\n#include \"util.h\"        /* Compiler options, UTIL_GetFileSize, UTIL_sleep */\n#include <stdlib.h>      /* malloc, free */\n#include <string.h>      /* memset */\n#include <stdio.h>       /* fprintf, fopen, ftello64 */\n#include <time.h>        /* clock_t, clock, CLOCKS_PER_SEC */\n#include <ctype.h>       /* toupper */\n#include <errno.h>       /* errno */\n\n#include \"timefn.h\"      /* UTIL_time_t, UTIL_getTime, UTIL_clockSpanMicro, UTIL_waitForNextTick */\n#include \"mem.h\"\n#define ZSTD_STATIC_LINKING_ONLY\n#include \"zstd.h\"\n#include \"datagen.h\"     /* RDG_genBuffer */\n#include \"xxhash.h\"\n\n#include \"../zstd_zlibwrapper.h\"\n\n\n\n/*-************************************\n*  Tuning parameters\n**************************************/\n#ifndef ZSTDCLI_CLEVEL_DEFAULT\n#  define ZSTDCLI_CLEVEL_DEFAULT 3\n#endif\n\n\n/*-************************************\n*  Constants\n**************************************/\n#define COMPRESSOR_NAME \"Zstandard wrapper for zlib command line interface\"\n#ifndef ZSTD_VERSION\n#  define ZSTD_VERSION \"v\" ZSTD_VERSION_STRING\n#endif\n#define AUTHOR \"Yann Collet\"\n#define WELCOME_MESSAGE \"*** %s %i-bits %s, by %s ***\\n\", COMPRESSOR_NAME, (int)(sizeof(size_t)*8), ZSTD_VERSION, AUTHOR\n\n#ifndef ZSTD_GIT_COMMIT\n#  define ZSTD_GIT_COMMIT_STRING \"\"\n#else\n#  define ZSTD_GIT_COMMIT_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_GIT_COMMIT)\n#endif\n\n#define NBLOOPS               3\n#define TIMELOOP_MICROSEC     1*1000000ULL /* 1 second */\n#define ACTIVEPERIOD_MICROSEC 70*1000000ULL /* 70 seconds */\n#define COOLPERIOD_SEC        10\n\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\nstatic const size_t maxMemory = (sizeof(size_t)==4)  ?  (2 GB - 64 MB) : (size_t)(1ULL << ((sizeof(size_t)*8)-31));\n\nstatic U32 g_compressibilityDefault = 50;\n\n\n/* *************************************\n*  console display\n***************************************/\n#define DEFAULT_DISPLAY_LEVEL 2\n#define DISPLAY(...)         fprintf(displayOut, __VA_ARGS__)\n#define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); }\nstatic unsigned g_displayLevel = DEFAULT_DISPLAY_LEVEL;   /* 0 : no display;   1: errors;   2 : + result + interaction + warnings;   3 : + progression;   4 : + information */\nstatic FILE* displayOut;\n\n#define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \\\n            if ((clock() - g_time > refreshRate) || (g_displayLevel>=4)) \\\n            { g_time = clock(); DISPLAY(__VA_ARGS__); \\\n            if (g_displayLevel>=4) fflush(displayOut); } }\nstatic const clock_t refreshRate = CLOCKS_PER_SEC * 15 / 100;\nstatic clock_t g_time = 0;\n\n\n/* *************************************\n*  Exceptions\n***************************************/\n#ifndef DEBUG\n#  define DEBUG 0\n#endif\n#define DEBUGOUTPUT(...) { if (DEBUG) DISPLAY(__VA_ARGS__); }\n#define EXM_THROW(error, ...)                                             \\\n{                                                                         \\\n    DEBUGOUTPUT(\"Error defined at %s, line %i : \\n\", __FILE__, __LINE__); \\\n    DISPLAYLEVEL(1, \"Error %i : \", error);                                \\\n    DISPLAYLEVEL(1, __VA_ARGS__);                                         \\\n    DISPLAYLEVEL(1, \"\\n\");                                                \\\n    exit(error);                                                          \\\n}\n\n\n/* *************************************\n*  Benchmark Parameters\n***************************************/\nstatic unsigned g_nbIterations = NBLOOPS;\nstatic size_t g_blockSize = 0;\nint g_additionalParam = 0;\n\nstatic void BMK_setNotificationLevel(unsigned level) { g_displayLevel=level; }\n\nstatic void BMK_setAdditionalParam(int additionalParam) { g_additionalParam=additionalParam; }\n\nstatic void BMK_SetNbIterations(unsigned nbLoops)\n{\n    g_nbIterations = nbLoops;\n    DISPLAYLEVEL(3, \"- test >= %u seconds per compression / decompression -\\n\", g_nbIterations);\n}\n\nstatic void BMK_SetBlockSize(size_t blockSize)\n{\n    g_blockSize = blockSize;\n    DISPLAYLEVEL(2, \"using blocks of size %u KB \\n\", (unsigned)(blockSize>>10));\n}\n\n\n/* ********************************************************\n*  Bench functions\n**********************************************************/\n#undef MIN\n#undef MAX\n#define MIN(a,b) ((a)<(b) ? (a) : (b))\n#define MAX(a,b) ((a)>(b) ? (a) : (b))\n\ntypedef struct\n{\n    z_const char* srcPtr;\n    size_t srcSize;\n    char*  cPtr;\n    size_t cRoom;\n    size_t cSize;\n    char*  resPtr;\n    size_t resSize;\n} blockParam_t;\n\ntypedef enum { BMK_ZSTD, BMK_ZSTD_STREAM, BMK_ZLIB, BMK_ZWRAP_ZLIB, BMK_ZWRAP_ZSTD, BMK_ZLIB_REUSE, BMK_ZWRAP_ZLIB_REUSE, BMK_ZWRAP_ZSTD_REUSE } BMK_compressor;\n\n\nstatic int BMK_benchMem(z_const void* srcBuffer, size_t srcSize,\n                        const char* displayName, int cLevel,\n                        const size_t* fileSizes, U32 nbFiles,\n                        const void* dictBuffer, size_t dictBufferSize, BMK_compressor compressor)\n{\n    size_t const blockSize = (g_blockSize>=32 ? g_blockSize : srcSize) + (!srcSize) /* avoid div by 0 */ ;\n    size_t const avgSize = MIN(g_blockSize, (srcSize / nbFiles));\n    U32 const maxNbBlocks = (U32) ((srcSize + (blockSize-1)) / blockSize) + nbFiles;\n    blockParam_t* const blockTable = (blockParam_t*) malloc(maxNbBlocks * sizeof(blockParam_t));\n    size_t const maxCompressedSize = ZSTD_compressBound(srcSize) + (maxNbBlocks * 1024);   /* add some room for safety */\n    void* const compressedBuffer = malloc(maxCompressedSize);\n    void* const resultBuffer = malloc(srcSize);\n    ZSTD_CCtx* const ctx = ZSTD_createCCtx();\n    ZSTD_DCtx* const dctx = ZSTD_createDCtx();\n    U32 nbBlocks;\n\n    /* checks */\n    if (!compressedBuffer || !resultBuffer || !blockTable || !ctx || !dctx)\n        EXM_THROW(31, \"allocation error : not enough memory\");\n\n    /* init */\n    if (strlen(displayName)>17) displayName += strlen(displayName)-17;   /* can only display 17 characters */\n\n    /* Init blockTable data */\n    {   z_const char* srcPtr = (z_const char*)srcBuffer;\n        char* cPtr = (char*)compressedBuffer;\n        char* resPtr = (char*)resultBuffer;\n        U32 fileNb;\n        for (nbBlocks=0, fileNb=0; fileNb<nbFiles; fileNb++) {\n            size_t remaining = fileSizes[fileNb];\n            U32 const nbBlocksforThisFile = (U32)((remaining + (blockSize-1)) / blockSize);\n            U32 const blockEnd = nbBlocks + nbBlocksforThisFile;\n            for ( ; nbBlocks<blockEnd; nbBlocks++) {\n                size_t const thisBlockSize = MIN(remaining, blockSize);\n                blockTable[nbBlocks].srcPtr = srcPtr;\n                blockTable[nbBlocks].cPtr = cPtr;\n                blockTable[nbBlocks].resPtr = resPtr;\n                blockTable[nbBlocks].srcSize = thisBlockSize;\n                blockTable[nbBlocks].cRoom = ZSTD_compressBound(thisBlockSize);\n                srcPtr += thisBlockSize;\n                cPtr += blockTable[nbBlocks].cRoom;\n                resPtr += thisBlockSize;\n                remaining -= thisBlockSize;\n    }   }   }\n\n    /* warming up memory */\n    RDG_genBuffer(compressedBuffer, maxCompressedSize, 0.10, 0.50, 1);\n\n    /* Bench */\n    {   U64 fastestC = (U64)(-1LL), fastestD = (U64)(-1LL);\n        U64 const crcOrig = XXH64(srcBuffer, srcSize, 0);\n        UTIL_time_t coolTime;\n        U64 const maxTime = (g_nbIterations * TIMELOOP_MICROSEC) + 100;\n        U64 totalCTime=0, totalDTime=0;\n        U32 cCompleted=0, dCompleted=0;\n#       define NB_MARKS 4\n        const char* const marks[NB_MARKS] = { \" |\", \" /\", \" =\",  \"\\\\\" };\n        U32 markNb = 0;\n        size_t cSize = 0;\n        double ratio = 0.;\n\n        coolTime = UTIL_getTime();\n        DISPLAYLEVEL(2, \"\\r%79s\\r\", \"\");\n        while (!cCompleted | !dCompleted) {\n            UTIL_time_t clockStart;\n            U64 clockLoop = g_nbIterations ? TIMELOOP_MICROSEC : 1;\n\n            /* overheat protection */\n            if (UTIL_clockSpanMicro(coolTime) > ACTIVEPERIOD_MICROSEC) {\n                DISPLAYLEVEL(2, \"\\rcooling down ...    \\r\");\n                UTIL_sleep(COOLPERIOD_SEC);\n                coolTime = UTIL_getTime();\n            }\n\n            /* Compression */\n            DISPLAYLEVEL(2, \"%2s-%-17.17s :%10u ->\\r\", marks[markNb], displayName, (unsigned)srcSize);\n            if (!cCompleted) memset(compressedBuffer, 0xE5, maxCompressedSize);  /* warm up and erase result buffer */\n\n            UTIL_sleepMilli(1);  /* give processor time to other processes */\n            UTIL_waitForNextTick();\n            clockStart = UTIL_getTime();\n\n            if (!cCompleted) {   /* still some time to do compression tests */\n                U32 nbLoops = 0;\n                if (compressor == BMK_ZSTD) {\n                    ZSTD_parameters const zparams = ZSTD_getParams(cLevel, avgSize, dictBufferSize);\n                    ZSTD_customMem const cmem = { NULL, NULL, NULL };\n                    ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictBufferSize, ZSTD_dlm_byRef, ZSTD_dct_auto, zparams.cParams, cmem);\n                    if (cdict==NULL) EXM_THROW(1, \"ZSTD_createCDict_advanced() allocation failure\");\n\n                    do {\n                        U32 blockNb;\n                        size_t rSize;\n                        for (blockNb=0; blockNb<nbBlocks; blockNb++) {\n                            if (dictBufferSize) {\n                                rSize = ZSTD_compress_usingCDict(ctx,\n                                                blockTable[blockNb].cPtr,  blockTable[blockNb].cRoom,\n                                                blockTable[blockNb].srcPtr,blockTable[blockNb].srcSize,\n                                                cdict);\n                            } else {\n                                rSize = ZSTD_compressCCtx (ctx,\n                                                blockTable[blockNb].cPtr,  blockTable[blockNb].cRoom,\n                                                blockTable[blockNb].srcPtr,blockTable[blockNb].srcSize, cLevel);\n                            }\n                            if (ZSTD_isError(rSize)) EXM_THROW(1, \"ZSTD_compress_usingCDict() failed : %s\", ZSTD_getErrorName(rSize));\n                            blockTable[blockNb].cSize = rSize;\n                        }\n                        nbLoops++;\n                    } while (UTIL_clockSpanMicro(clockStart) < clockLoop);\n                    ZSTD_freeCDict(cdict);\n                } else if (compressor == BMK_ZSTD_STREAM) {\n                    ZSTD_parameters const zparams = ZSTD_getParams(cLevel, avgSize, dictBufferSize);\n                    ZSTD_inBuffer inBuffer;\n                    ZSTD_outBuffer outBuffer;\n                    ZSTD_CStream* zbc = ZSTD_createCStream();\n                    size_t rSize;\n                    ZSTD_CCtx_params* cctxParams = ZSTD_createCCtxParams();\n\n                    if (!cctxParams) EXM_THROW(1, \"ZSTD_createCCtxParams() allocation failure\");\n                    if (zbc == NULL) EXM_THROW(1, \"ZSTD_createCStream() allocation failure\");\n\n                    {   int initErr = 0;\n                        initErr |= ZSTD_isError(ZSTD_CCtx_reset(zbc, ZSTD_reset_session_only));\n                        initErr |= ZSTD_isError(ZSTD_CCtxParams_init_advanced(cctxParams, zparams));\n                        initErr |= ZSTD_isError(ZSTD_CCtx_setParametersUsingCCtxParams(zbc, cctxParams));\n                        initErr |= ZSTD_isError(ZSTD_CCtx_setPledgedSrcSize(zbc, avgSize));\n                        initErr |= ZSTD_isError(ZSTD_CCtx_loadDictionary(zbc, dictBuffer, dictBufferSize));\n\n                        ZSTD_freeCCtxParams(cctxParams);\n                        if (initErr) EXM_THROW(1, \"CCtx init failed!\");\n                    }\n\n                    do {\n                        U32 blockNb;\n                        for (blockNb=0; blockNb<nbBlocks; blockNb++) {\n                            rSize = ZSTD_CCtx_reset(zbc, ZSTD_reset_session_only);\n                            if (ZSTD_isError(rSize)) EXM_THROW(1, \"ZSTD_CCtx_reset() failed : %s\", ZSTD_getErrorName(rSize));\n                            rSize = ZSTD_CCtx_setPledgedSrcSize(zbc, blockTable[blockNb].srcSize);\n                            if (ZSTD_isError(rSize)) EXM_THROW(1, \"ZSTD_CCtx_setPledgedSrcSize() failed : %s\", ZSTD_getErrorName(rSize));\n                            inBuffer.src = blockTable[blockNb].srcPtr;\n                            inBuffer.size = blockTable[blockNb].srcSize;\n                            inBuffer.pos = 0;\n                            outBuffer.dst = blockTable[blockNb].cPtr;\n                            outBuffer.size = blockTable[blockNb].cRoom;\n                            outBuffer.pos = 0;\n                            rSize = ZSTD_compressStream(zbc, &outBuffer, &inBuffer);\n                            if (ZSTD_isError(rSize)) EXM_THROW(1, \"ZSTD_compressStream() failed : %s\", ZSTD_getErrorName(rSize));\n                            rSize = ZSTD_endStream(zbc, &outBuffer);\n                            if (ZSTD_isError(rSize)) EXM_THROW(1, \"ZSTD_endStream() failed : %s\", ZSTD_getErrorName(rSize));\n                            blockTable[blockNb].cSize = outBuffer.pos;\n                        }\n                        nbLoops++;\n                    } while (UTIL_clockSpanMicro(clockStart) < clockLoop);\n                    ZSTD_freeCStream(zbc);\n                } else if (compressor == BMK_ZWRAP_ZLIB_REUSE || compressor == BMK_ZWRAP_ZSTD_REUSE || compressor == BMK_ZLIB_REUSE) {\n                    z_stream def;\n                    int ret;\n                    int useSetDict = (dictBuffer != NULL);\n                    if (compressor == BMK_ZLIB_REUSE || compressor == BMK_ZWRAP_ZLIB_REUSE) ZWRAP_useZSTDcompression(0);\n                    else ZWRAP_useZSTDcompression(1);\n                    def.zalloc = Z_NULL;\n                    def.zfree = Z_NULL;\n                    def.opaque = Z_NULL;\n                    ret = deflateInit(&def, cLevel);\n                    if (ret != Z_OK) EXM_THROW(1, \"deflateInit failure\");\n                 /*   if (ZWRAP_isUsingZSTDcompression()) {\n                        ret = ZWRAP_setPledgedSrcSize(&def, avgSize);\n                        if (ret != Z_OK) EXM_THROW(1, \"ZWRAP_setPledgedSrcSize failure\");\n                    } */\n                    do {\n                        U32 blockNb;\n                        for (blockNb=0; blockNb<nbBlocks; blockNb++) {\n                            if (ZWRAP_isUsingZSTDcompression())\n                                ret = ZWRAP_deflateReset_keepDict(&def); /* reuse dictionary to make compression faster */\n                            else\n                                ret = deflateReset(&def);\n                            if (ret != Z_OK) EXM_THROW(1, \"deflateReset failure\");\n                            if (useSetDict) {\n                                ret = deflateSetDictionary(&def, (const z_Bytef*)dictBuffer, dictBufferSize);\n                                if (ret != Z_OK) EXM_THROW(1, \"deflateSetDictionary failure\");\n                                if (ZWRAP_isUsingZSTDcompression()) useSetDict = 0; /* zstd doesn't require deflateSetDictionary after ZWRAP_deflateReset_keepDict */\n                            }\n                            def.next_in = (z_const z_Bytef*) blockTable[blockNb].srcPtr;\n                            def.avail_in = (uInt)blockTable[blockNb].srcSize;\n                            def.total_in = 0;\n                            def.next_out = (z_Bytef*) blockTable[blockNb].cPtr;\n                            def.avail_out = (uInt)blockTable[blockNb].cRoom;\n                            def.total_out = 0;\n                            ret = deflate(&def, Z_FINISH);\n                            if (ret != Z_STREAM_END) EXM_THROW(1, \"deflate failure ret=%d srcSize=%d\" , ret, (int)blockTable[blockNb].srcSize);\n                            blockTable[blockNb].cSize = def.total_out;\n                        }\n                        nbLoops++;\n                    } while (UTIL_clockSpanMicro(clockStart) < clockLoop);\n                    ret = deflateEnd(&def);\n                    if (ret != Z_OK) EXM_THROW(1, \"deflateEnd failure\");\n                } else {\n                    z_stream def;\n                    if (compressor == BMK_ZLIB || compressor == BMK_ZWRAP_ZLIB) ZWRAP_useZSTDcompression(0);\n                    else ZWRAP_useZSTDcompression(1);\n                    do {\n                        U32 blockNb;\n                        for (blockNb=0; blockNb<nbBlocks; blockNb++) {\n                            int ret;\n                            def.zalloc = Z_NULL;\n                            def.zfree = Z_NULL;\n                            def.opaque = Z_NULL;\n                            ret = deflateInit(&def, cLevel);\n                            if (ret != Z_OK) EXM_THROW(1, \"deflateInit failure\");\n                            if (dictBuffer) {\n                                ret = deflateSetDictionary(&def, (const z_Bytef*)dictBuffer, dictBufferSize);\n                                if (ret != Z_OK) EXM_THROW(1, \"deflateSetDictionary failure\");\n                            }\n                            def.next_in = (z_const z_Bytef*) blockTable[blockNb].srcPtr;\n                            def.avail_in = (uInt)blockTable[blockNb].srcSize;\n                            def.total_in = 0;\n                            def.next_out = (z_Bytef*) blockTable[blockNb].cPtr;\n                            def.avail_out = (uInt)blockTable[blockNb].cRoom;\n                            def.total_out = 0;\n                            ret = deflate(&def, Z_FINISH);\n                            if (ret != Z_STREAM_END) EXM_THROW(1, \"deflate failure\");\n                            ret = deflateEnd(&def);\n                            if (ret != Z_OK) EXM_THROW(1, \"deflateEnd failure\");\n                            blockTable[blockNb].cSize = def.total_out;\n                        }\n                        nbLoops++;\n                    } while (UTIL_clockSpanMicro(clockStart) < clockLoop);\n                }\n                {   U64 const clockSpan = UTIL_clockSpanMicro(clockStart);\n                    if (clockSpan < fastestC*nbLoops) fastestC = clockSpan / nbLoops;\n                    totalCTime += clockSpan;\n                    cCompleted = totalCTime>maxTime;\n            }   }\n\n            cSize = 0;\n            { U32 blockNb; for (blockNb=0; blockNb<nbBlocks; blockNb++) cSize += blockTable[blockNb].cSize; }\n            ratio = (double)srcSize / (double)cSize;\n            markNb = (markNb+1) % NB_MARKS;\n            DISPLAYLEVEL(2, \"%2s-%-17.17s :%10u ->%10u (%5.3f),%6.1f MB/s\\r\",\n                    marks[markNb], displayName, (unsigned)srcSize, (unsigned)cSize, ratio,\n                    (double)srcSize / (double)fastestC );\n\n            (void)fastestD; (void)crcOrig;   /*  unused when decompression disabled */\n#if 1\n            /* Decompression */\n            if (!dCompleted) memset(resultBuffer, 0xD6, srcSize);  /* warm result buffer */\n\n            UTIL_sleepMilli(1); /* give processor time to other processes */\n            UTIL_waitForNextTick();\n            clockStart = UTIL_getTime();\n\n            if (!dCompleted) {\n                U32 nbLoops = 0;\n                if (compressor == BMK_ZSTD) {\n                    ZSTD_DDict* ddict = ZSTD_createDDict(dictBuffer, dictBufferSize);\n                    if (!ddict) EXM_THROW(2, \"ZSTD_createDDict() allocation failure\");\n                    do {\n                        unsigned blockNb;\n                        for (blockNb=0; blockNb<nbBlocks; blockNb++) {\n                            size_t const regenSize = ZSTD_decompress_usingDDict(dctx,\n                                blockTable[blockNb].resPtr, blockTable[blockNb].srcSize,\n                                blockTable[blockNb].cPtr, blockTable[blockNb].cSize,\n                                ddict);\n                            if (ZSTD_isError(regenSize)) {\n                                DISPLAY(\"ZSTD_decompress_usingDDict() failed on block %u : %s  \\n\",\n                                          blockNb, ZSTD_getErrorName(regenSize));\n                                clockLoop = 0;   /* force immediate test end */\n                                break;\n                            }\n                            blockTable[blockNb].resSize = regenSize;\n                        }\n                        nbLoops++;\n                    } while (UTIL_clockSpanMicro(clockStart) < clockLoop);\n                    ZSTD_freeDDict(ddict);\n                } else if (compressor == BMK_ZSTD_STREAM) {\n                    ZSTD_inBuffer inBuffer;\n                    ZSTD_outBuffer outBuffer;\n                    ZSTD_DStream* zbd = ZSTD_createDStream();\n                    size_t rSize;\n                    if (zbd == NULL) EXM_THROW(1, \"ZSTD_createDStream() allocation failure\");\n                    rSize = ZSTD_DCtx_reset(zbd, ZSTD_reset_session_only);\n                    if (ZSTD_isError(rSize)) EXM_THROW(1, \"ZSTD_DCtx_reset() failed : %s\", ZSTD_getErrorName(rSize));\n                    rSize = ZSTD_DCtx_loadDictionary(zbd, dictBuffer, dictBufferSize);\n                    if (ZSTD_isError(rSize)) EXM_THROW(1, \"ZSTD_DCtx_loadDictionary() failed : %s\", ZSTD_getErrorName(rSize));\n                    do {\n                        U32 blockNb;\n                        for (blockNb=0; blockNb<nbBlocks; blockNb++) {\n                            rSize = ZSTD_DCtx_reset(zbd, ZSTD_reset_session_only);\n                            if (ZSTD_isError(rSize)) EXM_THROW(1, \"ZSTD_DCtx_reset() failed : %s\", ZSTD_getErrorName(rSize));\n                            inBuffer.src = blockTable[blockNb].cPtr;\n                            inBuffer.size = blockTable[blockNb].cSize;\n                            inBuffer.pos = 0;\n                            outBuffer.dst = blockTable[blockNb].resPtr;\n                            outBuffer.size = blockTable[blockNb].srcSize;\n                            outBuffer.pos = 0;\n                            rSize = ZSTD_decompressStream(zbd, &outBuffer, &inBuffer);\n                            if (ZSTD_isError(rSize)) EXM_THROW(1, \"ZSTD_decompressStream() failed : %s\", ZSTD_getErrorName(rSize));\n                            blockTable[blockNb].resSize = outBuffer.pos;\n                        }\n                        nbLoops++;\n                    } while (UTIL_clockSpanMicro(clockStart) < clockLoop);\n                    ZSTD_freeDStream(zbd);\n                } else if (compressor == BMK_ZWRAP_ZLIB_REUSE || compressor == BMK_ZWRAP_ZSTD_REUSE || compressor == BMK_ZLIB_REUSE) {\n                    z_stream inf;\n                    int ret;\n                    if (compressor == BMK_ZLIB_REUSE) ZWRAP_setDecompressionType(ZWRAP_FORCE_ZLIB);\n                    else ZWRAP_setDecompressionType(ZWRAP_AUTO);\n                    inf.zalloc = Z_NULL;\n                    inf.zfree = Z_NULL;\n                    inf.opaque = Z_NULL;\n                    ret = inflateInit(&inf);\n                    if (ret != Z_OK) EXM_THROW(1, \"inflateInit failure\");\n                    do {\n                        U32 blockNb;\n                        for (blockNb=0; blockNb<nbBlocks; blockNb++) {\n                            if (ZWRAP_isUsingZSTDdecompression(&inf))\n                                ret = ZWRAP_inflateReset_keepDict(&inf); /* reuse dictionary to make decompression faster; inflate will return Z_NEED_DICT only for the first time */\n                            else\n                                ret = inflateReset(&inf);\n                            if (ret != Z_OK) EXM_THROW(1, \"inflateReset failure\");\n                            inf.next_in = (z_const z_Bytef*) blockTable[blockNb].cPtr;\n                            inf.avail_in = (uInt)blockTable[blockNb].cSize;\n                            inf.total_in = 0;\n                            inf.next_out = (z_Bytef*) blockTable[blockNb].resPtr;\n                            inf.avail_out = (uInt)blockTable[blockNb].srcSize;\n                            inf.total_out = 0;\n                            ret = inflate(&inf, Z_FINISH);\n                            if (ret == Z_NEED_DICT) {\n                                ret = inflateSetDictionary(&inf, (const z_Bytef*)dictBuffer, dictBufferSize);\n                                if (ret != Z_OK) EXM_THROW(1, \"inflateSetDictionary failure\");\n                                ret = inflate(&inf, Z_FINISH);\n                            }\n                            if (ret != Z_STREAM_END) EXM_THROW(1, \"inflate failure\");\n                            blockTable[blockNb].resSize = inf.total_out;\n                        }\n                        nbLoops++;\n                    } while (UTIL_clockSpanMicro(clockStart) < clockLoop);\n                    ret = inflateEnd(&inf);\n                    if (ret != Z_OK) EXM_THROW(1, \"inflateEnd failure\");\n                } else {\n                    z_stream inf;\n                    if (compressor == BMK_ZLIB) ZWRAP_setDecompressionType(ZWRAP_FORCE_ZLIB);\n                    else ZWRAP_setDecompressionType(ZWRAP_AUTO);\n                    do {\n                        U32 blockNb;\n                        for (blockNb=0; blockNb<nbBlocks; blockNb++) {\n                            int ret;\n                            inf.zalloc = Z_NULL;\n                            inf.zfree = Z_NULL;\n                            inf.opaque = Z_NULL;\n                            ret = inflateInit(&inf);\n                            if (ret != Z_OK) EXM_THROW(1, \"inflateInit failure\");\n                            inf.next_in = (z_const z_Bytef*) blockTable[blockNb].cPtr;\n                            inf.avail_in = (uInt)blockTable[blockNb].cSize;\n                            inf.total_in = 0;\n                            inf.next_out = (z_Bytef*) blockTable[blockNb].resPtr;\n                            inf.avail_out = (uInt)blockTable[blockNb].srcSize;\n                            inf.total_out = 0;\n                            ret = inflate(&inf, Z_FINISH);\n                            if (ret == Z_NEED_DICT) {\n                                ret = inflateSetDictionary(&inf, (const z_Bytef*) dictBuffer, dictBufferSize);\n                                if (ret != Z_OK) EXM_THROW(1, \"inflateSetDictionary failure\");\n                                ret = inflate(&inf, Z_FINISH);\n                            }\n                            if (ret != Z_STREAM_END) EXM_THROW(1, \"inflate failure\");\n                            ret = inflateEnd(&inf);\n                            if (ret != Z_OK) EXM_THROW(1, \"inflateEnd failure\");\n                            blockTable[blockNb].resSize = inf.total_out;\n                        }\n                        nbLoops++;\n                    } while (UTIL_clockSpanMicro(clockStart) < clockLoop);\n                }\n                {   U64 const clockSpan = UTIL_clockSpanMicro(clockStart);\n                    if (clockSpan < fastestD*nbLoops) fastestD = clockSpan / nbLoops;\n                    totalDTime += clockSpan;\n                    dCompleted = totalDTime>maxTime;\n            }   }\n\n            markNb = (markNb+1) % NB_MARKS;\n            DISPLAYLEVEL(2, \"%2s-%-17.17s :%10u ->%10u (%5.3f),%6.1f MB/s ,%6.1f MB/s\\r\",\n                    marks[markNb], displayName, (unsigned)srcSize, (unsigned)cSize, ratio,\n                    (double)srcSize / (double)fastestC,\n                    (double)srcSize / (double)fastestD );\n\n            /* CRC Checking */\n            {   U64 const crcCheck = XXH64(resultBuffer, srcSize, 0);\n                if (crcOrig!=crcCheck) {\n                    size_t u;\n                    DISPLAY(\"!!! WARNING !!! %14s : Invalid Checksum : %x != %x   \\n\", displayName, (unsigned)crcOrig, (unsigned)crcCheck);\n                    for (u=0; u<srcSize; u++) {\n                        if (((const BYTE*)srcBuffer)[u] != ((const BYTE*)resultBuffer)[u]) {\n                            unsigned segNb, bNb, pos;\n                            size_t bacc = 0;\n                            DISPLAY(\"Decoding error at pos %u \", (unsigned)u);\n                            for (segNb = 0; segNb < nbBlocks; segNb++) {\n                                if (bacc + blockTable[segNb].srcSize > u) break;\n                                bacc += blockTable[segNb].srcSize;\n                            }\n                            pos = (U32)(u - bacc);\n                            bNb = pos / (128 KB);\n                            DISPLAY(\"(block %u, sub %u, pos %u) \\n\", segNb, bNb, pos);\n                            break;\n                        }\n                        if (u==srcSize-1) {  /* should never happen */\n                            DISPLAY(\"no difference detected\\n\");\n                    }   }\n                    break;\n            }   }   /* CRC Checking */\n#endif\n        }   /* for (testNb = 1; testNb <= (g_nbIterations + !g_nbIterations); testNb++) */\n\n        if (g_displayLevel == 1) {\n            double cSpeed = (double)srcSize / (double)fastestC;\n            double dSpeed = (double)srcSize / (double)fastestD;\n            if (g_additionalParam)\n                DISPLAY(\"-%-3i%11i (%5.3f) %6.2f MB/s %6.1f MB/s  %s (param=%d)\\n\", cLevel, (int)cSize, ratio, cSpeed, dSpeed, displayName, g_additionalParam);\n            else\n                DISPLAY(\"-%-3i%11i (%5.3f) %6.2f MB/s %6.1f MB/s  %s\\n\", cLevel, (int)cSize, ratio, cSpeed, dSpeed, displayName);\n        }\n        DISPLAYLEVEL(2, \"%2i#\\n\", cLevel);\n    }   /* Bench */\n\n    /* clean up */\n    free(blockTable);\n    free(compressedBuffer);\n    free(resultBuffer);\n    ZSTD_freeCCtx(ctx);\n    ZSTD_freeDCtx(dctx);\n    return 0;\n}\n\n\nstatic size_t BMK_findMaxMem(U64 requiredMem)\n{\n    size_t const step = 64 MB;\n    BYTE* testmem = NULL;\n\n    requiredMem = (((requiredMem >> 26) + 1) << 26);\n    requiredMem += step;\n    if (requiredMem > maxMemory) requiredMem = maxMemory;\n\n    do {\n        testmem = (BYTE*)malloc((size_t)requiredMem);\n        requiredMem -= step;\n    } while (!testmem && requiredMem);   /* do not allocate zero bytes */\n\n    free(testmem);\n    return (size_t)(requiredMem+1);  /* avoid zero */\n}\n\nstatic void BMK_benchCLevel(void* srcBuffer, size_t benchedSize,\n                            const char* displayName, int cLevel, int cLevelLast,\n                            const size_t* fileSizes, unsigned nbFiles,\n                            const void* dictBuffer, size_t dictBufferSize)\n{\n    int l;\n\n    const char* pch = strrchr(displayName, '\\\\'); /* Windows */\n    if (!pch) pch = strrchr(displayName, '/'); /* Linux */\n    if (pch) displayName = pch+1;\n\n    SET_REALTIME_PRIORITY;\n\n    if (g_displayLevel == 1 && !g_additionalParam)\n        DISPLAY(\"bench %s %s: input %u bytes, %u seconds, %u KB blocks\\n\",\n                ZSTD_VERSION_STRING, ZSTD_GIT_COMMIT_STRING,\n                (unsigned)benchedSize, g_nbIterations, (unsigned)(g_blockSize>>10));\n\n    if (cLevelLast < cLevel) cLevelLast = cLevel;\n\n    DISPLAY(\"benchmarking zstd %s (using ZSTD_CStream)\\n\", ZSTD_VERSION_STRING);\n    for (l=cLevel; l <= cLevelLast; l++) {\n        BMK_benchMem(srcBuffer, benchedSize,\n                     displayName, l,\n                     fileSizes, nbFiles,\n                     dictBuffer, dictBufferSize, BMK_ZSTD_STREAM);\n    }\n\n    DISPLAY(\"benchmarking zstd %s (using ZSTD_CCtx)\\n\", ZSTD_VERSION_STRING);\n    for (l=cLevel; l <= cLevelLast; l++) {\n        BMK_benchMem(srcBuffer, benchedSize,\n                     displayName, l,\n                     fileSizes, nbFiles,\n                     dictBuffer, dictBufferSize, BMK_ZSTD);\n    }\n\n    DISPLAY(\"benchmarking zstd %s (using zlibWrapper)\\n\", ZSTD_VERSION_STRING);\n    for (l=cLevel; l <= cLevelLast; l++) {\n        BMK_benchMem(srcBuffer, benchedSize,\n                     displayName, l,\n                     fileSizes, nbFiles,\n                     dictBuffer, dictBufferSize, BMK_ZWRAP_ZSTD_REUSE);\n    }\n\n    DISPLAY(\"benchmarking zstd %s (zlibWrapper not reusing a context)\\n\", ZSTD_VERSION_STRING);\n    for (l=cLevel; l <= cLevelLast; l++) {\n        BMK_benchMem(srcBuffer, benchedSize,\n                     displayName, l,\n                     fileSizes, nbFiles,\n                     dictBuffer, dictBufferSize, BMK_ZWRAP_ZSTD);\n    }\n\n\n    if (cLevelLast > Z_BEST_COMPRESSION) cLevelLast = Z_BEST_COMPRESSION;\n\n    DISPLAY(\"\\n\");\n    DISPLAY(\"benchmarking zlib %s\\n\", ZLIB_VERSION);\n    for (l=cLevel; l <= cLevelLast; l++) {\n        BMK_benchMem(srcBuffer, benchedSize,\n                     displayName, l,\n                     fileSizes, nbFiles,\n                     dictBuffer, dictBufferSize, BMK_ZLIB_REUSE);\n    }\n\n    DISPLAY(\"benchmarking zlib %s (zlib not reusing a context)\\n\", ZLIB_VERSION);\n    for (l=cLevel; l <= cLevelLast; l++) {\n        BMK_benchMem(srcBuffer, benchedSize,\n                     displayName, l,\n                     fileSizes, nbFiles,\n                     dictBuffer, dictBufferSize, BMK_ZLIB);\n    }\n\n    DISPLAY(\"benchmarking zlib %s (using zlibWrapper)\\n\", ZLIB_VERSION);\n    for (l=cLevel; l <= cLevelLast; l++) {\n        BMK_benchMem(srcBuffer, benchedSize,\n                     displayName, l,\n                     fileSizes, nbFiles,\n                     dictBuffer, dictBufferSize, BMK_ZWRAP_ZLIB_REUSE);\n    }\n\n    DISPLAY(\"benchmarking zlib %s (zlibWrapper not reusing a context)\\n\", ZLIB_VERSION);\n    for (l=cLevel; l <= cLevelLast; l++) {\n        BMK_benchMem(srcBuffer, benchedSize,\n                     displayName, l,\n                     fileSizes, nbFiles,\n                     dictBuffer, dictBufferSize, BMK_ZWRAP_ZLIB);\n    }\n}\n\n\n/*! BMK_loadFiles() :\n    Loads `buffer` with content of files listed within `fileNamesTable`.\n    At most, fills `buffer` entirely */\nstatic void BMK_loadFiles(void* buffer, size_t bufferSize,\n                          size_t* fileSizes,\n                          const char** fileNamesTable, unsigned nbFiles)\n{\n    size_t pos = 0, totalSize = 0;\n    unsigned n;\n    for (n=0; n<nbFiles; n++) {\n        FILE* f;\n        U64 fileSize = UTIL_getFileSize(fileNamesTable[n]);\n        if (UTIL_isDirectory(fileNamesTable[n])) {\n            DISPLAYLEVEL(2, \"Ignoring %s directory...       \\n\", fileNamesTable[n]);\n            fileSizes[n] = 0;\n            continue;\n        }\n        if (fileSize == UTIL_FILESIZE_UNKNOWN) {\n            DISPLAYLEVEL(2, \"Cannot determine size of %s ...    \\n\", fileNamesTable[n]);\n            fileSizes[n] = 0;\n            continue;\n        }\n        f = fopen(fileNamesTable[n], \"rb\");\n        if (f==NULL) EXM_THROW(10, \"impossible to open file %s\", fileNamesTable[n]);\n        DISPLAYUPDATE(2, \"Loading %s...       \\r\", fileNamesTable[n]);\n        if (fileSize > bufferSize-pos) fileSize = bufferSize-pos, nbFiles=n;   /* buffer too small - stop after this file */\n        { size_t const readSize = fread(((char*)buffer)+pos, 1, (size_t)fileSize, f);\n          if (readSize != (size_t)fileSize) EXM_THROW(11, \"could not read %s\", fileNamesTable[n]);\n          pos += readSize; }\n        fileSizes[n] = (size_t)fileSize;\n        totalSize += (size_t)fileSize;\n        fclose(f);\n    }\n\n    if (totalSize == 0) EXM_THROW(12, \"no data to bench\");\n}\n\nstatic void BMK_benchFileTable(const char** fileNamesTable, unsigned nbFiles,\n                               const char* dictFileName, int cLevel, int cLevelLast)\n{\n    void* srcBuffer;\n    size_t benchedSize;\n    void* dictBuffer = NULL;\n    size_t dictBufferSize = 0;\n    size_t* fileSizes = (size_t*)malloc(nbFiles * sizeof(size_t));\n    U64 const totalSizeToLoad = UTIL_getTotalFileSize(fileNamesTable, nbFiles);\n    char mfName[20] = {0};\n\n    if (!fileSizes) EXM_THROW(12, \"not enough memory for fileSizes\");\n\n    /* Load dictionary */\n    if (dictFileName != NULL) {\n        U64 const dictFileSize = UTIL_getFileSize(dictFileName);\n        if (dictFileSize > 64 MB)\n            EXM_THROW(10, \"dictionary file %s too large\", dictFileName);\n        dictBufferSize = (size_t)dictFileSize;\n        dictBuffer = malloc(dictBufferSize);\n        if (dictBuffer==NULL)\n            EXM_THROW(11, \"not enough memory for dictionary (%u bytes)\", (unsigned)dictBufferSize);\n        BMK_loadFiles(dictBuffer, dictBufferSize, fileSizes, &dictFileName, 1);\n    }\n\n    /* Memory allocation & restrictions */\n    benchedSize = BMK_findMaxMem(totalSizeToLoad * 3) / 3;\n    if ((U64)benchedSize > totalSizeToLoad) benchedSize = (size_t)totalSizeToLoad;\n    if (benchedSize < totalSizeToLoad)\n        DISPLAY(\"Not enough memory; testing %u MB only...\\n\", (unsigned)(benchedSize >> 20));\n    srcBuffer = malloc(benchedSize + !benchedSize);\n    if (!srcBuffer) EXM_THROW(12, \"not enough memory\");\n\n    /* Load input buffer */\n    BMK_loadFiles(srcBuffer, benchedSize, fileSizes, fileNamesTable, nbFiles);\n\n    /* Bench */\n    snprintf (mfName, sizeof(mfName), \" %u files\", nbFiles);\n    {   const char* displayName = (nbFiles > 1) ? mfName : fileNamesTable[0];\n        BMK_benchCLevel(srcBuffer, benchedSize,\n                        displayName, cLevel, cLevelLast,\n                        fileSizes, nbFiles,\n                        dictBuffer, dictBufferSize);\n    }\n\n    /* clean up */\n    free(srcBuffer);\n    free(dictBuffer);\n    free(fileSizes);\n}\n\n\nstatic void BMK_syntheticTest(int cLevel, int cLevelLast, double compressibility)\n{\n    char name[20] = {0};\n    size_t benchedSize = 10000000;\n    void* const srcBuffer = malloc(benchedSize);\n\n    /* Memory allocation */\n    if (!srcBuffer) EXM_THROW(21, \"not enough memory\");\n\n    /* Fill input buffer */\n    RDG_genBuffer(srcBuffer, benchedSize, compressibility, 0.0, 0);\n\n    /* Bench */\n    snprintf (name, sizeof(name), \"Synthetic %2u%%\", (unsigned)(compressibility*100));\n    BMK_benchCLevel(srcBuffer, benchedSize, name, cLevel, cLevelLast, &benchedSize, 1, NULL, 0);\n\n    /* clean up */\n    free(srcBuffer);\n}\n\n\nstatic int BMK_benchFiles(const char** fileNamesTable, unsigned nbFiles,\n                   const char* dictFileName, int cLevel, int cLevelLast)\n{\n    double const compressibility = (double)g_compressibilityDefault / 100;\n\n    if (nbFiles == 0)\n        BMK_syntheticTest(cLevel, cLevelLast, compressibility);\n    else\n        BMK_benchFileTable(fileNamesTable, nbFiles, dictFileName, cLevel, cLevelLast);\n    return 0;\n}\n\n\n\n\n/*-************************************\n*  Command Line\n**************************************/\nstatic int usage(const char* programName)\n{\n    DISPLAY(WELCOME_MESSAGE);\n    DISPLAY( \"Usage :\\n\");\n    DISPLAY( \"      %s [args] [FILE(s)] [-o file]\\n\", programName);\n    DISPLAY( \"\\n\");\n    DISPLAY( \"FILE    : a filename\\n\");\n    DISPLAY( \"          with no FILE, or when FILE is - , read standard input\\n\");\n    DISPLAY( \"Arguments :\\n\");\n    DISPLAY( \" -D file: use `file` as Dictionary \\n\");\n    DISPLAY( \" -h/-H  : display help/long help and exit\\n\");\n    DISPLAY( \" -V     : display Version number and exit\\n\");\n    DISPLAY( \" -v     : verbose mode; specify multiple times to increase log level (default:%d)\\n\", DEFAULT_DISPLAY_LEVEL);\n    DISPLAY( \" -q     : suppress warnings; specify twice to suppress errors too\\n\");\n#ifdef UTIL_HAS_CREATEFILELIST\n    DISPLAY( \" -r     : operate recursively on directories\\n\");\n#endif\n    DISPLAY( \"\\n\");\n    DISPLAY( \"Benchmark arguments :\\n\");\n    DISPLAY( \" -b#    : benchmark file(s), using # compression level (default : %d) \\n\", ZSTDCLI_CLEVEL_DEFAULT);\n    DISPLAY( \" -e#    : test all compression levels from -bX to # (default: %d)\\n\", ZSTDCLI_CLEVEL_DEFAULT);\n    DISPLAY( \" -i#    : minimum evaluation time in seconds (default : 3s)\\n\");\n    DISPLAY( \" -B#    : cut file into independent chunks of size # (default: no chunking)\\n\");\n    return 0;\n}\n\nstatic int badusage(const char* programName)\n{\n    DISPLAYLEVEL(1, \"Incorrect parameters\\n\");\n    if (g_displayLevel >= 1) usage(programName);\n    return 1;\n}\n\nstatic void waitEnter(void)\n{\n    int unused;\n    DISPLAY(\"Press enter to continue...\\n\");\n    unused = getchar();\n    (void)unused;\n}\n\n/*! readU32FromChar() :\n    @return : unsigned integer value reach from input in `char` format\n    Will also modify `*stringPtr`, advancing it to position where it stopped reading.\n    Note : this function can overflow if digit string > MAX_UINT */\nstatic unsigned readU32FromChar(const char** stringPtr)\n{\n    unsigned result = 0;\n    while ((**stringPtr >='0') && (**stringPtr <='9'))\n        result *= 10, result += (unsigned)(**stringPtr - '0'), (*stringPtr)++ ;\n    return result;\n}\n\n\n#define CLEAN_RETURN(i) { operationResult = (i); goto _end; }\n\nint main(int argCount, char** argv)\n{\n    int argNb,\n        main_pause=0,\n        nextEntryIsDictionary=0,\n        operationResult=0,\n        nextArgumentIsFile=0;\n    int cLevel = ZSTDCLI_CLEVEL_DEFAULT;\n    int cLevelLast = 1;\n    unsigned recursive = 0;\n    FileNamesTable* filenames = UTIL_allocateFileNamesTable((size_t)argCount);\n    const char* programName = argv[0];\n    const char* dictFileName = NULL;\n    char* dynNameSpace = NULL;\n\n    /* init */\n    if (filenames==NULL) { DISPLAY(\"zstd: %s \\n\", strerror(errno)); exit(1); }\n    displayOut = stderr;\n\n    /* Pick out program name from path. Don't rely on stdlib because of conflicting behavior */\n    {   size_t pos;\n        for (pos = strlen(programName); pos > 0; pos--) { if (programName[pos] == '/') { pos++; break; } }\n        programName += pos;\n    }\n\n     /* command switches */\n    for(argNb=1; argNb<argCount; argNb++) {\n        const char* argument = argv[argNb];\n        if(!argument) continue;   /* Protection if argument empty */\n\n        if (nextArgumentIsFile==0) {\n\n            /* long commands (--long-word) */\n            if (!strcmp(argument, \"--\")) { nextArgumentIsFile=1; continue; }\n            if (!strcmp(argument, \"--version\")) { displayOut=stdout; DISPLAY(WELCOME_MESSAGE); CLEAN_RETURN(0); }\n            if (!strcmp(argument, \"--help\")) { displayOut=stdout; CLEAN_RETURN(usage(programName)); }\n            if (!strcmp(argument, \"--verbose\")) { g_displayLevel++; continue; }\n            if (!strcmp(argument, \"--quiet\")) { g_displayLevel--; continue; }\n\n            /* Decode commands (note : aggregated commands are allowed) */\n            if (argument[0]=='-') {\n                argument++;\n\n                while (argument[0]!=0) {\n                    switch(argument[0])\n                    {\n                        /* Display help */\n                    case 'V': displayOut=stdout; DISPLAY(WELCOME_MESSAGE); CLEAN_RETURN(0);   /* Version Only */\n                    case 'H':\n                    case 'h': displayOut=stdout; CLEAN_RETURN(usage(programName));\n\n                        /* Use file content as dictionary */\n                    case 'D': nextEntryIsDictionary = 1; argument++; break;\n\n                        /* Verbose mode */\n                    case 'v': g_displayLevel++; argument++; break;\n\n                        /* Quiet mode */\n                    case 'q': g_displayLevel--; argument++; break;\n\n#ifdef UTIL_HAS_CREATEFILELIST\n                        /* recursive */\n                    case 'r': recursive=1; argument++; break;\n#endif\n\n                        /* Benchmark */\n                    case 'b':\n                            /* first compression Level */\n                            argument++;\n                            cLevel = (int)readU32FromChar(&argument);\n                            break;\n\n                        /* range bench (benchmark only) */\n                    case 'e':\n                            /* last compression Level */\n                            argument++;\n                            cLevelLast = (int)readU32FromChar(&argument);\n                            break;\n\n                        /* Modify Nb Iterations (benchmark only) */\n                    case 'i':\n                        argument++;\n                        {   U32 const iters = readU32FromChar(&argument);\n                            BMK_setNotificationLevel(g_displayLevel);\n                            BMK_SetNbIterations(iters);\n                        }\n                        break;\n\n                        /* cut input into blocks (benchmark only) */\n                    case 'B':\n                        argument++;\n                        {   size_t bSize = readU32FromChar(&argument);\n                            if (toupper(*argument)=='K') bSize<<=10, argument++;  /* allows using KB notation */\n                            if (toupper(*argument)=='M') bSize<<=20, argument++;\n                            if (toupper(*argument)=='B') argument++;\n                            BMK_setNotificationLevel(g_displayLevel);\n                            BMK_SetBlockSize(bSize);\n                        }\n                        break;\n\n                        /* Pause at the end (-p) or set an additional param (-p#) (hidden option) */\n                    case 'p': argument++;\n                        if ((*argument>='0') && (*argument<='9')) {\n                            BMK_setAdditionalParam((int)readU32FromChar(&argument));\n                        } else\n                            main_pause=1;\n                        break;\n                        /* unknown command */\n                    default : CLEAN_RETURN(badusage(programName));\n                    }\n                }\n                continue;\n            }   /* if (argument[0]=='-') */\n\n        }   /* if (nextArgumentIsAFile==0) */\n\n        if (nextEntryIsDictionary) {\n            nextEntryIsDictionary = 0;\n            dictFileName = argument;\n            continue;\n        }\n\n        /* add filename to list */\n        UTIL_refFilename(filenames, argument);\n    }\n\n    /* Welcome message (if verbose) */\n    DISPLAYLEVEL(3, WELCOME_MESSAGE);\n\n#ifdef UTIL_HAS_CREATEFILELIST\n    if (recursive) {\n        UTIL_expandFNT(&filenames, 1);\n    }\n#endif\n\n    BMK_setNotificationLevel(g_displayLevel);\n    BMK_benchFiles(filenames->fileNames, (unsigned)filenames->tableSize, dictFileName, cLevel, cLevelLast);\n\n_end:\n    if (main_pause) waitEnter();\n    free(dynNameSpace);\n    UTIL_freeFileNamesTable(filenames);\n    return operationResult;\n}\n"
  },
  {
    "path": "zlibWrapper/gzclose.c",
    "content": "/* gzclose.c contains minimal changes required to be compiled with zlibWrapper:\n * - gz_statep was converted to union to work with -Wstrict-aliasing=1      */\n\n/* gzclose.c -- zlib gzclose() function\n * Copyright (C) 2004, 2010 Mark Adler\n * For conditions of distribution and use, see https://www.zlib.net/zlib_license.html\n */\n\n#include \"gzguts.h\"\n\n/* gzclose() is in a separate file so that it is linked in only if it is used.\n   That way the other gzclose functions can be used instead to avoid linking in\n   unneeded compression or decompression routines. */\nint ZEXPORT gzclose(gzFile file) {\n#ifndef NO_GZCOMPRESS\n    gz_statep state;\n\n    if (file == NULL)\n        return Z_STREAM_ERROR;\n    state.file = file;\n\n    return state.state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file);\n#else\n    return gzclose_r(file);\n#endif\n}\n"
  },
  {
    "path": "zlibWrapper/gzcompatibility.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n\n#if ZLIB_VERNUM <= 0x1240\nZEXTERN int ZEXPORT gzclose_r _Z_OF((gzFile file));\nZEXTERN int ZEXPORT gzclose_w _Z_OF((gzFile file));\nZEXTERN int ZEXPORT gzbuffer _Z_OF((gzFile file, unsigned size));\nZEXTERN z_off_t ZEXPORT gzoffset _Z_OF((gzFile file));\n\n#if !defined(_WIN32) && defined(Z_LARGE64)\n#  define z_off64_t off64_t\n#else\n#  if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)\n#    define z_off64_t __int64\n#  else\n#    define z_off64_t z_off_t\n#  endif\n#endif\n#endif\n\n\n#if ZLIB_VERNUM <= 0x1250\nstruct gzFile_s {\n    unsigned have;\n    unsigned char *next;\n    z_off64_t pos;\n};\n#endif\n\n\n#if ZLIB_VERNUM <= 0x1270\n#if defined(_WIN32) && !defined(Z_SOLO)\n#    include <stddef.h>         /* for wchar_t */\nZEXTERN gzFile         ZEXPORT gzopen_w _Z_OF((const wchar_t *path,\n                                            const char *mode));\n#endif\n#endif\n\n\n#if ZLIB_VERNUM < 0x12B0\n#ifdef Z_SOLO\n   typedef unsigned long z_size_t;\n#else\n#  define z_longlong long long\n#  if defined(NO_SIZE_T)\n     typedef unsigned NO_SIZE_T z_size_t;\n#  elif defined(STDC)\n#    include <stddef.h>\n     typedef size_t z_size_t;\n#  else\n     typedef unsigned long z_size_t;\n#  endif\n#  undef z_longlong\n#endif\nZEXTERN z_size_t ZEXPORT gzfread _Z_OF((voidp buf, z_size_t size, z_size_t nitems,\n                                     gzFile file));\nZEXTERN z_size_t ZEXPORT gzfwrite _Z_OF((voidpc buf, z_size_t size,\n                                      z_size_t nitems, gzFile file));\n#endif\n"
  },
  {
    "path": "zlibWrapper/gzguts.h",
    "content": "/* gzguts.h contains minimal changes required to be compiled with zlibWrapper:\n * - #include \"zlib.h\" was changed to #include \"zstd_zlibwrapper.h\"\n * - gz_statep was converted to union to work with -Wstrict-aliasing=1      */\n\n/* gzguts.h -- zlib internal header definitions for gz* operations\n * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler\n * For conditions of distribution and use, see https://www.zlib.net/zlib_license.html\n */\n\n#ifdef _LARGEFILE64_SOURCE\n#  ifndef _LARGEFILE_SOURCE\n#    define _LARGEFILE_SOURCE 1\n#  endif\n#  ifdef _FILE_OFFSET_BITS\n#    undef _FILE_OFFSET_BITS\n#  endif\n#endif\n\n#ifdef HAVE_HIDDEN\n#  define ZLIB_INTERNAL __attribute__((visibility (\"hidden\")))\n#else\n#  define ZLIB_INTERNAL\n#endif\n\n#include <stdio.h>\n#include \"zstd_zlibwrapper.h\"\n#include \"gzcompatibility.h\"\n#ifdef STDC\n#  include <string.h>\n#  include <stdlib.h>\n#  include <limits.h>\n#endif\n\n#ifndef _POSIX_SOURCE\n#  define _POSIX_SOURCE\n#endif\n#include <fcntl.h>\n\n#ifdef _WIN32\n#  include <stddef.h>\n#else\n#  include <unistd.h>\n#endif\n\n#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)\n#  include <io.h>\n#endif\n\n#if defined(_WIN32)\n#  define WIDECHAR\n#endif\n\n#ifdef WINAPI_FAMILY\n#  define open _open\n#  define read _read\n#  define write _write\n#  define close _close\n#endif\n\n#ifdef NO_DEFLATE       /* for compatibility with old definition */\n#  define NO_GZCOMPRESS\n#endif\n\n#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)\n#  ifndef HAVE_VSNPRINTF\n#    define HAVE_VSNPRINTF\n#  endif\n#endif\n\n#if defined(__CYGWIN__)\n#  ifndef HAVE_VSNPRINTF\n#    define HAVE_VSNPRINTF\n#  endif\n#endif\n\n#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410)\n#  ifndef HAVE_VSNPRINTF\n#    define HAVE_VSNPRINTF\n#  endif\n#endif\n\n#ifndef HAVE_VSNPRINTF\n#  ifdef MSDOS\n/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),\n   but for now we just assume it doesn't. */\n#    define NO_vsnprintf\n#  endif\n#  ifdef __TURBOC__\n#    define NO_vsnprintf\n#  endif\n#  ifdef WIN32\n/* In Win32, vsnprintf is available as the \"non-ANSI\" _vsnprintf. */\n#    if !defined(vsnprintf) && !defined(NO_vsnprintf)\n#      if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )\n#         define vsnprintf _vsnprintf\n#      endif\n#    endif\n#  endif\n#  ifdef __SASC\n#    define NO_vsnprintf\n#  endif\n#  ifdef VMS\n#    define NO_vsnprintf\n#  endif\n#  ifdef __OS400__\n#    define NO_vsnprintf\n#  endif\n#  ifdef __MVS__\n#    define NO_vsnprintf\n#  endif\n#endif\n\n/* unlike snprintf (which is required in C99), _snprintf does not guarantee\n   null termination of the result -- however this is only used in gzlib.c where\n   the result is assured to fit in the space provided */\n#if defined(_MSC_VER) && _MSC_VER < 1900\n#  define snprintf _snprintf\n#endif\n\n#ifndef local\n#  define local static\n#endif\n/* since \"static\" is used to mean two completely different things in C, we\n   define \"local\" for the non-static meaning of \"static\", for readability\n   (compile with -Dlocal if your debugger can't find static symbols) */\n\n/* gz* functions always use library allocation functions */\n#ifndef STDC\n  extern voidp  malloc _Z_OF((uInt size));\n  extern void   free   _Z_OF((voidpf ptr));\n#endif\n\n/* get errno and strerror definition */\n#if defined UNDER_CE\n#  include <windows.h>\n#  define zstrerror() gz_strwinerror((DWORD)GetLastError())\n#else\n#  ifndef NO_STRERROR\n#    include <errno.h>\n#    define zstrerror() strerror(errno)\n#  else\n#    define zstrerror() \"stdio error (consult errno)\"\n#  endif\n#endif\n\n/* provide prototypes for these when building zlib without LFS */\n#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0\n    ZEXTERN gzFile ZEXPORT gzopen64 _Z_OF((const char *, const char *));\n    ZEXTERN z_off64_t ZEXPORT gzseek64 _Z_OF((gzFile, z_off64_t, int));\n    ZEXTERN z_off64_t ZEXPORT gztell64 _Z_OF((gzFile));\n    ZEXTERN z_off64_t ZEXPORT gzoffset64 _Z_OF((gzFile));\n#endif\n\n/* default memLevel */\n#if MAX_MEM_LEVEL >= 8\n#  define DEF_MEM_LEVEL 8\n#else\n#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL\n#endif\n\n/* default i/o buffer size -- double this for output when reading (this and\n   twice this must be able to fit in an unsigned type) */\n#define GZBUFSIZE 8192\n\n/* gzip modes, also provide a little integrity check on the passed structure */\n#define GZ_NONE 0\n#define GZ_READ 7247\n#define GZ_WRITE 31153\n#define GZ_APPEND 1     /* mode set to GZ_WRITE after the file is opened */\n\n/* values for gz_state how */\n#define LOOK 0      /* look for a gzip header */\n#define COPY 1      /* copy input directly */\n#define GZIP 2      /* decompress a gzip stream */\n\n/* internal gzip file state data structure */\ntypedef struct {\n        /* exposed contents for gzgetc() macro */\n    struct gzFile_s x;      /* \"x\" for exposed */\n                            /* x.have: number of bytes available at x.next */\n                            /* x.next: next output data to deliver or write */\n                            /* x.pos: current position in uncompressed data */\n        /* used for both reading and writing */\n    int mode;               /* see gzip modes above */\n    int fd;                 /* file descriptor */\n    char *path;             /* path or fd for error messages */\n    unsigned size;          /* buffer size, zero if not allocated yet */\n    unsigned want;          /* requested buffer size, default is GZBUFSIZE */\n    unsigned char *in;      /* input buffer (double-sized when writing) */\n    unsigned char *out;     /* output buffer (double-sized when reading) */\n    int direct;             /* 0 if processing gzip, 1 if transparent */\n        /* just for reading */\n    int how;                /* 0: get header, 1: copy, 2: decompress */\n    z_off64_t start;        /* where the gzip data started, for rewinding */\n    int eof;                /* true if end of input file reached */\n    int past;               /* true if read requested past end */\n        /* just for writing */\n    int level;              /* compression level */\n    int strategy;           /* compression strategy */\n        /* seek request */\n    z_off64_t skip;         /* amount to skip (already rewound if backwards) */\n    int seek;               /* true if seek request pending */\n        /* error information */\n    int err;                /* error code */\n    char *msg;              /* error message */\n        /* zlib inflate or deflate stream */\n    z_stream strm;          /* stream structure in-place (not a pointer) */\n} gz_state;\n\ntypedef union {\n    gz_state FAR *state;\n    gzFile file;\n} gz_statep;\n\n/* shared functions */\nvoid ZLIB_INTERNAL gz_error _Z_OF((gz_statep, int, const char *));\n#if defined UNDER_CE\nchar ZLIB_INTERNAL *gz_strwinerror _Z_OF((DWORD error));\n#endif\n\n/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t\n   value -- needed when comparing unsigned to z_off64_t, which is signed\n   (possible z_off64_t types off_t, off64_t, and long are all signed) */\n#ifdef INT_MAX\n#  define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)\n#else\nunsigned ZLIB_INTERNAL gz_intmax _Z_OF((void));\n#  define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())\n#endif\n"
  },
  {
    "path": "zlibWrapper/gzlib.c",
    "content": "/* gzlib.c contains minimal changes required to be compiled with zlibWrapper:\n * - gz_statep was converted to union to work with -Wstrict-aliasing=1      */\n\n/* gzlib.c -- zlib functions common to reading and writing gzip files\n * Copyright (C) 2004-2017 Mark Adler\n * For conditions of distribution and use, see https://www.zlib.net/zlib_license.html\n */\n\n#include \"gzguts.h\"\n\n#if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__)\n#  define LSEEK _lseeki64\n#else\n#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0\n#  define LSEEK lseek64\n#else\n#  define LSEEK lseek\n#endif\n#endif\n\n/* Local functions */\nlocal void gz_reset _Z_OF((gz_statep));\nlocal gzFile gz_open _Z_OF((const void *, int, const char *));\n\n#if defined UNDER_CE\n\n/* Map the Windows error number in ERROR to a locale-dependent error message\n   string and return a pointer to it.  Typically, the values for ERROR come\n   from GetLastError.\n\n   The string pointed to shall not be modified by the application, but may be\n   overwritten by a subsequent call to gz_strwinerror\n\n   The gz_strwinerror function does not change the current setting of\n   GetLastError. */\nchar ZLIB_INTERNAL *gz_strwinerror(DWORD error) {\n    static char buf[1024];\n\n    wchar_t *msgbuf;\n    DWORD lasterr = GetLastError();\n    DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM\n        | FORMAT_MESSAGE_ALLOCATE_BUFFER,\n        NULL,\n        error,\n        0, /* Default language */\n        (LPVOID)&msgbuf,\n        0,\n        NULL);\n    if (chars != 0) {\n        /* If there is an \\r\\n appended, zap it.  */\n        if (chars >= 2\n            && msgbuf[chars - 2] == '\\r' && msgbuf[chars - 1] == '\\n') {\n            chars -= 2;\n            msgbuf[chars] = 0;\n        }\n\n        if (chars > sizeof (buf) - 1) {\n            chars = sizeof (buf) - 1;\n            msgbuf[chars] = 0;\n        }\n\n        wcstombs(buf, msgbuf, chars + 1);\n        LocalFree(msgbuf);\n    }\n    else {\n        sprintf(buf, \"unknown win32 error (%ld)\", error);\n    }\n\n    SetLastError(lasterr);\n    return buf;\n}\n\n#endif /* UNDER_CE */\n\n/* Reset gzip file state */\nlocal void gz_reset(gz_statep state) {\n    state.state->x.have = 0;              /* no output data available */\n    if (state.state->mode == GZ_READ) {   /* for reading ... */\n        state.state->eof = 0;             /* not at end of file */\n        state.state->past = 0;            /* have not read past end yet */\n        state.state->how = LOOK;          /* look for gzip header */\n    }\n    state.state->seek = 0;                /* no seek request pending */\n    gz_error(state, Z_OK, NULL);    /* clear error */\n    state.state->x.pos = 0;               /* no uncompressed data yet */\n    state.state->strm.avail_in = 0;       /* no input data yet */\n}\n\n/* Open a gzip file either by name or file descriptor. */\nlocal gzFile gz_open(const void *path, int fd, const char *mode) {\n    gz_statep state;\n    z_size_t len;\n    int oflag;\n#ifdef O_CLOEXEC\n    int cloexec = 0;\n#endif\n#ifdef O_EXCL\n    int exclusive = 0;\n#endif\n\n    /* check input */\n    if (path == NULL)\n        return NULL;\n\n    /* allocate gzFile structure to return */\n    state.state = (gz_state*)malloc(sizeof(gz_state));\n    if (state.state == NULL)\n        return NULL;\n    state.state->size = 0;            /* no buffers allocated yet */\n    state.state->want = GZBUFSIZE;    /* requested buffer size */\n    state.state->msg = NULL;          /* no error message yet */\n\n    /* interpret mode */\n    state.state->mode = GZ_NONE;\n    state.state->level = Z_DEFAULT_COMPRESSION;\n    state.state->strategy = Z_DEFAULT_STRATEGY;\n    state.state->direct = 0;\n    while (*mode) {\n        if (*mode >= '0' && *mode <= '9')\n            state.state->level = *mode - '0';\n        else\n            switch (*mode) {\n            case 'r':\n                state.state->mode = GZ_READ;\n                break;\n#ifndef NO_GZCOMPRESS\n            case 'w':\n                state.state->mode = GZ_WRITE;\n                break;\n            case 'a':\n                state.state->mode = GZ_APPEND;\n                break;\n#endif\n            case '+':       /* can't read and write at the same time */\n                free(state.state);\n                return NULL;\n            case 'b':       /* ignore -- will request binary anyway */\n                break;\n#ifdef O_CLOEXEC\n            case 'e':\n                cloexec = 1;\n                break;\n#endif\n#ifdef O_EXCL\n            case 'x':\n                exclusive = 1;\n                break;\n#endif\n            case 'f':\n                state.state->strategy = Z_FILTERED;\n                break;\n            case 'h':\n                state.state->strategy = Z_HUFFMAN_ONLY;\n                break;\n            case 'R':\n                state.state->strategy = Z_RLE;\n                break;\n            case 'F':\n                state.state->strategy = Z_FIXED;\n                break;\n            case 'T':\n                state.state->direct = 1;\n                break;\n            default:        /* could consider as an error, but just ignore */\n                ;\n            }\n        mode++;\n    }\n\n    /* must provide an \"r\", \"w\", or \"a\" */\n    if (state.state->mode == GZ_NONE) {\n        free(state.state);\n        return NULL;\n    }\n\n    /* can't force transparent read */\n    if (state.state->mode == GZ_READ) {\n        if (state.state->direct) {\n            free(state.state);\n            return NULL;\n        }\n        state.state->direct = 1;      /* for empty file */\n    }\n\n    /* save the path name for error messages */\n#ifdef WIDECHAR\n    if (fd == -2) {\n        len = wcstombs(NULL, path, 0);\n        if (len == (z_size_t)-1)\n            len = 0;\n    }\n    else\n#endif\n        len = strlen((const char *)path);\n    state.state->path = (char *)malloc(len + 1);\n    if (state.state->path == NULL) {\n        free(state.state);\n        return NULL;\n    }\n#ifdef WIDECHAR\n    if (fd == -2)\n        if (len)\n            wcstombs(state.state->path, path, len + 1);\n        else\n            *(state.state->path) = 0;\n    else\n#endif\n#if !defined(NO_snprintf) && !defined(NO_vsnprintf)\n        (void)snprintf(state.state->path, len + 1, \"%s\", (const char *)path);\n#else\n        strcpy(state.state->path, (const char*)path);\n#endif\n\n    /* compute the flags for open() */\n    oflag =\n#ifdef O_LARGEFILE\n        O_LARGEFILE |\n#endif\n#ifdef O_BINARY\n        O_BINARY |\n#endif\n#ifdef O_CLOEXEC\n        (cloexec ? O_CLOEXEC : 0) |\n#endif\n        (state.state->mode == GZ_READ ?\n         O_RDONLY :\n         (O_WRONLY | O_CREAT |\n#ifdef O_EXCL\n          (exclusive ? O_EXCL : 0) |\n#endif\n          (state.state->mode == GZ_WRITE ?\n           O_TRUNC :\n           O_APPEND)));\n\n    /* open the file with the appropriate flags (or just use fd) */\n    state.state->fd = fd > -1 ? fd : (\n#ifdef WIDECHAR\n        fd == -2 ? _wopen(path, oflag, 0666) :\n#endif\n        open((const char *)path, oflag, 0666));\n    if (state.state->fd == -1) {\n        free(state.state->path);\n        free(state.state);\n        return NULL;\n    }\n    if (state.state->mode == GZ_APPEND) {\n        LSEEK(state.state->fd, 0, SEEK_END);  /* so gzoffset() is correct */\n        state.state->mode = GZ_WRITE;         /* simplify later checks */\n    }\n\n    /* save the current position for rewinding (only if reading) */\n    if (state.state->mode == GZ_READ) {\n        state.state->start = LSEEK(state.state->fd, 0, SEEK_CUR);\n        if (state.state->start == -1) state.state->start = 0;\n    }\n\n    /* initialize stream */\n    gz_reset(state);\n\n    /* return stream */\n    return state.file;\n}\n\n/* -- see zlib.h -- */\ngzFile ZEXPORT gzopen(const char *path, const char *mode) {\n    return gz_open(path, -1, mode);\n}\n\n/* -- see zlib.h -- */\ngzFile ZEXPORT gzopen64(const char *path, const char *mode) {\n    return gz_open(path, -1, mode);\n}\n\n/* -- see zlib.h -- */\ngzFile ZEXPORT gzdopen(int fd, const char *mode) {\n    char *path;         /* identifier for error messages */\n    gzFile gz;\n\n    if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)\n        return NULL;\n#if !defined(NO_snprintf) && !defined(NO_vsnprintf)\n    (void)snprintf(path, 7 + 3 * sizeof(int), \"<fd:%d>\", fd);\n#else\n    sprintf(path, \"<fd:%d>\", fd);   /* for debugging */\n#endif\n    gz = gz_open(path, fd, mode);\n    free(path);\n    return gz;\n}\n\n/* -- see zlib.h -- */\n#ifdef WIDECHAR\ngzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode) {\n    return gz_open(path, -2, mode);\n}\n#endif\n\n/* -- see zlib.h -- */\nint ZEXPORT gzbuffer(gzFile file, unsigned size) {\n    gz_statep state;\n\n    /* get internal structure and check integrity */\n    if (file == NULL)\n        return -1;\n    state.file = file;\n    if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)\n        return -1;\n\n    /* make sure we haven't already allocated memory */\n    if (state.state->size != 0)\n        return -1;\n\n    /* check and set requested size */\n    if ((size << 1) < size)\n        return -1;              /* need to be able to double it */\n    if (size < 2)\n        size = 2;               /* need two bytes to check magic header */\n    state.state->want = size;\n    return 0;\n}\n\n/* -- see zlib.h -- */\nint ZEXPORT gzrewind(gzFile file) {\n    gz_statep state;\n\n    /* get internal structure */\n    if (file == NULL)\n        return -1;\n    state.file = file;\n\n    /* check that we're reading and that there's no error */\n    if (state.state->mode != GZ_READ ||\n            (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))\n        return -1;\n\n    /* back up and start over */\n    if (LSEEK(state.state->fd, state.state->start, SEEK_SET) == -1)\n        return -1;\n    gz_reset(state);\n    return 0;\n}\n\n/* -- see zlib.h -- */\nz_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) {\n    unsigned n;\n    z_off64_t ret;\n    gz_statep state;\n\n    /* get internal structure and check integrity */\n    if (file == NULL)\n        return -1;\n    state.file = file;\n    if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)\n        return -1;\n\n    /* check that there's no error */\n    if (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR)\n        return -1;\n\n    /* can only seek from start or relative to current position */\n    if (whence != SEEK_SET && whence != SEEK_CUR)\n        return -1;\n\n    /* normalize offset to a SEEK_CUR specification */\n    if (whence == SEEK_SET)\n        offset -= state.state->x.pos;\n    else if (state.state->seek)\n        offset += state.state->skip;\n    state.state->seek = 0;\n\n    /* if within raw area while reading, just go there */\n    if (state.state->mode == GZ_READ && state.state->how == COPY &&\n            state.state->x.pos + offset >= 0) {\n        ret = LSEEK(state.state->fd, offset - state.state->x.have, SEEK_CUR);\n        if (ret == -1)\n            return -1;\n        state.state->x.have = 0;\n        state.state->eof = 0;\n        state.state->past = 0;\n        state.state->seek = 0;\n        gz_error(state, Z_OK, NULL);\n        state.state->strm.avail_in = 0;\n        state.state->x.pos += offset;\n        return state.state->x.pos;\n    }\n\n    /* calculate skip amount, rewinding if needed for back seek when reading */\n    if (offset < 0) {\n        if (state.state->mode != GZ_READ)         /* writing -- can't go backwards */\n            return -1;\n        offset += state.state->x.pos;\n        if (offset < 0)                     /* before start of file! */\n            return -1;\n        if (gzrewind(file) == -1)           /* rewind, then skip to offset */\n            return -1;\n    }\n\n    /* if reading, skip what's in output buffer (one less gzgetc() check) */\n    if (state.state->mode == GZ_READ) {\n        n = GT_OFF(state.state->x.have) || (z_off64_t)state.state->x.have > offset ?\n            (unsigned)offset : state.state->x.have;\n        state.state->x.have -= n;\n        state.state->x.next += n;\n        state.state->x.pos += n;\n        offset -= n;\n    }\n\n    /* request skip (if not zero) */\n    if (offset) {\n        state.state->seek = 1;\n        state.state->skip = offset;\n    }\n    return state.state->x.pos + offset;\n}\n\n/* -- see zlib.h -- */\nz_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) {\n    z_off64_t ret;\n\n    ret = gzseek64(file, (z_off64_t)offset, whence);\n    return ret == (z_off_t)ret ? (z_off_t)ret : -1;\n}\n\n/* -- see zlib.h -- */\nz_off64_t ZEXPORT gztell64(gzFile file) {\n    gz_statep state;\n\n    /* get internal structure and check integrity */\n    if (file == NULL)\n        return -1;\n    state.file = file;\n    if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)\n        return -1;\n\n    /* return position */\n    return state.state->x.pos + (state.state->seek ? state.state->skip : 0);\n}\n\n/* -- see zlib.h -- */\nz_off_t ZEXPORT gztell(gzFile file) {\n    z_off64_t ret;\n\n    ret = gztell64(file);\n    return ret == (z_off_t)ret ? (z_off_t)ret : -1;\n}\n\n/* -- see zlib.h -- */\nz_off64_t ZEXPORT gzoffset64(gzFile file) {\n    z_off64_t offset;\n    gz_statep state;\n\n    /* get internal structure and check integrity */\n    if (file == NULL)\n        return -1;\n    state.file = file;\n    if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)\n        return -1;\n\n    /* compute and return effective offset in file */\n    offset = LSEEK(state.state->fd, 0, SEEK_CUR);\n    if (offset == -1)\n        return -1;\n    if (state.state->mode == GZ_READ)             /* reading */\n        offset -= state.state->strm.avail_in;     /* don't count buffered input */\n    return offset;\n}\n\n/* -- see zlib.h -- */\nz_off_t ZEXPORT gzoffset(gzFile file) {\n    z_off64_t ret;\n\n    ret = gzoffset64(file);\n    return ret == (z_off_t)ret ? (z_off_t)ret : -1;\n}\n\n/* -- see zlib.h -- */\nint ZEXPORT gzeof(gzFile file) {\n    gz_statep state;\n\n    /* get internal structure and check integrity */\n    if (file == NULL)\n        return 0;\n    state.file = file;\n    if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)\n        return 0;\n\n    /* return end-of-file state */\n    return state.state->mode == GZ_READ ? state.state->past : 0;\n}\n\n/* -- see zlib.h -- */\nconst char * ZEXPORT gzerror(gzFile file, int *errnum) {\n    gz_statep state;\n\n    /* get internal structure and check integrity */\n    if (file == NULL)\n        return NULL;\n    state.file = file;\n    if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)\n        return NULL;\n\n    /* return error information */\n    if (errnum != NULL)\n        *errnum = state.state->err;\n    return state.state->err == Z_MEM_ERROR ? \"out of memory\" :\n                                       (state.state->msg == NULL ? \"\" : state.state->msg);\n}\n\n/* -- see zlib.h -- */\nvoid ZEXPORT gzclearerr(gzFile file) {\n    gz_statep state;\n\n    /* get internal structure and check integrity */\n    if (file == NULL)\n        return;\n    state.file = file;\n    if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)\n        return;\n\n    /* clear error and end-of-file */\n    if (state.state->mode == GZ_READ) {\n        state.state->eof = 0;\n        state.state->past = 0;\n    }\n    gz_error(state, Z_OK, NULL);\n}\n\n/* Create an error message in allocated memory and set state.state->err and\n   state.state->msg accordingly.  Free any previous error message already there.  Do\n   not try to free or allocate space if the error is Z_MEM_ERROR (out of\n   memory).  Simply save the error message as a static string.  If there is an\n   allocation failure constructing the error message, then convert the error to\n   out of memory. */\nvoid ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) {\n    /* free previously allocated message and clear */\n    if (state.state->msg != NULL) {\n        if (state.state->err != Z_MEM_ERROR)\n            free(state.state->msg);\n        state.state->msg = NULL;\n    }\n\n    /* if fatal, set state.state->x.have to 0 so that the gzgetc() macro fails */\n    if (err != Z_OK && err != Z_BUF_ERROR)\n        state.state->x.have = 0;\n\n    /* set error code, and if no message, then done */\n    state.state->err = err;\n    if (msg == NULL)\n        return;\n\n    /* for an out of memory error, return literal string when requested */\n    if (err == Z_MEM_ERROR)\n        return;\n\n    /* construct error message with path */\n    if ((state.state->msg = (char *)malloc(strlen(state.state->path) + strlen(msg) + 3)) ==\n            NULL) {\n        state.state->err = Z_MEM_ERROR;\n        return;\n    }\n#if !defined(NO_snprintf) && !defined(NO_vsnprintf)\n    (void)snprintf(state.state->msg, strlen(state.state->path) + strlen(msg) + 3,\n                   \"%s%s%s\", state.state->path, \": \", msg);\n#else\n    strcpy(state.state->msg, state.state->path);\n    strcat(state.state->msg, \": \");\n    strcat(state.state->msg, msg);\n#endif\n}\n\n#ifndef INT_MAX\n/* portably return maximum value for an int (when limits.h presumed not\n   available) -- we need to do this to cover cases where 2's complement not\n   used, since C standard permits 1's complement and sign-bit representations,\n   otherwise we could just use ((unsigned)-1) >> 1 */\nunsigned ZLIB_INTERNAL gz_intmax() {\n    unsigned p, q;\n\n    p = 1;\n    do {\n        q = p;\n        p <<= 1;\n        p++;\n    } while (p > q);\n    return q >> 1;\n}\n#endif\n"
  },
  {
    "path": "zlibWrapper/gzread.c",
    "content": "/* gzread.c contains minimal changes required to be compiled with zlibWrapper:\n * - gz_statep was converted to union to work with -Wstrict-aliasing=1      */\n\n /* gzread.c -- zlib functions for reading gzip files\n * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler\n * For conditions of distribution and use, see https://www.zlib.net/zlib_license.html\n */\n\n#include \"gzguts.h\"\n\n/* fix for Visual Studio, which doesn't support ssize_t type.\n * see https://github.com/facebook/zstd/issues/1800#issuecomment-545945050 */\n#if defined(_MSC_VER) && !defined(ssize_t)\n#  include <BaseTsd.h>\n   typedef SSIZE_T ssize_t;\n#endif\n\n\n/* Local functions */\nlocal int gz_load _Z_OF((gz_statep, unsigned char *, unsigned, unsigned *));\nlocal int gz_avail _Z_OF((gz_statep));\nlocal int gz_look _Z_OF((gz_statep));\nlocal int gz_decomp _Z_OF((gz_statep));\nlocal int gz_fetch _Z_OF((gz_statep));\nlocal int gz_skip _Z_OF((gz_statep, z_off64_t));\nlocal z_size_t gz_read _Z_OF((gz_statep, voidp, z_size_t));\n\n/* Use read() to load a buffer -- return -1 on error, otherwise 0.  Read from\n   state.state->fd, and update state.state->eof, state.state->err, and state.state->msg as appropriate.\n   This function needs to loop on read(), since read() is not guaranteed to\n   read the number of bytes requested, depending on the type of descriptor. */\nlocal int gz_load(gz_statep state, unsigned char *buf, unsigned len,\n                  unsigned *have) {\n    ssize_t ret;\n    unsigned get, max = ((unsigned)-1 >> 2) + 1;\n\n    *have = 0;\n    do {\n        get = len - *have;\n        if (get > max)\n            get = max;\n        ret = read(state.state->fd, buf + *have, get);\n        if (ret <= 0)\n            break;\n        *have += (unsigned)ret;\n    } while (*have < len);\n    if (ret < 0) {\n        gz_error(state, Z_ERRNO, zstrerror());\n        return -1;\n    }\n    if (ret == 0)\n        state.state->eof = 1;\n    return 0;\n}\n\n/* Load up input buffer and set eof flag if last data loaded -- return -1 on\n   error, 0 otherwise.  Note that the eof flag is set when the end of the input\n   file is reached, even though there may be unused data in the buffer.  Once\n   that data has been used, no more attempts will be made to read the file.\n   If strm->avail_in != 0, then the current data is moved to the beginning of\n   the input buffer, and then the remainder of the buffer is loaded with the\n   available data from the input file. */\nlocal int gz_avail(gz_statep state)\n{\n    unsigned got;\n    z_streamp strm = &(state.state->strm);\n\n    if (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR)\n        return -1;\n    if (state.state->eof == 0) {\n        if (strm->avail_in) {       /* copy what's there to the start */\n            unsigned char *p = state.state->in;\n            unsigned const char *q = strm->next_in;\n            unsigned n = strm->avail_in;\n            do {\n                *p++ = *q++;\n            } while (--n);\n        }\n        if (gz_load(state, state.state->in + strm->avail_in,\n                    state.state->size - strm->avail_in, &got) == -1)\n            return -1;\n        strm->avail_in += got;\n        strm->next_in = state.state->in;\n    }\n    return 0;\n}\n\n/* Look for gzip header, set up for inflate or copy.  state.state->x.have must be 0.\n   If this is the first time in, allocate required memory.  state.state->how will be\n   left unchanged if there is no more input data available, will be set to COPY\n   if there is no gzip header and direct copying will be performed, or it will\n   be set to GZIP for decompression.  If direct copying, then leftover input\n   data from the input buffer will be copied to the output buffer.  In that\n   case, all further file reads will be directly to either the output buffer or\n   a user buffer.  If decompressing, the inflate state will be initialized.\n   gz_look() will return 0 on success or -1 on failure. */\nlocal int gz_look(gz_statep state) {\n    z_streamp strm = &(state.state->strm);\n\n    /* allocate read buffers and inflate memory */\n    if (state.state->size == 0) {\n        /* allocate buffers */\n        state.state->in = (unsigned char *)malloc(state.state->want);\n        state.state->out = (unsigned char *)malloc(state.state->want << 1);\n        if (state.state->in == NULL || state.state->out == NULL) {\n            free(state.state->out);\n            free(state.state->in);\n            gz_error(state, Z_MEM_ERROR, \"out of memory\");\n            return -1;\n        }\n        state.state->size = state.state->want;\n\n        /* allocate inflate memory */\n        state.state->strm.zalloc = Z_NULL;\n        state.state->strm.zfree = Z_NULL;\n        state.state->strm.opaque = Z_NULL;\n        state.state->strm.avail_in = 0;\n        state.state->strm.next_in = Z_NULL;\n        if (inflateInit2(&(state.state->strm), 15 + 16) != Z_OK) {    /* gunzip */\n            free(state.state->out);\n            free(state.state->in);\n            state.state->size = 0;\n            gz_error(state, Z_MEM_ERROR, \"out of memory\");\n            return -1;\n        }\n    }\n\n    /* get at least the magic bytes in the input buffer */\n    if (strm->avail_in < 2) {\n        if (gz_avail(state) == -1)\n            return -1;\n        if (strm->avail_in == 0)\n            return 0;\n    }\n\n    /* look for gzip magic bytes -- if there, do gzip decoding (note: there is\n       a logical dilemma here when considering the case of a partially written\n       gzip file, to wit, if a single 31 byte is written, then we cannot tell\n       whether this is a single-byte file, or just a partially written gzip\n       file -- for here we assume that if a gzip file is being written, then\n       the header will be written in a single operation, so that reading a\n       single byte is sufficient indication that it is not a gzip file) */\n    if (strm->avail_in > 1 &&\n            ((strm->next_in[0] == 31 && strm->next_in[1] == 139) /* gz header */\n            || (strm->next_in[0] == 40 && strm->next_in[1] == 181))) { /* zstd header */\n        inflateReset(strm);\n        state.state->how = GZIP;\n        state.state->direct = 0;\n        return 0;\n    }\n\n    /* no gzip header -- if we were decoding gzip before, then this is trailing\n       garbage.  Ignore the trailing garbage and finish. */\n    if (state.state->direct == 0) {\n        strm->avail_in = 0;\n        state.state->eof = 1;\n        state.state->x.have = 0;\n        return 0;\n    }\n\n    /* doing raw i/o, copy any leftover input to output -- this assumes that\n       the output buffer is larger than the input buffer, which also assures\n       space for gzungetc() */\n    state.state->x.next = state.state->out;\n    if (strm->avail_in) {\n        memcpy(state.state->x.next, strm->next_in, strm->avail_in);\n        state.state->x.have = strm->avail_in;\n        strm->avail_in = 0;\n    }\n    state.state->how = COPY;\n    state.state->direct = 1;\n    return 0;\n}\n\n/* Decompress from input to the provided next_out and avail_out in the state.\n   On return, state.state->x.have and state.state->x.next point to the just decompressed\n   data.  If the gzip stream completes, state.state->how is reset to LOOK to look for\n   the next gzip stream or raw data, once state.state->x.have is depleted.  Returns 0\n   on success, -1 on failure. */\nlocal int gz_decomp(gz_statep state) {\n    int ret = Z_OK;\n    unsigned had;\n    z_streamp strm = &(state.state->strm);\n\n    /* fill output buffer up to end of deflate stream */\n    had = strm->avail_out;\n    do {\n        /* get more input for inflate() */\n        if (strm->avail_in == 0 && gz_avail(state) == -1)\n            return -1;\n        if (strm->avail_in == 0) {\n            gz_error(state, Z_BUF_ERROR, \"unexpected end of file\");\n            break;\n        }\n\n        /* decompress and handle errors */\n        ret = inflate(strm, Z_NO_FLUSH);\n        if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {\n            gz_error(state, Z_STREAM_ERROR,\n                     \"internal error: inflate stream corrupt\");\n            return -1;\n        }\n        if (ret == Z_MEM_ERROR) {\n            gz_error(state, Z_MEM_ERROR, \"out of memory\");\n            return -1;\n        }\n        if (ret == Z_DATA_ERROR) {              /* deflate stream invalid */\n            gz_error(state, Z_DATA_ERROR,\n                     strm->msg == NULL ? \"compressed data error\" : strm->msg);\n            return -1;\n        }\n    } while (strm->avail_out && ret != Z_STREAM_END);\n\n    /* update available output */\n    state.state->x.have = had - strm->avail_out;\n    state.state->x.next = strm->next_out - state.state->x.have;\n\n    /* if the gzip stream completed successfully, look for another */\n    if (ret == Z_STREAM_END)\n        state.state->how = LOOK;\n\n    /* good decompression */\n    return 0;\n}\n\n/* Fetch data and put it in the output buffer.  Assumes state.state->x.have is 0.\n   Data is either copied from the input file or decompressed from the input\n   file depending on state.state->how.  If state.state->how is LOOK, then a gzip header is\n   looked for to determine whether to copy or decompress.  Returns -1 on error,\n   otherwise 0.  gz_fetch() will leave state.state->how as COPY or GZIP unless the\n   end of the input file has been reached and all data has been processed.  */\nlocal int gz_fetch(gz_statep state) {\n    z_streamp strm = &(state.state->strm);\n\n    do {\n        switch(state.state->how) {\n        case LOOK:      /* -> LOOK, COPY (only if never GZIP), or GZIP */\n            if (gz_look(state) == -1)\n                return -1;\n            if (state.state->how == LOOK)\n                return 0;\n            break;\n        case COPY:      /* -> COPY */\n            if (gz_load(state, state.state->out, state.state->size << 1, &(state.state->x.have))\n                    == -1)\n                return -1;\n            state.state->x.next = state.state->out;\n            return 0;\n        case GZIP:      /* -> GZIP or LOOK (if end of gzip stream) */\n            strm->avail_out = state.state->size << 1;\n            strm->next_out = state.state->out;\n            if (gz_decomp(state) == -1)\n                return -1;\n        }\n    } while (state.state->x.have == 0 && (!state.state->eof || strm->avail_in));\n    return 0;\n}\n\n/* Skip len uncompressed bytes of output.  Return -1 on error, 0 on success. */\nlocal int gz_skip(gz_statep state, z_off64_t len) {\n    unsigned n;\n\n    /* skip over len bytes or reach end-of-file, whichever comes first */\n    while (len)\n        /* skip over whatever is in output buffer */\n        if (state.state->x.have) {\n            n = GT_OFF(state.state->x.have) || (z_off64_t)state.state->x.have > len ?\n                (unsigned)len : state.state->x.have;\n            state.state->x.have -= n;\n            state.state->x.next += n;\n            state.state->x.pos += n;\n            len -= n;\n        }\n\n        /* output buffer empty -- return if we're at the end of the input */\n        else if (state.state->eof && state.state->strm.avail_in == 0)\n            break;\n\n        /* need more data to skip -- load up output buffer */\n        else {\n            /* get more output, looking for header if required */\n            if (gz_fetch(state) == -1)\n                return -1;\n        }\n    return 0;\n}\n\n/* Read len bytes into buf from file, or less than len up to the end of the\n   input.  Return the number of bytes read.  If zero is returned, either the\n   end of file was reached, or there was an error.  state.state->err must be\n   consulted in that case to determine which. */\nlocal z_size_t gz_read(gz_statep state, voidp buf, z_size_t len) {\n    z_size_t got;\n    unsigned n;\n\n    /* if len is zero, avoid unnecessary operations */\n    if (len == 0)\n        return 0;\n\n    /* process a skip request */\n    if (state.state->seek) {\n        state.state->seek = 0;\n        if (gz_skip(state, state.state->skip) == -1)\n            return 0;\n    }\n\n    /* get len bytes to buf, or less than len if at the end */\n    got = 0;\n    do {\n        /* set n to the maximum amount of len that fits in an unsigned int */\n        n = -1;\n        if (n > len)\n            n = (unsigned)len;\n\n        /* first just try copying data from the output buffer */\n        if (state.state->x.have) {\n            if (state.state->x.have < n)\n                n = state.state->x.have;\n            memcpy(buf, state.state->x.next, n);\n            state.state->x.next += n;\n            state.state->x.have -= n;\n        }\n\n        /* output buffer empty -- return if we're at the end of the input */\n        else if (state.state->eof && state.state->strm.avail_in == 0) {\n            state.state->past = 1;        /* tried to read past end */\n            break;\n        }\n\n        /* need output data -- for small len or new stream load up our output\n           buffer */\n        else if (state.state->how == LOOK || n < (state.state->size << 1)) {\n            /* get more output, looking for header if required */\n            if (gz_fetch(state) == -1)\n                return 0;\n            continue;       /* no progress yet -- go back to copy above */\n            /* the copy above assures that we will leave with space in the\n               output buffer, allowing at least one gzungetc() to succeed */\n        }\n\n        /* large len -- read directly into user buffer */\n        else if (state.state->how == COPY) {      /* read directly */\n            if (gz_load(state, (unsigned char *)buf, n, &n) == -1)\n                return 0;\n        }\n\n        /* large len -- decompress directly into user buffer */\n        else {  /* state.state->how == GZIP */\n            state.state->strm.avail_out = n;\n            state.state->strm.next_out = (unsigned char *)buf;\n            if (gz_decomp(state) == -1)\n                return 0;\n            n = state.state->x.have;\n            state.state->x.have = 0;\n        }\n\n        /* update progress */\n        len -= n;\n        buf = (char *)buf + n;\n        got += n;\n        state.state->x.pos += n;\n    } while (len);\n\n    /* return number of bytes read into user buffer */\n    return got;\n}\n\n/* -- see zlib.h -- */\nint ZEXPORT gzread(gzFile file, voidp buf, unsigned len) {\n    gz_statep state;\n\n    /* get internal structure */\n    if (file == NULL)\n        return -1;\n    state.file = file;\n\n    /* check that we're reading and that there's no (serious) error */\n    if (state.state->mode != GZ_READ ||\n            (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))\n        return -1;\n\n    /* since an int is returned, make sure len fits in one, otherwise return\n       with an error (this avoids a flaw in the interface) */\n    if ((int)len < 0) {\n        gz_error(state, Z_STREAM_ERROR, \"request does not fit in an int\");\n        return -1;\n    }\n\n    /* read len or fewer bytes to buf */\n    len = (unsigned)gz_read(state, buf, len);\n\n    /* check for an error */\n    if (len == 0 && state.state->err != Z_OK && state.state->err != Z_BUF_ERROR)\n        return -1;\n\n    /* return the number of bytes read (this is assured to fit in an int) */\n    return (int)len;\n}\n\n/* -- see zlib.h -- */\nz_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems,\n                         gzFile file) {\n    z_size_t len;\n    gz_statep state;\n\n    /* get internal structure */\n    if (file == NULL)\n        return 0;\n    state.file = file;\n\n    /* check that we're reading and that there's no (serious) error */\n    if (state.state->mode != GZ_READ ||\n            (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))\n        return 0;\n\n    /* compute bytes to read -- error on overflow */\n    len = nitems * size;\n    if (size && len / size != nitems) {\n        gz_error(state, Z_STREAM_ERROR, \"request does not fit in a size_t\");\n        return 0;\n    }\n\n    /* read len or fewer bytes to buf, return the number of full items read */\n    return len ? gz_read(state, buf, len) / size : 0;\n}\n\n/* -- see zlib.h -- */\n#if ZLIB_VERNUM >= 0x1261\n#ifdef Z_PREFIX_SET\n#  undef z_gzgetc\n#else\n#  undef gzgetc\n#endif\n#endif\n\n#if ZLIB_VERNUM == 0x1260\n#  undef gzgetc\n#endif\n\n#if ZLIB_VERNUM <= 0x1250\nZEXTERN int ZEXPORT gzgetc _Z_OF((gzFile file));\nZEXTERN int ZEXPORT gzgetc_ _Z_OF((gzFile file));\n#endif\n\nint ZEXPORT gzgetc(gzFile file) {\n    int ret;\n    unsigned char buf[1];\n    gz_statep state;\n\n    /* get internal structure */\n    if (file == NULL)\n        return -1;\n    state.file = file;\n\n    /* check that we're reading and that there's no (serious) error */\n    if (state.state->mode != GZ_READ ||\n        (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))\n        return -1;\n\n    /* try output buffer (no need to check for skip request) */\n    if (state.state->x.have) {\n        state.state->x.have--;\n        state.state->x.pos++;\n        return *(state.state->x.next)++;\n    }\n\n    /* nothing there -- try gz_read() */\n    ret = (int)gz_read(state, buf, 1);\n    return ret < 1 ? -1 : buf[0];\n}\n\nint ZEXPORT gzgetc_(gzFile file) {\n    return gzgetc(file);\n}\n\n/* -- see zlib.h -- */\nint ZEXPORT gzungetc(int c, gzFile file) {\n    gz_statep state;\n\n    /* get internal structure */\n    if (file == NULL)\n        return -1;\n    state.file = file;\n\n    /* check that we're reading and that there's no (serious) error */\n    if (state.state->mode != GZ_READ ||\n        (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))\n        return -1;\n\n    /* process a skip request */\n    if (state.state->seek) {\n        state.state->seek = 0;\n        if (gz_skip(state, state.state->skip) == -1)\n            return -1;\n    }\n\n    /* can't push EOF */\n    if (c < 0)\n        return -1;\n\n    /* if output buffer empty, put byte at end (allows more pushing) */\n    if (state.state->x.have == 0) {\n        state.state->x.have = 1;\n        state.state->x.next = state.state->out + (state.state->size << 1) - 1;\n        state.state->x.next[0] = (unsigned char)c;\n        state.state->x.pos--;\n        state.state->past = 0;\n        return c;\n    }\n\n    /* if no room, give up (must have already done a gzungetc()) */\n    if (state.state->x.have == (state.state->size << 1)) {\n        gz_error(state, Z_DATA_ERROR, \"out of room to push characters\");\n        return -1;\n    }\n\n    /* slide output data if needed and insert byte before existing data */\n    if (state.state->x.next == state.state->out) {\n        unsigned char *src = state.state->out + state.state->x.have;\n        unsigned char *dest = state.state->out + (state.state->size << 1);\n        while (src > state.state->out)\n            *--dest = *--src;\n        state.state->x.next = dest;\n    }\n    state.state->x.have++;\n    state.state->x.next--;\n    state.state->x.next[0] = (unsigned char)c;\n    state.state->x.pos--;\n    state.state->past = 0;\n    return c;\n}\n\n/* -- see zlib.h -- */\nchar * ZEXPORT gzgets(gzFile file, char *buf, int len) {\n    unsigned left, n;\n    char *str;\n    unsigned char *eol;\n    gz_statep state;\n\n    /* check parameters and get internal structure */\n    if (file == NULL || buf == NULL || len < 1)\n        return NULL;\n    state.file = file;\n\n    /* check that we're reading and that there's no (serious) error */\n    if (state.state->mode != GZ_READ ||\n        (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))\n        return NULL;\n\n    /* process a skip request */\n    if (state.state->seek) {\n        state.state->seek = 0;\n        if (gz_skip(state, state.state->skip) == -1)\n            return NULL;\n    }\n\n    /* copy output bytes up to new line or len - 1, whichever comes first --\n       append a terminating zero to the string (we don't check for a zero in\n       the contents, let the user worry about that) */\n    str = buf;\n    left = (unsigned)len - 1;\n    if (left) do {\n        /* assure that something is in the output buffer */\n        if (state.state->x.have == 0 && gz_fetch(state) == -1)\n            return NULL;                /* error */\n        if (state.state->x.have == 0) {       /* end of file */\n            state.state->past = 1;            /* read past end */\n            break;                      /* return what we have */\n        }\n\n        /* look for end-of-line in current output buffer */\n        n = state.state->x.have > left ? left : state.state->x.have;\n        eol = (unsigned char *)memchr(state.state->x.next, '\\n', n);\n        if (eol != NULL)\n            n = (unsigned)(eol - state.state->x.next) + 1;\n\n        /* copy through end-of-line, or remainder if not found */\n        memcpy(buf, state.state->x.next, n);\n        state.state->x.have -= n;\n        state.state->x.next += n;\n        state.state->x.pos += n;\n        left -= n;\n        buf += n;\n    } while (left && eol == NULL);\n\n    /* return terminated string, or if nothing, end of file */\n    if (buf == str)\n        return NULL;\n    buf[0] = 0;\n    return str;\n}\n\n/* -- see zlib.h -- */\nint ZEXPORT gzdirect(gzFile file) {\n    gz_statep state;\n\n    /* get internal structure */\n    if (file == NULL)\n        return 0;\n    state.file = file;\n\n    /* if the state is not known, but we can find out, then do so (this is\n       mainly for right after a gzopen() or gzdopen()) */\n    if (state.state->mode == GZ_READ && state.state->how == LOOK && state.state->x.have == 0)\n        (void)gz_look(state);\n\n    /* return 1 if transparent, 0 if processing a gzip stream */\n    return state.state->direct;\n}\n\n/* -- see zlib.h -- */\nint ZEXPORT gzclose_r(gzFile file) {\n    int ret, err;\n    gz_statep state;\n\n    /* get internal structure */\n    if (file == NULL)\n        return Z_STREAM_ERROR;\n    state.file = file;\n\n    /* check that we're reading */\n    if (state.state->mode != GZ_READ)\n        return Z_STREAM_ERROR;\n\n    /* free memory and close file */\n    if (state.state->size) {\n        inflateEnd(&(state.state->strm));\n        free(state.state->out);\n        free(state.state->in);\n    }\n    err = state.state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;\n    gz_error(state, Z_OK, NULL);\n    free(state.state->path);\n    ret = close(state.state->fd);\n    free(state.state);\n    return ret ? Z_ERRNO : err;\n}\n"
  },
  {
    "path": "zlibWrapper/gzwrite.c",
    "content": "/* gzwrite.c contains minimal changes required to be compiled with zlibWrapper:\n * - gz_statep was converted to union to work with -Wstrict-aliasing=1      */\n\n /* gzwrite.c -- zlib functions for writing gzip files\n * Copyright (C) 2004-2017 Mark Adler\n * For conditions of distribution and use, see https://www.zlib.net/zlib_license.html\n */\n\n#include <assert.h>\n\n#include \"gzguts.h\"\n\n/* Local functions */\nlocal int gz_init _Z_OF((gz_statep));\nlocal int gz_comp _Z_OF((gz_statep, int));\nlocal int gz_zero _Z_OF((gz_statep, z_off64_t));\nlocal z_size_t gz_write _Z_OF((gz_statep, voidpc, z_size_t));\n\n/* Initialize state for writing a gzip file.  Mark initialization by setting\n   state.state->size to non-zero.  Return -1 on a memory allocation failure, or 0 on\n   success. */\nlocal int gz_init(gz_statep state) {\n    int ret;\n    z_streamp strm = &(state.state->strm);\n\n    /* allocate input buffer (double size for gzprintf) */\n    state.state->in = (unsigned char*)malloc(state.state->want << 1);\n    if (state.state->in == NULL) {\n        gz_error(state, Z_MEM_ERROR, \"out of memory\");\n        return -1;\n    }\n\n    /* only need output buffer and deflate state if compressing */\n    if (!state.state->direct) {\n        /* allocate output buffer */\n        state.state->out = (unsigned char*)malloc(state.state->want);\n        if (state.state->out == NULL) {\n            free(state.state->in);\n            gz_error(state, Z_MEM_ERROR, \"out of memory\");\n            return -1;\n        }\n\n        /* allocate deflate memory, set up for gzip compression */\n        strm->zalloc = Z_NULL;\n        strm->zfree = Z_NULL;\n        strm->opaque = Z_NULL;\n        ret = deflateInit2(strm, state.state->level, Z_DEFLATED,\n                           MAX_WBITS + 16, DEF_MEM_LEVEL, state.state->strategy);\n        if (ret != Z_OK) {\n            free(state.state->out);\n            free(state.state->in);\n            gz_error(state, Z_MEM_ERROR, \"out of memory\");\n            return -1;\n        }\n        strm->next_in = NULL;\n    }\n\n    /* mark state as initialized */\n    state.state->size = state.state->want;\n\n    /* initialize write buffer if compressing */\n    if (!state.state->direct) {\n        strm->avail_out = state.state->size;\n        strm->next_out = state.state->out;\n        state.state->x.next = strm->next_out;\n    }\n\n    return 0;\n}\n\n/* Compress whatever is at avail_in and next_in and write to the output file.\n   Return -1 if there is an error writing to the output file or if gz_init()\n   fails to allocate memory, otherwise 0.  flush is assumed to be a valid\n   deflate() flush value.  If flush is Z_FINISH, then the deflate() state is\n   reset to start a new gzip stream.  If gz->direct is true, then simply write\n   to the output file without compressing, and ignore flush. */\nlocal int gz_comp(gz_statep state, int flush) {\n    int ret, writ;\n    unsigned have, put, max = ((unsigned)-1 >> 2) + 1;\n    z_streamp strm = &(state.state->strm);\n\n    /* allocate memory if this is the first time through */\n    if (state.state->size == 0 && gz_init(state) == -1)\n        return -1;\n\n    /* write directly if requested */\n    if (state.state->direct) {\n        while (strm->avail_in) {\n            put = strm->avail_in > max ? max : strm->avail_in;\n            writ = (int)write(state.state->fd, strm->next_in, put);\n            if (writ < 0) {\n                gz_error(state, Z_ERRNO, zstrerror());\n                return -1;\n            }\n            strm->avail_in -= (unsigned)writ;\n            strm->next_in += writ;\n        }\n        return 0;\n    }\n\n    /* run deflate() on provided input until it produces no more output */\n    ret = Z_OK;\n    do {\n        /* write out current buffer contents if full, or if flushing, but if\n           doing Z_FINISH then don't write until we get to Z_STREAM_END */\n        if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&\n            (flush != Z_FINISH || ret == Z_STREAM_END))) {\n            while (strm->next_out > state.state->x.next) {\n                put = strm->next_out - state.state->x.next > (int)max ? max :\n                      (unsigned)(strm->next_out - state.state->x.next);\n                writ = (int)write(state.state->fd, state.state->x.next, put);\n                if (writ < 0) {\n                    gz_error(state, Z_ERRNO, zstrerror());\n                    return -1;\n                }\n                state.state->x.next += writ;\n            }\n            if (strm->avail_out == 0) {\n                strm->avail_out = state.state->size;\n                strm->next_out = state.state->out;\n                state.state->x.next = state.state->out;\n            }\n        }\n\n        /* compress */\n        have = strm->avail_out;\n        ret = deflate(strm, flush);\n        if (ret == Z_STREAM_ERROR) {\n            gz_error(state, Z_STREAM_ERROR,\n                      \"internal error: deflate stream corrupt\");\n            return -1;\n        }\n        have -= strm->avail_out;\n    } while (have);\n\n    /* if that completed a deflate stream, allow another to start */\n    if (flush == Z_FINISH)\n        deflateReset(strm);\n\n    /* all done, no errors */\n    return 0;\n}\n\n/* Compress len zeros to output.  Return -1 on a write error or memory\n   allocation failure by gz_comp(), or 0 on success. */\nlocal int gz_zero(gz_statep state, z_off64_t len) {\n    int first;\n    unsigned n;\n    z_streamp strm = &(state.state->strm);\n\n    /* consume whatever's left in the input buffer */\n    if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)\n        return -1;\n\n    /* compress len zeros (len guaranteed > 0) */\n    first = 1;\n    while (len) {\n        n = GT_OFF(state.state->size) || (z_off64_t)state.state->size > len ?\n            (unsigned)len : state.state->size;\n        if (first) {\n            memset(state.state->in, 0, n);\n            first = 0;\n        }\n        strm->avail_in = n;\n        strm->next_in = state.state->in;\n        state.state->x.pos += n;\n        if (gz_comp(state, Z_NO_FLUSH) == -1)\n            return -1;\n        len -= n;\n    }\n    return 0;\n}\n\n/* Write len bytes from buf to file.  Return the number of bytes written.  If\n   the returned value is less than len, then there was an error. */\nlocal z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) {\n    z_size_t put = len;\n\n    /* if len is zero, avoid unnecessary operations */\n    if (len == 0)\n        return 0;\n\n    /* allocate memory if this is the first time through */\n    if (state.state->size == 0 && gz_init(state) == -1)\n        return 0;\n\n    /* check for seek request */\n    if (state.state->seek) {\n        state.state->seek = 0;\n        if (gz_zero(state, state.state->skip) == -1)\n            return 0;\n    }\n\n    /* for small len, copy to input buffer, otherwise compress directly */\n    if (len < state.state->size) {\n        /* copy to input buffer, compress when full */\n        do {\n            z_size_t have, copy;\n\n            if (state.state->strm.avail_in == 0)\n                state.state->strm.next_in = state.state->in;\n            have = (unsigned)((state.state->strm.next_in + state.state->strm.avail_in) -\n                              state.state->in);\n            copy = state.state->size - have;\n            if (copy > len)\n                copy = len;\n            memcpy(state.state->in + have, buf, copy);\n            state.state->strm.avail_in += copy;\n            state.state->x.pos += copy;\n            buf = (const char *)buf + copy;\n            len -= copy;\n            if (len && gz_comp(state, Z_NO_FLUSH) == -1)\n                return 0;\n        } while (len);\n    }\n    else {\n        /* consume whatever's left in the input buffer */\n        if (state.state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)\n            return 0;\n\n        /* directly compress user buffer to file */\n        state.state->strm.next_in = (z_const Bytef *)buf;\n        do {\n            z_size_t n = (unsigned)-1;\n            if (n > len)\n                n = len;\n            state.state->strm.avail_in = (uInt)n;\n            state.state->x.pos += n;\n            if (gz_comp(state, Z_NO_FLUSH) == -1)\n                return 0;\n            len -= n;\n        } while (len);\n    }\n\n    /* input was all buffered or compressed */\n    return put;\n}\n\n/* -- see zlib.h -- */\nint ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) {\n    gz_statep state;\n\n    /* get internal structure */\n    if (file == NULL)\n        return 0;\n    state.file = file;\n\n    /* check that we're writing and that there's no error */\n    if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)\n        return 0;\n\n    /* since an int is returned, make sure len fits in one, otherwise return\n       with an error (this avoids a flaw in the interface) */\n    if ((int)len < 0) {\n        gz_error(state, Z_DATA_ERROR, \"requested length does not fit in int\");\n        return 0;\n    }\n\n    /* write len bytes from buf (the return value will fit in an int) */\n    return (int)gz_write(state, buf, len);\n}\n\n/* -- see zlib.h -- */\nz_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems,\n                          gzFile file) {\n    z_size_t len;\n    gz_statep state;\n\n    /* get internal structure */\n    assert(size != 0);\n    if (file == NULL)\n        return 0;\n    state.file = file;\n\n    /* check that we're writing and that there's no error */\n    if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)\n        return 0;\n\n    /* compute bytes to read -- error on overflow */\n    len = nitems * size;\n    if (size && (len / size != nitems)) {\n        gz_error(state, Z_STREAM_ERROR, \"request does not fit in a size_t\");\n        return 0;\n    }\n\n    /* write len bytes to buf, return the number of full items written */\n    return len ? gz_write(state, buf, len) / size : 0;\n}\n\n/* -- see zlib.h -- */\nint ZEXPORT gzputc(gzFile file, int c) {\n    unsigned have;\n    unsigned char buf[1];\n    gz_statep state;\n    z_streamp strm;\n\n    /* get internal structure */\n    if (file == NULL)\n        return -1;\n    state.file = file;\n    strm = &(state.state->strm);\n\n    /* check that we're writing and that there's no error */\n    if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)\n        return -1;\n\n    /* check for seek request */\n    if (state.state->seek) {\n        state.state->seek = 0;\n        if (gz_zero(state, state.state->skip) == -1)\n            return -1;\n    }\n\n    /* try writing to input buffer for speed (state.state->size == 0 if buffer not\n       initialized) */\n    if (state.state->size) {\n        if (strm->avail_in == 0)\n            strm->next_in = state.state->in;\n        have = (unsigned)((strm->next_in + strm->avail_in) - state.state->in);\n        if (have < state.state->size) {\n            state.state->in[have] = (unsigned char)c;\n            strm->avail_in++;\n            state.state->x.pos++;\n            return c & 0xff;\n        }\n    }\n\n    /* no room in buffer or not initialized, use gz_write() */\n    buf[0] = (unsigned char)c;\n    if (gz_write(state, buf, 1) != 1)\n        return -1;\n    return c & 0xff;\n}\n\n/* -- see zlib.h -- */\nint ZEXPORT gzputs(gzFile file, const char *str) {\n    int ret;\n    z_size_t len;\n    gz_statep state;\n\n    /* get internal structure */\n    if (file == NULL)\n        return -1;\n    state.file = file;\n\n    /* check that we're writing and that there's no error */\n    if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)\n        return -1;\n\n    /* write string */\n    len = strlen(str);\n    ret = (int)gz_write(state, str, len);\n    return ret == 0 && len != 0 ? -1 : ret;\n}\n\n#if defined(STDC) || defined(Z_HAVE_STDARG_H)\n#include <stdarg.h>\n\n/* -- see zlib.h -- */\nint ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) {\n    int len;\n    unsigned left;\n    char *next;\n    gz_statep state;\n    z_streamp strm;\n\n    /* get internal structure */\n    if (file == NULL)\n        return Z_STREAM_ERROR;\n    state.file = file;\n    strm = &(state.state->strm);\n\n    /* check that we're writing and that there's no error */\n    if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)\n        return Z_STREAM_ERROR;\n\n    /* make sure we have some buffer space */\n    if (state.state->size == 0 && gz_init(state) == -1)\n        return state.state->err;\n\n    /* check for seek request */\n    if (state.state->seek) {\n        state.state->seek = 0;\n        if (gz_zero(state, state.state->skip) == -1)\n            return state.state->err;\n    }\n\n    /* do the printf() into the input buffer, put length in len -- the input\n       buffer is double-sized just for this function, so there is guaranteed to\n       be state.state->size bytes available after the current contents */\n    if (strm->avail_in == 0)\n        strm->next_in = state.state->in;\n    next = (char *)(state.state->in + (strm->next_in - state.state->in) + strm->avail_in);\n    next[state.state->size - 1] = 0;\n#ifdef NO_vsnprintf\n#  ifdef HAS_vsprintf_void\n    (void)vsprintf(next, format, va);\n    for (len = 0; len < state.state->size; len++)\n        if (next[len] == 0) break;\n#  else\n    len = vsprintf(next, format, va);\n#  endif\n#else\n#  ifdef HAS_vsnprintf_void\n    (void)vsnprintf(next, state.state->size, format, va);\n    len = strlen(next);\n#  else\n    len = vsnprintf(next, state.state->size, format, va);\n#  endif\n#endif\n\n    /* check that printf() results fit in buffer */\n    if (len == 0 || (unsigned)len >= state.state->size || next[state.state->size - 1] != 0)\n        return 0;\n\n    /* update buffer and position, compress first half if past that */\n    strm->avail_in += (unsigned)len;\n    state.state->x.pos += len;\n    if (strm->avail_in >= state.state->size) {\n        left = strm->avail_in - state.state->size;\n        strm->avail_in = state.state->size;\n        if (gz_comp(state, Z_NO_FLUSH) == -1)\n            return state.state->err;\n        memcpy(state.state->in, state.state->in + state.state->size, left);\n        strm->next_in = state.state->in;\n        strm->avail_in = left;\n    }\n    return len;\n}\n\nint ZEXPORTVA gzprintf(gzFile file, const char *format, ...) {\n    va_list va;\n    int ret;\n\n    va_start(va, format);\n    ret = gzvprintf(file, format, va);\n    va_end(va);\n    return ret;\n}\n\n#else /* !STDC && !Z_HAVE_STDARG_H */\n\n/* -- see zlib.h -- */\nint ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3,\n                       int a4, int a5, int a6, int a7, int a8, int a9, int a10,\n                       int a11, int a12, int a13, int a14, int a15, int a16,\n                       int a17, int a18, int a19, int a20) {\n    unsigned len, left;\n    char *next;\n    gz_statep state;\n    z_streamp strm;\n\n    /* get internal structure */\n    if (file == NULL)\n        return Z_STREAM_ERROR;\n    state = (gz_statep)file;\n    strm = &(state.state->strm);\n\n    /* check that can really pass pointer in ints */\n    if (sizeof(int) != sizeof(void *))\n        return Z_STREAM_ERROR;\n\n    /* check that we're writing and that there's no error */\n    if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)\n        return Z_STREAM_ERROR;\n\n    /* make sure we have some buffer space */\n    if (state.state->size == 0 && gz_init(state) == -1)\n        return state.state->error;\n\n    /* check for seek request */\n    if (state.state->seek) {\n        state.state->seek = 0;\n        if (gz_zero(state, state.state->skip) == -1)\n            return state.state->error;\n    }\n\n    /* do the printf() into the input buffer, put length in len -- the input\n       buffer is double-sized just for this function, so there is guaranteed to\n       be state.state->size bytes available after the current contents */\n    if (strm->avail_in == 0)\n        strm->next_in = state.state->in;\n    next = (char *)(strm->next_in + strm->avail_in);\n    next[state.state->size - 1] = 0;\n#ifdef NO_snprintf\n#  ifdef HAS_sprintf_void\n    sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,\n            a13, a14, a15, a16, a17, a18, a19, a20);\n    for (len = 0; len < size; len++)\n        if (next[len] == 0)\n            break;\n#  else\n    len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,\n                  a12, a13, a14, a15, a16, a17, a18, a19, a20);\n#  endif\n#else\n#  ifdef HAS_snprintf_void\n    snprintf(next, state.state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,\n             a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);\n    len = strlen(next);\n#  else\n    len = snprintf(next, state.state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,\n                   a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);\n#  endif\n#endif\n\n    /* check that printf() results fit in buffer */\n    if (len == 0 || len >= state.state->size || next[state.state->size - 1] != 0)\n        return 0;\n\n    /* update buffer and position, compress first half if past that */\n    strm->avail_in += len;\n    state.state->x.pos += len;\n    if (strm->avail_in >= state.state->size) {\n        left = strm->avail_in - state.state->size;\n        strm->avail_in = state.state->size;\n        if (gz_comp(state, Z_NO_FLUSH) == -1)\n            return state.state->err;\n        memcpy(state.state->in, state.state->in + state.state->size, left);\n        strm->next_in = state.state->in;\n        strm->avail_in = left;\n    }\n    return (int)len;\n}\n\n#endif\n\n/* -- see zlib.h -- */\nint ZEXPORT gzflush(gzFile file, int flush) {\n    gz_statep state;\n\n    /* get internal structure */\n    if (file == NULL)\n        return Z_STREAM_ERROR;\n    state.file = file;\n\n    /* check that we're writing and that there's no error */\n    if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)\n        return Z_STREAM_ERROR;\n\n    /* check flush parameter */\n    if (flush < 0 || flush > Z_FINISH)\n        return Z_STREAM_ERROR;\n\n    /* check for seek request */\n    if (state.state->seek) {\n        state.state->seek = 0;\n        if (gz_zero(state, state.state->skip) == -1)\n            return state.state->err;\n    }\n\n    /* compress remaining data with requested flush */\n    (void)gz_comp(state, flush);\n    return state.state->err;\n}\n\n/* -- see zlib.h -- */\nint ZEXPORT gzsetparams(gzFile file, int level, int strategy) {\n    gz_statep state;\n    z_streamp strm;\n\n    /* get internal structure */\n    if (file == NULL)\n        return Z_STREAM_ERROR;\n    state.file = file;\n    strm = &(state.state->strm);\n\n    /* check that we're writing and that there's no error */\n    if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)\n        return Z_STREAM_ERROR;\n\n    /* if no change is requested, then do nothing */\n    if (level == state.state->level && strategy == state.state->strategy)\n        return Z_OK;\n\n    /* check for seek request */\n    if (state.state->seek) {\n        state.state->seek = 0;\n        if (gz_zero(state, state.state->skip) == -1)\n            return state.state->err;\n    }\n\n    /* change compression parameters for subsequent input */\n    if (state.state->size) {\n        /* flush previous input with previous parameters before changing */\n        if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)\n            return state.state->err;\n        deflateParams(strm, level, strategy);\n    }\n    state.state->level = level;\n    state.state->strategy = strategy;\n    return Z_OK;\n}\n\n/* -- see zlib.h -- */\nint ZEXPORT gzclose_w(gzFile file) {\n    int ret = Z_OK;\n    gz_statep state;\n\n    /* get internal structure */\n    if (file == NULL)\n        return Z_STREAM_ERROR;\n    state.file = file;\n\n    /* check that we're writing */\n    if (state.state->mode != GZ_WRITE)\n        return Z_STREAM_ERROR;\n\n    /* check for seek request */\n    if (state.state->seek) {\n        state.state->seek = 0;\n        if (gz_zero(state, state.state->skip) == -1)\n            ret = state.state->err;\n    }\n\n    /* flush, free memory, and close file */\n    if (gz_comp(state, Z_FINISH) == -1)\n        ret = state.state->err;\n    if (state.state->size) {\n        if (!state.state->direct) {\n            (void)deflateEnd(&(state.state->strm));\n            free(state.state->out);\n        }\n        free(state.state->in);\n    }\n    gz_error(state, Z_OK, NULL);\n    free(state.state->path);\n    if (close(state.state->fd) == -1)\n        ret = Z_ERRNO;\n    free(state.state);\n    return ret;\n}\n"
  },
  {
    "path": "zlibWrapper/zstd_zlibwrapper.c",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/* ===   Tuning parameters   === */\n#ifndef ZWRAP_USE_ZSTD\n    #define ZWRAP_USE_ZSTD 0\n#endif\n\n\n/* ===   Dependencies   === */\n#include <stdlib.h>\n#include <stdio.h>                 /* vsprintf */\n#include <stdarg.h>                /* va_list, for z_gzprintf */\n#include <string.h>\n#define NO_DUMMY_DECL\n#define ZLIB_CONST\n#include <zlib.h>                  /* without #define Z_PREFIX */\n#include \"zstd_zlibwrapper.h\"\n#define ZSTD_STATIC_LINKING_ONLY   /* ZSTD_isFrame, ZSTD_MAGICNUMBER, ZSTD_customMem */\n#include \"zstd.h\"\n\n\n/* ===   Constants   === */\n#define Z_INFLATE_SYNC              8\n#define ZLIB_HEADERSIZE             4\n#define ZSTD_HEADERSIZE             ZSTD_FRAMEHEADERSIZE_MIN(ZSTD_f_zstd1)\n#define ZWRAP_DEFAULT_CLEVEL        3   /* Z_DEFAULT_COMPRESSION is translated to ZWRAP_DEFAULT_CLEVEL for zstd */\n\n\n/* ===   Debug   === */\n#define LOG_WRAPPERC(...)  /* fprintf(stderr, __VA_ARGS__) */\n#define LOG_WRAPPERD(...)  /* fprintf(stderr, __VA_ARGS__) */\n\n#define FINISH_WITH_GZ_ERR(msg) { (void)msg; return Z_STREAM_ERROR; }\n#define FINISH_WITH_NULL_ERR(msg) { (void)msg; return NULL; }\n\n/* ===   Utility   === */\n\n#define MIN(x,y) ((x) < (y) ? (x) : (y))\n\nstatic unsigned ZWRAP_isLittleEndian(void)\n{\n    const union { unsigned u; char c[4]; } one = { 1 };   /* don't use static : performance detrimental  */\n    return one.c[0];\n}\n\n#ifndef __has_builtin\n# define __has_builtin(x) 0\n#endif\n\nstatic unsigned ZWRAP_swap32(unsigned in)\n{\n#if defined(_MSC_VER)     /* Visual Studio */\n    return _byteswap_ulong(in);\n#elif (defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) \\\n  || (defined(__clang__) && __has_builtin(__builtin_bswap32))\n    return __builtin_bswap32(in);\n#else\n    return  ((in << 24) & 0xff000000 ) |\n            ((in <<  8) & 0x00ff0000 ) |\n            ((in >>  8) & 0x0000ff00 ) |\n            ((in >> 24) & 0x000000ff );\n#endif\n}\n\nstatic unsigned ZWRAP_readLE32(const void* ptr)\n{\n    unsigned value;\n    memcpy(&value, ptr, sizeof(value));\n    if (ZWRAP_isLittleEndian())\n        return value;\n    else\n        return ZWRAP_swap32(value);\n}\n\n\n/* ===   Wrapper   === */\nstatic int g_ZWRAP_useZSTDcompression = ZWRAP_USE_ZSTD; /* 0 = don't use ZSTD */\n\nvoid ZWRAP_useZSTDcompression(int turn_on) { g_ZWRAP_useZSTDcompression = turn_on; }\n\nint ZWRAP_isUsingZSTDcompression(void) { return g_ZWRAP_useZSTDcompression; }\n\n\n\nstatic ZWRAP_decompress_type g_ZWRAPdecompressionType = ZWRAP_AUTO;\n\nvoid ZWRAP_setDecompressionType(ZWRAP_decompress_type type) { g_ZWRAPdecompressionType = type; }\n\nZWRAP_decompress_type ZWRAP_getDecompressionType(void) { return g_ZWRAPdecompressionType; }\n\n\n\nconst char * zstdVersion(void) { return ZSTD_VERSION_STRING; }\n\nZEXTERN const char * ZEXPORT z_zlibVersion _Z_OF((void)) { return zlibVersion();  }\n\nstatic void* ZWRAP_allocFunction(void* opaque, size_t size)\n{\n    z_streamp strm = (z_streamp) opaque;\n    void* address = strm->zalloc(strm->opaque, 1, (uInt)size);\n    /* LOG_WRAPPERC(\"ZWRAP alloc %p, %d \\n\", address, (int)size); */\n    return address;\n}\n\nstatic void ZWRAP_freeFunction(void* opaque, void* address)\n{\n    z_streamp strm = (z_streamp) opaque;\n    strm->zfree(strm->opaque, address);\n   /* if (address) LOG_WRAPPERC(\"ZWRAP free %p \\n\", address); */\n}\n\nstatic void* ZWRAP_customMalloc(size_t size, ZSTD_customMem customMem)\n{\n    if (customMem.customAlloc)\n        return customMem.customAlloc(customMem.opaque, size);\n    return malloc(size);\n}\n\nstatic void* ZWRAP_customCalloc(size_t size, ZSTD_customMem customMem)\n{\n    if (customMem.customAlloc) {\n        /* calloc implemented as malloc+memset;\n         * not as efficient as calloc, but next best guess for custom malloc */\n        void* const ptr = customMem.customAlloc(customMem.opaque, size);\n        memset(ptr, 0, size);\n        return ptr;\n    }\n    return calloc(1, size);\n}\n\nstatic void ZWRAP_customFree(void* ptr, ZSTD_customMem customMem)\n{\n    if (ptr!=NULL) {\n        if (customMem.customFree)\n            customMem.customFree(customMem.opaque, ptr);\n        else\n            free(ptr);\n    }\n}\n\n\n\n/* ===   Compression   === */\ntypedef enum { ZWRAP_useInit, ZWRAP_useReset, ZWRAP_streamEnd } ZWRAP_state_t;\n\ntypedef struct {\n    ZSTD_CStream* zbc;\n    int compressionLevel;\n    int streamEnd; /* a flag to signal the end of a stream */\n    unsigned long long totalInBytes; /* we need it as strm->total_in can be reset by user */\n    ZSTD_customMem customMem;\n    z_stream allocFunc; /* copy of zalloc, zfree, opaque */\n    ZSTD_inBuffer inBuffer;\n    ZSTD_outBuffer outBuffer;\n    ZWRAP_state_t comprState;\n    unsigned long long pledgedSrcSize;\n} ZWRAP_CCtx;\n\n/* typedef ZWRAP_CCtx internal_state; */\n\n\n\nstatic size_t ZWRAP_freeCCtx(ZWRAP_CCtx* zwc)\n{\n    if (zwc==NULL) return 0;   /* support free on NULL */\n    ZSTD_freeCStream(zwc->zbc);\n    ZWRAP_customFree(zwc, zwc->customMem);\n    return 0;\n}\n\n\nstatic ZWRAP_CCtx* ZWRAP_createCCtx(z_streamp strm)\n{\n    ZWRAP_CCtx* zwc;\n    ZSTD_customMem customMem = { NULL, NULL, NULL };\n\n    if (strm->zalloc && strm->zfree) {\n        customMem.customAlloc = ZWRAP_allocFunction;\n        customMem.customFree = ZWRAP_freeFunction;\n    }\n    customMem.opaque = strm;\n\n    zwc = (ZWRAP_CCtx*)ZWRAP_customCalloc(sizeof(ZWRAP_CCtx), customMem);\n    if (zwc == NULL) return NULL;\n    zwc->allocFunc = *strm;\n    customMem.opaque = &zwc->allocFunc;\n    zwc->customMem = customMem;\n\n    return zwc;\n}\n\n\nstatic int ZWRAP_initializeCStream(ZWRAP_CCtx* zwc, const void* dict, size_t dictSize, unsigned long long pledgedSrcSize)\n{\n    LOG_WRAPPERC(\"- ZWRAP_initializeCStream=%p\\n\", zwc);\n    if (zwc == NULL || zwc->zbc == NULL) return Z_STREAM_ERROR;\n\n    if (!pledgedSrcSize) pledgedSrcSize = zwc->pledgedSrcSize;\n    {   unsigned initErr = 0;\n        ZSTD_parameters const params = ZSTD_getParams(zwc->compressionLevel, pledgedSrcSize, dictSize);\n        ZSTD_CCtx_params* cctxParams = ZSTD_createCCtxParams();\n        if (!cctxParams) return Z_STREAM_ERROR;\n        LOG_WRAPPERC(\"pledgedSrcSize=%d windowLog=%d chainLog=%d hashLog=%d searchLog=%d minMatch=%d strategy=%d\\n\",\n                    (int)pledgedSrcSize, params.cParams.windowLog, params.cParams.chainLog, params.cParams.hashLog, params.cParams.searchLog, params.cParams.minMatch, params.cParams.strategy);\n\n        initErr |= ZSTD_isError(ZSTD_CCtx_reset(zwc->zbc, ZSTD_reset_session_only));\n        initErr |= ZSTD_isError(ZSTD_CCtxParams_init_advanced(cctxParams, params));\n        initErr |= ZSTD_isError(ZSTD_CCtx_setParametersUsingCCtxParams(zwc->zbc, cctxParams));\n        initErr |= ZSTD_isError(ZSTD_CCtx_setPledgedSrcSize(zwc->zbc, pledgedSrcSize));\n        initErr |= ZSTD_isError(ZSTD_CCtx_loadDictionary(zwc->zbc, dict, dictSize));\n\n        ZSTD_freeCCtxParams(cctxParams);\n        if (initErr) return Z_STREAM_ERROR;\n    }\n\n    return Z_OK;\n}\n\n\nstatic int ZWRAPC_finishWithError(ZWRAP_CCtx* zwc, z_streamp strm, int error)\n{\n    LOG_WRAPPERC(\"- ZWRAPC_finishWithError=%d\\n\", error);\n    if (zwc) ZWRAP_freeCCtx(zwc);\n    if (strm) strm->state = NULL;\n    return (error) ? error : Z_STREAM_ERROR;\n}\n\n\nstatic int ZWRAPC_finishWithErrorMsg(z_streamp strm, char* message)\n{\n    ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->state;\n    strm->msg = message;\n    if (zwc == NULL) return Z_STREAM_ERROR;\n\n    return ZWRAPC_finishWithError(zwc, strm, 0);\n}\n\n\nint ZWRAP_setPledgedSrcSize(z_streamp strm, unsigned long long pledgedSrcSize)\n{\n    ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->state;\n    if (zwc == NULL) return Z_STREAM_ERROR;\n\n    zwc->pledgedSrcSize = pledgedSrcSize;\n    zwc->comprState = ZWRAP_useInit;\n    return Z_OK;\n}\n\nstatic struct internal_state* convert_into_sis(void* ptr)\n{\n    return (struct internal_state*) ptr;\n}\n\nZEXTERN int ZEXPORT z_deflateInit_ _Z_OF((z_streamp strm, int level,\n                                     const char *version, int stream_size))\n{\n    ZWRAP_CCtx* zwc;\n\n    LOG_WRAPPERC(\"- deflateInit level=%d\\n\", level);\n    if (!g_ZWRAP_useZSTDcompression) {\n        return deflateInit_((strm), (level), version, stream_size);\n    }\n\n    zwc = ZWRAP_createCCtx(strm);\n    if (zwc == NULL) return Z_MEM_ERROR;\n\n    if (level == Z_DEFAULT_COMPRESSION)\n        level = ZWRAP_DEFAULT_CLEVEL;\n\n    zwc->streamEnd = 0;\n    zwc->totalInBytes = 0;\n    zwc->compressionLevel = level;\n    strm->state = convert_into_sis(zwc); /* use state which in not used by user */\n    strm->total_in = 0;\n    strm->total_out = 0;\n    strm->adler = 0;\n    return Z_OK;\n}\n\n\nZEXTERN int ZEXPORT z_deflateInit2_ _Z_OF((z_streamp strm, int level, int method,\n                                      int windowBits, int memLevel,\n                                      int strategy, const char *version,\n                                      int stream_size))\n{\n    if (!g_ZWRAP_useZSTDcompression)\n        return deflateInit2_(strm, level, method, windowBits, memLevel, strategy, version, stream_size);\n\n    return z_deflateInit_ (strm, level, version, stream_size);\n}\n\n\nint ZWRAP_deflateReset_keepDict(z_streamp strm)\n{\n    LOG_WRAPPERC(\"- ZWRAP_deflateReset_keepDict\\n\");\n    if (!g_ZWRAP_useZSTDcompression)\n        return deflateReset(strm);\n\n    { ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->state;\n      if (zwc) {\n          zwc->streamEnd = 0;\n          zwc->totalInBytes = 0;\n      }\n    }\n\n    strm->total_in = 0;\n    strm->total_out = 0;\n    strm->adler = 0;\n    return Z_OK;\n}\n\n\nZEXTERN int ZEXPORT z_deflateReset _Z_OF((z_streamp strm))\n{\n    LOG_WRAPPERC(\"- deflateReset\\n\");\n    if (!g_ZWRAP_useZSTDcompression)\n        return deflateReset(strm);\n\n    ZWRAP_deflateReset_keepDict(strm);\n\n    { ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->state;\n      if (zwc) zwc->comprState = ZWRAP_useInit;\n    }\n    return Z_OK;\n}\n\n\nZEXTERN int ZEXPORT z_deflateSetDictionary _Z_OF((z_streamp strm,\n                                             const Bytef *dictionary,\n                                             uInt  dictLength))\n{\n    if (!g_ZWRAP_useZSTDcompression) {\n        LOG_WRAPPERC(\"- deflateSetDictionary\\n\");\n        return deflateSetDictionary(strm, dictionary, dictLength);\n    }\n\n    {   ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->state;\n        LOG_WRAPPERC(\"- deflateSetDictionary level=%d\\n\", (int)zwc->compressionLevel);\n        if (!zwc) return Z_STREAM_ERROR;\n        if (zwc->zbc == NULL) {\n            zwc->zbc = ZSTD_createCStream_advanced(zwc->customMem);\n            if (zwc->zbc == NULL) return ZWRAPC_finishWithError(zwc, strm, 0);\n        }\n        { int res = ZWRAP_initializeCStream(zwc, dictionary, dictLength, ZSTD_CONTENTSIZE_UNKNOWN);\n          if (res != Z_OK) return ZWRAPC_finishWithError(zwc, strm, res); }\n        zwc->comprState = ZWRAP_useReset;\n    }\n\n    return Z_OK;\n}\n\n\nZEXTERN int ZEXPORT z_deflate _Z_OF((z_streamp strm, int flush))\n{\n    ZWRAP_CCtx* zwc;\n\n    if (!g_ZWRAP_useZSTDcompression) {\n        LOG_WRAPPERC(\"- deflate1 flush=%d avail_in=%d avail_out=%d total_in=%d total_out=%d\\n\",\n                    (int)flush, (int)strm->avail_in, (int)strm->avail_out, (int)strm->total_in, (int)strm->total_out);\n        return deflate(strm, flush);\n    }\n\n    zwc = (ZWRAP_CCtx*) strm->state;\n    if (zwc == NULL) { LOG_WRAPPERC(\"zwc == NULL\\n\"); return Z_STREAM_ERROR; }\n\n    if (zwc->zbc == NULL) {\n        zwc->zbc = ZSTD_createCStream_advanced(zwc->customMem);\n        if (zwc->zbc == NULL) return ZWRAPC_finishWithError(zwc, strm, 0);\n        { int const initErr = ZWRAP_initializeCStream(zwc, NULL, 0, (flush == Z_FINISH) ? strm->avail_in : ZSTD_CONTENTSIZE_UNKNOWN);\n          if (initErr != Z_OK) return ZWRAPC_finishWithError(zwc, strm, initErr); }\n        if (flush != Z_FINISH) zwc->comprState = ZWRAP_useReset;\n    } else {\n        if (zwc->totalInBytes == 0) {\n            if (zwc->comprState == ZWRAP_useReset) {\n                size_t resetErr = ZSTD_CCtx_reset(zwc->zbc, ZSTD_reset_session_only);\n                if (ZSTD_isError(resetErr)) {\n                    LOG_WRAPPERC(\"ERROR: ZSTD_CCtx_reset errorCode=%s\\n\",\n                                ZSTD_getErrorName(resetErr));\n                    return ZWRAPC_finishWithError(zwc, strm, 0);\n                }\n                resetErr = ZSTD_CCtx_setPledgedSrcSize(zwc->zbc, (flush == Z_FINISH) ? strm->avail_in : zwc->pledgedSrcSize);\n                if (ZSTD_isError(resetErr)) {\n                    LOG_WRAPPERC(\"ERROR: ZSTD_CCtx_setPledgedSrcSize errorCode=%s\\n\",\n                                ZSTD_getErrorName(resetErr));\n                    return ZWRAPC_finishWithError(zwc, strm, 0);\n                }\n            } else {\n                int const res = ZWRAP_initializeCStream(zwc, NULL, 0, (flush == Z_FINISH) ? strm->avail_in : ZSTD_CONTENTSIZE_UNKNOWN);\n                if (res != Z_OK) return ZWRAPC_finishWithError(zwc, strm, res);\n                if (flush != Z_FINISH) zwc->comprState = ZWRAP_useReset;\n            }\n        }  /* (zwc->totalInBytes == 0) */\n    }  /* ! (zwc->zbc == NULL) */\n\n    LOG_WRAPPERC(\"- deflate2 flush=%d avail_in=%d avail_out=%d total_in=%d total_out=%d\\n\", (int)flush, (int)strm->avail_in, (int)strm->avail_out, (int)strm->total_in, (int)strm->total_out);\n    if (strm->avail_in > 0) {\n        zwc->inBuffer.src = strm->next_in;\n        zwc->inBuffer.size = strm->avail_in;\n        zwc->inBuffer.pos = 0;\n        zwc->outBuffer.dst = strm->next_out;\n        zwc->outBuffer.size = strm->avail_out;\n        zwc->outBuffer.pos = 0;\n        { size_t const cErr = ZSTD_compressStream(zwc->zbc, &zwc->outBuffer, &zwc->inBuffer);\n          LOG_WRAPPERC(\"deflate ZSTD_compressStream srcSize=%d dstCapacity=%d\\n\", (int)zwc->inBuffer.size, (int)zwc->outBuffer.size);\n          if (ZSTD_isError(cErr)) return ZWRAPC_finishWithError(zwc, strm, 0);\n        }\n        strm->next_out += zwc->outBuffer.pos;\n        strm->total_out += zwc->outBuffer.pos;\n        strm->avail_out -= zwc->outBuffer.pos;\n        strm->total_in += zwc->inBuffer.pos;\n        zwc->totalInBytes += zwc->inBuffer.pos;\n        strm->next_in += zwc->inBuffer.pos;\n        strm->avail_in -= zwc->inBuffer.pos;\n    }\n\n    if (flush == Z_FULL_FLUSH\n#if ZLIB_VERNUM >= 0x1240\n        || flush == Z_TREES\n#endif\n        || flush == Z_BLOCK)\n        return ZWRAPC_finishWithErrorMsg(strm, \"Z_FULL_FLUSH, Z_BLOCK and Z_TREES are not supported!\");\n\n    if (flush == Z_FINISH) {\n        size_t bytesLeft;\n        if (zwc->streamEnd) return Z_STREAM_END;\n        zwc->outBuffer.dst = strm->next_out;\n        zwc->outBuffer.size = strm->avail_out;\n        zwc->outBuffer.pos = 0;\n        bytesLeft = ZSTD_endStream(zwc->zbc, &zwc->outBuffer);\n        LOG_WRAPPERC(\"deflate ZSTD_endStream dstCapacity=%d bytesLeft=%d\\n\", (int)strm->avail_out, (int)bytesLeft);\n        if (ZSTD_isError(bytesLeft)) return ZWRAPC_finishWithError(zwc, strm, 0);\n        strm->next_out += zwc->outBuffer.pos;\n        strm->total_out += zwc->outBuffer.pos;\n        strm->avail_out -= zwc->outBuffer.pos;\n        if (bytesLeft == 0) {\n            zwc->streamEnd = 1;\n            LOG_WRAPPERC(\"Z_STREAM_END2 strm->total_in=%d strm->avail_out=%d strm->total_out=%d\\n\",\n                        (int)strm->total_in, (int)strm->avail_out, (int)strm->total_out);\n            return Z_STREAM_END;\n    }   }\n    else\n    if (flush == Z_SYNC_FLUSH || flush == Z_PARTIAL_FLUSH) {\n        size_t bytesLeft;\n        zwc->outBuffer.dst = strm->next_out;\n        zwc->outBuffer.size = strm->avail_out;\n        zwc->outBuffer.pos = 0;\n        bytesLeft = ZSTD_flushStream(zwc->zbc, &zwc->outBuffer);\n        LOG_WRAPPERC(\"deflate ZSTD_flushStream dstCapacity=%d bytesLeft=%d\\n\", (int)strm->avail_out, (int)bytesLeft);\n        if (ZSTD_isError(bytesLeft)) return ZWRAPC_finishWithError(zwc, strm, 0);\n        strm->next_out += zwc->outBuffer.pos;\n        strm->total_out += zwc->outBuffer.pos;\n        strm->avail_out -= zwc->outBuffer.pos;\n    }\n    LOG_WRAPPERC(\"- deflate3 flush=%d avail_in=%d avail_out=%d total_in=%d total_out=%d\\n\", (int)flush, (int)strm->avail_in, (int)strm->avail_out, (int)strm->total_in, (int)strm->total_out);\n    return Z_OK;\n}\n\n\nZEXTERN int ZEXPORT z_deflateEnd _Z_OF((z_streamp strm))\n{\n    if (!g_ZWRAP_useZSTDcompression) {\n        LOG_WRAPPERC(\"- deflateEnd\\n\");\n        return deflateEnd(strm);\n    }\n    LOG_WRAPPERC(\"- deflateEnd total_in=%d total_out=%d\\n\", (int)(strm->total_in), (int)(strm->total_out));\n    {   size_t errorCode;\n        ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->state;\n        if (zwc == NULL) return Z_OK;  /* structures are already freed */\n        strm->state = NULL;\n        errorCode = ZWRAP_freeCCtx(zwc);\n        if (ZSTD_isError(errorCode)) return Z_STREAM_ERROR;\n    }\n    return Z_OK;\n}\n\n\nZEXTERN uLong ZEXPORT z_deflateBound _Z_OF((z_streamp strm,\n                                       uLong sourceLen))\n{\n    if (!g_ZWRAP_useZSTDcompression)\n        return deflateBound(strm, sourceLen);\n\n    return ZSTD_compressBound(sourceLen);\n}\n\n\nZEXTERN int ZEXPORT z_deflateParams _Z_OF((z_streamp strm,\n                                      int level,\n                                      int strategy))\n{\n    if (!g_ZWRAP_useZSTDcompression) {\n        LOG_WRAPPERC(\"- deflateParams level=%d strategy=%d\\n\", level, strategy);\n        return deflateParams(strm, level, strategy);\n    }\n\n    return Z_OK;\n}\n\n\n\n\n\n/* ===   Decompression   === */\n\ntypedef enum { ZWRAP_ZLIB_STREAM, ZWRAP_ZSTD_STREAM, ZWRAP_UNKNOWN_STREAM } ZWRAP_stream_type;\n\ntypedef struct {\n    ZSTD_DStream* zbd;\n    char headerBuf[16];   /* must be >= ZSTD_frameHeaderSize_min */\n    int errorCount;\n    unsigned long long totalInBytes; /* we need it as strm->total_in can be reset by user */\n    ZWRAP_state_t decompState;\n    ZSTD_inBuffer inBuffer;\n    ZSTD_outBuffer outBuffer;\n\n    /* zlib params */\n    int stream_size;\n    char *version;\n    int windowBits;\n    ZSTD_customMem customMem;\n    z_stream allocFunc; /* just to copy zalloc, zfree, opaque */\n} ZWRAP_DCtx;\n\n\nstatic void ZWRAP_initDCtx(ZWRAP_DCtx* zwd)\n{\n    zwd->errorCount = 0;\n    zwd->outBuffer.pos = 0;\n    zwd->outBuffer.size = 0;\n}\n\nstatic ZWRAP_DCtx* ZWRAP_createDCtx(z_streamp strm)\n{\n    ZWRAP_DCtx* zwd;\n    ZSTD_customMem customMem = { NULL, NULL, NULL };\n\n    if (strm->zalloc && strm->zfree) {\n        customMem.customAlloc = ZWRAP_allocFunction;\n        customMem.customFree = ZWRAP_freeFunction;\n    }\n    customMem.opaque = strm;\n\n    zwd = (ZWRAP_DCtx*)ZWRAP_customCalloc(sizeof(ZWRAP_DCtx), customMem);\n    if (zwd == NULL) return NULL;\n    zwd->allocFunc = *strm;\n    customMem.opaque = &zwd->allocFunc;\n    zwd->customMem = customMem;\n\n    ZWRAP_initDCtx(zwd);\n    return zwd;\n}\n\nstatic size_t ZWRAP_freeDCtx(ZWRAP_DCtx* zwd)\n{\n    if (zwd==NULL) return 0;   /* support free on null */\n    ZSTD_freeDStream(zwd->zbd);\n    ZWRAP_customFree(zwd->version, zwd->customMem);\n    ZWRAP_customFree(zwd, zwd->customMem);\n    return 0;\n}\n\n\nint ZWRAP_isUsingZSTDdecompression(z_streamp strm)\n{\n    if (strm == NULL) return 0;\n    return (strm->reserved == ZWRAP_ZSTD_STREAM);\n}\n\n\nstatic int ZWRAPD_finishWithError(ZWRAP_DCtx* zwd, z_streamp strm, int error)\n{\n    LOG_WRAPPERD(\"- ZWRAPD_finishWithError=%d\\n\", error);\n    ZWRAP_freeDCtx(zwd);\n    strm->state = NULL;\n    return (error) ? error : Z_STREAM_ERROR;\n}\n\nstatic int ZWRAPD_finishWithErrorMsg(z_streamp strm, char* message)\n{\n    ZWRAP_DCtx* const zwd = (ZWRAP_DCtx*) strm->state;\n    strm->msg = message;\n    if (zwd == NULL) return Z_STREAM_ERROR;\n\n    return ZWRAPD_finishWithError(zwd, strm, 0);\n}\n\n\nZEXTERN int ZEXPORT z_inflateInit_ _Z_OF((z_streamp strm,\n                                     const char* version, int stream_size))\n{\n    if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB) {\n        strm->reserved = ZWRAP_ZLIB_STREAM;\n        return inflateInit(strm);\n    }\n\n    {   ZWRAP_DCtx* const zwd = ZWRAP_createDCtx(strm);\n        LOG_WRAPPERD(\"- inflateInit\\n\");\n        if (zwd == NULL) return ZWRAPD_finishWithError(zwd, strm, 0);\n\n        zwd->version = (char*)ZWRAP_customMalloc(strlen(version)+1, zwd->customMem);\n        if (zwd->version == NULL) return ZWRAPD_finishWithError(zwd, strm, 0);\n        strcpy(zwd->version, version);\n\n        zwd->stream_size = stream_size;\n        zwd->totalInBytes = 0;\n        strm->state = convert_into_sis(zwd);\n        strm->total_in = 0;\n        strm->total_out = 0;\n        strm->reserved = ZWRAP_UNKNOWN_STREAM;\n        strm->adler = 0;\n    }\n\n    return Z_OK;\n}\n\n\nZEXTERN int ZEXPORT z_inflateInit2_ _Z_OF((z_streamp strm, int  windowBits,\n                                      const char *version, int stream_size))\n{\n    if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB) {\n        return inflateInit2_(strm, windowBits, version, stream_size);\n    }\n\n    {   int const ret = z_inflateInit_ (strm, version, stream_size);\n        LOG_WRAPPERD(\"- inflateInit2 windowBits=%d\\n\", windowBits);\n        if (ret == Z_OK) {\n            ZWRAP_DCtx* const zwd = (ZWRAP_DCtx*)strm->state;\n            if (zwd == NULL) return Z_STREAM_ERROR;\n            zwd->windowBits = windowBits;\n        }\n        return ret;\n    }\n}\n\nint ZWRAP_inflateReset_keepDict(z_streamp strm)\n{\n    LOG_WRAPPERD(\"- ZWRAP_inflateReset_keepDict\\n\");\n    if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)\n        return inflateReset(strm);\n\n    {   ZWRAP_DCtx* const zwd = (ZWRAP_DCtx*) strm->state;\n        if (zwd == NULL) return Z_STREAM_ERROR;\n        ZWRAP_initDCtx(zwd);\n        zwd->decompState = ZWRAP_useReset;\n        zwd->totalInBytes = 0;\n    }\n\n    strm->total_in = 0;\n    strm->total_out = 0;\n    return Z_OK;\n}\n\n\nZEXTERN int ZEXPORT z_inflateReset _Z_OF((z_streamp strm))\n{\n    LOG_WRAPPERD(\"- inflateReset\\n\");\n    if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)\n        return inflateReset(strm);\n\n    { int const ret = ZWRAP_inflateReset_keepDict(strm);\n      if (ret != Z_OK) return ret; }\n\n    { ZWRAP_DCtx* const zwd = (ZWRAP_DCtx*) strm->state;\n      if (zwd == NULL) return Z_STREAM_ERROR;\n      zwd->decompState = ZWRAP_useInit; }\n\n    return Z_OK;\n}\n\n\n#if ZLIB_VERNUM >= 0x1240\nZEXTERN int ZEXPORT z_inflateReset2 _Z_OF((z_streamp strm,\n                                      int windowBits))\n{\n    if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)\n        return inflateReset2(strm, windowBits);\n\n    {   int const ret = z_inflateReset (strm);\n        if (ret == Z_OK) {\n            ZWRAP_DCtx* const zwd = (ZWRAP_DCtx*)strm->state;\n            if (zwd == NULL) return Z_STREAM_ERROR;\n            zwd->windowBits = windowBits;\n        }\n        return ret;\n    }\n}\n#endif\n\n\nZEXTERN int ZEXPORT z_inflateSetDictionary _Z_OF((z_streamp strm,\n                                             const Bytef *dictionary,\n                                             uInt  dictLength))\n{\n    LOG_WRAPPERD(\"- inflateSetDictionary\\n\");\n    if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)\n        return inflateSetDictionary(strm, dictionary, dictLength);\n\n    {   ZWRAP_DCtx* const zwd = (ZWRAP_DCtx*) strm->state;\n        if (zwd == NULL || zwd->zbd == NULL) return Z_STREAM_ERROR;\n        { size_t const resetErr = ZSTD_DCtx_reset(zwd->zbd, ZSTD_reset_session_only);\n          if (ZSTD_isError(resetErr)) return ZWRAPD_finishWithError(zwd, strm, 0); }\n        { size_t const loadErr = ZSTD_DCtx_loadDictionary(zwd->zbd, dictionary, dictLength);\n          if (ZSTD_isError(loadErr)) return ZWRAPD_finishWithError(zwd, strm, 0); }\n        zwd->decompState = ZWRAP_useReset;\n\n        if (zwd->totalInBytes == ZSTD_HEADERSIZE) {\n            zwd->inBuffer.src = zwd->headerBuf;\n            zwd->inBuffer.size = zwd->totalInBytes;\n            zwd->inBuffer.pos = 0;\n            zwd->outBuffer.dst = strm->next_out;\n            zwd->outBuffer.size = 0;\n            zwd->outBuffer.pos = 0;\n            {   size_t const errorCode = ZSTD_decompressStream(zwd->zbd, &zwd->outBuffer, &zwd->inBuffer);\n                LOG_WRAPPERD(\"inflateSetDictionary ZSTD_decompressStream errorCode=%d srcSize=%d dstCapacity=%d\\n\",\n                             (int)errorCode, (int)zwd->inBuffer.size, (int)zwd->outBuffer.size);\n                if (zwd->inBuffer.pos < zwd->outBuffer.size || ZSTD_isError(errorCode)) {\n                    LOG_WRAPPERD(\"ERROR: ZSTD_decompressStream %s\\n\",\n                                 ZSTD_getErrorName(errorCode));\n                    return ZWRAPD_finishWithError(zwd, strm, 0);\n    }   }   }   }\n\n    return Z_OK;\n}\n\n\nZEXTERN int ZEXPORT z_inflate _Z_OF((z_streamp strm, int flush))\n{\n    ZWRAP_DCtx* zwd;\n\n    if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved) {\n        int const result = inflate(strm, flush);\n        LOG_WRAPPERD(\"- inflate2 flush=%d avail_in=%d avail_out=%d total_in=%d total_out=%d res=%d\\n\",\n                     (int)flush, (int)strm->avail_in, (int)strm->avail_out, (int)strm->total_in, (int)strm->total_out, result);\n        return result;\n    }\n\n    if (strm->avail_in <= 0) return Z_OK;\n\n    zwd = (ZWRAP_DCtx*) strm->state;\n    LOG_WRAPPERD(\"- inflate1 flush=%d avail_in=%d avail_out=%d total_in=%d total_out=%d\\n\",\n                 (int)flush, (int)strm->avail_in, (int)strm->avail_out, (int)strm->total_in, (int)strm->total_out);\n\n    if (zwd == NULL) return Z_STREAM_ERROR;\n    if (zwd->decompState == ZWRAP_streamEnd) return Z_STREAM_END;\n\n    if (zwd->totalInBytes < ZLIB_HEADERSIZE) {\n        if (zwd->totalInBytes == 0 && strm->avail_in >= ZLIB_HEADERSIZE) {\n            if (ZWRAP_readLE32(strm->next_in) != ZSTD_MAGICNUMBER) {\n                {   int const initErr = (zwd->windowBits) ?\n                                inflateInit2_(strm, zwd->windowBits, zwd->version, zwd->stream_size) :\n                                inflateInit_(strm, zwd->version, zwd->stream_size);\n                    LOG_WRAPPERD(\"ZLIB inflateInit errorCode=%d\\n\", initErr);\n                    if (initErr != Z_OK) return ZWRAPD_finishWithError(zwd, strm, initErr);\n                }\n\n                strm->reserved = ZWRAP_ZLIB_STREAM;\n                { size_t const freeErr = ZWRAP_freeDCtx(zwd);\n                  if (ZSTD_isError(freeErr)) goto error; }\n\n                {   int const result = (flush == Z_INFLATE_SYNC) ?\n                                        inflateSync(strm) :\n                                        inflate(strm, flush);\n                    LOG_WRAPPERD(\"- inflate3 flush=%d avail_in=%d avail_out=%d total_in=%d total_out=%d res=%d\\n\",\n                                 (int)flush, (int)strm->avail_in, (int)strm->avail_out, (int)strm->total_in, (int)strm->total_out, res);\n                    return result;\n            }   }\n        } else {  /* ! (zwd->totalInBytes == 0 && strm->avail_in >= ZLIB_HEADERSIZE) */\n            size_t const srcSize = MIN(strm->avail_in, ZLIB_HEADERSIZE - zwd->totalInBytes);\n            memcpy(zwd->headerBuf+zwd->totalInBytes, strm->next_in, srcSize);\n            strm->total_in += srcSize;\n            zwd->totalInBytes += srcSize;\n            strm->next_in += srcSize;\n            strm->avail_in -= srcSize;\n            if (zwd->totalInBytes < ZLIB_HEADERSIZE) return Z_OK;\n\n            if (ZWRAP_readLE32(zwd->headerBuf) != ZSTD_MAGICNUMBER) {\n                z_stream strm2;\n                strm2.next_in = strm->next_in;\n                strm2.avail_in = strm->avail_in;\n                strm2.next_out = strm->next_out;\n                strm2.avail_out = strm->avail_out;\n\n                {   int const initErr = (zwd->windowBits) ?\n                                inflateInit2_(strm, zwd->windowBits, zwd->version, zwd->stream_size) :\n                                inflateInit_(strm, zwd->version, zwd->stream_size);\n                    LOG_WRAPPERD(\"ZLIB inflateInit errorCode=%d\\n\", initErr);\n                    if (initErr != Z_OK) return ZWRAPD_finishWithError(zwd, strm, initErr);\n                }\n\n                /* inflate header */\n                strm->next_in = (unsigned char*)zwd->headerBuf;\n                strm->avail_in = ZLIB_HEADERSIZE;\n                strm->avail_out = 0;\n                {   int const dErr = inflate(strm, Z_NO_FLUSH);\n                    LOG_WRAPPERD(\"ZLIB inflate errorCode=%d strm->avail_in=%d\\n\",\n                                  dErr, (int)strm->avail_in);\n                    if (dErr != Z_OK)\n                        return ZWRAPD_finishWithError(zwd, strm, dErr);\n                }\n                if (strm->avail_in > 0) goto error;\n\n                strm->next_in = strm2.next_in;\n                strm->avail_in = strm2.avail_in;\n                strm->next_out = strm2.next_out;\n                strm->avail_out = strm2.avail_out;\n\n                strm->reserved = ZWRAP_ZLIB_STREAM; /* mark as zlib stream */\n                { size_t const freeErr = ZWRAP_freeDCtx(zwd);\n                  if (ZSTD_isError(freeErr)) goto error; }\n\n                {   int const result = (flush == Z_INFLATE_SYNC) ?\n                                       inflateSync(strm) :\n                                       inflate(strm, flush);\n                    LOG_WRAPPERD(\"- inflate2 flush=%d avail_in=%d avail_out=%d total_in=%d total_out=%d res=%d\\n\",\n                                 (int)flush, (int)strm->avail_in, (int)strm->avail_out, (int)strm->total_in, (int)strm->total_out, res);\n                    return result;\n        }   }   }  /* if ! (zwd->totalInBytes == 0 && strm->avail_in >= ZLIB_HEADERSIZE) */\n    }  /* (zwd->totalInBytes < ZLIB_HEADERSIZE) */\n\n    strm->reserved = ZWRAP_ZSTD_STREAM; /* mark as zstd steam */\n\n    if (flush == Z_INFLATE_SYNC) { strm->msg = \"inflateSync is not supported!\"; goto error; }\n\n    if (!zwd->zbd) {\n        zwd->zbd = ZSTD_createDStream_advanced(zwd->customMem);\n        if (zwd->zbd == NULL) { LOG_WRAPPERD(\"ERROR: ZSTD_createDStream_advanced\\n\"); goto error; }\n        zwd->decompState = ZWRAP_useInit;\n    }\n\n    if (zwd->totalInBytes < ZSTD_HEADERSIZE) {\n        if (zwd->totalInBytes == 0 && strm->avail_in >= ZSTD_HEADERSIZE) {\n            if (zwd->decompState == ZWRAP_useInit) {\n                size_t const initErr = ZSTD_initDStream(zwd->zbd);\n                if (ZSTD_isError(initErr)) {\n                    LOG_WRAPPERD(\"ERROR: ZSTD_initDStream errorCode=%s\\n\",\n                                 ZSTD_getErrorName(initErr));\n                    goto error;\n                }\n            } else {\n                size_t const resetErr = ZSTD_DCtx_reset(zwd->zbd, ZSTD_reset_session_only);\n                if (ZSTD_isError(resetErr)) goto error;\n            }\n        } else {\n            size_t const srcSize = MIN(strm->avail_in, ZSTD_HEADERSIZE - zwd->totalInBytes);\n            memcpy(zwd->headerBuf+zwd->totalInBytes, strm->next_in, srcSize);\n            strm->total_in += srcSize;\n            zwd->totalInBytes += srcSize;\n            strm->next_in += srcSize;\n            strm->avail_in -= srcSize;\n            if (zwd->totalInBytes < ZSTD_HEADERSIZE) return Z_OK;\n\n            if (zwd->decompState == ZWRAP_useInit) {\n                size_t const initErr = ZSTD_initDStream(zwd->zbd);\n                if (ZSTD_isError(initErr)) {\n                    LOG_WRAPPERD(\"ERROR: ZSTD_initDStream errorCode=%s\\n\",\n                                ZSTD_getErrorName(initErr));\n                    goto error;\n                }\n            } else {\n                size_t const resetErr = ZSTD_DCtx_reset(zwd->zbd, ZSTD_reset_session_only);\n                if (ZSTD_isError(resetErr)) goto error;\n            }\n\n            zwd->inBuffer.src = zwd->headerBuf;\n            zwd->inBuffer.size = ZSTD_HEADERSIZE;\n            zwd->inBuffer.pos = 0;\n            zwd->outBuffer.dst = strm->next_out;\n            zwd->outBuffer.size = 0;\n            zwd->outBuffer.pos = 0;\n            {   size_t const dErr = ZSTD_decompressStream(zwd->zbd, &zwd->outBuffer, &zwd->inBuffer);\n                LOG_WRAPPERD(\"inflate ZSTD_decompressStream1 errorCode=%d srcSize=%d dstCapacity=%d\\n\",\n                            (int)dErr, (int)zwd->inBuffer.size, (int)zwd->outBuffer.size);\n                if (ZSTD_isError(dErr)) {\n                    LOG_WRAPPERD(\"ERROR: ZSTD_decompressStream1 %s\\n\", ZSTD_getErrorName(dErr));\n                    goto error;\n            }   }\n            if (zwd->inBuffer.pos != zwd->inBuffer.size) goto error; /* not consumed */\n        }\n    }   /* (zwd->totalInBytes < ZSTD_HEADERSIZE) */\n\n    zwd->inBuffer.src = strm->next_in;\n    zwd->inBuffer.size = strm->avail_in;\n    zwd->inBuffer.pos = 0;\n    zwd->outBuffer.dst = strm->next_out;\n    zwd->outBuffer.size = strm->avail_out;\n    zwd->outBuffer.pos = 0;\n    {   size_t const dErr = ZSTD_decompressStream(zwd->zbd, &zwd->outBuffer, &zwd->inBuffer);\n        LOG_WRAPPERD(\"inflate ZSTD_decompressStream2 errorCode=%d srcSize=%d dstCapacity=%d\\n\",\n                    (int)dErr, (int)strm->avail_in, (int)strm->avail_out);\n        if (ZSTD_isError(dErr)) {\n            zwd->errorCount++;\n            LOG_WRAPPERD(\"ERROR: ZSTD_decompressStream2 %s zwd->errorCount=%d\\n\",\n                        ZSTD_getErrorName(dErr), zwd->errorCount);\n            if (zwd->errorCount<=1) return Z_NEED_DICT; else goto error;\n        }\n        LOG_WRAPPERD(\"inflate inBuffer.pos=%d inBuffer.size=%d outBuffer.pos=%d outBuffer.size=%d o\\n\",\n                    (int)zwd->inBuffer.pos, (int)zwd->inBuffer.size, (int)zwd->outBuffer.pos, (int)zwd->outBuffer.size);\n        strm->next_out += zwd->outBuffer.pos;\n        strm->total_out += zwd->outBuffer.pos;\n        strm->avail_out -= zwd->outBuffer.pos;\n        strm->total_in += zwd->inBuffer.pos;\n        zwd->totalInBytes += zwd->inBuffer.pos;\n        strm->next_in += zwd->inBuffer.pos;\n        strm->avail_in -= zwd->inBuffer.pos;\n        if (dErr == 0) {\n            LOG_WRAPPERD(\"inflate Z_STREAM_END1 avail_in=%d avail_out=%d total_in=%d total_out=%d\\n\",\n                        (int)strm->avail_in, (int)strm->avail_out, (int)strm->total_in, (int)strm->total_out);\n            zwd->decompState = ZWRAP_streamEnd;\n            return Z_STREAM_END;\n        }\n    }  /* dErr lifetime */\n\n    LOG_WRAPPERD(\"- inflate2 flush=%d avail_in=%d avail_out=%d total_in=%d total_out=%d res=%d\\n\",\n                (int)flush, (int)strm->avail_in, (int)strm->avail_out, (int)strm->total_in, (int)strm->total_out, Z_OK);\n    return Z_OK;\n\nerror:\n    return ZWRAPD_finishWithError(zwd, strm, 0);\n}\n\n\nZEXTERN int ZEXPORT z_inflateEnd _Z_OF((z_streamp strm))\n{\n    if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)\n        return inflateEnd(strm);\n\n    LOG_WRAPPERD(\"- inflateEnd total_in=%d total_out=%d\\n\",\n                (int)(strm->total_in), (int)(strm->total_out));\n    {   ZWRAP_DCtx* const zwd = (ZWRAP_DCtx*) strm->state;\n        if (zwd == NULL) return Z_OK;  /* structures are already freed */\n        { size_t const freeErr = ZWRAP_freeDCtx(zwd);\n          if (ZSTD_isError(freeErr)) return Z_STREAM_ERROR; }\n        strm->state = NULL;\n    }\n    return Z_OK;\n}\n\n\nZEXTERN int ZEXPORT z_inflateSync _Z_OF((z_streamp strm))\n{\n    if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved) {\n        return inflateSync(strm);\n    }\n\n    return z_inflate(strm, Z_INFLATE_SYNC);\n}\n\n\n\n/* Advanced compression functions */\nZEXTERN int ZEXPORT z_deflateCopy _Z_OF((z_streamp dest,\n                                    z_streamp source))\n{\n    if (!g_ZWRAP_useZSTDcompression)\n        return deflateCopy(dest, source);\n    return ZWRAPC_finishWithErrorMsg(source, \"deflateCopy is not supported!\");\n}\n\n\nZEXTERN int ZEXPORT z_deflateTune _Z_OF((z_streamp strm,\n                                    int good_length,\n                                    int max_lazy,\n                                    int nice_length,\n                                    int max_chain))\n{\n    if (!g_ZWRAP_useZSTDcompression)\n        return deflateTune(strm, good_length, max_lazy, nice_length, max_chain);\n    return ZWRAPC_finishWithErrorMsg(strm, \"deflateTune is not supported!\");\n}\n\n\n#if ZLIB_VERNUM >= 0x1260\nZEXTERN int ZEXPORT z_deflatePending _Z_OF((z_streamp strm,\n                                       unsigned *pending,\n                                       int *bits))\n{\n    if (!g_ZWRAP_useZSTDcompression)\n        return deflatePending(strm, pending, bits);\n    return ZWRAPC_finishWithErrorMsg(strm, \"deflatePending is not supported!\");\n}\n#endif\n\n\nZEXTERN int ZEXPORT z_deflatePrime _Z_OF((z_streamp strm,\n                                     int bits,\n                                     int value))\n{\n    if (!g_ZWRAP_useZSTDcompression)\n        return deflatePrime(strm, bits, value);\n    return ZWRAPC_finishWithErrorMsg(strm, \"deflatePrime is not supported!\");\n}\n\n\nZEXTERN int ZEXPORT z_deflateSetHeader _Z_OF((z_streamp strm,\n                                         gz_headerp head))\n{\n    if (!g_ZWRAP_useZSTDcompression)\n        return deflateSetHeader(strm, head);\n    return ZWRAPC_finishWithErrorMsg(strm, \"deflateSetHeader is not supported!\");\n}\n\n\n\n\n/* Advanced decompression functions */\n#if ZLIB_VERNUM >= 0x1280\nZEXTERN int ZEXPORT z_inflateGetDictionary _Z_OF((z_streamp strm,\n                                             Bytef *dictionary,\n                                             uInt  *dictLength))\n{\n    if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)\n        return inflateGetDictionary(strm, dictionary, dictLength);\n    return ZWRAPD_finishWithErrorMsg(strm, \"inflateGetDictionary is not supported!\");\n}\n#endif\n\n\nZEXTERN int ZEXPORT z_inflateCopy _Z_OF((z_streamp dest,\n                                    z_streamp source))\n{\n    if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !source->reserved)\n        return inflateCopy(dest, source);\n    return ZWRAPD_finishWithErrorMsg(source, \"inflateCopy is not supported!\");\n}\n\n\n#if ZLIB_VERNUM >= 0x1240\nZEXTERN long ZEXPORT z_inflateMark _Z_OF((z_streamp strm))\n{\n    if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)\n        return inflateMark(strm);\n    return ZWRAPD_finishWithErrorMsg(strm, \"inflateMark is not supported!\");\n}\n#endif\n\n\nZEXTERN int ZEXPORT z_inflatePrime _Z_OF((z_streamp strm,\n                                     int bits,\n                                     int value))\n{\n    if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)\n        return inflatePrime(strm, bits, value);\n    return ZWRAPD_finishWithErrorMsg(strm, \"inflatePrime is not supported!\");\n}\n\n\nZEXTERN int ZEXPORT z_inflateGetHeader _Z_OF((z_streamp strm,\n                                         gz_headerp head))\n{\n    if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)\n        return inflateGetHeader(strm, head);\n    return ZWRAPD_finishWithErrorMsg(strm, \"inflateGetHeader is not supported!\");\n}\n\n\nZEXTERN int ZEXPORT z_inflateBackInit_ _Z_OF((z_streamp strm, int windowBits,\n                                         unsigned char FAR *window,\n                                         const char *version,\n                                         int stream_size))\n{\n    if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)\n        return inflateBackInit_(strm, windowBits, window, version, stream_size);\n    return ZWRAPD_finishWithErrorMsg(strm, \"inflateBackInit is not supported!\");\n}\n\n\nZEXTERN int ZEXPORT z_inflateBack _Z_OF((z_streamp strm,\n                                    in_func in, void FAR *in_desc,\n                                    out_func out, void FAR *out_desc))\n{\n    if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)\n        return inflateBack(strm, in, in_desc, out, out_desc);\n    return ZWRAPD_finishWithErrorMsg(strm, \"inflateBack is not supported!\");\n}\n\n\nZEXTERN int ZEXPORT z_inflateBackEnd _Z_OF((z_streamp strm))\n{\n    if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)\n        return inflateBackEnd(strm);\n    return ZWRAPD_finishWithErrorMsg(strm, \"inflateBackEnd is not supported!\");\n}\n\n\nZEXTERN uLong ZEXPORT z_zlibCompileFlags _Z_OF((void)) { return zlibCompileFlags(); }\n\n\n\n                    /* ===   utility functions  === */\n#ifndef Z_SOLO\n\nZEXTERN int ZEXPORT z_compress _Z_OF((Bytef *dest,   uLongf *destLen,\n                                 const Bytef *source, uLong sourceLen))\n{\n    if (!g_ZWRAP_useZSTDcompression)\n        return compress(dest, destLen, source, sourceLen);\n\n    {   size_t dstCapacity = *destLen;\n        size_t const cSize = ZSTD_compress(dest, dstCapacity,\n                                           source, sourceLen,\n                                           ZWRAP_DEFAULT_CLEVEL);\n        LOG_WRAPPERD(\"z_compress sourceLen=%d dstCapacity=%d\\n\",\n                    (int)sourceLen, (int)dstCapacity);\n        if (ZSTD_isError(cSize)) return Z_STREAM_ERROR;\n        *destLen = cSize;\n    }\n    return Z_OK;\n}\n\n\nZEXTERN int ZEXPORT z_compress2 _Z_OF((Bytef *dest,   uLongf *destLen,\n                                  const Bytef *source, uLong sourceLen,\n                                  int level))\n{\n    if (!g_ZWRAP_useZSTDcompression)\n        return compress2(dest, destLen, source, sourceLen, level);\n\n    { size_t dstCapacity = *destLen;\n      size_t const cSize = ZSTD_compress(dest, dstCapacity, source, sourceLen, level);\n      if (ZSTD_isError(cSize)) return Z_STREAM_ERROR;\n      *destLen = cSize;\n    }\n    return Z_OK;\n}\n\n\nZEXTERN uLong ZEXPORT z_compressBound _Z_OF((uLong sourceLen))\n{\n    if (!g_ZWRAP_useZSTDcompression)\n        return compressBound(sourceLen);\n\n    return ZSTD_compressBound(sourceLen);\n}\n\n\nZEXTERN int ZEXPORT z_uncompress _Z_OF((Bytef *dest,   uLongf *destLen,\n                                   const Bytef *source, uLong sourceLen))\n{\n    if (!ZSTD_isFrame(source, sourceLen))\n        return uncompress(dest, destLen, source, sourceLen);\n\n    { size_t dstCapacity = *destLen;\n      size_t const dSize = ZSTD_decompress(dest, dstCapacity, source, sourceLen);\n      if (ZSTD_isError(dSize)) return Z_STREAM_ERROR;\n      *destLen = dSize;\n     }\n    return Z_OK;\n}\n\n#endif /* !Z_SOLO */\n\n\n                        /* checksum functions */\n\nZEXTERN uLong ZEXPORT z_adler32 _Z_OF((uLong adler, const Bytef *buf, uInt len))\n{\n    return adler32(adler, buf, len);\n}\n\nZEXTERN uLong ZEXPORT z_crc32   _Z_OF((uLong crc, const Bytef *buf, uInt len))\n{\n    return crc32(crc, buf, len);\n}\n\n\n#if ZLIB_VERNUM >= 0x12B0\nZEXTERN uLong ZEXPORT z_adler32_z _Z_OF((uLong adler, const Bytef *buf, z_size_t len))\n{\n    return adler32_z(adler, buf, len);\n}\n\nZEXTERN uLong ZEXPORT z_crc32_z _Z_OF((uLong crc, const Bytef *buf, z_size_t len))\n{\n    return crc32_z(crc, buf, len);\n}\n#endif\n\n\n#if ZLIB_VERNUM >= 0x1270\nZEXTERN const z_crc_t FAR * ZEXPORT z_get_crc_table    _Z_OF((void))\n{\n    return get_crc_table();\n}\n#endif\n\n                        /* Error function */\nZEXTERN const char * ZEXPORT z_zError _Z_OF((int err))\n{\n    /* Just use zlib Error function */\n    return zError(err);\n}\n"
  },
  {
    "path": "zlibWrapper/zstd_zlibwrapper.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_ZLIBWRAPPER_H\n#define ZSTD_ZLIBWRAPPER_H\n\n#define ZLIB_CONST\n#define Z_PREFIX\n#define ZLIB_INTERNAL   /* disables gz*64 functions but fixes zlib 1.2.4 with Z_PREFIX */\n#include <zlib.h>\n\n#if !defined(z_const)\n    #define z_const\n#endif\n\n#if !defined(_Z_OF)\n    #define _Z_OF OF\n#endif\n\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* returns a string with version of zstd library */\nconst char * zstdVersion(void);\n\n\n/*** COMPRESSION ***/\n/* ZWRAP_useZSTDcompression() enables/disables zstd compression during runtime.\n   By default zstd compression is disabled. To enable zstd compression please use one of the methods:\n   - compilation with the additional option -DZWRAP_USE_ZSTD=1\n   - using '#define ZWRAP_USE_ZSTD 1' in source code before '#include \"zstd_zlibwrapper.h\"'\n   - calling ZWRAP_useZSTDcompression(1)\n   All above-mentioned methods will enable zstd compression for all threads.\n   Be aware that ZWRAP_useZSTDcompression() is not thread-safe and may lead to a race condition. */\nvoid ZWRAP_useZSTDcompression(int turn_on);\n\n/* checks if zstd compression is turned on */\nint ZWRAP_isUsingZSTDcompression(void);\n\n/* Changes a pledged source size for a given compression stream.\n   It will change ZSTD compression parameters what may improve compression speed and/or ratio.\n   The function should be called just after deflateInit() or deflateReset() and before deflate() or deflateSetDictionary().\n   It's only helpful when data is compressed in blocks.\n   There will be no change in case of deflateInit() or deflateReset() immediately followed by deflate(strm, Z_FINISH)\n   as this case is automatically detected.  */\nint ZWRAP_setPledgedSrcSize(z_streamp strm, unsigned long long pledgedSrcSize);\n\n/* Similar to deflateReset but preserves dictionary set using deflateSetDictionary.\n   It should improve compression speed because there will be less calls to deflateSetDictionary\n   When using zlib compression this method redirects to deflateReset. */\nint ZWRAP_deflateReset_keepDict(z_streamp strm);\n\n\n\n/*** DECOMPRESSION ***/\ntypedef enum { ZWRAP_FORCE_ZLIB, ZWRAP_AUTO } ZWRAP_decompress_type;\n\n/* ZWRAP_setDecompressionType() enables/disables automatic recognition of zstd/zlib compressed data during runtime.\n   By default auto-detection of zstd and zlib streams in enabled (ZWRAP_AUTO).\n   Forcing zlib decompression with ZWRAP_setDecompressionType(ZWRAP_FORCE_ZLIB) slightly improves\n   decompression speed of zlib-encoded streams.\n   Be aware that ZWRAP_setDecompressionType() is not thread-safe and may lead to a race condition. */\nvoid ZWRAP_setDecompressionType(ZWRAP_decompress_type type);\n\n/* checks zstd decompression type */\nZWRAP_decompress_type ZWRAP_getDecompressionType(void);\n\n/* Checks if zstd decompression is used for a given stream.\n   If will return 1 only when inflate() was called and zstd header was detected. */\nint ZWRAP_isUsingZSTDdecompression(z_streamp strm);\n\n/* Similar to inflateReset but preserves dictionary set using inflateSetDictionary.\n   inflate() will return Z_NEED_DICT only for the first time what will improve decompression speed.\n   For zlib streams this method redirects to inflateReset. */\nint ZWRAP_inflateReset_keepDict(z_streamp strm);\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* ZSTD_ZLIBWRAPPER_H */\n"
  }
]